オープンソースライブラリ編・・・。
初めてということでまずはlibjpegから・・・。
libjpegはJpeg画像を圧縮・伸長をするライブラリ・・・。
今回はLinux(Ubuntu)でビットマップをJpegに変換してみる・・・。
まず、ビットマップのデータを格納する構造体や、関数を作る必要がある・・・。
bitmap.hを用意し、
まずはビットマップファイルヘッダ・・・。
ここで注意しなければならないのは、typeがunsigned shortの2バイトに対して、そのあとのsizeがunsigned intの4バイトということ・・・。
構造体のワード境界が4バイトなので、typeとsizeの間に2バイト空白領域が存在する・・・。
freadでファイルから構造体に読み込んだ時に、この2バイト分位置がずれてしまう・・・。
そこで#pragma pack(2)とすることで、ワード境界を2バイトにし、隙間なく読み込めるように・・・。
元に戻して、今度はビットマップ情報ヘッダ・・・。
今回は24bitビットマップのみ扱うので、カラーテーブルは使わない・・・。
最終的にビットマップは、ファイルヘッダ、情報ヘッダ、ピクセルバッファ、の3部分からなる・・・。
load_bitmapで、ビットマップのこれらの情報を読み込む・・・。
bitmap.cにある定義では、
渡されたfilenameのビットマップを開いて、freadでファイルヘッダ、情報ヘッダを、渡されたbitmap_ptrの要素に格納・・・。
ピクセルバッファのサイズは、statで調べたファイルサイズから、2つのヘッダのサイズを引いたものなので、mallocでその分のバッファを確保して、そこにfreadで読み込む・・・。
でファイルを閉じる・・・。
これで構造体にビットマップのデータが入った・・・。
destroy_bitmapは、ピクセルバッファを破棄して、ファイルヘッダ、情報ヘッダをクリアにする・・・。
destroy_bitmapの定義は、
ピクセルバッファをfreeして、bitmap_ptrの参照先を0で埋める・・・。
これでビットマップ読み込みの準備はできたので、
$ sudo apt-get install libjpeg-dev パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています 状態情報を読み取っています... 完了 以下の追加パッケージがインストールされます: libjpeg-turbo8-dev libjpeg8-dev 以下のパッケージが新たにインストールされます: libjpeg-dev libjpeg-turbo8-dev libjpeg8-dev アップグレード: 0 個、新規インストール: 3 個、削除: 0 個、保留: 272 個。 257 kB のアーカイブを取得する必要があります。 この操作後に追加で 1,471 kB のディスク容量が消費されます。 続行しますか? [Y/n] y 取得:1 http://jp.archive.ubuntu.com/ubuntu xenial/main amd64 libjpeg-turbo8-dev amd64 1.4.2-0ubuntu3 [254 kB] 取得:2 http://jp.archive.ubuntu.com/ubuntu xenial/main amd64 libjpeg8-dev amd64 8c-2ubuntu8 [1,552 B] 取得:3 http://jp.archive.ubuntu.com/ubuntu xenial/main amd64 libjpeg-dev amd64 8c-2ubuntu8 [1,546 B] 257 kB を 1秒 で取得しました (243 kB/s) 以前に未選択のパッケージ libjpeg-turbo8-dev:amd64 を選択しています。 (データベースを読み込んでいます ... 現在 208532 個のファイルとディレクトリがインストールされています。) .../libjpeg-turbo8-dev_1.4.2-0ubuntu3_amd64.deb を展開する準備をしています ... libjpeg-turbo8-dev:amd64 (1.4.2-0ubuntu3) を展開しています... 以前に未選択のパッケージ libjpeg8-dev:amd64 を選択しています。 .../libjpeg8-dev_8c-2ubuntu8_amd64.deb を展開する準備をしています ... libjpeg8-dev:amd64 (8c-2ubuntu8) を展開しています... 以前に未選択のパッケージ libjpeg-dev:amd64 を選択しています。 .../libjpeg-dev_8c-2ubuntu8_amd64.deb を展開する準備をしています ... libjpeg-dev:amd64 (8c-2ubuntu8) を展開しています... libjpeg-turbo8-dev:amd64 (1.4.2-0ubuntu3) を設定しています ... libjpeg8-dev:amd64 (8c-2ubuntu8) を設定しています ... libjpeg-dev:amd64 (8c-2ubuntu8) を設定しています ... $
apt-getでlibjpeg-devをインストール・・・。
main.cは、
jpeglib.hをインクルード・・・。(libjpegなのにjpeglib.h・・・。)
また先ほど作ったbitmap.hもインクルード・・・。
cinfoがJpeg圧縮情報で、ほとんどの関数でこれを渡す・・・。
load_bitmapで"test.bmp"をロードしたら、Jpegエラー処理を初期化・・・。(Jpegエラー処理はいずれ扱う・・・。)
"test.jpg"を開いて、Jpeg出力先をそこに・・・。
各パラメータの設定など・・・。画質は50にしている・・・。
24ビットなら3色なので、3色 * 幅で行が構成されるかと思うが、実際にはビットマップファイルはワード境界のこともあり、最後に4で割った余りの部分が空白領域paddingとして付加されている・・・。
この情報をもとにline_bufferを作成・・・。
行ごとにビットマップのピクセルバッファを流し込んでいく・・・。
jpeg_start_compressで圧縮開始、
ビットマップのピクセルバッファを行ごとにline_bufferに受け渡し、line_bufferをjpeg_write_scanlinesで書き込み、jpeg_finish_compressで圧縮終了・・・。
ビットマップのピクセルバッファはRGBではなくBGRの順で格納されているので注意・・・。
また、上下も逆なので、その辺も気を付けて受け渡し・・・。
line_bufferを解放、jpeg_destroy_compressでcinfoも破棄・・・。
fcloseでfpも閉じて、destroy_bitmapでビットマップも破棄・・・。
これでJpegが出力できるかな・・・。
$ gcc -o main main.c bitmap.c -ljpeg $ ls bitmap.c bitmap.h license.txt main main.c test.bmp $ ./main $ ls bitmap.c bitmap.h license.txt main main.c test.bmp test.jpg $
libjpegをリンクするときは-ljpegを付ける・・・。
実行すると、test.jpgが生成されてるのがわかる・・・。
test.bmpとほぼ同じようなtest.jpgを生成できてる・・・。