c# save bitmapimage

c# - Guardar BitmapImage en archivo



save (2)

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

<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:u="clr-namespace:MyNamespace" d:DesignHeight="500" d:DesignWidth="420"> <UserControl.Resources> <ResourceDictionary> <u:UriToCachedImageConverter x:Key="UrlToCachedImageConverter" /> </ResourceDictionary> </UserControl.Resources> </UserControl>

Y usa el convertidor en una imagen

<Image Source="{Binding URL, Mode=OneWay, Converter={StaticResource UrlToCachedImageConverter}, IsAsync=true}"/>

Estoy trabajando en un programa que descarga imágenes de una URL a una imagen de mapa de bits y lo muestra. A continuación, intento guardar la imagen de mapa de bits 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://www.google.ca/intl/en_com/images/srpr/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); } }