2

PNG ファイルを保持するシーク不可のストリームがあります。BitmapDecoderこれを WPF のクラスを使ってデコードしたいと思います。ドキュメントには、シーク可能なストリームを渡す必要があるとは記載されておらず、そうしてもコードがスローされないため、動作するはずであると結論付けています。

しかし、私はそれを機能させることができません。問題を示す不自然な例を次に示します。

// This is an 8x8 all-red PNG:
var bytes = Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLb"
            + "SncAAAAEElEQVQIHWP8z4AdMA4tCQB8/QgBp6L0HwAAAABJRU5ErkJggg==");

BitmapDecoder decoder;
using (var stream = new MemoryStream(bytes))
    decoder = BitmapDecoder.Create(stream, BitmapCreateOptions.None,
                                   BitmapCacheOption.OnLoad);

Console.WriteLine(decoder.Frames[0].PixelWidth); // outputs 8, correctly

using (var stream = new UnseekableStream(new MemoryStream(bytes)))
    decoder = BitmapDecoder.Create(stream, BitmapCreateOptions.None,
                                   BitmapCacheOption.OnLoad);

Console.WriteLine(decoder.Frames[0].PixelWidth); // outputs 1, wrongly

ドキュメントOnLoadには、フラグを渡すとすぐにストリームを破棄できるはずであると記載されています。

もちろん、すべてをMemoryStream最初に読むこともできますが、それは正しくありません。私は何か間違ったことをしていますか、それともBitmapDecoderここでバグがありますか?

UnseekableStreamPS上記の例で使用されている「圧縮された」ソースは次のとおりです。

public sealed class UnseekableStream : Stream
{
    private Stream _stream;
    public UnseekableStream(Stream underlyingStream) { _stream = underlyingStream; }

    private bool _disposed = false;
    protected override void Dispose(bool disposing)
    {
        if (_disposed) return;
        _disposed = true; _stream.Dispose(); base.Dispose();
    }
    public override bool CanSeek { get { return false; } }
    public override bool CanWrite { get { return _stream.CanWrite; } }
    public override bool CanRead { get { return _stream.CanRead; } }
    public override void Flush() { _stream.Flush(); }
    public override long Length { get { return _stream.Length; } }
    public override void SetLength(long value) { _stream.SetLength(value); }
    public override long Position { get { return _stream.Position; } set { _stream.Position = value; } }
    public override long Seek(long offset, SeekOrigin origin) { return _stream.Seek(offset, origin); }
    public override int Read(byte[] buffer, int offset, int count) { return _stream.Read(buffer, offset, count); }
    public override void Write(byte[] buffer, int offset, int count) { _stream.Write(buffer, offset, count); }
}
4

1 に答える 1

1

直接使用できますPngBitmapDecoder

using (var stream = new UnseekStream(new MemoryStream(bytes)))
{
    decoder = new PngBitmapDecoder(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}

BitmapDecoder.Create適切なデコーダーで実際にデコードする前に、ストリームに含まれる画像形式を見つけるために、ストリームをシーク可能にするだけでよいと思います。

于 2013-01-11T21:55:56.623 に答える