jpeg 文件转换成yuv

   某天接到个任务,要求读取jpeg文件转换成YUV格式,因为从来没有过这样的经历,第一反应上GOOGLE。

   刚开始的做法是直接读取jpeg文件读取RGB,然后直接RGB转换成YUV。 但后来同事说jpeg文件本事就是YUV颜色编码,可以直接读取成YUV。于是乎又要开始新的搜索了。

    刚开始搜索接触到了jpeglib这个库,大概了解了下jpeglib库和jpeg文件的格式。刚开始直接读取但是发现读取之后的yuv并不能显示出来,是不是哪里弄错了?后来搜索到别人的代码才似乎了解应该怎么去读数据(参考:jpeg_read_raw_data) 。代码如下:


  

#pragma warning(disable: 4786)
#include <vector>
typedef std::vector<unsigned char> buffer;

#define NEW_BUFFER(param, len)  if(NULL != param) \
{delete param;param = new BYTE[len];}\
else{param = new BYTE[len];}

#define DELETE_BUFFER(param)  if (NULL != m_pUbuffer)\
{	delete param;	param = NULL;	}
			

class CDecompressor 
{
public:  
    
	CDecompressor()  : yuvbuf_(3) 
	{         
		info_.err = jpeg_std_error(&e_);         
		jpeg_create_decompress(&info_); 
		
		m_pYbuffer = NULL;
		m_pUbuffer= NULL;
		m_pVbuffer = NULL;
		
		for (int i = 0; i < 3; ++i)
		{
			yuvptr_[i] = NULL;
		}
		
	}   
	
	virtual ~CDecompressor()     
	{        
		jpeg_destroy_decompress(&info_); 

		DELETE_BUFFER(m_pYbuffer);
		DELETE_BUFFER(m_pUbuffer);
		DELETE_BUFFER(m_pVbuffer);
	
	}   


	virtual void DecodeJpeg(unsigned char* pBuffer, int nSize)
	{

		jpeg_mem_src(&info_, pBuffer, nSize);    指定图片在内存的地址及大小

		jpeg_read_header(&info_, 1);          
		info_.raw_data_out = 1;          
		jpeg_start_decompress(&info_);  

		for (int i = 0; i < 3; ++i)
		{
			yuvbuf_[i].resize(info_.output_width); 
			yuvptr_[i] = &yuvbuf_[i][0]; 		
		}

		int nLen = info_.output_width * info_.output_height;

		NEW_BUFFER(m_pYbuffer, nLen);
		NEW_BUFFER(m_pUbuffer, nLen);
		NEW_BUFFER(m_pVbuffer, nLen);

		unsigned char* row = m_pYbuffer;
		yuvptr_[0][0] = row;
		for ( i = 0; i < info_.output_height; ++i, row += info_.output_width)         
		{            
			yuvptr_[0][i] = row;      //y 分量空间初始化   
		} 
        
		row = m_pUbuffer;	
		for (i = 0; i < info_.output_height; i += 2, row += info_.output_width / 2)         
		{            
			yuvptr_[1][i / 2] = row;      //u 分量初始化
			
		} 
		
		row = m_pVbuffer;  
		for ( i = 0; i < info_.output_height; i += 2, row += info_.output_width / 2)        
		{            
			yuvptr_[2][i / 2] = row;         
		}   
		
		for ( i = 0; i < info_.output_height; i += 16)        
		{            
			int nRows = 16;
			if((info_.output_height) < (i + 16))
			{
				nRows = info_.output_height - i;
			}
			jpeg_read_raw_data(&info_, yuvptr_, nRows);              
			yuvptr_[0] += 16;            
			yuvptr_[1] += 8;            
			yuvptr_[2] += 8;         
		}		
		jpeg_finish_decompress(&info_);   
	
	}


	virtual void GetYUVData(unsigned char* &pYData,  unsigned char* &pUData, unsigned char* &pVData, 
						int &nHeight, int &nWidth)
	{
		nWidth = info_.output_width ;           
		nHeight = info_.output_height;
		int nLen1 = info_.output_height * info_.output_width;	

		pYData = m_pYbuffer;
		pUData = m_pUbuffer;
		pVData = m_pVbuffer;

		return ;

	}
protected:     
	jpeg_decompress_struct info_;     
	jpeg_error_mgr e_;     
//	buffer& ibuf_;      
	std::vector< std::vector< unsigned char* > > yuvbuf_;      
	unsigned char** yuvptr_[3]; 
	buffer pYbuffer;
	buffer pUbuffer;
	buffer pVbuffer;

	BYTE* m_pYbuffer;
	BYTE* m_pUbuffer;
	BYTE* m_pVbuffer;
}; 

       编译的时候请使用jpeglib库,在win7系统 vc6.0 下经过测试验证。 (讨论群:视频监控2(143642819) )


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 首先需要安装libjpeg库,可以使用命令行进行安装: ``` sudo apt-get install libjpeg-dev ``` 2. 然后创建一个C文件,例如convert.c,包含以下代码: ```c #include <stdio.h> #include <stdlib.h> #include <jpeglib.h> int main(int argc, char *argv[]) { if (argc != 4) { fprintf(stderr, "Usage: %s <input_yuv_file> <width> <height>\n", argv[0]); exit(EXIT_FAILURE); } char *input_file = argv[1]; int width = atoi(argv[2]); int height = atoi(argv[3]); FILE *fp_in = fopen(input_file, "rb"); if (fp_in == NULL) { fprintf(stderr, "Error opening input file: %s\n", input_file); exit(EXIT_FAILURE); } FILE *fp_out = fopen("output.jpg", "wb"); if (fp_out == NULL) { fprintf(stderr, "Error creating output file\n"); exit(EXIT_FAILURE); } struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo, fp_out); cinfo.image_width = width; cinfo.image_height = height; cinfo.input_components = 3; cinfo.in_color_space = JCS_YCbCr; jpeg_set_defaults(&cinfo); jpeg_start_compress(&cinfo, TRUE); JSAMPROW row_pointer[1]; row_pointer[0] = malloc(width * 3); int y, u, v; unsigned char *buffer = malloc(width * height * 3); fread(buffer, width * height * 3, 1, fp_in); for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { y = buffer[(i * width + j) * 3]; u = buffer[(i * width + j) * 3 + 1]; v = buffer[(i * width + j) * 3 + 2]; row_pointer[0][j * 3] = y; row_pointer[0][j * 3 + 1] = u; row_pointer[0][j * 3 + 2] = v; } jpeg_write_scanlines(&cinfo, row_pointer, 1); } jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); fclose(fp_in); fclose(fp_out); return 0; } ``` 3. 编译上述代码,可以使用以下命令: ``` gcc -o convert convert.c -ljpeg ``` 4. 运行程序,命令格式为: ``` ./convert <input_yuv_file> <width> <height> ``` 其中,input_yuv_file为需要转换的YUV图像文件,width和height为图像的宽度和高度。 例如,转换名为test.yuv的图像,宽度为640,高度为480,可以使用以下命令: ``` ./convert test.yuv 640 480 ``` 5. 转换后的JPEG文件将保存在当前目录下的output.jpg中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值