此处的YUV数据指I420,I422应该做一下修改也能用,这个我没有测试。Jpeg的宽度、和高度可以是任意的,原来在网上找的都只能是16的倍数才行。
压缩流程:
<1>分配和初始化一个jpeg压缩对象。
<2>指定压缩数据保存的位置。
<3>设置压缩参数。
<4>开启一个压缩循环。
<5>逐行扫描,压缩图像。
<6>结束压缩循环
<7>释放jpeg压缩对象
函数实现如下:
参数说明:
Filename:jpg文件名字
yuvData:输入的yuv缓存地址
quality:压缩质量 1-100
image_width:图像宽度
image_height:图像高度
#include <jpeglib.h>
//#include <jpeg_mem_dest.h>
static int write_JPEG_file (const 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);
return -1;
}
jpeg_stdio_dest(&cinfo, outfile);
// 不能在jpeg_start_compress与jpeg_finish_compress之间更改数据保存的位置。
// 设置压缩对象参数,这里主要需要设置的参数有:
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 (在此为1,表示灰度图, 如果是彩色位图,则为3 );
cinfo.in_color_space = JCS_RGB; //colorspace of input image (输入图像的色阶,JCS_GRAYSCALE代表灰阶,JCS_RGB代表彩色图像);
jpeg_set_defaults(&cinfo); // 设置压缩参数;
jpeg_set_quality(&cinfo, quality, true ); //设置质量参数;质量参数(0~100)
//
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开始一个压缩循环
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压缩对象
jpeg_destroy_compress(&cinfo);
return 0;
}
调用示例:
void CNotifyItem::ProcesIntelligents(unsigned char *pBuffer, int nSize
, int nWidth, int nHeight, int nPixelFormat, int nIndex)
{
string strFile;
if (1)
{
strFile = Rosoo::RsFormat("%s/TempFile/Email/%s_%d_%d.jpg"
, g_pMainService->m_vProductInfo.m_szLogPath.c_str()
, m_strNodeKey.c_str(), m_nFileNum, nIndex);
write_JPEG_file(strFile.c_str(),pBuffer, 50, nWidth, nHeight);
}
else
{
strFile = Rosoo::RsFormat("%s/TempFile/Email/%s_%d_%d.pgm"
, g_pMainService->m_vProductInfo.m_szLogPath.c_str()
, m_strNodeKey.c_str(), m_nFileNum, nIndex);
pgmyuv_save(strFile.c_str(), nWidth, nHeight, pBuffer);
}
}
转载:
罗素实验室