2013-06-14 14 views
15

Pracuję nad aplikacją Metro w Windows 8, która stosuje filtry do obrazów. Mam wersję internetową aplikacji i chciałem ją przenieść. Ale jak wszyscy wiemy, WinRT nie ma wszystkich dobrych rzeczy. NET stanowi inaczej:/C# Windows 8 Store (Metro, WinRT) Tablica bajtów do BitmapImage

Obecnie stosuję filtry w tablicy bajtów i chcę zachować to w ten sposób, ponieważ jest super szybki! Tak więc od kilku dni szukam sposobów konwersji pliku StorageFile na bajt [], a następnie bajtu [] na BitmapImage.

Do tej pory udało mi się zrobić pierwszy (StorageFile to byte []). Oto jak to zrobić:

public async Task<Byte[]> ImageFileToByteArray(StorageFile file) 
    { 
     IRandomAccessStream stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read); 
     BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream); 
     PixelDataProvider pixelData = await decoder.GetPixelDataAsync(); 
     return pixelData.DetachPixelData(); 
    } 

Ten fragment kodu zwraca byte[] który zawiera dane pikseli jak BGRA.

I tu pojawia się trudna część. Nie mogę pomyślnie przekonwertować tablicy bajtów na obraz bitmapowy. Przeszukałem wszystkie miejsca i wiele osób sugeruje użycie WriteableBitmap, ale to nie ma dla mnie większego znaczenia. Znalazłem także fragmenty kodu, które powinny działać ... ale nie działają.

Jednym z rozwiązań, jakie stosuje InMemoryRandomAccessStream próbowano tak:

public async Task<BitmapImage> ByteArrayToBitmapImage(Byte[] pixels) 
    { 
     var stream = new InMemoryRandomAccessStream(); 
     await stream.WriteAsync(pixels.AsBuffer()); 
     stream.Seek(0); 
     var image = new BitmapImage(); 
     await image.SetSourceAsync(stream); 
     return image; 
    } 

Ten wyrzuca następujące wyjątki:

wyjątek typu „System.Exception” w module mscorlib. dll, ale nie było obsługiwane w kodzie użytkownika

Informacje dodatkowe: Komponent nie może zostać znaleziony. (Wyjątek od HRESULT: 0x88982F50)

Próbowałem za pomocą tej linii zamiast:

PixelDataProvider pixelData = await decoder.GetPixelDataAsync(
      BitmapPixelFormat.Bgra8, 
      BitmapAlphaMode.Ignore, 
      new BitmapTransform(), 
      ExifOrientationMode.IgnoreExifOrientation, 
      ColorManagementMode.DoNotColorManage); 

Ale zrobił mi nic dobrego, ponieważ wciąż otrzymuję ten wyjątek.

Próbowałem też tak:

var bitmapImage = new BitmapImage(); 
     var pixels = await ImageFileToByteArray(file); 
     ImageSource imgSource; 
     using (InMemoryRandomAccessStream ms = new InMemoryRandomAccessStream()) 
     { 
      using (DataWriter writer = new DataWriter(ms.GetOutputStreamAt(0))) 
      { 
       writer.WriteBytes(pixels); 
       await writer.StoreAsync(); 
      } 

      await bitmapImage.SetSourceAsync(ms); 
      imgSource = bitmapImage; 
     } 

I uzyskać ten sam wyjątek jako pierwszy kawałek kodu.

Próbowałem również kilka innych sposobów, które obejmują używanie normalnego strumienia, a następnie konwersję do IRandomAccessStream, ale nie działały.

Wszystkie powyższe kody wydają mi się w porządku. W tej chwili domyślam się, że problem występuje w byte[]. Zgaduję, że format wewnątrz pliku pixelData jest nieprawidłowy, więc próbowałem zmienić go na RGBA, ale to też nie pomogło. Również PixelHeight i PixelWidth z BitmapImage są 0.

+0

Znalazłeś rozwiązanie tego? Mam również ten sam problem. – TheQuestioner

Odpowiedz

12

To działa dla mnie,

private async Task<BitmapImage> ByteArrayToBitmapImage(byte[] byteArray) 
    { 
     var bitmapImage = new BitmapImage(); 

     var stream = new InMemoryRandomAccessStream(); 
     await stream.WriteAsync(byteArray.AsBuffer()); 
     stream.Seek(0); 

     bitmapImage.SetSource(stream); 
     return bitmapImage; 
    } 
+0

musiał dążyć do zera (stream.Seek (0)) do pracy :) dziękuję bardzo :) –

1

to mój pierwszy answer..hope to pomoże.

Miałem dokładnie ten sam problem i spanduję ponad 6 godzin próbując to rozgryźć. Oto, co wymyśliłem: to, co powiedziałeś, było słuszne.istnieją 2 waye do konwersji obrazu do ByteArray:

Pierwsze Aproach (twoje)

 public async Task<byte[]> ImageFileToByteArrayAsync(StorageFile file) 
    { 
     IRandomAccessStream stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read); 
     BitmapDecoder decoder = await BitmapDecoder.CreateAsync(stream); 
     PixelDataProvider pixelData = await decoder.GetPixelDataAsync(); 
     return pixelData.DetachPixelData(); 
    } 

drugie aproach

 public async Task<byte[]> ImageFileToByteArrayAsync(StorageFile file) 
    { 
     var inputStream = await file.OpenSequentialReadAsync(); 
     var readStream = inputStream.AsStreamForRead(); 
     var buffer = new byte[readStream.Length]; 
     await readStream.ReadAsync(buffer, 0, buffer.Length); 
     return buffer; 
    } 

jeśli będziesz używać drugiego Aproach do dekodowania pic, bez Pixel, ten konwerter będzie działał:

public class ByteArrayToImageConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, string language) 
    { 
     if (value == null || !(value is byte[])) 
      return null; 

     using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream()) 
     { 
      using (DataWriter writer = new DataWriter(stream.GetOutputStreamAt(0))) 
      { 
       writer.WriteBytes((byte[])value); 
       writer.StoreAsync().GetResults(); 
      } 
      BitmapImage image = new BitmapImage(); 
      image.SetSource(stream); 
      return image; 
     } 
    } 
    public object ConvertBack(object value, Type targetType, object parameter, string language)                   
    { 
     throw new NotImplementedException(); 
    } 

za pierwszy aproach musisz pracować z Writeabl eBitmap jak powiedziałeś.

Powiązane problemy