Guardar BitmapImage en archivo

Estoy trabajando en un progtwig que descarga imágenes de una URL a una imagen de bitmap y lo muestra. A continuación, bash guardar la imagen de bitmap en el disco duro usando jpegbitmapencoder. El archivo se creó con éxito, pero la imagen JPEG actual está vacía o 1 píxel negro.

public Guid SavePhoto(string istrImagePath) { ImagePath = istrImagePath; BitmapImage objImage = new BitmapImage( new Uri(istrImagePath, UriKind.RelativeOrAbsolute)); PictureDisplayed.Source = objImage; savedCreationObject = objImage; Guid photoID = System.Guid.NewGuid(); string photolocation = photoID.ToString() + ".jpg"; //file name FileStream filestream = new FileStream(photolocation, FileMode.Create); JpegBitmapEncoder encoder = new JpegBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(objImage)); encoder.Save(filestream); return photoID; } 

Esta es la función que guarda y muestra la foto. La foto se muestra correctamente pero de nuevo cuando se guarda, obtengo un jpeg vacío o 1 píxel negro.

Cuando crea su BitmapImage desde un Uri, se requiere tiempo para descargar la imagen.

Si marca la siguiente propiedad, es probable que el valor sea VERDADERO

 objImage.IsDownloading 

Como tal, se conecta mucho un oyente al controlador de eventos DownloadCompleted y se mueve todo el procesamiento a ese EventHandler.

 objImage.DownloadCompleted += objImage_DownloadCompleted; 

Donde ese controlador se verá algo así como:

 private void objImage_DownloadCompleted(object sender, EventArgs e) { JpegBitmapEncoder encoder = new JpegBitmapEncoder(); Guid photoID = System.Guid.NewGuid(); String photolocation = photoID.ToString() + ".jpg"; //file name encoder.Frames.Add(BitmapFrame.Create((BitmapImage)sender)); using (var filestream = new FileStream(photolocation, FileMode.Create)) encoder.Save(filestream); } 

También es probable que desee agregar otro EventHandler para DownloadFailed para manejar con gracia cualquier caso de error.

Editar

Se agregó una clase de muestra completa basada en el comentario de Ben:

 public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); SavePhoto("http://sofes.miximages.com/c%23/logo1w.png"); } public void SavePhoto(string istrImagePath) { BitmapImage objImage = new BitmapImage(new Uri(istrImagePath, UriKind.RelativeOrAbsolute)); objImage.DownloadCompleted += objImage_DownloadCompleted; } private void objImage_DownloadCompleted(object sender, EventArgs e) { JpegBitmapEncoder encoder = new JpegBitmapEncoder(); Guid photoID = System.Guid.NewGuid(); String photolocation = photoID.ToString() + ".jpg"; //file name encoder.Frames.Add(BitmapFrame.Create((BitmapImage)sender)); using (var filestream = new FileStream(photolocation, FileMode.Create)) encoder.Save(filestream); } } 

Ampliando la solución de Chris Baxter, este convertidor usa la versión local si existe, de lo contrario la descarga y guarda el archivo.

 using System; using System.Globalization; using System.IO; using System.Windows.Data; using System.Windows.Media.Imaging; namespace MyNamespace { public sealed class UriToCachedImageConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var url = value as string; if (url == null) return null; var webUri = new Uri(url, UriKind.Absolute); var filename = Path.GetFileName(webUri.AbsolutePath); var localFilePath = Path.Combine("C:\\MyImagesFolder\\", filename); if (File.Exists(localFilePath)) { return BitmapFrame.Create(new Uri(localFilePath, UriKind.Absolute)); } var image = new BitmapImage(); image.BeginInit(); image.CacheOption = BitmapCacheOption.OnLoad; image.UriSource = webUri; image.EndInit(); SaveImage(image, localFilePath); return image; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } public void SaveImage(BitmapImage image, string localFilePath) { image.DownloadCompleted += (sender, args) => { var encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create((BitmapImage) sender)); using (var filestream = new FileStream(localFilePath, FileMode.Create)) { encoder.Save(filestream); } }; } } } 

Y asegúrate de que puedes acceder al convertidor dentro de tu xaml

        

Y usa el convertidor en una imagen