返回首页

Direct2D 中的 WIC:图像解码

本文档描述了 Windows 中用于解码图像的关键 WIC 接口。提供了使用 IWICBitmapDecoder 和 IWICBitmapFrameDecode 方法从文件、流和内存创建解码器的示例。完整代码演示了集成到应用程序中。

通过 WIC 进行图像解码:完整指南
Advertisement 728x90

Direct2D 中的 Windows 图像组件:图像解码与处理

Windows 图像组件(WIC)提供了一组 COM 接口,用于从文件、流或内存中解码压缩图像。主要对象包括:IWICBitmapDecoder 作为帧和元数据的容器,IWICBitmapFrameDecode 用于访问单个帧的像素,以及 IWICBitmapSourceTransform 用于实时变换。

还包括其他接口,如 IWICBitmap 用于内存中的可变栅格数据,IWICFormatConverter 用于格式转换,以及 IWICBitmapScalerIWICBitmapClipperIWICBitmapFlipRotator 用于图像修改。所有操作都从创建工厂开始:IWICImagingFactoryIWICImagingFactory2

#include <wincodec.h>
#include <wrl/client.h>

using Microsoft::WRL::ComPtr;

ComPtr<IWICImagingFactory> pFactory;
HRESULT hr = CoCreateInstance(
    CLSID_WICImagingFactory,
    nullptr,
    CLSCTX_INPROC_SERVER,
    IID_IWICImagingFactory,
    reinterpret_cast<void**>(&pFactory)
);

工厂使用 CLSCTX_INPROC_SERVER 上下文加载到当前进程中。

Google AdInline article slot

从文件、流和内存解码图像

要从文件加载,使用 CreateDecoderFromFilename,参数包括路径(wchar_t*)、首选供应商(nullptr)、GENERIC_READ 模式,以及 WICDecodeMetadataCacheOnLoad 缓存。

ComPtr<IWICBitmapDecoder> pDecoder;
 hr = pFactory->CreateDecoderFromFilename(
     L"C:\\images\\photo.jpg",
     nullptr,
     GENERIC_READ,
     WICDecodeMetadataCacheOnLoad,
     &pDecoder
 );

IStream(通过 SHCreateStreamOnFile)加载——使用 CreateDecoderFromStream。内存加载:使用 CreateStream 并调用 InitializeFromMemory,然后 CreateDecoderFromStream

ComPtr<IStream> pStream;
SHCreateStreamOnFile(L"C:\\images\\photo.jpg", STGM_READ, &pStream);

ComPtr<IWICBitmapDecoder> pDecoder;
pFactory->CreateDecoderFromStream(pStream.Get(), nullptr, WICDecodeMetadataCacheOnLoad, &pDecoder);
ComPtr<IWICStream> pStream;
pFactory->CreateStream(&pStream);
pStream->InitializeFromMemory(pBuffer, cbSize);

ComPtr<IWICBitmapDecoder> pDecoder;
pFactory->CreateDecoderFromStream(pStream.Get(), nullptr, WICDecodeMetadataCacheOnLoad, &pDecoder);

IWICBitmapDecoder 方法

此接口提供对图像结构的访问:

Google AdInline article slot
  • *QueryCapability(IStream, DWORD):检查解码器能力(位掩码:CanDecodeSomeImagesCanDecodeAllImages* 等)。
  • *GetContainerFormat(GUID):容器格式 GUID(例如 GUID_ContainerFormatJpeg**)。
  • *GetFrameCount(UINT)**:帧数量。
  • GetFrame(UINT, IWICBitmapFrameDecode):按索引获取帧。
  • GetPreview/IGetThumbnail(IWICBitmapSource):预览或缩略图。
  • GetMetadataQueryReader(IWICMetadataQueryReader):全局元数据。

完整方法列表可控制缓存、调色板和颜色上下文。

IWICBitmapFrameDecode 方法

继承 IWICBitmapSourceGetSizeGetPixelFormatGetResolutionCopyPixelsCopyPalette),额外包括:

  • GetThumbnail(IWICBitmapSource) —— 帧缩略图。
  • GetColorContexts(UINT, IWICColorContext, UINT*) —— ICC 配置文件。
  • GetMetadataQueryReader(IWICMetadataQueryReader) —— 帧元数据(EXIF、XMP)。

CopyPixels 将数据提取到指定缓冲区,考虑步长和区域。

Google AdInline article slot

完整解码示例与信息输出

#include <windows.h>
#include <wincodec.h>
#include <wrl/client.h>
#include <iostream>
#include <vector>
#include <propvarutil.h>

using Microsoft::WRL::ComPtr;

void PrintGUID(const GUID& guid) {
    wchar_t str[39];
    StringFromGUID2(guid, str, 39);
    wprintf(L"%s", str);
}

int wmain(int argc, wchar_t* argv[]) {
    if (argc < 2) {
        wprintf(L"Usage: WICFullDemo.exe <imagefile>\n");
        return 1;
    }
    const wchar_t* filename = argv[1];

    HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
    if (FAILED(hr)) return 1;

    ComPtr<IWICImagingFactory> pFactory;
    hr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pFactory));
    if (FAILED(hr)) {
        CoUninitialize();
        return 1;
    }

    ComPtr<IWICBitmapDecoder> pDecoder;
    hr = pFactory->CreateDecoderFromFilename(filename, nullptr, GENERIC_READ, WICDecodeMetadataCacheOnLoad, &pDecoder);
    if (FAILED(hr)) {
        CoUninitialize();
        return 1;
    }

    wprintf(L"=== IWICBitmapDecoder methods ===\n");

    ComPtr<IStream> pStream;
    SHCreateStreamOnFile(filename, STGM_READ, &pStream);
    if (SUCCEEDED(hr)) {
        DWORD caps = 0;
        hr = pDecoder->QueryCapability(pStream.Get(), &caps);
        if (SUCCEEDED(hr)) {
            wprintf(L"QueryCapability: capabilities = 0x%08X\n", caps);
        }
    }

    // Further processing of frames, metadata, and pixels
    CoUninitialize();
    return 0;
}

此示例展示了 COM 初始化、工厂创建、解码器设置和 QueryCapability。生产代码中需添加 GetFrameCopyPixels 和变换。

关键要点

  • WIC 支持流式解码图像,无需全部加载到内存,并缓存元数据。
  • IWICBitmapDecoder 处理容器,IWICBitmapFrameDecode 管理单个帧和像素。
  • CreateDecoderFromFilename/Stream/Memory 覆盖所有输入场景。
  • GetFrameCount/GetFrame/GetMetadataQueryReader 提供结构和 EXIF 数据访问。
  • 始终检查 HRESULT 并使用 ComPtr 实现 RAII。

— Editorial Team

Advertisement 728x90

继续阅读