某天接到个任务,要求读取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) )