Direct2D에서 Windows Imaging Component: 이미지 디코딩 및 처리
Windows Imaging Component(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 컨텍스트를 사용합니다.
파일, 스트림, 메모리에서 디코딩하기
파일에서 로드하려면 경로(wchar_t*), 선호 벤더(nullptr), GENERIC_READ 모드, WICDecodeMetadataCacheOnLoad 캐싱을 사용해 CreateDecoderFromFilename을 호출합니다.
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);
}
}
// 프레임, 메타데이터, 픽셀 추가 처리
CoUninitialize();
return 0;
}
이 예제는 COM 초기화, 팩토리 생성, 디코더 설정, QueryCapability를 보여줍니다. 실제 코드에서는 GetFrame, CopyPixels, 변환을 추가하세요.
주요 요점
- WIC는 메모리 전체 로드 없이 이미지를 디코딩하며, 스트림과 메타데이터 캐싱을 지원합니다.
- IWICBitmapDecoder는 컨테이너를, IWICBitmapFrameDecode는 개별 프레임과 픽셀을 관리합니다.
- CreateDecoderFromFilename/Stream/Memory로 모든 입력을 커버합니다.
- GetFrameCount/GetFrame/GetMetadataQueryReader로 구조와 EXIF 데이터에 접근합니다.
- 항상 HRESULT를 확인하고 ComPtr로 RAII를 사용하세요.
— Editorial Team
아직 댓글이 없습니다.