Direct2D 中的 Windows 图像组件:图像解码与处理
Windows 图像组件(WIC)提供了一组 COM 接口,用于从文件、流或内存中解码压缩图像。主要对象包括:IWICBitmapDecoder 作为帧和元数据的容器,IWICBitmapFrameDecode 用于访问单个帧的像素,以及 IWICBitmapSourceTransform 用于实时变换。
还包括其他接口,如 IWICBitmap 用于内存中的可变栅格数据,IWICFormatConverter 用于格式转换,以及 IWICBitmapScaler、IWICBitmapClipper 和 IWICBitmapFlipRotator 用于图像修改。所有操作都从创建工厂开始:IWICImagingFactory 或 IWICImagingFactory2。
#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 上下文加载到当前进程中。
从文件、流和内存解码图像
要从文件加载,使用 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 方法
此接口提供对图像结构的访问:
- *QueryCapability(IStream, DWORD):检查解码器能力(位掩码:CanDecodeSomeImages、CanDecodeAllImages* 等)。
- *GetContainerFormat(GUID):容器格式 GUID(例如 GUID_ContainerFormatJpeg**)。
- *GetFrameCount(UINT)**:帧数量。
- GetFrame(UINT, IWICBitmapFrameDecode):按索引获取帧。
- GetPreview/IGetThumbnail(IWICBitmapSource):预览或缩略图。
- GetMetadataQueryReader(IWICMetadataQueryReader):全局元数据。
完整方法列表可控制缓存、调色板和颜色上下文。
IWICBitmapFrameDecode 方法
继承 IWICBitmapSource(GetSize、GetPixelFormat、GetResolution、CopyPixels、CopyPalette),额外包括:
- GetThumbnail(IWICBitmapSource) —— 帧缩略图。
- GetColorContexts(UINT, IWICColorContext, UINT*) —— ICC 配置文件。
- GetMetadataQueryReader(IWICMetadataQueryReader) —— 帧元数据(EXIF、XMP)。
CopyPixels 将数据提取到指定缓冲区,考虑步长和区域。
完整解码示例与信息输出
#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。生产代码中需添加 GetFrame、CopyPixels 和变换。
关键要点
- WIC 支持流式解码图像,无需全部加载到内存,并缓存元数据。
- IWICBitmapDecoder 处理容器,IWICBitmapFrameDecode 管理单个帧和像素。
- CreateDecoderFromFilename/Stream/Memory 覆盖所有输入场景。
- GetFrameCount/GetFrame/GetMetadataQueryReader 提供结构和 EXIF 数据访问。
- 始终检查 HRESULT 并使用 ComPtr 实现 RAII。
— Editorial Team
暂无评论。