此处的YUV数据指I420,I422应该做一下修改也能用,这个我没有测试。
Jpeg的宽度、和高度可以是任意的,原来在网上找的都只能是16的倍数才行。
下面的函数经过测试可用,有什么问题可以与我联系 [email protected]
函数实现如下:
参数说明:
Filename:jpg文件名字
yuvData:输入的yuv缓存地址
quality:压缩质量 1-100
image_width:图像宽度
image_height:图像高度
int write_JPEG_file (char * filename, unsigned char* yuvData, int quality,int image_width,int image_height)
{
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
FILE * outfile; // target file
JSAMPROW row_pointer[1]; // pointer to JSAMPLE row[s]
int row_stride; // physical row width in image buffer
JSAMPIMAGE buffer;
unsigned char *pSrc,*pDst;
int band,i,buf_width[3],buf_height[3];
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
if ((outfile = fopen(filename, "wb")) == NULL) {
fprintf(stderr, "can't open %s/n", filename);
exit(1);
}
jpeg_stdio_dest(&cinfo, outfile);
cinfo.image_width = image_width; // image width and height, in pixels
cinfo.image_height = image_height;
cinfo.input_components = 3; // # of color components per pixel
cinfo.in_color_space = JCS_RGB; //colorspace of input image
jpeg_set_defaults(&cinfo);
jpeg_set_quality(&cinfo, quality, TRUE );
//////////////////////////////
cinfo.raw_data_in = TRUE;
cinfo.jpeg_color_space = JCS_YCbCr;
cinfo.comp_info[0].h_samp_factor = 2;
cinfo.comp_info[0].v_samp_factor = 2;
/////////////////////////
jpeg_start_compress(&cinfo, TRUE);
buffer = (JSAMPIMAGE) (*cinfo.mem->alloc_small) ((j_common_ptr) &cinfo,
JPOOL_IMAGE, 3 * sizeof(JSAMPARRAY));
for(band=0; band <3; band++)
{
buf_width[band] = cinfo.comp_info[band].width_in_blocks * DCTSIZE;
buf_height[band] = cinfo.comp_info[band].v_samp_factor * DCTSIZE;
buffer[band] = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo,
JPOOL_IMAGE, buf_width[band], buf_height[band]);
}
unsigned char *rawData[3];
rawData[0]=yuvData;
rawData[1]=yuvData+image_width*image_height;
rawData[2]=yuvData+image_width*image_height*5/4;
int src_width[3],src_height[3];
for(int i=0;i<3;i++)
{
src_width[i]=(i==0)?image_width:image_width/2;
src_height[i]=(i==0)?image_height:image_height/2;
}
//max_line一般为16,外循环每次处理16行数据。
int max_line = cinfo.max_v_samp_factor*DCTSIZE;
for(int counter=0; cinfo.next_scanline < cinfo.image_height; counter++)
{
//buffer image copy.
for(band=0; band <3; band++) //每个分量分别处理
{
int mem_size = src_width[band];//buf_width[band];
pDst = (unsigned char *) buffer[band][0];
pSrc = (unsigned char *) rawData[band] + counter*buf_height[band] * src_width[band];//buf_width[band]; //yuv.data[band]分别表示YUV起始地址
for(i=0; i <buf_height[band]; i++) //处理每行数据
{
memcpy(pDst, pSrc, mem_size);
pSrc += src_width[band];//buf_width[band];
pDst += buf_width[band];
}
}
jpeg_write_raw_data(&cinfo, buffer, max_line);
}
jpeg_finish_compress(&cinfo);
fclose(outfile);
jpeg_destroy_compress(&cinfo);
return 0;
}