2010-11-12 23 views
20

Pracuję nad programem, który pobiera obrazy z adresu URL do bitmapy i wyświetla je. Następnie próbuję zapisać bitmapimage na twardym dysku za pomocą jpegbitmapencoder. Plik został pomyślnie utworzony, ale rzeczywisty obraz jpeg jest pusty lub 1 czarny piksel.Zapisz BitmapImage do pliku

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

Jest to funkcja, która zapisuje i wyświetla zdjęcie. Zdjęcie jest wyświetlane poprawnie, ale znowu po zapisaniu otrzymuję pusty jpeg lub 1 czarny piksel.

+0

Wystarczy użyć encoder.Frames.Add (BitmapFrame.Create (nowa WriteableBitmap (objImage))); – Andreas

Odpowiedz

28

Po utworzeniu obrazu bitmapowego z Uri wymagany jest czas na pobranie obrazu.

Jeśli zaznaczysz następującą właściwość, wartość będzie prawdopodobnie TRUE

objImage.IsDownloading 

Jako takie, to znacznie dołączyć słuchacza do obsługi zdarzeń DownloadCompleted i przenieść wszystkie przetwarzanie tej EventHandler.

objImage.DownloadCompleted += objImage_DownloadCompleted; 

Gdzie że handler będzie wyglądać mniej więcej tak:

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

będzie prawdopodobnie również dodać kolejny eventhandler dla DownloadFailed aby bezpiecznie obsługiwać wszelkie przypadki błędów.

Edit

Dodano pełną klasy próbki oparte na komentarz Bena:

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

Przetestowałem Twój kod i ten sam problem nadal występuje. jpeg zapisany jest pusty lub ma 1 czarny piksel. –

+0

@Ben - Kod działa ... zaktualizowana odpowiedź będzie pełna kod przykładowy użyłem do przetestowania mojej odpowiedzi; Czy to Ci pasuje? Należy pobrać logo Google 9KB i zapisać je na dysku. –

+0

Dzięki temu twój kod działa doskonale i działa również w moim kodzie. Problemem, który wskazałeś, było to, że zdjęcie nie zostało całkowicie pobrane z Uri. Jeszcze raz dzięki. –

4

rozwijając rozwiązania Chris Baxter, ten konwerter wykorzystuje lokalną wersję jeśli istnieje, w przeciwnym razie pliki do pobrania go i zapisuje plik .

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

I upewnij się, można uzyskać dostęp do konwertera obrębie 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> 

i skorzystać z konwertera na obrazie

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