さて、前回の方針(注)にそって学習を進めましょう。
注:「ということで(何が「ということ」なのか、分かりませんが)、「GDI+をカバーする」なんて大口はたたかず、GDI+で拡張された種々のイメージファイルの読み書きのみを先ずは当たろうか、ということで考えています。」
定石1:GDI+の開始の際のお作法
GDI+を使うには、その為のDLLをアプロードし、その為の定義が入ったヘッダーが必要です。また、それらは専用ネームスペースにあるので使えるようにします。
//GDI+のインクルード
#include <gdiplus.h>
#include <wchar.h>
#pragma comment(lib,"gdiplus.lib")
using namespace Gdiplus;
次にGDI+の初期化に関わる専用の変数と関数を呼びます。
GdiplusStartupInput m_gdiSI; //GDI+のスタートアップインプット
ULONG_PTR m_gdiToken; //GDI+のトークン
//GDI+の開始
GdiplusStartup(&m_gdiToken, &m_gdiSI, NULL);
これでGDI+が使えるようになります。なお、新し系のサービスではワイド文字を使っているので"wchar.h"を入れておくのが良いでしょう。またその際には必ずワイド文字-マルチバイト文字変換があるのでロケール設定関数も必要です。
//ワイド文字使用のためロケールの初期化(日本語)
setlocale(LC_CTYPE, "JPN");
定石2:GDI+の終了の際のお作法
C++では入り口にお作法(例:コンストラクター)があれば、必ず出口にもお作法(例:デストラクター)があります。GDI+の場合は以下の通りです。
//GDI+の終了
GdiplusShutdown(m_gdiToken);
ここまではすべてのGDI+の利用に共通です。掘り下げて学びたい方は↓をご覧ください。
学習用-GDI+ (復習用-Windows GDI)
なお、20ものヘッダーファイルリストがありますが、BCC102のインクルードファイルで見ると全てgdiplus.hで済まされそうです。(エラーが出たらその時に考えましょう。)
定石3:GDI+のイメージ描画のお作法
今回やるイメージファイルからのイメージの読みこみ、ウィンドウへの表示には、次の二つのクラスがかかわってきます。(というか、老人には荷が重いので、今回はこれだけしか使わないつもりです。)また、GDI+はC++で書かれているようで同一名のメソッド(関数のオーバーロード)がおおく(注)、いちいち確認して進めることが肝要です。
注:例えばGraphicsクラスのイメージを表示するDrawImageメソッドだけで30ものオーバーロード関数があることは前回書きました。
Graphics
The Graphics class provides methods for drawing lines, curves, figures, images, and text. A Graphics object stores attributes of the display device and attributes of the items to be drawn.(線、曲線、図形、像や文章を描画するメソッドを規定するクラスで、その実体(インスタンス)は描画デバイスと描画対象の属性を保有します。)
これを使えるようにするにはコンストラクターが必要です。これもオーバーロード関数がいくつかありますが、次が簡単でしょう。
第2引数のboolは色調整を行うか否かの指示で既定値はFALSEです。Graphics(hWnd)と省略して書く事が出来ます。
例:Graphics* m_pGraphics = new Graphics(m_hDC);
Image
The Image class provides methods for loading and saving raster images (bitmaps) and vector images (metafiles).(ラスターイメージ(ビットマップ)とベクターイメージ(メタファイル)の読み込み、書き込みメソッドを規定するクラスです。)(注)
注:「なんだ、ビットマップだけなんだ」と思わないでください。データとして保有するのはビットマップ形式ですが、読み込み(デコード)と書き込み(エンコード)には多彩な種類があります。これは末尾に確認するコードを載せておきます。また、ビットマップとメタファイル(よくワードやエクセルの画像などで出てきますよね?)については次を参考にしてください。
コンストラクターは大きく、ファイルからとストリームからの二つあります。
初心者の私は勿論前者のファイルからのものを使います。(ここでwcharが出てきましたね。)
例:Image* m_Image[m_NoI] = new (Image)(m_WFileName); //m_WFileNameはワイド文字のフルパス名です。
このGraphicsクラスのインスタンスとImageクラスのインスタンスを使った画像表示は次のようになります。(これも↑で書いたように30のオーバーロード関数があります。)
例:m_pGraphics->DrawImage(m_Image[m_Selected], x, y, w, h); //GraphicsクラスのインスタンスのDrawImageメソッドの引数にImageクラスのインスタンスへのポインターを入れ、x,y座標に幅(w)、高さ(h)指定で表示する。
ここまでくれば、GDI+によるファイルの読み込み、表示ができるようになりますね。
<ご参考-ご自身のPCで読み書きできるイメージファイルの列挙(MSDNの例を改造)>
#include <windows.h>
#include <gdiplus.h>
#include <stdio.h>
#include <conio.h>
using namespace Gdiplus;
INT main() {
// Initialize GDI+.
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
//Variables to use
UINT num; // number of image encoders
UINT size; // size, in bytes, of the image encoder array
ImageCodecInfo* pImageCodecInfo; //ImageCodeInfo
//<<< Encoder List>>>
// How many encoders are there?
// How big (in bytes) is the array of all ImageCodecInfo objects?
GetImageEncodersSize(&num, &size);
// Create a buffer large enough to hold the array of ImageCodecInfo
// objects that will be returned by GetImageEncoders.
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
// GetImageEncoders creates an array of ImageCodecInfo objects
// and copies that array into a previously allocated buffer.
// The third argument, imageCodecInfo, is a pointer to that buffer.
GetImageEncoders(num, size, pImageCodecInfo);
// Display the graphics file format (MimeType)
// for each ImageCodecInfo object.
printf("--------------------\r\nEncoder list of GDI+\r\n--------------------\r\n");
for(UINT j = 0; j < num; ++j) {
wprintf(L"%s\n", pImageCodecInfo[j].MimeType);
}
free(pImageCodecInfo);
//<<< Decoder List>>>
// How many decoders are there?
// How big (in bytes) is the array of all ImageCodecInfo objects?
GetImageDecodersSize(&num, &size);
// Create a buffer large enough to hold the array of ImageCodecInfo
// objects that will be returned by GetImageDecoders.
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
// GetImageDecoders creates an array of ImageCodecInfo objects
// and copies that array into a previously allocated buffer.
// The third argument, imageCodecInfo, is a pointer to that buffer.
GetImageDecoders(num, size, pImageCodecInfo);
// Display the graphics file format (MimeType)
// for each ImageCodecInfo object.
printf("--------------------\r\nDecoder list of GDI+\r\n--------------------\r\n");
for(UINT j = 0; j < num; ++j) {
wprintf(L"%s\n", pImageCodecInfo[j].MimeType);
}
free(pImageCodecInfo);
//Finalizing
GdiplusShutdown(gdiplusToken);
getch();
return 0;
}
<私のPCの出力結果>
--------------------
Encoder list of GDI+
--------------------
image/bmp
image/jpeg
image/gif
image/tiff
image/png
--------------------
Decoder list of GDI+
--------------------
image/bmp
image/jpeg
image/gif
image/x-emf
image/x-wmf
image/tiff
image/png
image/x-icon
