私のアプリケーションは一度に多数の画像サムネイルを表示します。現在、すべてのフルサイズの画像をメモリに保持し、UI で画像を単純にスケーリングしてサムネイルを作成しています。ただし、小さなサムネイルをメモリに保持し、必要な場合にのみフルサイズの画像をロードしたいと思います。
これは簡単だと思いましたが、生成しているサムネイルは、UI でフルサイズの画像を拡大縮小するだけの場合と比べて、ひどくぼやけています。
イメージは、ヘッダー情報を持たないバイト配列です。サイズと形式は事前にわかっているので、BitmapSource.Create を使用して ImageSource を作成できます。
//This image source, when bound to the UI and scaled down creates a nice looking thumbnail
var imageSource = BitmapSource.Create(
imageWidth,
imageHeight,
dpiXDirection,
dpiYDirection,
format,
palette,
byteArray,
stride);
using (var ms = new MemoryStream())
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(imageSource);
encoder.Save(ms);
var bi = new BitmapImage();
bi.BeginInit();
bi.CacheOption = BitmapCacheOption.OnLoad;
//I can't just create a MemoryStream from the original byte array because there is no header info and it doesn't know how to decode the image!
bi.StreamSource = ms;
bi.DecodePixelWidth = 60;
bi.EndInit();
//This thumbnail is blurry!!!
Thumbnail = bi;
}
最初にpngに変換しているのでぼやけていると思いますが、BmpBitmapEncoderを使用すると、「使用可能なイメージングコンポーネントがありません」というエラーが発生します。この場合、私の画像はGray8ですが、なぜPngEncoderがそれを理解できるのにBmpEncoderがそれを理解できないのかわかりません。
最初にビットマップ形式にエンコードすることなく、元の ImageSource からサムネイルを作成する何らかの方法が必要でしょうか? BitmapSource.Create で、BitmapImage クラスのようにデコード幅/高さを指定できるようにしてほしいと思います。
編集
最後の答えは、TransformBitmap と WriteableBitmap を使用してサムネイルを作成し、元のフルサイズの画像を削除することです。
var imageSource = BitmapSource.Create(...raw bytes and stuff...);
var width = 100d;
var scale = width / imageSource.PixelWidth;
WriteableBitmap writable = new WriteableBitmap(new TransformedBitmap(imageSource, new ScaleTransform(scale, scale)));
writable.Freeze();
Thumbnail = writable;