画像ファイルフォーマットのC,C++での取り扱い.
Windows Bitmap†
単純にビットマップ画像というと,色を表すピクセルを格子状に並べて画像を表現したもの(相対するものにベクタ画像がある)であるが,Windows Bitmapというと
Windows標準の画像ファイル形式を指す.拡張子はbmp.
Windows BitmapはOS/2用とWindows用に大きく分けることができ,
細かくは以下の5種類が存在する.
- OS/2(COREタイプ)
- OS/2 V2(INFO2タイプ)
- Windows V3(INFOタイプ)
- Windows V4(V4タイプ)
- Windows V5(V5タイプ)
一般的にはINFOタイプが用いられている.
V4はINFOにカラーマネジメント,V5はさらにカラープロファイルを追加した形式.
基本的には無圧縮で使われるが,Windows V3-5ではRLE,JPEG,PNG圧縮が規定されている.
各形式のヘッダ構成はWikipediaのBMP file format参照.
コード例†
Windows Bitmapファイルの読み込み,書き出しを行う関数を実装したヘッダファイルを以下に置く.
注意事項
- OS/2(V1), Windows(V3,V4,V5)の非圧縮BMPに対応
- ビットフィールド付きビットマップ,カラーパレット付きBMPの読み込み(書き込みは未対応)に対応.ただし,サンプルとなるファイルがなかったので動作は未確認
- RLE, JPEG, PNG圧縮は未対応
- V4,V5のカラーマネジメント,プロファイルは未対応
- 2016年2月18日更新 : 横の解像度が4nでないものに対応していなかったのを修正
JPEG†
JPEGはJoint Photographic Experts Groupによる非可逆圧縮画像フォーマット.圧縮率の高さからWeb,デジカメなど多くの場所で用いられている.デジカメでは記録時の情報(日付や画像の向き,カメラの種類など)を格納できるように拡張されたEXIF(Exchangeable image file format)がよく用いられている.拡張子はjpg,jpeg,jpe,jfif,jfi,jifの6つ.
DCT(離散コサイン変換)による周波数領域への変換などにより非常に高い圧縮率(だいたい1/10〜1/100)を実現しているが,画像をブロックに分割した上でDCTを掛けているので,ブロックノイズと呼ばれるノイズが発生する.そのため,画像処理などを行う際の中間フォーマットには用いない方がよい.最終的にできた画像を公開するなどのときにJPEGに変換するのがよい.
libjpegライブラリ†
libjpegはC言語で書かれたJPEGファイルの入出力ライブラリ.BMPと違い,JPEGファイルを読み書きするコードを自分で一から作るととても大変なので,こういったライブラリを用いた方がよい.以下にビルド方法とコード例を示す.
libjpegのビルド†
- ビルド : nmakeでVC2010プロジェクトファイルを生成
- ダウンロードしたファイルを解凍
- Visual Studio コマンドプロンプトを開いて,libjpegのフォルダに移動
- 以下のコマンドを実行
*1
nmake /f makefile.vc setup-v10
Visual Studio 2012だとwin32.makがないというエラーがでる(理由と対処法はこちら).
VS2012 Update1でwin32.makはインストールされてるのだがどうもパスは通してくれないみたいなので上記コマンドを打つ前に以下のコマンドを実行しておく.
SET Include=%Include%;"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include"
C:\Program Files (x86)\〜の部分は自分の環境に合わせて変えること.
- 生成されたjpeg.slnを開いてコンパイル(必要に応じてビルドオプションを設定)
*2
- Releaseフォルダにjpeg.libが生成されるので読み込ませたいプロジェクトから見える位置にコピー
- ビルド : nmakeで直接生成
- ダウンロードしたファイルを解凍
- 解凍したフォルダの jconfig.vc を jconfig.h に名前変更(jconfig.vcはVisual C++用のjconfig.hファイル)
- Visual Studio コマンドプロンプト
*3
を開いて,libjpegのフォルダに移動
- 以下のコマンドを実行
nmake nodebug=1 /f makefile.vc clean all
デバッグ情報を含めたい場合はnodebug=1を削除.
ランタイムライブラリの設定などは,makefile.vcの最初の法のCFLAGSに設定を追加する.
マルチスレッド : /MT
マルチスレッド DLL : /MD
最適化の設定は以下
最大限の最適化 : /Ox
インライン関数の展開 拡張可能な関数すべて : /Ob2
組み込み関数の使用 : /Oi
実行速度優先 : /Ot, ファイルサイズ優先 : /Os
フレームポインターなし : /Oy
プログラム全体の最適化 : /GL
SSE2有効 : /arch:SSE2
- libjpegのフォルダにlibjpeg.libが生成されるので読み込ませたいプロジェクトから見える位置にコピー
コード例†
libjpegを用いてJPEGファイルの読み込み,書き出しを行う関数を実装したヘッダファイルを以下に置く.
使うときは,ライブラリファイルをリンクすること.VC++ならソースに以下のように記述しても良い
#ifdef _DEBUG
#pragma comment (lib, "libjpegd.lib")
#else
#pragma comment (lib, "libjpeg.lib")
#endif
PNG†
PNGはPortable Network Graphicsの略で,可逆圧縮画像フォーマットである.
1995年頃にGIFフォーマット(当時Web上で非常に良く用いられていた可逆画像フォーマット)に使われている圧縮方式に特許問題が発生した.そのときに代替になるものとして開発された(Png is Not Gifという意味も).
ただ,ブラウザが標準で対応しないことが多いなどもありGIFを完全に置き換えるとはならなかった.
拡張子はpng.
PNGは歴史的な経緯からGIFと比較されることが多いので,ここではGIFと比べた際の利点,欠点を挙げる.
- フルカラーサポート : GIFは256色(8ビット)であったが,PNGは16ビットグレイスケール,24/48ビットRGBフルカラーに対応している.
- アルファチャンネルのサポート : 8/16ビットアルファチャンネルが使える.GIFでは1色(透明が不透明で0か1)のみ.
- ガンマ補正のサポート
- 2次元インタレース : GIFより早めに全体像が見える.
- GIFより圧縮サイズが小さい : といっても5〜25%ぐらいらしいが.
欠点としては,
- アニメーション(複数画像)は対応していない : ただし拡張フォーマット(MNG,APNG)でサポート.
- 圧縮・展開に時間がかかる
その他の特徴は以下のページ参照.
PNGはJPEGほど圧縮率は高くないが,可逆圧縮なので画像が劣化しない.中間フォーマットなどに用いるのに最適である.
libpngライブラリ†
libpngはPNGファイルの入出力ライブラリ.以下にビルド方法とコード例を示す.
libpngのビルド†
- ダウンロード : libpngからlibpng-*.tar.gz
- ビルド
- ダウンロードしたファイルを解凍する.
- projects/vstudioフォルダにVS2010用のソリューションファイル vstudio.sln がある.
vstudio.sln を開く前に同フォルダのzlib.propsをテキストエディタで開き,
<ZLibSrcDir> ... </ZLibSrcDir>
にzlibのソースコードフォルダを指定する.相対パスを使う場合はプロジェクトファイル(*.vcxproj)からでなければならない
(slnのあるフォルダよりさらに1階層下).
- vstudio.sln を開いて(ダブルクリックで開けない場合は,Visual Studio 2010からファイルを指定して開く),Release, Release Libraryでビルド.
- 生成されるファイル(バージョンや環境に依存)
ビルド構成 | フォルダ | ファイル | 備考 |
Release | projects/vstudio/Release | libpng15.dll, libpng15.lib, zlib.lib | |
Release Library | projects/vstudio/Release Library | libpng15.lib, zlib.lib | スタティックリンク |
コード例†
libpngを用いてPNGファイルの読み込み,書き出しを行う関数を実装したヘッダファイルを以下に置く.
使うときは,ライブラリファイルをリンクすること.VC++ならソースに以下のように記述しても良い
#ifdef _DEBUG
#pragma comment (lib, "libpngd.lib")
#pragma comment (lib, "zlibd.lib")
#else
#pragma comment (lib, "libpng.lib")
#pragma comment (lib, "zlib.lib")
#endif
WebP†
WebP(ウェッピー)はGoogleが公開しているオープンな画像フォーマット.
動画フォーマットのWebMの静止画版.
WebMで使われているVP8を使って圧縮し,RIFFを元にしたコンテナに格納している.
可逆,不可逆圧縮両方に対応し,可逆圧縮の場合,PNGより28%小さく,不可逆圧縮の場合,同じクオリティのJPEGより25-34%小さいらしい.
対応ソフトウェア†
WebP画像ファイルへの変換は,WebPのページのDownloadから,Precompiled WebP utilities and library をダウンロードするとエンコーダ(cwebp.exe)とデコーダ(dwebp.exe)が得られる.Windowsのエクスプローラのプレビューやフォトビューアーでみたい場合は,WebP Codec for Windowsをダウンロードして,インストールすればよい.また,当然ながらGoogle Chromeはネイティブに対応しているので,単純に画像を確認したいならば,ChromeにD&Dすればよい.
libwebpライブラリ†
libwebpはGoogle codeで公開されているWebPを扱うためのライブラリ.以下にビルド方法とコード例を示す.
libwebpのビルド†
- ダウンロード
Google codeのWebPのページのDownloadから
ソースコード(libwebp-*.tar.gz)をダウンロード.
ちなみにビルド済みのライブラリ(libwebp-*-windows-x86.zip)もあるので,ビルドするのが面倒な場合はこちらを使う.
- ビルド
- ダウンロードしたファイルを解凍.解凍したフォルダを$WEBPとする.
- Visual Studio コマンドプロンプトを立ち上げる.
スタートメニュー -> Microsoft Visual Studio 2010 -> Visual Studio Tools -> Visual Studio コマンド プロンプト (2010)
- $WEBPに移動し,nmakeを使ってビルドする.
nmakeでの構文は,
nmake /f Makefile.vc [CFG=<config>] [OBJDIR=<path>] [RTLIBCFG=<rtlib>] [<target>]
である.それぞれの引数は,
- config : ビルドの種類
release-static, debug-static, release-dynamic, debug-dynamic
*-staticだとlibファイルのみ,*-dynamicだとlibとdllが作られる.
- rtlib : ランタイムライブラリ
static, dynamic
staticだと "/MT" or "/MTd",dynamicだと "/MD" or "/MDd" がコンパイルオプションとして指定される.
- path : objや生成されたlib,exeを出力するフォルダ.
- target : ビルド内容
clean, experimental
何も書かなければビルドが実行される.
- 例.ランタイムライブラリをマルチスレッドDLLにして,dllなしでビルド.
nmake /f Makefile.vc CFG=release-static RTLIBCFG=dynamic OBJDIR=output
- ビルドが成功すれば,OBJDIRに指定したフォルダ内にrelease-static/x86などのフォルダができ,
その中のlib,binフォルダにlib,dllファイルが生成される.
コード例†
libwebpを用いてWebPファイルの読み込み,書き出しを行う関数を実装したヘッダファイルを以下に置く.
libwebpのソースに付属のサンプルを元にしている.
使うときは,ライブラリファイルをリンクすること.VC++ならソースに以下のように記述しても良い
#ifdef _DEBUG
#pragma comment (lib, "libwebp_a_debug.lib")
#else
#pragma comment (lib, "libwebp_a.lib")
#endif
リンク†
C/C++での画像入出力に使えそうなライブラリ
- FreeImage : BMP,JPG,PNG,GIFといった基本的なものからRAW,WEBP,JPEG2000まで幅広い画像入出力が出来る.簡単な画像処理(色変換程度)はでき,OpenGLのテクスチャにも直接使える.
- OpenCV : 言わずと知れた画像処理系で最も有名なライブラリ.対応する画像フォーマットも多いが画像入出力だけに使うには導入が少しめんどくさい.各種画像処理も行いたいならこっちがよい.