GDI+ 使ってみた
急遽、画像処理をしなくてはならなくなったので、GDI+を使ってみた。
自分用メモも兼ねて簡単な使い方の紹介。
GDI+を使ってみたのは、なるべくたくさんのフォーマットの画像を読み書きしたかったから。
最初はBMP限定でやろうかと思ったけど、パレットとか色数とか、結局考慮しなきゃいけない点が多くて面倒だったから、いいものないかなって探してたら、たまたま見つけてGDI+を使ってみることにした。
とりあえず、参考にしたリンクを貼っ付けとく。
http://aki.issp.u-tokyo.ac.jp/itoh/PukiWiki/pukiwiki.php?%B2%E8%C1%FC
http://lamoo.s53.xrea.com/develop/gdiplus/gdiplus.html
http://park17.wakwak.com/~dragoon/gdiplus1.htm
http://weblog.rukihena.com/archives/2005/02/gdi_vc.html
http://www.nilab.info/resource/bbslog/megabbs/1093051600.html
だいたいこの辺がさんこうになるかと。
では、簡単な使い方のサンプル。
ちなみに、これはVC++2005proでしか動作確認してません。
まずは、プロジェクトの作成ってことで、Visual Studio 2005を起動して、[ファイル]-[新規作成]-[プロジェクト]から、プロジェクトの種類は「Win32コンソールアプリケーション」を選択。
もちろん、ほかのプロジェクトの種類でもOK(たぶん)。
で、プログラムの雛形ができたら、stdafx.hの最後に
#include <gdiplus.h> #pragma comment (lib, "Gdiplus.lib") using namespace Gdiplus;
を書き足す。
簡単に説明すると、1行目がヘッダファイルのインクルード、2行目がライブラリの追加、3行目で名前空間の追加といった感じ。
で、ここで注意しなきゃいけないのが、マイクロソフトのバグ。
実はこんな文書があって、
http://support.microsoft.com/kb/922323/
gdiplus.hをインクルードするとエラーが出るから、このページにも書いてあるけど、
#define WIN32_LEAN_AND_MEAN
をコメントアウト。
これで準備は整った!
次は、メイン関数への変更。
説明を省いて書いちゃうと、
GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
これが初期化で、
GdiplusShutdown(gdiplusToken);
こっちが終了処理。
これで、GDI+は使えちゃいます。
そんでもって、今回は画像処理をするのが目的だったので、とりあえず画像を読み込んで1ピクセルずつ取得する処理がこっち。
DWORD *LoadImage( wstring filename, UINT &width, UINT &height ) { Bitmap inputImage( filename.c_str() ); width = inputImage.GetWidth(); height = inputImage.GetHeight(); DWORD *image = new DWORD[width*height]; Color color; for (UINT y = 0; y < height; ++y) { for (UINT x = 0; x < width; ++x) { inputImage.GetPixel( x, y, &color ); image[y*width+x] = color.ToCOLORREF(); } } return image; }
これで、filenameって名前の画像から1ピクセルごとのデータと、幅と高さが取得できます。
で、保存はこっち。
といきたいんだけど、実はちょっと面倒な処理があるので、こちらのこのライブラリを借用しちゃって、使い方はライブラリの中に書いてあるので、メイン関数はそっちに置き換えればだいたいOK。
で、実際の保存用関数はだいたいこんな感じ。
int SaveImage( wstring filename, DWORD *image, UINT width, UINT height ) { Bitmap *outputImage = new Bitmap( width, height, PixelFormat32bppARGB ); Color color; for (UINT y = 0; y < height; ++y) { for (UINT x = 0; x < width; ++x) { color.SetFromCOLORREF( image[y*width+x] ); outputImage->SetPixel( x, y, color ); } } outputImage->Save( filename.c_str(), &theGdiplus.GetEncoderByExtension(filename.c_str())->Clsid ); return 0; }
これで、filenameって名前で、幅がwidth、高さがheightの画像ができちゃいます。
まぁざっとこんな感じで、途中紆余曲折があったけど、いろんな画像を読み込んで、なんか処理して、保存するってとこまでできるようになりました。