2013-06-14 18 views
15

Sto lavorando su un'app di Windows 8 Metro che applica i filtri alle immagini. Ho una versione web dell'app e ho voluto portarla. Ma come tutti sappiamo, WinRT non ha tutte le cose buone che .NET fornisce altrimenti:/C# Windows 8 Store (Metro, WinRT) Byte array a BitmapImage

Attualmente sto applicando i filtri su un array di byte e voglio mantenerlo in questo modo, perché è super veloce! Quindi negli ultimi giorni ho cercato modi per convertire uno StorageFile in byte [] e poi byte [] in BitmapImage.

Finora sono riuscito a eseguire il primo (StorageFile su byte []). Ecco come lo faccio:

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

Questo pezzo di codice restituisce un byte[] che contiene i dati dei pixel come BGRA.

E qui arriva la parte difficile. Non riesco a convertire correttamente l'array di byte in un BitmapImage. Ho cercato dappertutto e molte persone suggeriscono di usare WriteableBitmap ma questo non mi fa molto bene. Ho anche trovato alcuni pezzi di codice che dovrebbero funzionare ... ma non lo fanno.

Una delle soluzioni che ho provato sta usando InMemoryRandomAccessStream simili:

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

Questo genera la seguente eccezione:

Un'eccezione di tipo 'System.Exception' avvenuta in mscorlib. dll, ma non è stato gestito nel codice utente

Ulteriori informazioni: Impossibile trovare il componente. (Eccezione da HRESULT: 0x88982F50)

Ho provato ad utilizzare questa linea invece:

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

Ma mi ha fatto non va bene in quanto continuo a ricevere tale eccezione.

Inoltre ho provato questo:

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

E ottenere la stessa eccezione come il primo pezzo di codice.

Ho anche provato diversi altri modi che includono l'utilizzo di un flusso normale, quindi la conversione in IRandomAccessStream ma non hanno funzionato neanche.

Tutto il codice sopra mi sembra soddisfacente. Quindi la mia ipotesi al momento è che il problema sia nello byte[]. Immagino che il formato del pixelData all'interno non sia valido, quindi ho provato a cambiarlo in RGBA, ma non è stato d'aiuto neanche io. Anche il PixelHeight e PixelWidth del BitmapImage sono 0.

+0

Hai trovato una soluzione a questo? Sto anche avendo lo stesso problema. – TheQuestioner

risposta

12

Questo sta lavorando per me,

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

ha dovuto cercare di azzerare (stream.Seek (0)) per funzionare :) grazie mille :) –

1

questo è il mio primo answer..hope sarà di aiuto.

Ho avuto lo stesso identico problema e ho spanduto più di 6 ore cercando di capirlo. questo è quello che mi è venuto in mente: quello che hai detto era giusto.ci sono 2 waye per convertire immagini a ByteArray:

First aproach (il vostro)

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

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

se youll utilizza il secondo aproach per decodificare il pic, senza Pixel, questo convertitore funzionerà:

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

per il primo approccio, necessario lavorare con Writeabl eBitmap come hai detto.