用JpegLib壓縮YUV

此處的YUV數據指I420I422應該做一下修改也能用,這個我沒有測試。

Jpeg的寬度、和高度可以是任意的,原來在網上找的都只能是16的倍數才行。

下面的函數經過測試可用,有什麼問題可以與我聯繫 [email protected]

 

函數實現如下:

參數說明:

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;

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章