Windows Imaging Component w Direct2D: dekodowanie i przetwarzanie obrazów
Windows Imaging Component (WIC) dostarcza zestaw interfejsów COM do dekodowania skompresowanych obrazów z plików, strumieni lub pamięci. Kluczowe obiekty: IWICBitmapDecoder jako kontener klatek i metadanych, IWICBitmapFrameDecode dla dostępu do pikseli poszczególnych klatek, IWICBitmapSourceTransform dla transformacji w locie.
Dodatkowo używane są IWICBitmap dla zmiennych danych rastrowych w pamięci, IWICFormatConverter dla zmiany formatu, a także IWICBitmapScaler, IWICBitmapClipper i IWICBitmapFlipRotator dla modyfikacji. Wszystkie operacje zaczynają się od utworzenia fabryki IWICImagingFactory lub 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)
);
Fabryka zarządza kontekstem CLSCTX_INPROC_SERVER dla ładowania w bieżącym procesie.
Dekodowanie z pliku, strumienia i pamięci
Do ładowania z pliku stosuje się CreateDecoderFromFilename z parametrami ścieżki (wchar_t*), preferowanego producenta (nullptr), trybem GENERIC_READ i buforowaniem WICDecodeMetadataCacheOnLoad.
ComPtr<IWICBitmapDecoder> pDecoder;
hr = pFactory->CreateDecoderFromFilename(
L"C:\\images\\photo.jpg",
nullptr,
GENERIC_READ,
WICDecodeMetadataCacheOnLoad,
&pDecoder
);
Ze strumienia IStream (SHCreateStreamOnFile) — CreateDecoderFromStream. Dla pamięci: CreateStream z InitializeFromMemory, a następnie 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);
Metody IWICBitmapDecoder
Interfejs zapewnia dostęp do struktury obrazu:
- *QueryCapability(IStream, DWORD)*: sprawdzanie możliwości dekodera (maska bitowa: CanDecodeSomeImages, CanDecodeAllImages i inne).
- *GetContainerFormat(GUID)**: GUID formatu kontenera (GUID_ContainerFormatJpeg).
- *GetFrameCount(UINT)**: liczba klatek.
- GetFrame(UINT, IWICBitmapFrameDecode) : klatka według indeksu.
- GetPreview/IGetThumbnail(IWICBitmapSource) : podgląd lub miniatura.
- GetMetadataQueryReader(IWICMetadataQueryReader) : globalne metadane.
Pełna lista metod zapewnia kontrolę nad buforowaniem, paletą i kontekstami kolorów.
Metody IWICBitmapFrameDecode
Dziedziczy IWICBitmapSource (GetSize, GetPixelFormat, GetResolution, CopyPixels, CopyPalette) plus:
- GetThumbnail(IWICBitmapSource**) — miniatura klatki.
- GetColorContexts(UINT, IWICColorContext*, UINT) — profile ICC.
- GetMetadataQueryReader(IWICMetadataQueryReader**) — metadane klatki (EXIF, XMP).
CopyPixels wyodrębnia dane do określonego bufora z uwzględnieniem stride i regionu.
Pełny przykład dekodowania z wyświetlaniem informacji
#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"Użycie: WICFullDemo.exe <plikobrazu>\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"=== Metody IWICBitmapDecoder ===\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: możliwości = 0x%08X\n", caps);
}
}
// Dalsze przetwarzanie klatek, metadanych i pikseli
CoUninitialize();
return 0;
}
Przykład demonstruje inicjalizację COM, fabrykę, dekoder i QueryCapability. Dla produkcji dodaj obsługę GetFrame, CopyPixels i transformacje.
Co jest ważne
- WIC dekoduje obrazy bez pełnego ładowania do pamięci, wspierając strumienie i buforowanie metadanych.
- IWICBitmapDecoder zarządza kontenerem, IWICBitmapFrameDecode — poszczególnymi klatkami z pikselami.
- CreateDecoderFromFilename/Stream/Memory obejmują wszystkie scenariusze wejścia.
- Metody GetFrameCount/GetFrame/GetMetadataQueryReader dają dostęp do struktury i EXIF.
- Zawsze sprawdzaj HRESULT i używaj ComPtr dla RAII.
— Editorial Team
Brak komentarzy.