1

I would like to save image into memory (vector) using libjpeg library. I found there funcitons:

init_destination
empty_output_buffer 
term_destination

My question is how to do it safely and properly in parallel programs ? My function may be executed from different threads. I want to do it in c++ and Visual Studio 2010.

Other libraries with callback functionality always have additional function parameter to store some additional data. I don't see any way to add any additional parameters e.g. pointer to my local instance of vector.

Edit: The nice solution of mmy question is here: http://www.christian-etter.de/?cat=48

AdamF
  • 2,501
  • 17
  • 30
  • possible duplicate of [Write to memory buffer instead of file with libjpeg?](http://stackoverflow.com/questions/4559648/write-to-memory-buffer-instead-of-file-with-libjpeg) – nobody Oct 01 '14 at 14:48
  • I found this post, but there is used one global vector and therefore it is not safe in parallel programs. – AdamF Oct 01 '14 at 14:50
  • Did you look at the other answers? – nobody Oct 01 '14 at 14:53
  • I found nice solution here: http://www.christian-etter.de/?cat=48 – AdamF Oct 02 '14 at 10:28

1 Answers1

2

The nice solution is described here: http://www.christian-etter.de/?cat=48

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

Initialization:

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 we finished then we need to resize buffer to 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 too small then we need to increase it:

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;
}

Callbacks configuration:

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;
}

And sample usage:

jpeg_destination_mem_mgr dst_mem;
jpeg_compress_struct_wrapper cinfo;
j_compress_ptr pcinfo = cinfo;
jpeg_mem_dest( cinfo, &dst_mem);
AdamF
  • 2,501
  • 17
  • 30