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

画像を保存

Win32 WIC C++

処理が完了した画像を保存するには、IWICBitmapEncoderを利用する。
IWICBitmapEncoderのインスタンス作成時には、WIC GUIDs and CLSIDsにあるGUID_ContainerFormat*の中から、自分が使いたいフォーマットのエンコーダを選択する。

// TIFFエンコーダを作成
CComPtr<IWICBitmapEncoder> encoder;
imagingFactory->CreateEncoder(GUID_ContainerFormatTiff, NULL, &encoder);

次に、書き出し先のIStreamが必要になるが、これは、適宜、作成し、IWICBitmapEncoder::Initializeに渡して初期化する。

// output.tifに書き出す
CComPtr<IStream> stream;
// SHCreateStreamOnFile(_T("output.tif"), STGM_WRITE, &stream);
SHCreateStreamOnFileEx(_T("output.tif"), STGM_WRITE | STGM_FAILIFTHERE, 0, TRUE, NULL, &stream);

encoder->Initialize(stream, WICBitmapEncoderNoCache);

画像自体は、読み込み時と同様、フレームという単位で書き込む。TIFFだと複数ページを保存できるので、フレームを複数持つことができる。その他の画像フォーマットでは、1つのみ。いずれにしても、このフレームは、IWICBitmapEncoder::CreateNewFrameで行う。

// フレーム(ページ)を追加
CComPtr<IWICBitmapFrameEncode> frameEncode;
CComPtr<IPropertyBag2> propBag;
encoder->CreateNewFrame(&frameEncode, &propBag);

このとき、一緒に、IPropertyBag2のインスタンスが取得できるが、エンコードの品質などを設定しない場合には何もしなく良い。このインスタンスを、IWICBitmapEncoder::Initializeに直接渡すことによって、デフォルトの設定を利用できる。

// デフォルトの設定でエンコーダを初期化
frameEncode->Initialize(propBag);

IWICBitmapFrameEncodeに対しては、IWICBitmapFrameEncode::WriteSourceを呼び出して、すでに持っているIWICBitmapSourceのインスタンスを渡せばよい。ここでは、上記のサンプルでsRGBに変換した画像をそのまま利用する。

UINT width, height;
transform->GetSize(&width, &height);
frameEncode->SetSize(width, height);

GUID fmtOut = GUID_WICPixelFormat24bppBGR;
frameEncode->SetPixelFormat(&fmtOut);

WICRect rcSave = {0, 0, width, height};
frameEncode->WriteSource(transform, &rcSave);
frameEncode->Commit();
frameEncode = NULL; // もう必要ないので解放

最後には、IWICBitmapEncoder::Commitを呼び出して作業終了。

// 作成終了
encoder->Commit();
encoder = NULL; // もう必要ないので解放