Custom Memory Destination Manager for libjpeg

Similar to creating an in memory source manager for libjpeg decompression, we can also create a destination manager which will store the compressed data in memory.
FOr this purpose, the destination manager contains a byte vector:

typedef struct _jpeg_destination_mem_mgr
{
    jpeg_destination_mgr mgr;
    std::vector<unsigned char> data;
} jpeg_destination_mem_mgr;

Initialization takes place in the callback mem_init_destination():

static void mem_init_destination( j_compress_ptr cinfo )
{
    jpeg_destination_mem_mgr* dst = (jpeg_destination_mem_mgr*)cinfo->dest;
    dst->data.resize( JPEG_MEM_DST_MGR_BUFFER_SIZE );
    cinfo->dest->next_output_byte = dst->data.data();
    cinfo->dest->free_in_buffer = dst->data.size();
}

When the compression has finished, we need to resize the buffer to the actual size:

static void mem_term_destination( j_compress_ptr cinfo )
{
    jpeg_destination_mem_mgr* dst = (jpeg_destination_mem_mgr*)cinfo->dest;
    dst->data.resize( dst->data.size() - cinfo->dest->free_in_buffer );
}

When the buffer size is not large enough, the library requests more data in the following callback:

static boolean mem_empty_output_buffer( j_compress_ptr cinfo )
{
    jpeg_destination_mem_mgr* dst = (jpeg_destination_mem_mgr*)cinfo->dest;
    size_t oldsize = dst->data.size();
    dst->data.resize( oldsize + JPEG_MEM_DST_MGR_BUFFER_SIZE );
    cinfo->dest->next_output_byte = dst->data.data() + oldsize;
    cinfo->dest->free_in_buffer = JPEG_MEM_DST_MGR_BUFFER_SIZE;
    return true;
}

All callbacks are configured in jpeg_mem_dest():

static void jpeg_mem_dest( j_compress_ptr cinfo, jpeg_destination_mem_mgr * dst )
{
    cinfo->dest = (jpeg_destination_mgr*)dst;
    cinfo->dest->init_destination = mem_init_destination;
    cinfo->dest->term_destination = mem_term_destination;
    cinfo->dest->empty_output_buffer = mem_empty_output_buffer;
}

Usage:

jpeg_destination_mem_mgr dst_mem;
jpeg_compress_struct_wrapper cinfo;
j_compress_ptr pcinfo = cinfo;
jpeg_mem_dest( cinfo, &dst_mem);

After encoding has finished, data can be retrieved from the data member of the destination manager.

unsigned char * pjpeg_data = dst_mem.data.data();
size_t data_size = dst_mem.data.size();

Here is a link to the entire code: jpeg_mem_dst.h

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.