WinRT-Image-Handling

Ein Freund und ich verbrachten den größten Teil der letzten Nacht damit, uns fast die Haare auszureißen und zu versuchen, mit einigen Bildern in einer Metro-App zu arbeiten. Wir haben Bilder mit dem Freigabecharme in die App aufgenommen, und dann wollte ich mit ihnen eine andere Arbeit ausführen, die Bilder zuschneiden und sie wieder im AppData-Ordner speichern. Dies erwies sich als äußerst frustrierend.

Am Ende lautet meine Frage: "Was ist die richtige Vorgehensweise, ohne das Gefühl zu haben, dass ich ein paar nicht übereinstimmende Puzzleteile zusammenhämmere?"

Wenn Sie mehrere Bilder mit der App teilen, werden diese als Liste von angezeigtWindows.Storage.StorageFiles. Hier ist ein Code, der dafür verwendet wird.

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

Einige Online-Suchanfragen haben ergeben, dass derzeit aWindows.UI.Xaml.Media.Imaging.WriteableBitmap Nur so können Sie auf die Pixeldaten im Bild zugreifen.Diese Frage Enthält eine hilfreiche Antwort voller Erweiterungsmethoden zum Speichern von Bildern in einer Datei. Daher haben wir diese verwendet.

Unsere Probleme waren die schlimmsten, als ich später versuchte, die Dateien erneut zu öffnen. Ich habe etwas Ähnliches gemacht wie vorher:

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

Hier kommt ein Problem. Wie lang ist dieser Stream, wenn ich die Bytes raus haben will?

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

OK, versuch es nochmal.

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

Dies funktioniert, außer ... wenn das Bild komprimiert ist, ist der Stream kürzer als erwartet, sodass Sie möglicherweise eine Ausnahme außerhalb der Grenzen erhalten. Vorerst soll es sich um eine unkomprimierte Bitmap handeln.

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

Rate mal. Obwohl ich sagtebitmap.SetSource(fileStream); Um die Daten einzulesen, ist mein Bytearray immer noch voller Nullen. Ich habe keine Idee warum. Wenn ich das gleich übergebebitmap In einer Benutzeroberfläche über die Beispieldatengruppe wird das Bild einwandfrei angezeigt. Die Pixeldaten in dieser Bitmap sind also eindeutig irgendwo vorhanden, aber ich kann sie nicht auslesenbitmap.PixelBuffer? Warum nicht?

Schließlich ist hier, was tatsächlich funktioniert hat.

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

So, jetzt habe ich Bilddaten, aber ich habe immer noch ein großes Problem. Um etwas damit anfangen zu können, muss ich Annahmen über das Format treffen. Ich habe keine Ahnung, ob es rgba, rgb, abgr, bgra ist, was auch immer sie sein können. Wenn ich falsch denke, schlägt meine Verarbeitung fehl. Ich hatte Dutzende von Testläufen, in denen Null-Byte-Bilder und beschädigte Bilder, verkehrte Bilder (???), falsche Farben usw. ausgespuckt wurden. Ich hätte erwartet, dass ich einige dieser Informationen in der finden würdeproperties das habe ich von anrufen bekommenawait file.Properties.GetImagePropertiesAsync();, aber kein Glück. Das enthält nur die Bildbreite und -höhe sowie einige andere nutzlose Dinge. Minimale DokumentationHier.

Warum ist dieser Prozess so schmerzhaft? Spiegelt dies nur die Unreife der Bibliotheken wider, und kann ich damit rechnen, dass es besser wird? Oder gibt es dafür schon einen Standard? Ich wünschte, es wäre so einfach wie inSystem.Drawing. Das gab Ihnen alle Daten, die Sie jemals brauchten, und hat jeden Bildtyp korrekt geladen, ohne dass Sie sich selbst mit Streams befassen mussten.

Antworten auf die Frage(1)

Ihre Antwort auf die Frage