2010年10月02日

libjpegのインストール



「libpngのインストール」で解説したlibpngと同じようにオープンソースが入手できる、「Independent JPEG Group」というサイトで公開されているJPEGのフリーライブラリーについて解説します。


JPEGライブラリーのインストール

まずは「Independent JPEG Groupのホームページ」からJPEGライブラリーのソースコードをダウンロードしてください。



ホームページの文中で青色で選択された「jpegsr8b.zip.」をクリックすると、「jpegsr8b.zip」というファイルが自動でダウンロードされます。
ダウンロードした「jpegsr8b.zip」ファイルを所定のフォルダー内にWinRAR等を使って解凍すると、「jpeg-8b」と言う名のフォルダーが展開されます。



次に「VisualC++net2003」を起動し、「ファイル」/「新規」/「プロジェクト」を選択して、「新規プロジェクト」ダイヤログを表示させます。「Win32 プロジェクト」テンプレートを選択し、プロジェクト名を「libjpeg」と記入し、プロジェクトのロケーションは先ほど「jpeg-8b」フォルダーを展開したフォルダーに新しいプロジェクトを作成します。



「OK」ボタンを押すと「Win32アプリケーションウィザード」ダイヤログが表示されるので、「アプリケーションの設定」で「アプリケーションタイプ」は「スタティックライブラリー」を選択し、「追加サポート」の「MFC」にチェックを入れて、「追加オプション」の「プリコンパイルヘッダー」のチェックを外します。「完了」ボタンを押すと所定の位置に「libjpeg」フォルダーが作成されます。



「jpeg-8b」フォルダー内の「jconfig.vc」ファイルの拡張子を「.vc」から「.h」に変更します。



続いてソリューションエクスプローラにおいて、「libjpeg」上でマウスボタンを右クリックしてポップアップメニューを表示させ、「追加」/「既存アイテムの追加」を選択します。「既存アイテムの追加」ダイヤログが表示されるので、「jpeg-8b」フォルダー内のC言語のソースファイルとヘッダーファイルを「Ctrl+A」ですべて選択して、「libjpeg」プロジェクトに追加します。



「libjpeg」プロジェクトに追加したファイルの中から不要なファイルを削除します。ソリューションエクスプローラで「libjpeg」プロジェクトにあるファイル名をマウスの右クリックで選択してから、ポップアップメニュを表示させ「削除」で削除します。

削除するファイル

jmemdos.c jmemmac.c jmemdosa.asm example.c ansi2knr.c
jmemname.c jmemansi.c wrjpgcom.c rdjpgcom.c djpeg.c
ckconfig.c cjpeg.c jpegtran.c cdjpeg.c rdbmp.c
rdcolmap.c rdgif.c rdppm.c rdrle.c rdswitch.c
rdtarga.c transupp.c wrbmp.c wrgif.c wrppm.c
wrrle.c wrtarga.c



このままではCFileクラスを使用してファイルやメモリーにアクセスしたりすることが出来ないので、ソースコードに若干手を加えていきます。

まずは「jpeglib.h」の一番最後の行の「#endif /* JPEGLIB_H */」の直前に、赤字の行コードをコピー(Ctrl+C)/ペースト(Ctrl+V)で追加してください。

#ifdef __cplusplus
#ifndef DONT_USE_EXTERN_C
}
#endif
#endif

//ユーザー定義のファイル読み込み関数を呼び出すために追加
typedef unsigned int (__cdecl *jpeg_rw_ptr)(void* io_ptr, unsigned char* buf, unsigned int size);
typedef void (__cdecl *jpeg_flush_ptr)(void* io_ptr);
//ユーザー定義読み込み関数の定義
EXTERN(void)
jpeg_set_read_fn(j_decompress_ptr cinfo, void* io_ptr, jpeg_rw_ptr read_data_fn);
//ユーザー定義書き込み関数の定義
EXTERN(void)
jpeg_set_write_fn(j_compress_ptr cinfo, void* io_ptr, jpeg_rw_ptr write_data_fn,
jpeg_flush_ptr flush_data_fn);


#endif /* JPEGLIB_H */



