JPEG转RGB是RGB压缩的逆过程,从压缩后的图像数据,然后进过熵编码器,在经过量化器(逆),然后在经过逆DCT变换,得到解压后的图像数据,我们在使用jpeg.lib库进行解压,解压的函数如下:
//读取JPEG文件
//参数:
//lpstrFileName——包含JPEG文件的全路径名
//uWidth——图像的宽度
//uHeight——图像的高度
//返回值为解压后的数据缓冲区指针
BYTE* CJpeg::ReadJPEGFile(LPCSTR lpstrFileName, UINT *uWidth, UINT *uHeight)
{
*uWidth=0;
*uHeight=0;
//定义JPEG文件的解压信息
struct jpeg_decompress_struct cinfo;
//定义JPEG文件的错误信息
struct my_error_mgr jerr;
//定义缓冲区
FILE * infile;
JSAMPARRAY buffer;
int row_stride;
char buf[250];
//打开JPEG文件
if ((infile = fopen(lpstrFileName, "rb")) == NULL)
{
sprintf(buf, "JPEG :\nCan't open %s\n", lpstrFileName);
m_strJPEGError = buf;
return NULL;
}
//为JPEG文件解压对象分配内存并对其初始
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = my_error_exit;
if (setjmp(jerr.setjmp_buffer))
{
jpeg_destroy_decompress(&cinfo);
fclose(infile);
return NULL;
}
jpeg_create_decompress(&cinfo);
//设定数据源
jpeg_stdio_src(&cinfo, infile);
//读取JPEG文件参数
(void) jpeg_read_header(&cinfo, TRUE);
//开始解压
(void) jpeg_start_decompress(&cinfo);
BYTE *dataBuf;
dataBuf=(BYTE *)new BYTE[cinfo.output_width * 3 * cinfo.output_height];//存放解压后的数据
if (dataBuf==NULL)
{
m_strJPEGError = "JpegFile :\nOut of memory";
jpeg_destroy_decompress(&cinfo);
fclose(infile);
return NULL;
}
*uWidth = cinfo.output_width;
*uHeight = cinfo.output_height;
row_stride = cinfo.output_width * cinfo.output_components;
buffer = (*cinfo.mem->alloc_sarray)
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); //分配内存
//读取扫描线
while (cinfo.output_scanline < cinfo.output_height)
{
(void) jpeg_read_scanlines(&cinfo, buffer, 1);
if (cinfo.out_color_components==3)
{
j_putRGBScanline(buffer[0],
*uWidth,
dataBuf,
cinfo.output_scanline-1);
}
else if (cinfo.out_color_components==1)
{
j_putGrayScanlineToRGB(buffer[0],
*uWidth,
dataBuf,
cinfo.output_scanline-1);
}
}
//完成解压
(void) jpeg_finish_decompress(&cinfo);
//释放JPEG解压对象
jpeg_destroy_decompress(&cinfo);
fclose(infile);
return dataBuf;
}
//
// stash a scanline
//
void j_putRGBScanline(BYTE *jpegline,
int widthPix,
BYTE *outBuf,
int row)
{
int offset = row * widthPix * 3;
int count;
for (count=0;count<widthPix;count++) {
BYTE iRed, iBlu, iGrn;
LPBYTE oRed, oBlu, oGrn;
iRed = *(jpegline + count * 3 + 0);
iGrn = *(jpegline + count * 3 + 1);
iBlu = *(jpegline + count * 3 + 2);
oRed = outBuf + offset + count * 3 + 0;
oGrn = outBuf + offset + count * 3 + 1;
oBlu = outBuf + offset + count * 3 + 2;
*oRed = iRed;
*oGrn = iGrn;
*oBlu = iBlu;
}
}
//
// stash a gray scanline
//
void j_putGrayScanlineToRGB(BYTE *jpegline,
int widthPix,
BYTE *outBuf,
int row)
{
int offset = row * widthPix * 3;
int count;
for (count=0;count<widthPix;count++)
{
BYTE iGray;
LPBYTE oRed, oBlu, oGrn;
// get our grayscale value
iGray = *(jpegline + count);
oRed = outBuf + offset + count * 3;
oGrn = outBuf + offset + count * 3 + 1;
oBlu = outBuf + offset + count * 3 + 2;
*oRed = iGray;
*oGrn = iGray;
*oBlu = iGray;
}
}