libjpeg與turbo libjpeg的使用

LibJpeg作爲常用開源庫,已有很多相關介紹。

其中值得一提的是,早先的版本里沒有對內存中的Jpeg圖像編解碼的接口,而是使用Jpeg_stdio_src和jpeg_stdio_dest,這兩個都是直接針對File類對象操作,跳過了內存中圖像的這一步。有些文章介紹過如何在LibJpeg中添加針對內存圖像的解碼接口,但是沒有人添加過內存圖像的編碼接口。我直接把原有的jpeg_stdio_dest覆蓋成對內存中RGB圖像的編碼接口,輸出爲內存中的jpeg圖像。

頭文件和靜態庫已上傳到CSDN資源庫中,源碼也已經上傳,(添加對內存中Jpeg圖像編解碼接口的LibJpeg)可以自行編譯使用。

不過後來的turbo libjpeg將此問題解決了(上面上傳的代碼價值也就不大了),我沒有去看是不是新版本的LibJpeg也已經完善了這個問題。

turbo libjpeg的價值是利用SIMD指令集,加速了編解碼過程。官網上的介紹中提到某個案例中從原來的0.3左右降低到0.1,時間只有原來的1/3,在我的工程中,時間減少到原來LibJpeg的一半左右。而它的使用與之前的LibJpeg完全相同,只是添加完善了部分功能,完全可以直接替換,使用很方便。

下面的代碼既是使用LibJpeg做編解碼的方法,也是Turbo LibJpeg的使用方法(區別僅僅在於jpeg_mem_src和jpeg_mem_dst的使用):

值得注意的是,解碼的時候空間是由內部分配的,因爲這樣能夠準確分配內存空間,而不會造成浪費;

但是編碼的時候空間需要由外部分配,因爲準確的編碼後的空間大小不能獲知,當然完全可以分配一段和編碼前一樣大小的空間,這肯定是足夠的了,並且也不會造成太大的空間浪費。

turbo libjpeg可以在官網上去下載,目前的最新版本是1.3.1.


typedef unsigned char BYTE;
bool ReadJPEG( 
			  /*IN*/BYTE *src, int srcLen, 
			  /*OUT*/BYTE **_dst, int *dstLen, int *width, int *height, int *depth 
			  )
{
	// 【注意】dst空間由內部分配
	//定義JPEG文件的解壓信息
	struct jpeg_decompress_struct cinfo;

	//定義JPEG文件的錯誤信息
	struct jpeg_error_mgr jerr;

	cinfo.err=jpeg_std_error(&jerr);
	jpeg_create_decompress(&cinfo);

	jpeg_mem_src(&cinfo,src,srcLen);
	jpeg_read_header(&cinfo,TRUE);

	jpeg_start_decompress(&cinfo);
	(*width) = cinfo.output_width;
	(*height) = cinfo.output_height;
	(*depth) = cinfo.num_components;
	(*dstLen) = (*width)*(*height)*(*depth);
	BYTE *dst = new BYTE[*dstLen];

	JSAMPROW row_pointer[1];

	while (cinfo.output_scanline<cinfo.output_height)
	{
		row_pointer[0] = &dst[cinfo.output_scanline*cinfo.image_width*cinfo.num_components];
		jpeg_read_scanlines(&cinfo,row_pointer,1);
	}
	jpeg_finish_decompress(&cinfo);
	jpeg_destroy_decompress(&cinfo);
	*_dst = dst;

	return true;
}

bool WriteJPEG(
			   /*IN*/BYTE *src, int width, int height, int depth, 
			   /*OUT*/BYTE **dst, int *dstLen
			   )
{
	// 【注意】dst空間由外部分配,確保空間足夠
	unsigned long act_len = 0;
	struct jpeg_compress_struct jcs;
	struct jpeg_error_mgr jem;
	jcs.err = jpeg_std_error(&jem);

	jpeg_create_compress(&jcs);
	jpeg_mem_dest(&jcs, dst, &act_len);
	jcs.image_width = width;
	jcs.image_height = height;
	jcs.input_components = depth;
	jcs.in_color_space = JCS_RGB;

	jpeg_set_defaults(&jcs);
	jpeg_set_quality(&jcs,80,true);

	jcs.jpeg_color_space = JCS_YCbCr;
	jcs.comp_info[0].h_samp_factor = 2;
	jcs.comp_info[0].v_samp_factor = 2;

	jpeg_start_compress(&jcs,TRUE);
	JSAMPROW row_pointer[1];
	int row_stride = jcs.image_width*jcs.num_components;
	while (jcs.next_scanline<jcs.image_height)
	{
		row_pointer[0] =  &src[jcs.next_scanline*row_stride];
		jpeg_write_scanlines(&jcs,row_pointer,1);
	}
    jpeg_finish_compress(&jcs);
	jpeg_destroy_compress(&jcs);

	*dstLen = act_len;
	return true;
}


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