WICを使ってイメージからHBITMAPを取得

制作:KrK (Knuth for Kludge)

情報・ご感想はこちら

KrK's Cracked Text > はしくれコード


環境

ソース


#include <windows.h>    // Win32API
#include <wincodec.h>   // WIC
#include <objbase.h>    // COM
HBITMAP CreateHBitmapFromBitmapSource(IWICBitmapSource *pImage);

//-------------------------------------------------
// WICを使ってイメージからHBITMAPを取得
// 作成 20150120 KrK
// 引数 image:画像イメージ
// 引数 imageSize:画像イメージサイズ
// 戻り値:ビットマップハンドル
//-------------------------------------------------
HBITMAP LoadByWICFromImage(char *image, LONG imageSize)
{
    HRESULT hr;                               // 処理結果
    HBITMAP hBmp = NULL;                      // ビットマップハンドル
    IWICImagingFactory *pFactory = NULL;      // WIC
    IWICBitmapDecoder *pDecoder = NULL;       // WICデコーダ
    IWICFormatConverter *pConverter = NULL;   // WICコンバータ
    IWICBitmapFrameDecode *pFrame = NULL;     // WICフレーム
    IWICBitmapSource *pImage = NULL;          // WICイメージ
    IWICStream *pStream = NULL;               // WICストリーム

    // WIC初期化
    hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
        IID_PPV_ARGS(&pFactory));

    // ストリームを生成
    if (SUCCEEDED(hr))
    {
        hr = pFactory->CreateStream(&pStream);
    }
    if (SUCCEEDED(hr))
    {
        hr = pStream->InitializeFromMemory(
            reinterpret_cast<BYTE*>(image), imageSize);
    }

    // デコーダを生成
    if (SUCCEEDED(hr))
    {
      hr = pFactory->CreateDecoderFromStream(pStream,
          NULL, WICDecodeMetadataCacheOnDemand, &pDecoder);
    }

    // 最初のフレームを取得
    if (SUCCEEDED(hr))
    {
        hr = pDecoder->GetFrame(0, &pFrame);
    }

    // コンバータ生成 (32bppBGRAビットマップ)
    if (SUCCEEDED(hr))
    {
        hr = pFactory->CreateFormatConverter(&pConverter);
    }
    if (SUCCEEDED(hr))
    {
        hr = pConverter->Initialize(pFrame, GUID_WICPixelFormat32bppBGRA,
            WICBitmapDitherTypeNone, NULL, 0.f, WICBitmapPaletteTypeCustom);
    }

    // イメージ取得
    if (SUCCEEDED(hr))
    {
        hr = pConverter->QueryInterface(IID_PPV_ARGS(&pImage));
    }

    // イメージからビットマップに変換
    if (SUCCEEDED(hr))
    {
        hBmp = CreateHBitmapFromBitmapSource(pImage);
    }

    // 解放
    if (pImage != NULL)
    {
        pImage->Release();
    }
    if (pConverter != NULL)
    {
        pConverter->Release();
    }
    if (pFrame != NULL)
    {
        pFrame->Release();
    }
    if (pDecoder != NULL)
    {
        pDecoder->Release();
    }
    if (pStream != NULL)
    {
        pStream->Release();
    }
    if (pFactory != NULL)
    {
        pFactory->Release();
    }

    // ビットマップハンドルを返す
    return hBmp;
}

//-------------------------------------------------
// WICイメージからビットマップハンドルを生成
// 作成 20140913 KrK
// 引数 pBitmap:WICイメージ
//-------------------------------------------------
HBITMAP CreateHBitmapFromBitmapSource(IWICBitmapSource *pImage)
{
    HRESULT hr;                       // 処理結果
    WICPixelFormatGUID format;        // WICフォーマット
    BITMAPINFO bminfo = {};           // ビットマップヘッダ
    UINT width = 0;                   // ビットマップ幅
    UINT height = 0;                  // ビットマップ高さ
    HBITMAP hBmp = NULL;              // ビットマップハンドル
    LPVOID imageBits = NULL;          // ビットマップイメージ

    // 32bppBGRAか確認
    hr = pImage->GetPixelFormat(&format);
    if (SUCCEEDED(hr))
    {
        if (format == GUID_WICPixelFormat32bppBGRA)
        {
            hr = S_OK;
        }
        else
        {
            hr = E_FAIL;
        }
    }

    // ビットマップサイズを取得
    if (SUCCEEDED(hr))
    {
        hr = pImage->GetSize(&width, &height);
    }

    // DIBを生成
    if (SUCCEEDED(hr))
    {
        bminfo.bmiHeader.biSize = sizeof(BITMAPINFO);
        bminfo.bmiHeader.biBitCount = 32;
        bminfo.bmiHeader.biCompression = BI_RGB;
        bminfo.bmiHeader.biWidth = width;
        bminfo.bmiHeader.biHeight = -static_cast<LONG>(height);
        bminfo.bmiHeader.biPlanes = 1;
        hBmp = CreateDIBSection(NULL, &bminfo, DIB_RGB_COLORS,
            &imageBits, NULL, 0);
        if (hBmp)
        {
            hr = S_OK;
        }
        else
        {
            hr = E_FAIL;
        }
    }

    // イメージをコピー
    if (SUCCEEDED(hr))
    {
        hr = pImage->CopyPixels(NULL,
            width * 4,
            width * height * 4,
            reinterpret_cast<BYTE *>(imageBits));
    }
    else if (hBmp != NULL)
    {
        DeleteObject(hBmp);
        hBmp = NULL;
    }

    // ビットマップハンドルを返す
    return hBmp;
}

使い方


WCHAR filename[_MAX_PATH];  // ファイル名
HANDLE hFile;               // ファイルハンドル
CHAR *data;                 // データ
LONG dataSize;              // データサイズ
DWORD readBytes;            // 読んだバイト
HBITMAP hBmp;               // ビットマップハンドル

// COM初期化
CoInitialize(NULL);

// ファイルを開く
hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL,
  OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
  ~;
}
dataSize = GetFileSize(hFile, NULL);
data = new CHAR[dataSize];
rc = ReadFile(hFile, data, dataSize, &readBytes, NULL);
CloseHandle(hFile);
if (rc == FALSE)
{
  ~;
}

// ビットマップハンドルを取得
hBmp = LoadByWICFromImage(data, dataSize);

// 解放
CoUninitialize();
delete[] data;

使用条件

参考ページ


最終更新:2025/12/19

免責事項