C++Builder は、様々なフォーマットの画像を扱うのも簡単だ。……が、まとまった情報が見つからなくて苦労したので、ここにまとめておく。動作確認は C++Builder XE3。

例として、JPEG 画像を背景画像として、その上に、BMP 画像と透過 PNG 画像を重ねる。合成結果を PNG 画像として保存する。

背景 JPEGBMP透過 PNG
TestBG Test1
※Web 用に PNG に変換してあるが、元は BMP
Test2


準備として、ビットマップ形式以外の画像ファイルを読み書きしたい場合は、対応するヘッダをインクルードしておく。

#include <Jpeg.hpp>
#include <PNGImage.hpp>

ヘッダをインクルードしてしまえば、読み込みに関しては、画像フォーマットを気にせずに読み込めるようになる。書き込みは、対応する画像形式を扱うクラスに任せる。コードは以下。

void __fastcall TFormTest01::Button1Click(TObject *Sender)
{
    unique_ptr<TImage>        aImageMerge(new TImage(this));
    unique_ptr<TImage>        aImageBG(new TImage(this));
    unique_ptr<TImage>        aImage1(new TImage(this));
    unique_ptr<TImage>        aImage2(new TImage(this));
    unique_ptr<TPngImage>    aPng(new TPngImage());

    // 画像ロード
    aImageBG->AutoSize = true;
    aImageBG->Picture->LoadFromFile(L"R:\\TestBG.jpg");    // JPEG
    aImage1->AutoSize = true;
    aImage1->Picture->LoadFromFile(L"R:\\Test1.bmp");    // BMP
    aImage2->AutoSize = true;
    aImage2->Picture->LoadFromFile(L"R:\\Test2.png");    // PNG

    // 合成画像のサイズを背景画像に合わせる
    aImageMerge->Width = aImageBG->Width;
    aImageMerge->Height = aImageBG->Height;

    // 合成
    aImageMerge->Canvas->Draw(0, 0, aImageBG->Picture->Graphic);
    aImageMerge->Canvas->Draw(100, 200, aImage1->Picture->Graphic);
    aImageMerge->Canvas->Draw(300, 200, aImage2->Picture->Graphic);

    // PNG 保存
    aPng->Assign(aImageMerge->Picture->Graphic);
    aPng->SaveToFile(L"R:\\Result.png");
}

Result結果は右の画像のようになる。

シンプルなコードだが、透過もきちんと自動処理されている。

ポイントは、TImage を使うこと(ここでは動的生成しているが、もちろんフォームに貼り付けても良い)。TImage のローダーは、画像形式に関わらず読み込める。TBitmap を使うと PNG を読み込めなかった。

古いバージョンの C++Builder/Delphi だと、PNG の読み込みには TPngImage で画像の読み込みを行わなければならなかったようだが、現在は、TImage を使えば良い。

逆に、書き込みは、明示的に TPngImage を使っている。

aImageBG->Picture->SaveToFile(L"R:\\Result.png");

のように拡張子で自動的に PNG に変換してくれるかなーと期待したが、そんなことは無かった。