読者です 読者をやめる 読者になる 読者になる

既存のIWICBitmapSourceからの構築

すでにWICでメモリ上に持っているIWICBitmapSourceをコピーしてビットマップを初期化したい場合には、次のようなコードを書く必要があるかもしれません。エラーの処理は適当に追加してください。

// 適当に例外を投げるためのマクロ; 手抜きなので注意!!!
#define throwOnFail(expr) do { HRESULT hr = expr; if(FAILED(hr)) throw hr; } while(0)

// 入力ソースをBGR(プロファイルがある場合には、sRGB)に変換
IWICBitmapSource* ConvertToSRGB(IWICBitmapSource* bmpSrc, IWICImagingFactory* factory)
{
  WICPixelFormatGUID fmt;
  throwOnFail(bmpSrc->GetPixelFormat(&fmt));
  
  // RGBの画像じゃない場合には、カラープロファイルを用いたIWICColorTransformによる変換を試みる
  if(fmt != GUID_WICPixelFormat24bppBGR && fmt !=GUID_WICPixelFormat24bppRGB)
  {
    UINT co;
    CComPtr<IWICColorContext> cc_src;
    HRESULT hr = bmpSrc->GetColorContexts(1, &cc_src, &co);
    if(SUCCEEDED(hr) && co == 1 && cc_src)
    {
      // sRGB profile
      CComPtr<IWICColorContext> cc_sRGB;
      throwOnFail(factory->CreateColorContext(&cc_sRGB));
      throwOnFail(cc_sRGB->InitializeFromExifColorSpace(1));
      
      CComPtr<IWICColorTransform> txf;
      throwOnFail(factory->CreateColorTransformer(&txf));
      
      throwOnFail(txf->Initialize(
        frameDecode,
        cc_src,
        cc_sRGB,
        GUID_WICPixelFormat24bppBGR));
      
      IWICBitmapSource* output = NULL;
      throwOnFail(txf->QueryInterface(
        __uuidof(IWICBitmapSource), (void**)&output));
      return output;
    }
  }

  // どうにもうまくいかない場合には、適当に変換する
  CComPtr<IWICFormatConverter> cvtr;
  throwOnFail(factory->CreateFormatConverter(&cvtr));
  
  throwOnFail(cvtr->Initialize(
    bmpSrc,
    GUID_WICPixelFormat24bppBGR,
    WICBitmapDitherTypeNone,
    NULL,
    0.0,
    WICBitmapPaletteTypeCustom));

  IWICBitmapSource* output = NULL;
  throwOnFail(cvtr->QueryInterface(
    __uuidof(IWICBitmapSource), (void**)&output));
  return output;
}

// 
CComPtr<CWICGdiplusBgrBitmap> CopyToGdiplusBitmap(IWICBitmapSource* src, IWICImagingFactory* factory)
{
  CComPtr<IWICBitmapSource> bmpSrc = ConvertToSRGB(src, factory);

  UINT w, h;
  throwOnFail(bmpSrc->GetSize(&w, &h));

  CComPtr<CWICGdiplusBgrBitmap> outBmp;
  outBmp = CWICGdiplusBgrBitmap::Create(w, h);

  double resX, resY;
  if(SUCCEEDED(bmpSrc->GetResolution(&resX, &resY)))
    outBmp->SetResolution(resX, resY);
  
  CComPtr<IWICBitmapLock> lock;

  WICRect rcCopy = {0, 0, w, h};
  throwOnFail(outBmp->Lock(&rcCopy, WICBitmapLockWrite, &lock));
  UINT stride = 0, bufSize = 0;
  BYTE* raw = NULL;
  throwOnFail(lock->GetDataPointer(&bufSize, &raw));
  throwOnFail(lock->GetStride(&stride));
  throwOnFail(bmpSrc->CopyPixels(&rcCopy, stride, bufSize, raw));
  return outBmp;
}