とにかく奥が深い。何かやろうとするたびに、膨大なbackgroundに押し潰されそうになる。

EXIF *

デジカメなんかがjpegに各種情報を埋め込むための仕様なのだそうだ。どの受光素子が「画像の左上」か、なんて(カメラを縦向きで撮ったかどうか)なんかも記録してくれるので便利。でもどうやらメーカーごとに「方言」があるみたいなのが困る。

jpeg *

風景、人物写真などに適したフォーマットで、非常に広く普及している。

IJG *

IJGという所が総本山っぽい雰囲気である。スタンダードっぽいライブラリを提供しておった。関連webページは以下。

フォーマット *

画像の持つ情報量は多いので、ファイルの形式としては何らかの圧縮を施すのが通例であり、その方法の違いなどにより様々なファイル形式が存在する。一般に、写真画像ならjpegが適し、白の背景に黒の三角形を描きました、みたいなエッジのきいた人工的な図形ならPNGの方が適する場合が多い。

色とデータ量 *

一般的なPC上で、色は赤・緑・青(RGB)の各々の強度(加色混合)で表現される。各色の強度をどれだけ細かく制御するかで、表現できる色の数が決まる。

最近のPC上では約1677万色を区別して発色することが容易に可能で、これは大体人間の識別できる色数の限界といわれているらしい。この意味において、発色「数」に関してはPCまわりの技術は充分な水準に達しているといえる(無論、色空間の変換やらモニタの較正やら、他に考慮すべき事項もまだ沢山あるが、とりあえず「数」だけは充分)。

1677万とは 256*256*256=(2^8)^3 である。RGBに各々256種類(8bit)の情報を割り振ることによって実現される。つまり、ひとつの点の色を表現するのに 8bit + 8bit + 8bit = 24bit のデータ量が必要なわけである。このことから「1677万色の発色 」を24bitカラーと称することもある。True Colorと呼ばれているものも同様の意味を持つ。32bit PC上のデータ処理の観点からは、嘘データを8bitつめこんで、32bit/点 として扱う方が効率がよいらしい(アライメントの事情だかなんだか。よくわからん)。故に、32bitカラーと呼ばれているものも、色の数としては24bitカラーと変わらない。

これに対し、6万5千色を扱うHigh Colorあるいは16bitカラー(2^16=65536)と呼ばれるものもある。これはRとBを5bit、Gを6bitで表現している。業務用機器では、RGB各々10bitで表現している(2^(10+10+10)=1073741824 種類の発色ができる)ものもあるらしい。

以下参考文献。

グレースケール *

モノクロ画像だと色の情報は失われるが、データ量も小さいため、RGBをモノクロに変換したいこともままある。しかしこの変換も一筋縄ではいかず、色々と方式があって混乱したが、幾つかのすばらしい解説のおかげで理解がちょっぴり深まった。

BMP *

ビットマップ。文字通り、座標の各点(ビット)の色をSerialに記録(マップ)したもので、概念はとてもわかりやすい一方でデータ量はかなり多くなってしまう。

単純であるがため、歴史のある形式である。その結果、細かく仕様の異なるものが混在しているようで、全貌の把握にはなかなか骨が折れる。

幅とデータ量の検証 *

preface *

ビットマップを(数学でいうところの)行列として捉える。このとき行数は画像の高さ、列数は画像の幅を表す(単位はpixel)。上下の区別をとりあえず無視すると、ビットマップの画像データの並び方は次のように表現できる。

(第1行のデータ)(第2行のデータ)(第3行のデータ)...

つまり、横方向の1ラインをまずはドドっと格納し、そして次のラインをドドっと・・・という具合である。この時、ビットマップ形式のシキタリでは、1行(1ライン)あたりのbyte数は4の倍数でなくてはならないそうだ。画像の幅なんてのは千差万別なので、不幸にして生データ(pixel数ではない)が4の倍数にならないなんてことはザラにあるわけだが、その時は行の末尾に嘘データ(ゼロ)を詰めて無理矢理に一番近い4の倍数にしてしまうらしい。実感を得るために検証してみた。(ただの自己満足です)

準備と予想 *

最も使用頻度の大きいであろう24bitカラーのビットマップを、幅を1pixelずつ変えて保存し、各々のファイルサイズを比較するという作戦である。

素材としてC:\WINNT(windows2000)にある「フィッシング.bmp」を使う。Photoshopでサイズを128pixel(横) x 64pixel(縦)にし、さらに24bitカラーとした。

save_dialog.png

この時1行あたりのデータ量は、1pixelあたり3byte(24bit)であるから

128 x 3byte = 384byte

であり、4で割切れる(ので嘘データ不要)。この時のファイルサイズを起点とする。さて幅を1pixel増やすと1行あたり

129 x 3byte = 387byte

であって4で割切れない。割切れるように嘘データを詰めて1行あたり388byteとなるならば、全体として

(388 - 384)byte x 64 = 256byte

のファイルサイズの増加となるはずである。同様にして、

130 x 3byte = 390byte ==> (392 - 384)byte x 64 = 512byte ==> 512byteの増加
131 x 3byte = 393byte ==> (396 - 384)byte x 64 = 768byte ==> 768byteの増加
132 x 3byte = 396byte ==> (396 - 384)byte x 64 = 768byte ==> 768byteの増加
127 x 3byte = 381byte ==> (384 - 384)byte x 64 = 0byte ==> 0byteの増加

となるはずである。127と128、131と132のファイルサイズが変わらないあたりで4の倍数の実感が沸くはずである。

結果 *

予想通りとなった。知ってる人からするとバカらしい検証だろうが、うまくいったので満足。

127dlg.png


128dlg.png


129dlg.png


130dlg.png


131dlg.png


132dlg.png

PNG *

Portable Network Graphics のことで、GIFの後継として開発されたそうだ。

ライブラリ *

プログラムからPNGを扱うためにはzliblibpngが必要となる。ソースもバイナリも手に入るが、ソースを持ってきてもVisual Studio用のプロジェクトが付属するのでビルドは楽である。プロジェクトを開いて ビルド => アクティブな構成の設定 から好きなものを選ぶだけでよい。

PNGファイルフォーマット *

GDI+ *

Windowsにおいて、標準の画像フォーマットは所謂「ビットマップ」であるが、それ以外のjpegといったフォーマットの方が巷で専ら使用されている。GDI+は、そういった様々のフォーマットの画像(BMP, GIF, JPEG, PNG, TIFF, EMF)を扱うためのライブラリ。

platformSDKが必要みたいだ。

こんな感じのコードでjpegがピクチャコントロールに表示できた。初期化などはすでに終わっているものとする。

const HWND hWndPict = GetDlgItem(hWnd, IDC_PICT);
RECT Rect;
 GetClientRect(hWndPict, &Rect);
const int width = Rect.right - Rect.left;
const int height = Rect.bottom - Rect.top;

setlocale(LC_ALL,"");
HDC hdc = GetDC(hWndPict);
Graphics MyGraphics(hdc);
Image myImage(filename); // WCHAR* filename
MyGraphics.DrawImage(&myImage, 0, 0, width, height);

ReleaseDC(hWndPict, hdc);

添付ファイル: file132dlg.png 2245件 [詳細] file131dlg.png 2284件 [詳細] file130dlg.png 2241件 [詳細] file129dlg.png 2228件 [詳細] file128dlg.png 2287件 [詳細] file127dlg.png 2240件 [詳細] filesave_dialog.png 2347件 [詳細]

Last-modified: Sun, 30 Apr 2006 20:23:31 JST