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(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;

使用条件


最終更新:2023/09/13

免責事項