2010-11-12 2 views
20

Я работаю над программой, которая загружает изображения с URL-адреса в bitmapimage и отображает его. Затем я пытаюсь сохранить bitmapimage в harddrive с помощью jpegbitmapencoder. Файл успешно создан, но фактическое изображение 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 (new WriteableBitmap (objImage))); – Andreas

ответ

28

Когда вы создаете свой BitmapImage из Uri, для загрузки изображения требуется время.

Если проверить следующее свойство, значение, вероятно, будет ИСТИНА

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

Вы, вероятно, также хотят добавить еще один EventHandler для DownloadFailed, чтобы корректно обрабатывать любые случаи ошибок.

Редактировать

Добавлены полный класс образца на основе Бен комментарий:

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 черный пиксель. –

+0

@Ben - код работает ... обновленный ответ будет полным образцом кода, который я использовал для проверки моего ответа; это работает для вас? Необходимо загрузить логотип Google 9KB и сохранить его на диск. –

+0

Спасибо, что ваш код работает отлично, и он работает и в моем коде. Проблема, о которой вы указали, заключалась в том, что фотография не полностью загрузилась из Ури. Опять же, спасибо. –

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