用JpegLib压缩YUV

2 篇文章 0 订阅

此处的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); 
    } 
} 

转载:
罗素实验室

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值