3

I am using libjpeg to transform image buffer from OpenCV Mat and write it to a memory location

Here is the code:

bool mat2jpeg(cv::Mat frame, unsigned char **outbuffer
    , long unsigned int *outlen) {

    unsigned char *outdata = frame.data;

    struct jpeg_compress_struct cinfo = { 0 };
    struct jpeg_error_mgr jerr;
    JSAMPROW row_ptr[1];
    int row_stride;

    *outbuffer = NULL;
    *outlen = 0;

    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);
    jpeg_mem_dest(&cinfo, outbuffer, outlen);
    jpeg_set_quality(&cinfo, JPEG_QUALITY, TRUE);
    cinfo.image_width = frame.cols;
    cinfo.image_height = frame.rows;
    cinfo.input_components = 1;
    cinfo.in_color_space = JCS_GRAYSCALE;

    jpeg_set_defaults(&cinfo);
    jpeg_start_compress(&cinfo, TRUE);
    row_stride = frame.cols;

    while (cinfo.next_scanline < cinfo.image_height) {
        row_ptr[0] = &outdata[cinfo.next_scanline * row_stride];
        jpeg_write_scanlines(&cinfo, row_ptr, 1);
    }

    jpeg_finish_compress(&cinfo);
    jpeg_destroy_compress(&cinfo);


    return true;

}

The thing is I cannot deallocate outbuffer anywhere.

This is how I am using the function:

long unsigned int * __size__ = nullptr;

unsigned char * _buf = nullptr;

mat2jpeg(_img, &_buf, __size__);

both free(_buf) and free(*_buf) fails it seems i am trying to free the head of heap by doing so.

and mat2jpeg won't accept a pointer to pointer for outbuffer. any idea?

Galik
  • 47,303
  • 4
  • 80
  • 117
Nexus2020
  • 538
  • 6
  • 18

3 Answers3

0

I think your problem may be with your __size__ variable. Its not allocated anywhere. According to my reading of the libjpeg source code that means the buffer is never allocated and the program calls a fatal error function.

I think you need to call it like this:

long unsigned int __size__ = 0; // not a pointer

unsigned char * _buf = nullptr;

mat2jpeg(_img, &_buf, &__size__); // send address of __size__

Then you should be able to deallocate the buffer with:

free(_buf);
Galik
  • 47,303
  • 4
  • 80
  • 117
  • I have changed according to your comment. And the error persists. – Nexus2020 Sep 16 '15 at 01:23
  • I think the problem might be caused by release a memory allocated within a third party dll. So I am trying to release a memory allocated by jpeg.dll. But dll has different heap manager. I will go further to build from source to verify this. – Nexus2020 Sep 16 '15 at 07:27
  • This answer is right, also please note you can only call free(_buf) only AFTER the function jpeg_finish_compress has been called, otherwise you will get a segfault. – Étienne Aug 11 '16 at 20:16
  • This way I could not solve the issue, neither using .dll neither using .lib.. Whenever I tried to call free(_buf) keeps giving me an error.. – KronuZ Apr 06 '21 at 02:38
  • @KronuZ This answer correctly fixed a problem with the code provided in this question (sending the address of a non-allocated integer). If it doesn´t fix your code, why not post a question of your own with your specific code and your specific problem? – Galik Apr 06 '21 at 03:02
  • My code was nearly the same as in the question and did not work this solution for me.. – KronuZ Apr 16 '21 at 21:18
  • @KronuZ But this answer does fix ONE of the bugs in the code posed in THIS question. So this is a good and important answer to the question posted. – Galik Apr 16 '21 at 21:27
0

I have verified that it is the dll that caused the issue. I tried to recompiled libjpeg as static library and everything now works like a charm.

Nexus2020
  • 538
  • 6
  • 18
  • 1
    The issue here is actually a problem with libjpeg -- it seems to expect you to free the memory when it should be exposing a function for you to call to free the memory, thus resolving the issue of having it potentially allocated by one heap and freed on another – taxilian Mar 01 '17 at 22:03
0

In my case there was no way to free the memory image pointer, the only way to do that was reserving enough memory to the image, that way the library will not reserve memory for me and I have the control over the memory, the memory will be part of my own application and not library's dll or .lib:

//previous code...
struct jpeg_compress_struct cinfo;

//reserving the enough memory for my image (width * height)
unsigned char* _image = (unsigned char*)malloc(Width * Height);

//putting the reserved size into _imageSize
_imageSize = Width * Height;

//call the function like this:
jpeg_mem_dest(&cinfo, &_image, &_imageSize);
................
//releasing the reserved memory
free(_image);

NOTE: if you put _imageSize = 0, the library will assume that you have not reserve memory and the own library will do it.. so you need to put in _imageSize the amount of bytes reserved in _image

That way you have total control over the reserved memory and you can release it whenever you want in your software..

KronuZ
  • 378
  • 2
  • 13