使用 WIC 从流中解码图像

Decoding image from stream using WIC

我正在尝试使用 WIC 在 C# 中加载图像,并将 SharpDX 作为包装器(这是一个用 .NET 编写的 Direct2D 应用程序)。我可以通过创建 BitmapDecoder 来完美地加载我的图像:

C#代码:

new BitmapDecoder(Factory, fileName, NativeFileAccess.Read, DecodeOptions.CacheOnLoad)

C++ 等价物:

hr = m_pIWICFactory->CreateDecoderFromFilename(
    fileName,                
    NULL,                     
    GENERIC_READ,              
    WICDecodeMetadataCacheOnLoad, 
    &pIDecoder);

顺便说一下,fileName 包含 JPEG 图像的路径。现在,这工作得很好,但如果我尝试使用流加载图像,它就会崩溃:

C#代码:

new BitmapDecoder(Factory, stream, DecodeOptions.CacheOnLoad)

C++ 等价物:

hr = m_pIWICFactory->CreateDecoderFromStream(
    pIWICStream,                   
    NULL,
    WICDecodeMetadataCacheOnLoad,
    &pIDecoder);

这实际上与 JPEG 文件中存在的数据相同,并且它的大部分工作方式与以前的方式一样。但是当我调用 SharpDX.Direct2D1.Bitmap.FromWicBitmap() (ID2D1RenderTarget::CreateBitmapFromWicBitmap) 时它中断了。前一种方法完美无缺,而后一种方法会导致此函数 return HRESULT 0x88982F60 (WINCODEC_ERR_BADIMAGE)。

明确一点:图像的加载方式没有区别,除了从流而不是文件名加载图像之外。

为什么会发生这种情况,我该如何解决?我需要能够加载我只能作为流访问的图像,并且我不想将它们保存到临时文件来实现这一点。

这些是我创建的用于解码图像的方法:

    internal void Load(Stream stream)
    {
        using(var decoder = new BitmapDecoder(Factory, stream, DecodeOptions.CacheOnLoad))
            Decode(decoder);
    }

    internal void Load(string fn)
    {
        using (var decoder =
            new BitmapDecoder(Factory, fn, NativeFileAccess.Read, DecodeOptions.CacheOnLoad))
            Decode(decoder);
    }

显然,如果使用流,则无法在您仍在读取图像时处理掉解码器。去搞清楚。无论如何,这最终奏效了:

    internal void Load(Stream stream)
    {
        var decoder = new BitmapDecoder(Factory, stream, DecodeOptions.CacheOnLoad);
        Decode(decoder);
    }

    internal void Load(string fn)
    {
        using (var decoder =
            new BitmapDecoder(Factory, fn, NativeFileAccess.Read, DecodeOptions.CacheOnLoad))
            Decode(decoder);
    }

但现在我不得不担心以后处理解码器的问题。

更新:

这种奇怪的行为差异是由 SharpDX 的一个实现细节引起的:

public BitmapDecoder(ImagingFactory factory, Stream streamRef, SharpDX.WIC.DecodeOptions metadataOptions)
{
    internalWICStream = new WICStream(factory, streamRef);
    factory.CreateDecoderFromStream(internalWICStream, null, metadataOptions, this);
}

internalWICStreamBitmapDecoderclass持有的字段,在class销毁时销毁。这可能是问题的根源。与使用文件名的重载不同:

public BitmapDecoder(ImagingFactory factory, string filename, System.Guid? guidVendorRef, NativeFileAccess desiredAccess, SharpDX.WIC.DecodeOptions metadataOptions)
{
    factory.CreateDecoderFromFilename(filename, guidVendorRef, (int)desiredAccess, metadataOptions, this);
}

internalWICStream 未设置,因为流由 Windows 管理。因此,在处置托管 BitmapDecoder 对象时不会出现任何问题。