libjpegでメモリーへ書き出し (jpeg_memory_dest for IJG libjpeg)

仕事で必要がありIJGのlibjpegを漁ってみたところ、基本的にstdio経由の入出力しか実装されていないことが判明しげんなり。
libjpeg.docに簡単な説明があるものの、参考になるコードがあまり見つからずどん詰まりしていたところで、
http://blog.so-net.ne.jp/yarimit/archive/c105332
こちらの記事を発見。
大変参考になりました。m(_ _)m

ってことで、後はメモリーへの出力部分が問題に。

仕方がないので、ちゃっちゃっと作りました。
まぁ、libjpeg.docに言われるがまま必要項目を満たしていったら動きました。
Source&Destinationマネージャーの構造と動きを理解して、後は関数へのポインターを理解していれば特に難しいところはないはずです。

METHODDEF(void) memory_init_destination (j_compress_ptr cinfo){
memory_dst_ptr dest;
dest = (memory_dst_ptr)cinfo->dest;
dest->pub.free_in_buffer = dest->buffer_length;
dest->pub.next_output_byte = dest->buffer;

}

METHODDEF(boolean) memory_empty_output_buffer (j_compress_ptr cinfo){
return TRUE;
}

METHODDEF(void) memory_term_destination (j_compress_ptr cinfo){

}

GLOBAL(void) jpeg_memory_dest (j_compress_ptr cinfo, void* data, unsigned long len){
memory_dst_ptr dest;

if (cinfo->dest == NULL) {/* first time for this JPEG object? */
cinfo->dest = (struct jpeg_destination_mgr *)
(*cinfo->mem->alloc_small) *1;
}

dest = (memory_dst_ptr) cinfo->dest;
dest->pub.init_destination = memory_init_destination;
dest->pub.empty_output_buffer = memory_empty_output_buffer;
dest->pub.term_destination = memory_term_destination;
dest->buffer = data;
dest->buffer_length = len;
}

これをjpeg_stdio_destの代わりにjpeg_memory_dest(cinfo, 出力バッファーへのポインター, 出力バッファーのサイズ)のように呼んでください。
なお、当然ですが出力バッファーはデータを書き出すのに必要十分確保して渡してください。

圧縮後にこのDestination mgrを使用した場合、引数に指定した出力バッファーのサイズからcinfo.dest->free_in_bufferを引くことによってヘッダーを含めた(本来ファイルにかかれるはずだった)圧縮後のデータのサイズが分かります。

*1:j_common_ptr) cinfo, JPOOL_PERMANENT, SIZEOF(memory_destination_mgr