次に「jdatasrc.c」では追加する箇所が三箇所あります。

「my_source_mgr」構造体の要素に、以下の赤字の行を追加して下さい。

/* Expanded data source object for stdio input */

typedef struct {
struct jpeg_source_mgr pub; /* public fields */

FILE * infile;
/* source stream */
JOCTET * buffer;
/* start of buffer */
boolean start_of_file;
/* have we gotten any data yet? */

//ユーザー定義読み込み関数て使用するクラスへのポインタ
void* io_ptr;
//ユーザー定義の読み込み関数へのポインタ
jpeg_rw_ptr read_data_fn;


} my_source_mgr;


「fill_input_buffer」関数のファイル読み込みマクロの行をコメントアウトし、その直ぐ下に赤字で示した行コードを追加してください。

METHODDEF(boolean)
fill_input_buffer (j_decompress_ptr cinfo)
{
my_src_ptr src = (my_src_ptr) cinfo->src;
size_t nbytes;

// nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE);←コメントアウトしてください
// infileがNULLならユーザー定義関数から読み込む
if (src->infile) nbytes = JFREAD(src->infile, src->buffer, INPUT_BUF_SIZE);
else nbytes=((*(src->read_data_fn))(src->io_ptr,src->buffer,INPUT_BUF_SIZE));


if (nbytes <= 0) {
if (src->start_of_file) /* Treat empty input file as fatal error */
ERREXIT(cinfo, JERR_INPUT_EMPTY);
WARNMS(cinfo, JWRN_JPEG_EOF);
/* Insert a fake EOI marker */
src->buffer[0] = (JOCTET) 0xFF;
src->buffer[1] = (JOCTET) JPEG_EOI;
nbytes = 2;
}

src->pub.next_input_byte = src->buffer;
src->pub.bytes_in_buffer = nbytes;
src->start_of_file = FALSE;

return TRUE;
}


ユーザー定義の読み込み関数を登録する「jpeg_set_read_fn」関数を、一番最後の行のあとに追加してください。


//ユーザー定義読み込み関数の登録
GLOBAL(void)
jpeg_set_read_fn(j_decompress_ptr cinfo, void* io_ptr, jpeg_rw_ptr read_data_fn)
{
my_src_ptr src;

/* The source object and input buffer are made permanent so that a series
* of JPEG images can be read from the same file by calling jpeg_stdio_src
* only before the first one. (If we discarded the buffer at the end of
* one image, we'd likely lose the start of the next one.)
* This makes it unsafe to use this manager and a different source
* manager serially with the same JPEG object. Caveat programmer.
*/
if (cinfo->src == NULL) { /* first time for this JPEG object? */
cinfo->src = (struct jpeg_source_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
SIZEOF(my_source_mgr));
src = (my_src_ptr) cinfo->src;
src->buffer = (JOCTET *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
INPUT_BUF_SIZE * SIZEOF(JOCTET));
}

src = (my_src_ptr) cinfo->src;
src->pub.init_source = init_source;
src->pub.fill_input_buffer = fill_input_buffer;
src->pub.skip_input_data = skip_input_data;
src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
src->pub.term_source = term_source;
src->infile = NULL;//infile;
src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
src->pub.next_input_byte = NULL; /* until buffer loaded */
src->io_ptr=io_ptr; //ユーザー定義のクラスインスタンスへのポインタあるいはファイルハンドル
src->read_data_fn=read_data_fn;//ユーザー定義のファイル読み込み関数へのポインタ
}



最後に「jdatadst.c」では、追加する箇所が四箇所あります。

「my_destination_mgr」構造体の要素に、以下の赤字の行を追加して下さい。

/* Expanded data destination object for stdio output */

typedef struct {
struct jpeg_destination_mgr pub; /* public fields */

FILE * outfile; /* target stream */
JOCTET * buffer; /* start of buffer */

//ユーザー定義書き込み関数て使用するクラスへのポインタ
void* io_ptr;
//ユーザー定義の書き込み関数へのポインタ
jpeg_rw_ptr write_data_fn;
//ユーザー定義のフラッシュ関数へのポインタ
jpeg_flush_ptr flush_data_fn;


} my_destination_mgr;


