利用libjpeg库压缩成jpg图像,采用动态内存分配 /linux/c/c++

时间:2021-12-15 11:10:57

   利用ibjpeg库进行图片的压缩,经常调用jpeg_stdio_dest(&cinfo,fp/*文件指针*/)函数。由于fp文件是在调用函数之前就分配好了的足够大的内存来存储压缩后的图像,所以经过压缩后的图像大小(单位为kb)即为fp分配的内存大小。因此就会出现分配fp的内存越大就越会浪费空间;但如果分配fp的内存不够大,就会造成压缩崩溃。

   libjpeg图片压缩,只有在压缩结束后才知道具体的内存大小。所以动态的分配内存既不会造成空间浪费,也不会造成压缩崩溃。

   libjpeg库中提供了动态分配内存的函数jpeg_mem_dest(j_compress_ptr cinfo, unsigned char** outbuffer, unsigned long* outSize)。所以在压缩的过程中将jpeg_mem_dest()替换掉jpeg_stdio_dest()就可以弥补上述缺点。

   //jpeg_mem_dest()函数参数说明:

   oubuffer:压缩后的Jpg图像,由函数返回;其内存是在jpeg_mem_dest()函数中申请的,所以压缩完之后需要释放空间,否则造成内存泄露。

   outSize:压缩后图像的字节数,由函数返回。

   注意:可能不同的libjpeg库此函数名不同,有的为jpeg_memio_dest()。在调用前请查看开源库中jdatadst.c此函数名以及具体的参数。 

   //函数调用测试:

   inRgbImg为输入图像    //像素:1600*1200   大小:5.5M

   pOutJpgImg为输出图像  //首先分配的内存为1600*1200*3  输出实际图像的像素: 1600*1200  大小: 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;
}

在这个过程中主要用到了双指针

char* pOutImage //压缩前图片的字节数
void(char** ptr) {
*ptr = (char *)malloc(Size) ; //Size为压缩后图片的字节数
}