Image compression using the ibjpeg library often calls the pai_stdio_dest (& Cinfo, FP/* file pointer */) function. Since the FP file is allocated enough memory to store the compressed image before calling the function, the size of the compressed image (unit: KB) memory size allocated for FP. Therefore, the larger the memory allocated to FP is, the more space will be wasted. However, if the memory allocated to FP is not large enough, the compression will crash.
Libjpeg image compression: the memory size is only known after compression. Therefore, dynamic memory allocation does not cause space waste or compression crashes.
The libjpeg Library provides the function of dynamically allocating memory: performance_mem_dest (j_compress_ptr Cinfo, unsigned char ** outbuffer, unsigned long * outsize ). Therefore, replace pai_mem_dest () with pai_stdio_dest () in the compression process to make up for the above shortcomings.
// Parameter description of the performance_mem_dest () function:
Oubuffer: the Compressed JPG image, which is returned by the function. Its memory is applied in the pai_mem_dest () function. Therefore, space must be released after compression. Otherwise, memory leakage may occur.
Outsize: the number of bytes of the compressed image, which is returned by the function.
Note: Different libjpeg libraries may have different function names, some of which are pai_memio_dest (). Before calling jdatadst. C, check the function name and specific parameters in the open-source library.
// Function call test:
Inrgbimg is the input image // pixel: 1600*1200 size: 5.5 m
Poutjpgimg is the output image // The first allocated memory is 1600*1200*3 pixels of the actual output image: 1600*1200 size: 290kb
int quality = 90; struct jpeg_compress_struct cinfoDecodec; struct jpeg_error_mgr jerr; unsigned char* inImageBuffer; unsigned char* outbuffer; outbuffer = NULL; JSAMPROW row_pointer[1]; int row_stride; unsigned long outSize = 0; inImageBuffer = inRgbImg.bufferPtr; JSAMPROW row_pointer[1]; int row_stride; unsigned long outSize = 0; inImageBuffer = inRgbImg.bufferPtr; cinfoDecodec.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfoDecodec); jpeg_mem_dest (&cinfoDecodec, &outbuffer, &outSize); cinfoDecodec.image_width = inRgbImg.width; cinfoDecodec.image_height = inRgbImg.height; cinfoDecodec.input_components = 3; cinfoDecodec.in_color_space = JCS_RGB; jpeg_set_defaults(&cinfoDecodec); jpeg_set_quality(&cinfoDecodec, quality, true); jpeg_start_compress(&cinfoDecodec, TRUE); row_stride = inRgbImg.width * 3; while (cinfoDecodec.next_scanline < cinfoDecodec.image_height) { row_pointer[0] = & inImageBuffer[cinfoDecodec.next_scanline * row_stride]; (void) jpeg_write_scanlines(&cinfoDecodec, row_pointer, 1); } jpeg_finish_compress(&cinfoDecodec); for(int i = 0; i < outSize; i++) { (*pOutJpgImg).bufferPtr[i] = outbuffer[i]; } (*pOutJpgImg).bufferSize = outSize; jpeg_destroy_compress(&cinfoDecodec); if(NULL != outbuffer) { free(outbuffer); outbuffer = NULL; }
In this process, we mainly use double pointers.
Char * poutimage // number of bytes of the image before compression
Void (char ** PTR ){
* PTR = (char *) malloc (size); // size indicates the number of bytes of the compressed image.
}