「empty_output_buffer」関数のファイル書き出しマクロの行をコメントアウトし、その直ぐ下に赤字で示した行コードを追加してください。

METHODDEF(boolean)
empty_output_buffer (j_compress_ptr cinfo)
{
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;

/* if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE) != ←コメントアウトして下さい。
(size_t) OUTPUT_BUF_SIZE) ←コメントアウトして下さい。
ERREXIT(cinfo, JERR_FILE_WRITE);*/ ←コメントアウトして下さい。

//outfileがNULLならユーザー定義関数から書き出す
if (dest->outfile){
if (JFWRITE(dest->outfile, dest->buffer, OUTPUT_BUF_SIZE)!=(size_t)OUTPUT_BUF_SIZE)
ERREXIT(cinfo, JERR_FILE_WRITE);
}
else{
if (((*(dest->write_data_fn))(dest->io_ptr,dest->buffer,OUTPUT_BUF_SIZE))!=
(size_t)OUTPUT_BUF_SIZE)
ERREXIT(cinfo, JERR_FILE_WRITE);
}


dest->pub.next_output_byte = dest->buffer;
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;

return TRUE;
}


「term_destination」関数のファイル書き出しマクロの行をコメントアウトし、その直ぐ下に赤字で示した行コードを追加してください。

METHODDEF(void)
term_destination (j_compress_ptr cinfo)
{
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;

/* Write any data remaining in the buffer */
/*if (datacount > 0) { ←コメントアウトしてください
if (JFWRITE(dest->outfile, dest->buffer, datacount)!=datacount)←コメントアウトしてください。
ERREXIT(cinfo, JERR_FILE_WRITE); ←コメントアウトしてください。
} ←コメントアウトしてください。
fflush(dest->outfile);*/ ←コメントアウトしてください

//outfileがNULLならユーザー定義関数から書き出す
if (dest->outfile){
if (JFWRITE(dest->outfile, dest->buffer, datacount)!=datacount)
ERREXIT(cinfo, JERR_FILE_WRITE);
fflush(dest->outfile);
}
else {
if (((*(dest->write_data_fn))(dest->io_ptr,dest->buffer,(unsigned int)datacount))!=datacount)
ERREXIT(cinfo, JERR_FILE_WRITE);
(*(dest->flush_data_fn))(dest->io_ptr);
return;
}


/* Make sure we wrote the output file OK */
if (ferror(dest->outfile))
ERREXIT(cinfo, JERR_FILE_WRITE);
}


ユーザー定義の書き込み関数とフラッシュ関数を登録する「jpeg_set_write_fn」関数を、一番最後の行のあとに追加してください。

//ユーザー定義書き込み関数とフラッシュ関数の登録
GLOBAL(void)
jpeg_set_write_fn(j_compress_ptr cinfo, void* io_ptr, jpeg_rw_ptr write_data_fn,jpeg_flush_ptr flush_data_fn)
{
my_dest_ptr dest;

/* The destination object is made permanent so that multiple JPEG images
* can be written to the same file without re-executing jpeg_stdio_dest.
* This makes it dangerous to use this manager and a different destination
* manager serially with the same JPEG object, because their private object
* sizes may be different. Caveat programmer.
*/
if (cinfo->dest == NULL) { /* first time for this JPEG object? */
cinfo->dest = (struct jpeg_destination_mgr *)
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
SIZEOF(my_destination_mgr));
}

dest = (my_dest_ptr) cinfo->dest;
dest->pub.init_destination = init_destination;
dest->pub.empty_output_buffer = empty_output_buffer;
dest->pub.term_destination = term_destination;
dest->outfile = NULL;//outfile;
dest->io_ptr=io_ptr; //ユーザー定義のクラスインスタンスへのポインタあるいはファイルハンドル
dest->write_data_fn=write_data_fn;//ユーザー定義のファイル読み込み関数へのポインタ
dest->flush_data_fn=flush_data_fn;//ユーザー定義のファイルフラッシュ関数へのポインタ
}



最後にビルドしてエラーが出なければ成功です。






posted by ひろし at 11:35| Comment(0) | JPEGファイルフォーマット | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。