jpeglibの勉強

Adobe GILでもjpeglibが使われていた。自分もこれを使おうと思うので勉強。

テストコード

// jpeg_test.cpp
#include <stdio.h>
#include <stdlib.h>
#include <jpeglib.h>

int main(int argc, char **argv)
{
  struct jpeg_decompress_struct cinfo1;
  struct jpeg_error_mgr jerr;

  cinfo1.err = jpeg_std_error(&jerr);
  // 画像の展開
  jpeg_create_decompress(&cinfo1);

  FILE *infile = fopen(argv[1], "rb");
  jpeg_stdio_src(&cinfo1, infile);
  jpeg_read_header(&cinfo1, TRUE);

  jpeg_start_decompress(&cinfo1);

  int width = cinfo1.output_width;
  int height = cinfo1.output_height;

  JSAMPARRAY img = (JSAMPARRAY)malloc(sizeof(JSAMPROW)*height);

  for(int i = 0; i < height; ++i){
    img[i] = (JSAMPROW)calloc(sizeof(JSAMPLE), 3 * width);
  }

  while(cinfo1.output_scanline < cinfo1.output_height){
    jpeg_read_scanlines(&cinfo1,
        img + cinfo1.output_scanline,
        cinfo1.output_height - cinfo1.output_scanline);
  }

  jpeg_finish_decompress(&cinfo1);
  jpeg_destroy_decompress(&cinfo1);
  fclose(infile);

  // とりあえずRGB値を取り替えるだけ
  for(int i = 0; i < height; ++i){
    for(int j = 0; j < width; ++j){
      JSAMPLE tmp = img[i][j * 3 + 0];
      img[i][j * 3 + 0] = img[i][j * 3 + 1];
      img[i][j * 3 + 1] = img[i][j * 3 + 2];
      img[i][j * 3 + 2] = tmp;
    }
  }

  // 画像の圧縮
  struct jpeg_compress_struct cinfo2;
  cinfo2.err = jpeg_std_error(&jerr);
  jpeg_create_compress(&cinfo2);
  FILE *outfile = fopen(argv[2], "wb");
  jpeg_stdio_dest(&cinfo2, outfile);

  cinfo2.image_width = width;
  cinfo2.image_height = height;
  cinfo2.input_components = 3;
  cinfo2.in_color_space = JCS_RGB;

  jpeg_set_defaults(&cinfo2);

  jpeg_start_compress(&cinfo2, TRUE);
  jpeg_write_scanlines(&cinfo2, img, width);
  jpeg_finish_compress(&cinfo2);
  jpeg_destroy_compress(&cinfo2);
  fclose(outfile);
  
  for(int i = 0; i < height; ++i){
    free(img[i]);
  }
  free(img);

  return 0;
}

とりあえず、RGB値を取り換える処理だけをしている。

%g++ -o jpeg_test jpeg_test.cpp -ljpeg
%./jpeg_test input.jpg output.jpg

結果
input.jpg output.jpg

簡単に説明。
JSAMPLEがRGBのそれぞれの値を表していて3つで一つの画素を表す。(LCS_RGBの場合)
JSAMPARRAYはJSAMPROW(JSAMPLEの配列)の配列。
画像展開後のデータをこのバッファに読み込む。

jpeg_decompress_struct 画像の展開に関する情報
jpeg_error_mgr エラー処理に関するもの
jpeg_create_decompress/jpeg_destroy_decompress 必ず対で。初期化/後始末を行う。
jpeg_stdio_src 画像の読み込み先を指定。stdio streamを使用する。
jpeg_read_header 画像のサイズなどのヘッダ情報を読み込む。
jpeg_start_decompress/jpeg_finish_decompress 展開を開始/終了。
jpeg_read_scanlines 画像をバッファに読み込む。一度では全て読み込まれないので注意

画像の圧縮についても同様。