将BitmapImage保存到文件

我正在开发一个程序,将图像从URL下载到bitmapimage并显示出来。 接下来,我尝试使用jpegbitmapencoder将bitmapimage保存到硬盘上。 该文件已成功创build,但实际的JPEG图像是空的或1黑色像素。

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; } 

这是保存和显示照片的function。 照片显示正确,但保存时会再次显示空的jpeg或1个黑色像素。

当您从Uri创buildBitmapImage时,需要时间来下载图像。

如果您检查以下属性,则值可能为TRUE

 objImage.IsDownloading 

因此,您很多附加监听器到DownloadCompleted事件处理程序,并将所有处理移动到该EventHandler。

 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); } 

您可能还需要为DownloadFailed添加另一个EventHandler,以便优雅地处理任何错误情况。

编辑

根据Ben的评论添加完整的示例类:

 public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); SavePhoto("http://www.google.ca/intl/en_comhttp://img.dovov.comsrpr/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); } } 

克里斯·巴克斯特的解决scheme扩大,这个转换器使用本地版本,如果它存在,否则下载并保存该文件。

 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); } }; } } } 

并确保你可以在你的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> 

并在图像上使用转换器

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