とにかく奥が深い。何かやろうとするたびに、膨大なbackgroundに押し潰されそうになる。
デジカメなんかがjpegに各種情報を埋め込むための仕様なのだそうだ。どの受光素子が「画像の左上」か、なんて(カメラを縦向きで撮ったかどうか)なんかも記録してくれるので便利。でもどうやらメーカーごとに「方言」があるみたいなのが困る。
風景、人物写真などに適したフォーマットで、非常に広く普及している。
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をモノクロに変換したいこともままある。しかしこの変換も一筋縄ではいかず、色々と方式があって混乱したが、幾つかのすばらしい解説のおかげで理解がちょっぴり深まった。
ビットマップ。文字通り、座標の各点(ビット)の色をSerialに記録(マップ)したもので、概念はとてもわかりやすい一方でデータ量はかなり多くなってしまう。
単純であるがため、歴史のある形式である。その結果、細かく仕様の異なるものが混在しているようで、全貌の把握にはなかなか骨が折れる。
ビットマップを(数学でいうところの)行列として捉える。このとき行数は画像の高さ、列数は画像の幅を表す(単位はpixel)。上下の区別をとりあえず無視すると、ビットマップの画像データの並び方は次のように表現できる。
(第1行のデータ)(第2行のデータ)(第3行のデータ)...
つまり、横方向の1ラインをまずはドドっと格納し、そして次のラインをドドっと・・・という具合である。この時、ビットマップ形式のシキタリでは、1行(1ライン)あたりのbyte数は4の倍数でなくてはならないそうだ。画像の幅なんてのは千差万別なので、不幸にして生データ(pixel数ではない)が4の倍数にならないなんてことはザラにあるわけだが、その時は行の末尾に嘘データ(ゼロ)を詰めて無理矢理に一番近い4の倍数にしてしまうらしい。実感を得るために検証してみた。(ただの自己満足です)
最も使用頻度の大きいであろう24bitカラーのビットマップを、幅を1pixelずつ変えて保存し、各々のファイルサイズを比較するという作戦である。
素材としてC:\WINNT(windows2000)にある「フィッシング.bmp」を使う。Photoshopでサイズを128pixel(横) x 64pixel(縦)にし、さらに24bitカラーとした。
この時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の倍数の実感が沸くはずである。
予想通りとなった。知ってる人からするとバカらしい検証だろうが、うまくいったので満足。
Portable Network Graphics のことで、GIFの後継として開発されたそうだ。
プログラムからPNGを扱うためにはzlibとlibpngが必要となる。ソースもバイナリも手に入るが、ソースを持ってきてもVisual Studio用のプロジェクトが付属するのでビルドは楽である。プロジェクトを開いて ビルド => アクティブな構成の設定 から好きなものを選ぶだけでよい。
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);