二、基于C语言的JPEG解码代码详解

本文详细介绍了一种从JPEG格式图像解码至Bitmap的过程。包括读取JPEG数据、解析JPEG的头部信息、处理如DQT、DHT等关键字段、进行Huffman解码、逆量化及逆DCT变换,最终实现从JPEG到Bitmap的完整转换流程。
// JPEG解码
// 输入JPEG后输出Bitmap

#include <stdio.h>
#include <stdlib.h>

#pragma warning(disable : 4996)

unsigned int  BuffIndex;			// JPEG数据的位置
unsigned int  BuffSize;				// JPEG数据的大小
unsigned int  BuffX;				// 图像的横向尺寸
unsigned int  BuffY;				// 图像的垂直尺寸
unsigned int  BuffBlockX; 			// 横向MCU个数
unsigned int  BuffBlockY; 			// 纵向MCU个数
unsigned char *Buff;				// 装入解压数据的缓冲器

unsigned char  TableDQT[4][64];		// 量化表
unsigned short TableDHT[4][162]; 	// 霍夫曼表格

unsigned short TableHT[4][16];		// 霍夫曼起始表
unsigned char  TableHN[4][16];		// 霍夫曼起始号

unsigned char BitCount = 0;			// 压缩数据的读取位置
unsigned int  LineData;				// 解压缩时使用的数据
unsigned int  NextData;				// 解压缩时使用的数据

unsigned int  PreData[3];			// 用于DC分量的储存缓冲器

unsigned char CompCount;			// 组件数
unsigned char CompNum[4];			// 组件号(未使用)
unsigned char CompSample[4];	
unsigned char CompDQT[4];			// 组件的DQT表号
unsigned char CompDHT[4];			// 组件的DHT表号
unsigned char CompSampleX, CompSampleY;

// 反Zig-Zag表
int zigzag_table[]={
   
   
	0 ,  1, 8, 16, 9 , 2 , 3 , 10,
	17, 24,32, 25, 18, 11, 4 , 5,
	12, 19,26, 33, 40, 48, 41, 34,
	27, 20,13, 6 , 7 , 14, 21, 28,
	35, 42,49, 56, 57, 50, 43, 36,
	29, 22,15, 23, 30, 37, 44, 51,
	58, 59,52, 45, 38, 31, 39, 46,
	53, 60,61, 54, 47, 55, 62, 63, 0
};

typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef int LONG;

typedef struct tagBITMAPFILEHEADER {
   
   
	WORD	bfType;
	DWORD	bfSize;
	WORD	bfReserved1;
	WORD	bfReserved2;
	DWORD	bfOffBits;
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER{
   
   
	DWORD	biSize;
	LONG	biWidth;
	LONG	biHeight;
	WORD	biPlanes;
	WORD	biBitCount;
	DWORD	biCompression;
	DWORD	biSizeImage;
	LONG	biXPelsPerMeter;
	LONG	biYPelsPerMeter;
	DWORD	biClrUsed;
	DWORD	biClrImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;

//////////////////////////////////////////////////////////////////////////////
// Bitmap输出
// file: 文件名称
// x,y: 图像的尺寸
// b: 字节计数(1个点的字节数)
//////////////////////////////////////////////////////////////////////////////
void BmpSave(char *file,unsigned char *buff,unsigned int x,unsigned int y,unsigned int b)
{
   
   
	BITMAPFILEHEADER lpBf;
	BITMAPINFOHEADER lpBi;
	unsigned char tbuff[4];
	FILE *fp;
	unsigned char str;
	int i,k;

	if((fp = fopen(file,"wb")) == NULL)
	{
   
   
		perror(0);
		exit(0);
	}

	// 文件现在的设定
	tbuff[0] = 'B';
	tbuff[1] = 'M';
	fwrite(tbuff,2,1,fp);
	tbuff[3] = ((14 +40 +x *y *b) >> 24) & 0xff;
	tbuff[2] = ((14 +40 +x *y *b) >> 16) & 0xff;
	tbuff[1] = ((14 +40 +x *y *b) >>	8) & 0xff;
	tbuff[0] = ((14 +40 +x *y *b) >>	0) & 0xff;
	fwrite(tbuff,4,1,fp);
	tbuff[1] = 0;
	tbuff[0] = 0;
	fwrite(tbuff,2,1,fp);
	fwrite(tbuff,2,1,fp);
	tbuff[3] = 0;
	tbuff[2] = 0;
	tbuff[1] = 0;
	tbuff[0] = 54;
	fwrite(tbuff,4,1,fp);

	// 信息的设定
	lpBi.biSize				= 40;
	lpBi.biWidth			= x;
	lpBi.biHeight			= y;
	lpBi.biPlanes			= 1;
	lpBi.biBitCount			= b*8;
	lpBi.biCompression	 	= 0;
	lpBi.biSizeImage		= x*y*b;
	lpBi.biXPelsPerMeter	= 300;
	lpBi.biYPelsPerMeter	= 300;
	lpBi.biClrUsed		 	= 0;
	lpBi.biClrImportant		= 0;
	fwrite(&lpBi,1,40,fp);

	// 上下反转
	for(k=0;k<y/2;k++)
	{
   
   
		for(i=0;i<x*3;i++)
		{
   
   
			str = buff[k*x*3+i];
			buff[k*x*3+i] = buff[((y-1)*x*3 -k*x*3) +i];
			buff[((y-1)*x*3-k*x*3) +i] = str;
		}
	}

	fwrite(buff,1,x*y*b,fp);

	fclose(fp);
}

// 1Byte取得
unsigned char get_byte(unsigned char *buff)
{
   
   
	if(BuffIndex >= BuffSize) return 0;
	return buff[BuffIndex++];
}
//////////////////////////////////////////////////////////////////////////////
// 2Byte取得
unsigned short get_word(unsigned char *buff)
{
   
   
	unsigned char h,l;
	h = get_byte(buff);
	l = get_byte(buff);
	return (h<<8)|l;
}

// 32位数据取得(仅在解压缩时使用)
unsigned int get_data(unsigned char *buff)
{
   
   
	unsigned char str = 0;
	unsigned 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Da Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值