沧海一粟

修身养性,立志长远

yuv420存储为JPG

最近在做yuv存储为Jpg,这个涉及到jpg的编码压缩,是非常耗性能的,我们目前多用于手机上,在IOS上是通过将yuv 420转为rgb565->rgb8888然后通过oc提供的函数存储为jpg,整个比较繁琐,具体没有去关注性能,一直这么用着。android上面我们是直接转rgb存储为bmp,图片较大。

所以想搞成统一的,网上都说libjpeg-turbo性能高于libjpeg,他们的网站也是这么写的,当然我没有去比较。我移植到windows下是可以使用的。


网上有一段纯代码的yuv存jpg可以下载,通过“yuv2jpg 纯代码”可以搜索到,其中要注意stride为height+0x20,而且数据必须是ffmpeg解码后的data[0-2],如果你自己通过avpicture_fill转换了,或者自己转换了都是不会正常的,存储后的图片会只有一部分内容。


下面给出一段libjpeg-turbo Windows下编译的要点,这段文字是从http://blog.csdn.net/fengbingchun/article/details/10171583摘得。

编译libjpeg-turbo:

1、  从https://sourceforge.net/projects/libjpeg-turbo/通过TortoiseSVN下载libjpeg-turbo最新源代码,将其保存到D:\soft\libjpeg-turbo文件夹下;

2、  从http://www.cmake.org/下载最新版的CMake,并安装;

3、  在D:\soft\libjpeg-turbo文件夹下手动创建一个vs2010文件夹;

4、  打开CMake,其中where isthe source code选项,选择D:/soft/libjpeg-turbo/libjpeg-turbo;where to build thebinaries选项,选择D:/soft/libjpeg-turbo/vs2010;

5、  点击Configure,在弹出的对话框中选择VisualStudio 10,其它默认,点击Finish;

6、  如果有红色框显示,继续点击Configure(将CMAKE_INSTALL_PREFIX中的value改为D:\libjpeg-turbo);

7、  点击Generate,此时会在vs2010文件夹中看到libjpeg-turbo.sln文件;

8、  从https://sourceforge.net/projects/nasm/下载最新版的nasm;

9、  将nasm安装到D:\ProgramFiles\NASM文件夹下,并将其中的nasm.exe和ndisasm.exe两个文件拷贝到C:\ProgramFiles\Microsoft Visual Studio 10.0\VC\bin下(如果是64位,则拷贝到C:\ProgramFiles (x86)\Microsoft Visual Studio 10.0\VC\bin),将其D:\ProgramFiles\NASM添加到系统环境变量中;

10、             打开libjpeg-turbo.sln,分别在Debug和Release下,选择Solution Explorer里的Solution libjpeg-turbo,点击右键,运行”Rebuild Solution”,然后选中INSTALL, build;

11、             全部完成后会在D:\libjpeg-turbo文件夹下生成bin、doc、lib、include四个文件夹,编译成功(说明:默认的Debgu和Release下生成的所有文件夹都相同,注意区分);

12、             打开vs2010,新建一个控制台应用程序,为vs2010配置libjpeg-turbo环境:选择View--> Properties Manager-->分别选中Debug和Release上的Microsoft.Cpp.Win32.user,点击右键-->Properties:VC++ Directories,Include Directories:D:\libjpeg-turbo\include;Library Directories:D:\libjpeg-turbo\lib;

13、             选中工程-->Properties-->Configuration Properties-->Linker-->Input-->AdditionalDependencies:Debug和Release,添加相应的.lib库;

14、             将D:\libjpeg-turbo\bin加入到windows系统环境变量Path中,重启。

写jpg文件函数:

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;
}

Android/iOS的后续再补充!
阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/andrew57/article/details/45603063
个人分类: 流媒体
想对作者说点什么? 我来说一句

yuv420数据保存为bmp图片

2013年03月18日 1KB 下载

ffmpeg完成YUV到jpeg转换

baidu_26352053 baidu_26352053

2017-08-03 17:34:26

阅读数:426

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