Powrót do strony głównej

WIC w Direct2D: dekodowanie obrazów

Materia opisuje kluczowe interfejsy WIC do dekodowania obrazów w Windows. Podane są przykłady tworzenia dekodera z pliku, strumienia i pamięci z metodami IWICBitmapDecoder i IWICBitmapFrameDecode. Pełny kod demonstruje integrację w aplikacji.

Dekodowanie obrazów za pomocą WIC: pełne przewodnictwo
Advertisement 728x90

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.

Google AdInline article slot

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:

Google AdInline article slot
  • *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.

Google AdInline article slot

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

Advertisement 728x90

Czytaj dalej