PNG形式での保存方法。数回に分けて記事にする。

 それなりに頑張る必要はある。数行でOKというわけにはいかない。

 

 ポイントは

(1)DIB形式でデータ保持(24ビットでHBITMAPと連動しながら、透過情報を持たせる)

(2)GDI+をしっかり管理(初期化やメモリリーク防止など)

(3)CLSID sFormatClsid の取得
あたりだろうか。

 

(1)は、DIBクラスを独自に作成(世の中に例は多くある)。そこに透過情報をうまく加える。

(2)も、世の中、色々と使い方は例がある。

(3)は、MSDNのサンプルを解読して上手に使う。

 

SetPixel()を使うと処理が遅いけれど、仕方ないか。

 

 さて、独自のDIBクラスを作ってあるとして・・・

-----------------------------------------------------------------------------

#include <gdiplus.h>
using namespace Gdiplus;
// ライブラリ
#pragma comment( lib, "gdiplus.lib" )

-----------------------------------------------------------------------------

// (静的関数) DIB (CDibArgb) を PNG 形式で保存 //
BOOL SaveImageByPNG(LPCTSTR lpszPathFilename , const CDibArgb* pDibArgb)
{
    Gdiplus::Color sColor ;
    ARGB argb ;
    COLORREF clrRgb ;
    BOOL bTransparent ;

    // 1. 初期設定 //
    // (1). 不透明度 alpha //
    BYTE alpha[2] = { 255 , 0 } ; // 透明 = 0 //

    // (2). 画像サイズ //
    int width  = pDibArgb->GetWidth()  ;
    int height = pDibArgb->GetHeight() ;

    // (3). 拡張子 (大文字) //
    CString strEXT = (拡張子を抽出 / lpszPathFilename) ;

    // 2. PNG 形式のイメージ (BPP = 32ビット) を構築 //
    Gdiplus::Bitmap sImagePNG(width , height , PixelFormat32bppARGB) ;

    // 3. 全てのピクセルを設定 //
    for(int y = 0 ; y < height  ; y++)
    {
        for(int x = 0 ; x < width ; x++)
        {
            // (1). COLORREF 取得 //
            clrRgb = pDibArgb->GetPixel(x , y) ;

            // (2). 透過であるか取得 //
            bTransparent = pDibArgb->IsAttrTransparent(x , y) ;

            // (3). ARGB 作成 //
            argb = Gdiplus::Color::MakeARGB(
                            alpha[bTransparent] ,
                            GetRValue(clrRgb) ,
                            GetGValue(clrRgb) ,
                            GetBValue(clrRgb)
                        ) ;


            // (4). Color 変数を作成 //
            sColor.SetValue(argb) ;

            // (5). ピクセル設定 //
            sImagePNG.SetPixel(x , y , sColor) ;
        }
    }

    // 4. ファイルを PNG 形式で保存 //
    // (1). フォーマット //
    CLSID fPngClsid ;
    BOOL bResult = FindEncoderClsidByExt(strEXT , NULL , &fPngClsid , NULL) ;

    // (2). 保存 //
    if (bResult) sImagePNG.Save(lpszPathFilename , &fPngClsid , NULL) ;

    return bResult ;
}
-----------------------------------------------------------------------------
 独自で作成している関数がいくつもあって、これだけでは動かない。申し訳ない。

 

 for() 分の中身が重要だ。ピクセルに、透過情報を持った32ビット数値を代入して、GDI+に任せて保存している。

 それだけでよい。

 

あとは、(1)~(3)を、しっかり記述していくこと。

 

次回(2)に続く。

 

*************************************************************
Windows用フリーソフト(無料)
http://yoyontek-develop.minim.ne.jp/
-------------------------------------------------------------
【 背景透過&境界線お掃除 】
http://yoyontek-dev-clr.minim.ne.jp/
画像ファイルの背景を透過させ、境界線の汚れを除去(PNG対応)
-------------------------------------------------------------
【 休憩タイムアラート for KIDS 】
http://yoyontek-dev-alt.minim.ne.jp/
子供のゲーム中に休憩時間をお知らせ
*************************************************************