Chinaunix首页 | 论坛 | 博客
  • 博客访问: 168655
  • 博文数量: 27
  • 博客积分: 533
  • 博客等级: 中士
  • 技术积分: 426
  • 用 户 组: 普通用户
  • 注册时间: 2011-12-14 19:54
文章分类

全部博文(27)

文章存档

2013年(4)

2012年(18)

2011年(5)

分类: LINUX

2011-12-27 10:03:38

此处的YUV数据指I420I422应该做一下修改也能用,这个我没有测试。

Jpeg的宽度、和高度可以是任意的,原来在网上找的都只能是16的倍数才行。

下面的函数经过测试可用,有什么问题可以与我联系

 

函数实现如下:

参数说明:

Filenamejpg文件名字

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;

}

阅读(6469) | 评论(1) | 转发(2) |
给主人留下些什么吧!~~

youzpp2014-10-09 11:03:35

可以用,不过当高度不是16倍数的时候,yuvData数据长度似乎要比image_width*image_height*3/2大一点才行