« 物凄く久しぶりに『じゃんがら』で一杯♪ | トップページ | 『琥珀エビス』で乾杯♪ »

2010年12月22日 (水)

『GDI++』で『PNG』が扱えるようになったけど、どうやって中身にアクセスするか…

『GDI++』で『PNG』が扱えるようになったと
ネットで調べ物をしている最中に知ったのだが…
その中身をいじりたい時、どうすれば良いかが見つからない…。

例えば、『PNG』のカラーとマスクを分割して
『BMP』ファイルにセーブしたい場合とか…。

でも、どこかで出来るはず!

で…

調べても中々出てこない…

で、一回挫折した…。

だが、再び『PNG』が現れた!(笑)

ので…

またぞろ処理に挑戦してみようかと…
ざっくりとやってみた。

ネットで調べてもどうも見つける事ができない。

検索ワードが悪いのかも…。

さくっと気分を変えてヘッダーから
責めてみたりした…。

そうこうしていると

どうやら『image』関連のクラスで『Bitmap』が良さげ…。

で、結論から言ったら出来た♪

分かってしまうと、
「ああ、こうなっているね…。フフン♪」
ってなるけど…。

分からないと…
「どうやってやるんだよぉ~!(T_T)」
とゴロゴロする訳だ。

ちなみに『Bitmap』クラス…
もしかしたらとっても有り難いかも…。

何でもかんでもRGB/RGBAに直してくれる。

今まで『Targe』を使っていたがこれならありかも…。

メモとして以下にソースを置いとこう…。

『GetEncoderClsid』は、こちらから頂いた。

Retrieving the Class Identifier for an Encoder

//******************************************************************************
//    『PNG』のカラー情報とマスク情報の分割セーブ
//******************************************************************************
//**************************************
#pragma comment( lib, "Gdiplus.lib" )
//**************************************
#include    <windows.h>
//**************************************
#include    <gdiplus.h>
//**************************************
using namespace Gdiplus;
//**************************************
int GetEncoderClsid( const WCHAR* format, CLSID* pClsid )
{
    UINT            num        = 0;    // number of image encoders
    UINT            size    = 0;    // size of the image encoder array in bytes
    ImageCodecInfo*    pImageCodecInfo    = NULL;

    GetImageEncodersSize( &num, &size );
    if( size == 0 )
        return -1;    // Failure

    pImageCodecInfo    = ( ImageCodecInfo* )( malloc( size ) );
    if( pImageCodecInfo == NULL )
        return -1;    // Failure

    GetImageEncoders( num, size, pImageCodecInfo );
    for( UINT j = 0 ; j < num ; ++j )
    {
        if( wcscmp( pImageCodecInfo[j].MimeType, format ) == 0 )
        {
            *pClsid    = pImageCodecInfo[j].Clsid;
            free( pImageCodecInfo );
            return j;    // Success
        }
    }
    free( pImageCodecInfo );
    return -1;    // Failure
}
//**************************************
int main( int argc, char *argv[] )
{
    ULONG_PTR        GdiToken;
    GdiplusStartupInput    GdiSI;
    CLSID            encoderClsid;
    int                size_x, size_y;
    Bitmap            *source, *color, *mask;
    BitmapData        source_locked, color_locked, mask_locked;
    Rect            rect;
    int                x, y, source_step, color_step, mask_step;
    LPBYTE            source_buffer, color_buffer, mask_buffer;
    WCHAR            name[MAX_PATH * 2];

    if( argc == 1 )
        return -1;

    GdiplusStartup( &GdiToken, &GdiSI, NULL );

    mbstowcs( name, argv[1], strlen( argv[1] ) + 1 );

    source    = new Bitmap( name );
    if( source->GetPixelFormat( ) != PixelFormat32bppARGB )
        return -1;

    size_x    = source->GetWidth( );
    size_y    = source->GetHeight( );
    color    = new Bitmap( size_x, size_y, PixelFormat24bppRGB );
    mask    = new Bitmap( size_x, size_y, PixelFormat24bppRGB );
    rect    = Rect( 0, 0, size_x, size_y );

    source->LockBits( &rect, 0, source->GetPixelFormat( ), &source_locked );
    color->LockBits( &rect, 0, color->GetPixelFormat( ), &color_locked );
    mask->LockBits( &rect, 0, mask->GetPixelFormat( ), &mask_locked );

    source_buffer    = ( LPBYTE )source_locked.Scan0;
    color_buffer    = ( LPBYTE )color_locked.Scan0;
    mask_buffer        = ( LPBYTE )mask_locked.Scan0;

    source_step    = source_locked.Stride - size_x * 4;
    color_step    = color_locked.Stride - size_x * 3;
    mask_step    = mask_locked.Stride - size_x * 3;

    for( y = 0 ; y < size_y ; y++ )
    {
        for( x = 0 ; x < size_x ; x++ )
        {
            *color_buffer++    = *source_buffer++;
            *color_buffer++    = *source_buffer++;
            *color_buffer++    = *source_buffer++;
            *mask_buffer++    = *source_buffer;
            *mask_buffer++    = *source_buffer;
            *mask_buffer++    = *source_buffer++;
        }
        source_buffer    += source_step;
        color_buffer    += color_step;
        mask_buffer        += mask_step;
    }

    source->UnlockBits( &source_locked );
    color->UnlockBits( &color_locked );
    mask->UnlockBits( &mask_locked );

    if( 0 <= GetEncoderClsid( L"image/bmp", &encoderClsid ) )
    {
        color->Save( L"sample_color.bmp", &encoderClsid );
        mask->Save( L"sample_mask.bmp", &encoderClsid );
    }

    if( 0 <= GetEncoderClsid( L"image/jpeg", &encoderClsid ) )
    {
        color->Save( L"sample_color.jpg", &encoderClsid );
        mask->Save( L"sample_mask.jpg", &encoderClsid );
    }

    delete source;
    delete color;
    delete mask;

    // ※「Bitmap」を開放してから開放する。
    GdiplusShutdown( GdiToken );
    return 0;
}
//******************************************************************************

これで一通りの目的は、達成した!

これを元にツールも出来たし♪

他の処理にも組み込んでみよう~♪

|

« 物凄く久しぶりに『じゃんがら』で一杯♪ | トップページ | 『琥珀エビス』で乾杯♪ »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/108365/50364404

この記事へのトラックバック一覧です: 『GDI++』で『PNG』が扱えるようになったけど、どうやって中身にアクセスするか…:

« 物凄く久しぶりに『じゃんがら』で一杯♪ | トップページ | 『琥珀エビス』で乾杯♪ »