Windows Imaging Componentで画像を読み込む
Windows Imaging Component (WIC)は、.NET Framework 3.0でも利用されている画像処理のフレームワークで、Vistaでは標準インストールされており、Windows フォトギャラリーなどでも利用されているほか、Windows XPでも、.NET Framework 3.5をインストールしたり、または、WICを直接インストールしたり、あるいは、Windows Live フォトギャラリーをインストールしたりすることによって利用できるようになる。
また、Windows Imaging Componentは、サードパーティによって拡張可能なように設計されており、実際、カメラメーカーからは、RAW画像用のコーデックが公開されていたりもするため、今後、画像処理のコードを書くに当たっては、是非とも利用を検討したいフレームワークだ。
C++からだと、GDI+を使って画像を読み込むことは結構あると思うが、GDI+の画像ローダはバグも多く、Old JPEGなどの比較的難しいフォーマットは読めないことが多い。それから比べると、WICの完成度はかなりのもので、特に何の問題も感じずに利用することができる。.NETからであれば、BitmapDecoder クラスを使って画像のロードを行えるが、C++/CLIではなく、C++から使いたい場合には、COM経由で利用できる。その際、ほとんどのクラスは、IWIC + .NETのクラス名という形で存在している。下記は、利用例(エラーチェックは省いているので注意)。
CComPtr<IWICImagingFactory> imagingFactory; CoCreateInstance( CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, __uuidof(IWICImagingFactory), (LPVOID*)&imagingFactory); // input.tifを開く CComPtr<IStream> stream; SHCreateStreamOnFile(_T("input.tif"), STGM_READ, &stream); imagingFactory->CreateDecoderFromStream( stream, NULL, WICDecodeMetadataCacheOnDemand, &m_decoder); UINT frameCount = 0; m_decoder->GetFrameCount(&frameCount); for(UINT idx = 0; idx < frameCount; idx++) { CComPtr<IWICBitmapFrameDecode> frameDecode; m_decoder->GetFrame(idx, &frameDecode); UINT width, height; frameDecode->GetSize(&width, &height); double resX, resY; frameDecode->GetResolution(&resX, &resY); CComQIPtr<IWICBitmapSource> bmpSrc = frameDecode; WICPixelFormatGUID fmt; bmpSrc->GetPixelFormat(&fmt); UINT stride; if(fmt == GUID_WICPixelFormatBlackWhite) { stride = (w + 7) ~7; } else if(fmt == GUID_WICPixelFormat8bppGray) { stride = w; } else if(fmt == GUID_WICPixelFormat24bppBGR) { stride = w * 3; } else if(fmt == GUID_WICPixelFormat24bppRGB) { stride = w * 3; } else { // Unsupported pixel format } UINT size = stride * height; BYTE* buf = new BYTE[size]; WICRect rc = {0, 0, width, height}; HRESULT hr = bmpSrc->CopyPixels(&rc, stride, size, buf); ... delete[] buf; }