友人と私は、昨夜の大部分を地下鉄アプリでいくつかの画像を操作しようとして髪を引き裂くところだった. 共有チャームを使用してアプリに画像を取得した後、画像をトリミングして appdata フォルダーに保存し直すなど、他の作業を行いたいと考えました。これは非常にイライラさせられました。
私の質問は、これらすべての最後に、「ミスマッチのジグソー パズルのピースをたくさん組み合わせているように感じずに、これを行う適切な方法は何ですか?」ということになります。
アプリで複数の画像を共有する場合、それらは のリストとして表示されWindows.Storage.StorageFile
ます。これを処理するために使用されるコードを次に示します。
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);
}
オンラインで検索したところ、現在、Windows.UI.Xaml.Media.Imaging.WriteableBitmap
画像内のピクセル データにアクセスできるのは a だけであることがわかりました。この質問には、画像をファイルに保存するための拡張メソッドが満載の役立つ回答が含まれているため、それらを使用しました。
後でファイルを再度開いてみたとき、私たちの問題は最悪でした。私は前に似たようなことをしました:
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();
ここで問題が発生します。バイトを取り出したい場合、このストリームの長さはどれくらいですか?
// CRASH! Length isn't supported on an IRandomAccessStream.
var pixels = new byte[fileStream.Length];
もう一度試してください。
var pixels = new byte[stream.Length];
これは機能しますが、画像が圧縮されている場合、ストリームは予想よりも短いため、最終的に範囲外の例外が発生します。ここでは、圧縮されていないビットマップのふりをします。
await _stream.ReadAsync(pixels, 0, pixels.Length);
まあ何を推測します。データを読み込むように言いbitmap.SetSource(fileStream);
ましたが、バイト配列はまだゼロでいっぱいです。理由がわかりません。これをbitmap
サンプル データ グループを介して UI に渡すと、画像は問題なく表示されます。そのため、そのビットマップのピクセルデータは明らかにどこかにありますが、それを読み取ることはできませんbitmap.PixelBuffer
か? なぜだめですか?
最後に、実際に機能するようになったのは次のとおりです。
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
これで画像データができましたが、まだ大きな問題があります。それを使って何かをするためには、そのフォーマットについて仮定をしなければなりません。それが rgba、rgb、abgr、bgra のどれであるかはわかりません。私が間違っていると推測すると、私の処理は失敗します。properties
何十回ものテスト実行で、ゼロバイトや破損した画像、逆さまの画像 (???)、間違った色などを吐き出しましたawait file.Properties.GetImagePropertiesAsync();
。幸運。これには、画像の幅と高さ、およびその他の役に立たないものだけが含まれています。ここに最小限のドキュメント。
では、なぜこのプロセスはとても苦痛なのでしょうか? これは現在のライブラリの未熟さを反映しているだけで、改善されると期待できますか? または、これを行う標準的な方法がすでにありますか?のように簡単だったらいいのにSystem.Drawing
。これにより、必要なすべてのデータが得られ、自分でストリームを処理することなく、あらゆる種類の画像を正しくロードできました。