libjpegを使ってjpegファイルを出力する

libjpegというjpegを扱うライブラリを使ってjpegファイルを出力します。

インストール

Ubuntu 11.10 以降なら公式リポジトリにパッケージがあるそうなので、それを使います。

$ sudo apt-get install libjpeg-dev 

使い方

インクルード

インストールすると、/usr/include/jpeglib.h ができているのでそれをインクルードします。ファイルの入出力やエラーの出力のために、stdio.h もインクルードする必要があります。

#include <stdio.h>
#include <jpeglib.h>
jpegオブジェクトの初期設定

jpegファイルの出力にはjpeg_compress_structというjpegオブジェクトを使います。またエラー処理のための構造体jpeg_error_mgrも確保します。

struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;

エラーの処理はデフォルトで構わないので、jpeg_std_error()でデフォルト値を設定します。その後、jpeg_create_compress()でjpegオブジェクトを初期化します。

cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
出力ファイルの設定

バイナリ、書き込みモードでfopen()し、jpeg_stdio_dest()で出力先に設定します。

FILE *fp = fopen(filename, "wb");
jpeg_stdio_dest(&cinfo, fp);
画像のパラメータの設定

画像の幅、高さ、色の種類、画質などを設定します。幅はimage_widthプロパティ、高さはimage_heightプロパティで設定します。
色の種類は、RGBカラーならin_color_spaceにJCS_RGBを、input_componentsに3を設定します。グレースケールならin_color_spaceにJCS_GRAYSCALEを、input_componentsに1を設定します。
画質はjpeg_set_quality()で設定します。第2引数には0から100の値を指定し、値が大きいほど画質が良くなります。jpeg_set_quality()を使わないときのデフォルト値は75です。

cinfo.image_width = 256;
cinfo.image_height = 256;
cinfo.input_components = 3;
cinfo.in_color_space = JCS_RGB;
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, 75, TRUE);
書き込み

jpeg_start_compress()で圧縮を開始します。ピクセルごとの色を設定していき、jpeg_write_scanlines()でファイルに書き込みます。
色の設定は、JSAMPLE型を使って行います。RGBカラーならJSAMPLE型3つで1ピクセルを表します。JSAMPROW型はJSAMPLEの配列で、横1列分(1行)を表します。JSAMPARRAY型はJSAMPROWの配列で、画像全体を表します。

jpeg_start_compress(&cinfo, TRUE);

JSAMPARRAY img = (JSAMPARRAY) malloc(sizeof(JSAMPROW) * height);
for (int i = 0; i < height; i++) {
    img[i] = (JSAMPROW) malloc(sizeof(JSAMPLE) * 3 * width);
    for (int j = 0; j < width; j++) {
        img[i][j*3 + 0] = i;
        img[i][j*3 + 1] = j;
        img[i][j*3 + 2] = 127;
    }
}

jpeg_write_scanlines(&cinfo, img, height);
終了

jpeg_finish_compress()で圧縮を終了し、jpeg_destroy_compress()で圧縮に使ったjpegオブジェクトを破棄します。

jpeg_finish_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
コンパイル

コンパイル時にライブラリとリンクさせる必要があるため、コンパイルオプションに -ljpeg を付け加えます。

$ gcc test_libjpeg_compress.c -std=c99 -ljpeg

こんな画像が出力されました。