2010-11-12 125 views
20

我正在從一個程序下載圖像從一個URL到一個bitmapimage並顯示它。接下來,我嘗試使用jpegbitmapencoder將bitmapimage保存到硬盤上。該文件已成功創建,但實際的jpeg圖像爲空或1個黑色像素。保存BitmapImage到文件

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

這是保存並顯示照片的功能。照片顯示正確,但保存時會再次顯示空白jpeg或1個黑色像素。

+0

只需使用encoder.Frames.Add(BitmapFrame.Create(新的WriteableBitmap(objImage))); – Andreas 2016-06-09 13:16:55

回答

28

當您從Uri創建BitmapImage時,需要時間來下載圖像。

如果您檢查以下屬性,該值將可能是TRUE

objImage.IsDownloading 

因此,你多少附加一個監聽器DownloadCompleted事件處理程序,將所有處理該事件處理程序。

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,以便適當地處理任何錯誤情況。

編輯基於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); 
    } 
} 
+0

我測試了你的代碼,同樣的問題仍然存在。保存的jpeg爲空或具有1個黑色像素。 – 2010-11-12 04:07:30

+0

@Ben - 代碼運行...更新的答案將用於測試我的答案的完整示例代碼;那對你有用嗎?應下載9KB Google徽標並將其保存到磁盤。 – 2010-11-12 04:11:20

+0

感謝您的代碼完美工作,並且在我的代碼中工作。你指出的問題是該照片沒有完全從Uri下載。再次,謝謝。 – 2010-11-12 04:37:41

4

擴大克里斯·巴克斯特的解決方案,這種轉換器使用本地版本,如果它存在,否則它下載並保存文件。

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}"/>