Manejo de imagen WinRT

Un amigo y yo pasamos la mayor parte de la noche anterior casi arrancándonos el pelo tratando de trabajar con algunas imágenes en una aplicación de metro. Conseguimos imágenes en la aplicación con el encantamiento de compartir, y luego quise hacer algún otro trabajo con ellas, recortar las imágenes y guardarlas de nuevo en la carpeta appdata. Esto resultó extremadamente frustrante.

Mi pregunta, al final de todo esto, será "¿Cuál es la forma correcta de hacerlo, sin sentir que estoy armando un montón de piezas de rompecabezas que no coinciden?"

Al compartir varias imágenes con la aplicación, aparecen como una lista deWindows.Storage.StorageFiles. Aquí hay un código usado para manejar eso.

<code>var storageItems = await _shareOperation.Data.GetStorageItemsAsync();

foreach (StorageFile item in storageItems)
{
    var stream = await item.OpenReadAsync();
    var properties = await item.Properties.GetImagePropertiesAsync();

    var image = new WriteableBitmap((Int32)properties.Width, (Int32)properties.Height);
    image.SetSource(stream);

    images.Add(image);
}
</code>

Algunas búsquedas en línea han indicado que en la actualidad, unaWindows.UI.Xaml.Media.Imaging.WriteableBitmap es lo único capaz de permitirle acceder a los datos de píxeles en la imagen.Esta pregunta incluye una respuesta útil llena de métodos de extensión para guardar imágenes en un archivo, así que usamos esos.

Nuestros problemas fueron los peores cuando intenté abrir los archivos nuevamente más tarde. Hice algo parecido a antes:

<code>var files = await ApplicationData.Current.LocalFolder.GetFilesAsync();

foreach (var file in files)
{
    var fileStream = await file.OpenReadAsync();
    var properties = await file.Properties.GetImagePropertiesAsync();
    var bitmap = new WriteableBitmap((Int32)properties.Width, (Int32)properties.Height);
    bitmap.SetSource(fileStream);

    System.IO.Stream stream = bitmap.PixelBuffer.AsStream();
</code>

Aquí viene un problema. ¿Cuánto dura esta secuencia, si quiero que los bytes salgan de ella?

<code>    // CRASH! Length isn't supported on an IRandomAccessStream.
    var pixels = new byte[fileStream.Length];
</code>

Ok, intenta de nuevo.

<code>    var pixels = new byte[stream.Length];
</code>

Esto funciona, excepto ... si la imagen está comprimida, la secuencia es más corta de lo que cabría esperar, por lo que finalmente obtendrá una excepción fuera de límites. Por ahora finge que es un bitmap sin comprimir.

<code>    await _stream.ReadAsync(pixels, 0, pixels.Length);
</code>

Bien adivina que. Aunque dijebitmap.SetSource(fileStream); Para leer los datos, mi matriz de bytes todavía está llena de ceros. No tengo ni idea de porqué. Si paso este mismobitmap en mi interfaz de usuario a través del grupo de datos de muestra, la imagen se muestra bien. Así que claramente tiene los datos de píxeles en ese mapa de bits en algún lugar, pero no puedo leerlos fuera debitmap.PixelBuffer? Por qué no?

Finalmente, esto es lo que terminó trabajando.

<code>    var decoder = await BitmapDecoder.CreateAsync(BitmapDecoder.PngDecoderId, fileStream);
    var data = await decoder.GetPixelDataAsync();
    var bytes = data.DetachPixelData();

    /* process my data, finally */

} // end of that foreach I started a while ago
</code>

Así que ahora tengo datos de imagen, pero todavía tengo un gran problema. Para hacer algo con él, tengo que hacer suposiciones sobre su formato. No tengo idea de si es rgba, rgb, abgr, bgra, lo que puedan ser. Si me equivoco, mi procesamiento simplemente falla. He tenido docenas de ejecuciones de prueba que escupen cero bytes e imágenes dañadas, imágenes al revés (???), colores incorrectos, etc. Esperaba encontrar algo de esta información en elproperties que obtuve de llamarawait file.Properties.GetImagePropertiesAsync();, pero no hay suerte. Eso solo contiene el ancho y la altura de la imagen, además de algunas otras cosas inútiles. Documentación mínimaaquí.

Entonces, ¿por qué este proceso es tan doloroso? ¿Esto solo refleja la inmadurez de las bibliotecas en este momento y puedo esperar que mejore? ¿O ya hay alguna forma estándar de hacer esto? Ojalá fuera tan fácil como enSystem.Drawing. Eso te dio todos los datos que siempre has necesitado, y felizmente cargó cualquier tipo de imagen correctamente, sin hacerte lidiar con las transmisiones por ti mismo.

Respuestas a la pregunta(1)

Su respuesta a la pregunta