1. 程式人生 > >jpeg轉bmp實現c程式碼

jpeg轉bmp實現c程式碼

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

#pragma pack(1)
#define M_SOF0  0xc0
#define M_DHT   0xc4
#define M_EOI   0xd9
#define M_SOS   0xda
#define M_DQT   0xdb
#define M_DRI   0xdd
#define M_APP0  0xe0

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

#define W1 2841 /* 2048*sqrt(2)*cos(1*pi/16) */
#define W2 2676 /* 2048*sqrt(2)*cos(2*pi/16) */
#define W3 2408 /* 2048*sqrt(2)*cos(3*pi/16) */
#define W5 1609 /* 2048*sqrt(2)*cos(5*pi/16) */
#define W6 1108 /* 2048*sqrt(2)*cos(6*pi/16) */
#define W7 565  /* 2048*sqrt(2)*cos(7*pi/16) */

//*************************************************************************************
typedef char CHAR;
typedef short SHORT;
typedef long LONG;

typedef unsigned long       DWORD;
typedef int                 BOOL;
typedef unsigned char       BYTE;
typedef unsigned short      WORD;

typedef int HFILE;
typedef CHAR *LPSTR, *PSTR;

#define FALSE 0
#define TRUE 1

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, *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;

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

/* constants for the biCompression field */
#define BI_RGB        0L
#define BI_RLE8       1L
#define BI_RLE4       2L
#define BI_BITFIELDS  3L

typedef struct tagRGBQUAD {
	BYTE    rgbBlue;
	BYTE    rgbGreen;
	BYTE    rgbRed;
	BYTE    rgbReserved;
} RGBQUAD;
typedef RGBQUAD * LPRGBQUAD;

#define MAKEWORD(a, b)      ((WORD)(((BYTE)(a)) | ((WORD)((BYTE)(b))) << 8))
#define MAKELONG(a, b)      ((LONG)(((WORD)(a)) | ((DWORD)((WORD)(b))) << 16))
#define LOWORD(l)           ((WORD)(l))
#define HIWORD(l)           ((WORD)(((DWORD)(l) >> 16) & 0xFFFF))
#define LOBYTE(w)           ((BYTE)(w))
#define HIBYTE(w)           ((BYTE)(((WORD)(w) >> 8) & 0xFF))

//---yk--- add
#include "memory.h"
#include "math.h"
#include "stdio.h"
//macro definition
#define WIDTHBYTES(i)    ((i+31)/32*4)//??????????
#define PI 3.1415926535
//define return value of function
#define FUNC_OK 0
#define FUNC_MEMORY_ERROR 1
#define FUNC_FILE_ERROR 2
#define FUNC_FORMAT_ERROR 3

//////////////////////////////////////////////////
//Jpeg functions
BOOL LoadJpegFile(char *BmpFileName);
void showerror(int funcret);
int  InitTag();
void InitTable();
int  Decode();
int  DecodeMCUBlock();
int  HufBlock(BYTE dchufindex, BYTE achufindex);
int  DecodeElement();
void IQtIZzMCUComponent(short flag);
void IQtIZzBlock(short  *s, int * d, short flag);
void GetYUV(short flag);
void StoreBuffer();
BYTE ReadByte();
void Initialize_Fast_IDCT();
void Fast_IDCT(int * block);
void idctrow(int * blk);
void idctcol(int * blk);
//////////////////////////////////////////////////
//global variable declaration
BITMAPFILEHEADER   bf;
BITMAPINFOHEADER   bi;
//HPALETTE           hPalette=NULL;
//HBITMAP            hBitmap=NULL;
char *            hImgData = NULL;
DWORD              NumColors;
DWORD              LineBytes;
DWORD              ImgWidth = 0, ImgHeight = 0;
char*             lpPtr;
//////////////////////////////////////////////////
//variables used in jpeg function
short   SampRate_Y_H, SampRate_Y_V;
short   SampRate_U_H, SampRate_U_V;
short   SampRate_V_H, SampRate_V_V;
short   H_YtoU, V_YtoU, H_YtoV, V_YtoV;
short   Y_in_MCU, U_in_MCU, V_in_MCU;
unsigned char   *lpJpegBuf;
unsigned char   *lp;
short   qt_table[3][64];
short   comp_num;
BYTE   comp_index[3];
BYTE      YDcIndex, YAcIndex, UVDcIndex, UVAcIndex;
BYTE   HufTabIndex;
short      *YQtTable, *UQtTable, *VQtTable;
BYTE   And[9] = { 0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff };
short      code_pos_table[4][16], code_len_table[4][16];
unsigned short code_value_table[4][256];
unsigned short huf_max_value[4][16], huf_min_value[4][16];
short   BitPos, CurByte;
short   rrun, vvalue;
short   MCUBuffer[10 * 64];
int    QtZzMCUBuffer[10 * 64];
short   BlockBuffer[64];
short   ycoef, ucoef, vcoef;
BOOL   IntervalFlag;
short   interval = 0;
int    Y[4 * 64], U[4 * 64], V[4 * 64];
DWORD      sizei, sizej;
short    restart;
static  long iclip[1024];
static  long *iclp;

////////////////////////////////////////////////////////////////
BOOL LoadJpegFile(char *JpegFileName)
{
	FILE*      hfjpg;
	DWORD          ImgSize;
	DWORD              BufSize, JpegBufSize;
	FILE*              hfbmp;
	FILE*              IMGdata;
	void *      hJpegBuf;
	int       funcret;
	DWORD i;
	LPBITMAPINFOHEADER lpImgData;

	char * hImgData256;
	fopen_s(&hfjpg, JpegFileName, "rb");

	//get jpg file length
	fseek(hfjpg, 0L, SEEK_END);
	JpegBufSize = ftell(hfjpg);
	//rewind to the beginning of the file
	fseek(hfjpg, 0L, SEEK_SET);

	if ((hJpegBuf = malloc(JpegBufSize)) == NULL)
	{
		fclose(hfjpg);
		showerror(FUNC_MEMORY_ERROR);

		return FALSE;
	}
	lpJpegBuf = (unsigned char  *)hJpegBuf;
	fread((unsigned char  *)hJpegBuf, sizeof(char), JpegBufSize, hfjpg);
	fclose(hfjpg);

	InitTable();

	if ((funcret = InitTag()) != FUNC_OK)
	{
		// GlobalUnlock(hJpegBuf);
		free(hJpegBuf);
		showerror(funcret);
		return FALSE;
	}
	//create new bitmapfileheader and bitmapinfoheader
	memset((char *)&bf, 0, sizeof(BITMAPFILEHEADER));
	memset((char *)&bi, 0, sizeof(BITMAPINFOHEADER));

	bi.biSize = (DWORD)sizeof(BITMAPINFOHEADER);
	bi.biWidth = (LONG)(ImgWidth);
	bi.biHeight = (LONG)(ImgHeight);
	bi.biPlanes = 1;
	bi.biBitCount = 24;
	bi.biClrUsed = 0;
	bi.biClrImportant = 0;
	bi.biCompression = BI_RGB;
	NumColors = 0;
	printf("bi.biWidth is %ld/n", bi.biWidth);
	printf("bi.biBitCount is %ld/n", bi.biBitCount);
	LineBytes = (DWORD)WIDTHBYTES(bi.biWidth*bi.biBitCount);
	printf("LineBytes is %ld/n", LineBytes);
	ImgSize = (DWORD)LineBytes*bi.biHeight;//???????
	printf("size is %ld/n", ImgSize);
	bf.bfType = 0x4d42;
	int a = sizeof(BITMAPFILEHEADER);
	int b = sizeof(BITMAPINFOHEADER);
	//注意位元組對齊問題!!!!!!!!!!!!!!!!!!!!!!!!1
	//如果沒有#pragma pack(1),a是16~~~~~~~
	int c = NumColors*sizeof(RGBQUAD);

	bf.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD)+ImgSize;
	bf.bfOffBits = 54;//(DWORD)(NumColors*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER));
	BufSize = bf.bfSize - sizeof(BITMAPFILEHEADER);
	// printf("size is %ld/n",BufSize);
	if ((hImgData = (char*)malloc(BufSize)) == NULL)
	{
		//GlobalUnlock(hJpegBuf);
		free(hJpegBuf);
		showerror(FUNC_MEMORY_ERROR);
		showerror(FUNC_MEMORY_ERROR);
		return FALSE;
	}
	// lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData); 
	lpImgData = (LPBITMAPINFOHEADER)hImgData;
	memcpy(lpImgData, (char *)&bi, sizeof(BITMAPINFOHEADER));
	lpPtr = (char *)lpImgData + sizeof(BITMAPINFOHEADER);

	if ((SampRate_Y_H == 0) || (SampRate_Y_V == 0))
	{
		// GlobalUnlock(hJpegBuf);
		free(hJpegBuf);
		//GlobalUnlock(hImgData);
		free(hImgData);
		hImgData = NULL;
		showerror(FUNC_FORMAT_ERROR);
		return FALSE;
	}

	funcret = Decode();
	if (funcret == FUNC_OK)
	{
		fopen_s(&hfbmp, "jpeg2-bmp.bmp", "wb");
		fwrite((LPSTR)&bf, sizeof(BITMAPFILEHEADER), 1, hfbmp);
		fwrite((LPSTR)lpImgData, sizeof(char), BufSize, hfbmp);
		fopen_s(&IMGdata, "111.txt", "wb");

		DWORD xx = ImgWidth*ImgHeight;
		if ((hImgData256 = (char *)malloc(xx)) == NULL)
		{
			//GlobalUnlock(hJpegBuf);
			free(hImgData256);
			showerror(FUNC_MEMORY_ERROR);
			showerror(FUNC_MEMORY_ERROR);
			showerror(FUNC_MEMORY_ERROR);
			return FALSE;
		}

		char * temp = hImgData256;
		for (i = 0; i < xx; i++)
		{
			i;
			char t3 = *lpPtr;
			t3 &= 0xE0;
			char t1 = *(lpPtr + 1);
			t1 = t1 >> 3;
			t1 &= 0x1c;
			char t2 = *(lpPtr + 2);
			t2 = t2 >> 6;
			t2 &= 0x03;
			char t4 = t3 + t1 + t2;
			*temp++ = t4;
			lpPtr = lpPtr + 3;
			//不能使用temp+=3;
		}
		int count = fwrite(hImgData256, sizeof(char), xx, IMGdata);
		fclose(IMGdata);

		fclose(hfbmp);
		free(hJpegBuf);
		return TRUE;
	}
	else
	{
		free(hJpegBuf);
		free(hImgData);
		hImgData = NULL;
		showerror(funcret);
		return FALSE;
	}
}
/////////////////////////////////////////////////
void showerror(int funcret)
{
	switch (funcret)
	{
	case FUNC_MEMORY_ERROR:
		printf("Error alloc memory/n!");
		break;
	case FUNC_FILE_ERROR:
		printf("File not found!/n");
		break;
	case FUNC_FORMAT_ERROR:
		printf("File format error!/n");
		break;
	}
}
////////////////////////////////////////////////////////////////////////////////
int InitTag()
{
	BOOL finish = FALSE;
	BYTE id;
	short  llength;
	short  i, j, k;
	short  huftab1, huftab2;
	short  huftabindex;
	BYTE hf_table_index;
	BYTE qt_table_index;
	BYTE comnum;

	unsigned char  *lptemp;
	short  ccount;

	lp = lpJpegBuf + 2;

	while (!finish){
		id = *(lp + 1);
		lp += 2;
		switch (id){
		case M_APP0:
			llength = MAKEWORD(*(lp + 1), *lp);
			lp += llength;
			break;
		case M_DQT:
			llength = MAKEWORD(*(lp + 1), *lp);
			qt_table_index = (*(lp + 2)) & 0x0f;
			lptemp = lp + 3;
			if (llength<80){
				for (i = 0; i<64; i++)
					qt_table[qt_table_index][i] = (short)*(lptemp++);
			}
			else{
				for (i = 0; i<64; i++)
					qt_table[qt_table_index][i] = (short)*(lptemp++);
				qt_table_index = (*(lptemp++)) & 0x0f;
				for (i = 0; i<64; i++)
					qt_table[qt_table_index][i] = (short)*(lptemp++);
			}
			lp += llength;
			break;
		case M_SOF0:
			llength = MAKEWORD(*(lp + 1), *lp);
			ImgHeight = MAKEWORD(*(lp + 4), *(lp + 3));
			ImgWidth = MAKEWORD(*(lp + 6), *(lp + 5));
			comp_num = *(lp + 7);
			if ((comp_num != 1) && (comp_num != 3))
				return FUNC_FORMAT_ERROR;
			if (comp_num == 3){
				comp_index[0] = *(lp + 8);
				SampRate_Y_H = (*(lp + 9)) >> 4;
				SampRate_Y_V = (*(lp + 9)) & 0x0f;
				YQtTable = (short *)qt_table[*(lp + 10)];

				comp_index[1] = *(lp + 11);
				SampRate_U_H = (*(lp + 12)) >> 4;
				SampRate_U_V = (*(lp + 12)) & 0x0f;
				UQtTable = (short *)qt_table[*(lp + 13)];

				comp_index[2] = *(lp + 14);
				SampRate_V_H = (*(lp + 15)) >> 4;
				SampRate_V_V = (*(lp + 15)) & 0x0f;
				VQtTable = (short *)qt_table[*(lp + 16)];
			}
			else{
				comp_index[0] = *(lp + 8);
				SampRate_Y_H = (*(lp + 9)) >> 4;
				SampRate_Y_V = (*(lp + 9)) & 0x0f;
				YQtTable = (short *)qt_table[*(lp + 10)];

				comp_index[1] = *(lp + 8);
				SampRate_U_H = 1;
				SampRate_U_V = 1;
				UQtTable = (short *)qt_table[*(lp + 10)];

				comp_index[2] = *(lp + 8);
				SampRate_V_H = 1;
				SampRate_V_V = 1;
				VQtTable = (short *)qt_table[*(lp + 10)];
			}
			lp += llength;
			break;
		case M_DHT:
			llength = MAKEWORD(*(lp + 1), *lp);
			if (llength<0xd0){
				huftab1 = (short)(*(lp + 2)) >> 4;     //huftab1=0,1
				huftab2 = (short)(*(lp + 2)) & 0x0f;   //huftab2=0,1
				huftabindex = huftab1 * 2 + huftab2;
				lptemp = lp + 3;
				for (i = 0; i<16; i++)
					code_len_table[huftabindex][i] = (short)(*(lptemp++));
				j = 0;
				for (i = 0; i<16; i++)
				if (code_len_table[huftabindex][i] != 0){
					k = 0;
					while (k<code_len_table[huftabindex][i]){
						code_value_table[huftabindex][k + j] = (short)(*(lptemp++));
						k++;
					}
					j += k;
				}
				i = 0;
				while (code_len_table[huftabindex][i] == 0)
					i++;
				for (j = 0; j<i; j++){
					huf_min_value[huftabindex][j] = 0;
					huf_max_value[huftabindex][j] = 0;
				}
				huf_min_value[huftabindex][i] = 0;
				huf_max_value[huftabindex][i] = code_len_table[huftabindex][i] - 1;
				for (j = i + 1; j<16; j++){
					huf_min_value[huftabindex][j] = (huf_max_value[huftabindex][j - 1] + 1) << 1;
					huf_max_value[huftabindex][j] = huf_min_value[huftabindex][j] + code_len_table[huftabindex][j] - 1;
				}
				code_pos_table[huftabindex][0] = 0;
				for (j = 1; j<16; j++)
					code_pos_table[huftabindex][j] = code_len_table[huftabindex][j - 1] + code_pos_table[huftabindex][j - 1];
				lp += llength;
			}  //if
			else{
				hf_table_index = *(lp + 2);
				lp += 2;
				while (hf_table_index != 0xff){
					huftab1 = (short)hf_table_index >> 4;     //huftab1=0,1
					huftab2 = (short)hf_table_index & 0x0f;   //huftab2=0,1
					huftabindex = huftab1 * 2 + huftab2;
					lptemp = lp + 1;
					ccount = 0;
					for (i = 0; i<16; i++){
						code_len_table[huftabindex][i] = (short)(*(lptemp++));
						ccount += code_len_table[huftabindex][i];
					}
					ccount += 17;
					j = 0;
					for (i = 0; i<16; i++)
					if (code_len_table[huftabindex][i] != 0){
						k = 0;
						while (k<code_len_table[huftabindex][i])
						{
							code_value_table[huftabindex][k + j] = (short)(*(lptemp++));
							k++;
						}
						j += k;
					}
					i = 0;
					while (code_len_table[huftabindex][i] == 0)
						i++;
					for (j = 0; j<i; j++){
						huf_min_value[huftabindex][j] = 0;
						huf_max_value[huftabindex][j] = 0;
					}
					huf_min_value[huftabindex][i] = 0;
					huf_max_value[huftabindex][i] = code_len_table[huftabindex][i] - 1;
					for (j = i + 1; j<16; j++){
						huf_min_value[huftabindex][j] = (huf_max_value[huftabindex][j - 1] + 1) << 1;
						huf_max_value[huftabindex][j] = huf_min_value[huftabindex][j] + code_len_table[huftabindex][j] - 1;
					}
					code_pos_table[huftabindex][0] = 0;
					for (j = 1; j<16; j++)
						code_pos_table[huftabindex][j] = code_len_table[huftabindex][j - 1] + code_pos_table[huftabindex][j - 1];
					lp += ccount;
					hf_table_index = *lp;
				}  //while
			}  //else
			break;
		case M_DRI:
			llength = MAKEWORD(*(lp + 1), *lp);
			restart = MAKEWORD(*(lp + 3), *(lp + 2));
			lp += llength;
			break;
		case M_SOS:
			llength = MAKEWORD(*(lp + 1), *lp);
			comnum = *(lp + 2);
			if (comnum != comp_num)
				return FUNC_FORMAT_ERROR;
			lptemp = lp + 3;
			for (i = 0; i<comp_num; i++){
				if (*lptemp == comp_index[0]){
					YDcIndex = (*(lptemp + 1)) >> 4;   //Y
					YAcIndex = ((*(lptemp + 1)) & 0x0f) + 2;
				}
				else{
					UVDcIndex = (*(lptemp + 1)) >> 4;   //U,V
					UVAcIndex = ((*(lptemp + 1)) & 0x0f) + 2;
				}
				lptemp += 2;
			}
			lp += llength;
			finish = TRUE;
			break;
		case M_EOI:
			return FUNC_FORMAT_ERROR;
			break;
		default:
			if ((id & 0xf0) != 0xd0){
				llength = MAKEWORD(*(lp + 1), *lp);
				lp += llength;
			}
			else lp += 2;
			break;
		}  //switch
	} //while
	return FUNC_OK;
}
/////////////////////////////////////////////////////////////////
void InitTable()
{
	short i, j;
	sizei = sizej = 0;
	ImgWidth = ImgHeight = 0;
	rrun = vvalue = 0;
	BitPos = 0;
	CurByte = 0;
	IntervalFlag = FALSE;
	restart = 0;
	for (i = 0; i<3; i++)
	for (j = 0; j<64; j++)
		qt_table[i][j] = 0;
	comp_num = 0;
	HufTabIndex = 0;
	for (i = 0; i<3; i++)
		comp_index[i] = 0;
	for (i = 0; i<4; i++)
	for (j = 0; j<16; j++){
		code_len_table[i][j] = 0;
		code_pos_table[i][j] = 0;
		huf_max_value[i][j] = 0;
		huf_min_value[i][j] = 0;
	}
	for (i = 0; i<4; i++)
	for (j = 0; j<256; j++)
		code_value_table[i][j] = 0;

	for (i = 0; i<10 * 64; i++){
		MCUBuffer[i] = 0;
		QtZzMCUBuffer[i] = 0;
	}
	for (i = 0; i<64; i++){
		Y[i] = 0;
		U[i] = 0;
		V[i] = 0;
		BlockBuffer[i] = 0;
	}
	ycoef = ucoef = vcoef = 0;
}
/////////////////////////////////////////////////////////////////////////
int Decode()
{
	int funcret;

	Y_in_MCU = SampRate_Y_H*SampRate_Y_V;
	U_in_MCU = SampRate_U_H*SampRate_U_V;
	V_in_MCU = SampRate_V_H*SampRate_V_V;
	H_YtoU = SampRate_Y_H / SampRate_U_H;
	V_YtoU = SampRate_Y_V / SampRate_U_V;
	H_YtoV = SampRate_Y_H / SampRate_V_H;
	V_YtoV = SampRate_Y_V / SampRate_V_V;
	Initialize_Fast_IDCT();
	while ((funcret = DecodeMCUBlock()) == FUNC_OK){
		interval++;
		if ((restart) && (interval % restart == 0))
			IntervalFlag = TRUE;
		else
			IntervalFlag = FALSE;
		IQtIZzMCUComponent(0);
		IQtIZzMCUComponent(1);
		IQtIZzMCUComponent(2);
		GetYUV(0);
		GetYUV(1);
		GetYUV(2);
		StoreBuffer();
		sizej += SampRate_Y_H * 8;
		if (sizej >= ImgWidth){
			sizej = 0;
			sizei += SampRate_Y_V * 8;
		}
		if ((sizej == 0) && (sizei >= ImgHeight))
			break;
	}
	return funcret;
}
/////////////////////////////////////////////////////////////////////////////////////////
void  GetYUV(short flag)
{
	short H, VV;
	short i, j, k, h;
	int  *buf;
	int  *pQtZzMCU;
	buf = Y;
	pQtZzMCU = QtZzMCUBuffer;
	switch (flag){
	case 0:
		H = SampRate_Y_H;
		VV = SampRate_Y_V;
		buf = Y;
		pQtZzMCU = QtZzMCUBuffer;
		break;
	case 1:
		H = SampRate_U_H;
		VV = SampRate_U_V;
		buf = U;
		pQtZzMCU = QtZzMCUBuffer + Y_in_MCU * 64;
		break;
	case 2:
		H = SampRate_V_H;
		VV = SampRate_V_V;
		buf = V;
		pQtZzMCU = QtZzMCUBuffer + (Y_in_MCU + U_in_MCU) * 64;
		break;
	}
	for (i = 0; i<VV; i++)
	for (j = 0; j<H; j++)
	for (k = 0; k<8; k++)
	for (h = 0; h<8; h++)
		buf[(i * 8 + k)*SampRate_Y_H * 8 + j * 8 + h] = *pQtZzMCU++;
}
///////////////////////////////////////////////////////////////////////////////
void StoreBuffer()
{
	short i, j;
	unsigned char  *lpbmp;
	unsigned char R, G, B;
	int y, u, v, rr, gg, bb;

	for (i = 0; i<SampRate_Y_V * 8; i++){
		if ((sizei + i)<ImgHeight){
			lpbmp = ((unsigned char *)lpPtr + (DWORD)(ImgHeight - sizei - i - 1)*LineBytes + sizej * 3);
			for (j = 0; j<SampRate_Y_H * 8; j++){
				if ((sizej + j)<ImgWidth){
					y = Y[i * 8 * SampRate_Y_H + j];
					u = U[(i / V_YtoU) * 8 * SampRate_Y_H + j / H_YtoU];
					v = V[(i / V_YtoV) * 8 * SampRate_Y_H + j / H_YtoV];
					rr = ((y << 8) + 18 * u + 367 * v) >> 8;
					gg = ((y << 8) - 159 * u - 220 * v) >> 8;
					bb = ((y << 8) + 411 * u - 29 * v) >> 8;
					R = (unsigned char)rr;
					G = (unsigned char)gg;
					B = (unsigned char)bb;
					if (rr & 0xffffff00) if (rr>255) R = 255; else if (rr<0) R = 0;
					if (gg & 0xffffff00) if (gg>255) G = 255; else if (gg<0) G = 0;
					if (bb & 0xffffff00) if (bb>255) B = 255; else if (bb<0) B = 0;
					*lpbmp++ = B;
					*lpbmp++ = G;
					*lpbmp++ = R;


				}
				else  break;
			}
		}
		else break;
	}
}
///////////////////////////////////////////////////////////////////////////////
int DecodeMCUBlock()
{
	short *lpMCUBuffer;
	short i, j;
	int funcret;

	if (IntervalFlag){
		lp += 2;
		ycoef = ucoef = vcoef = 0;
		BitPos = 0;
		CurByte = 0;
	}
	switch (comp_num){
	case 3:
		lpMCUBuffer = MCUBuffer;
		for (i = 0; i<SampRate_Y_H*SampRate_Y_V; i++)  //Y
		{
			funcret = HufBlock(YDcIndex, YAcIndex);
			if (funcret != FUNC_OK)
				return funcret;
			BlockBuffer[0] = BlockBuffer[0] + ycoef;
			ycoef = BlockBuffer[0];
			for (j = 0; j<64; j++)
				*lpMCUBuffer++ = BlockBuffer[j];
		}
		for (i = 0; i<SampRate_U_H*SampRate_U_V; i++)  //U
		{
			funcret = HufBlock(UVDcIndex, UVAcIndex);
			if (funcret != FUNC_OK)
				return funcret;
			BlockBuffer[0] = BlockBuffer[0] + ucoef;
			ucoef = BlockBuffer[0];
			for (j = 0; j<64; j++)
				*lpMCUBuffer++ = BlockBuffer[j];
		}
		for (i = 0; i<SampRate_V_H*SampRate_V_V; i++)  //V
		{
			funcret = HufBlock(UVDcIndex, UVAcIndex);
			if (funcret != FUNC_OK)
				return funcret;
			BlockBuffer[0] = BlockBuffer[0] + vcoef;
			vcoef = BlockBuffer[0];
			for (j = 0; j<64; j++)
				*lpMCUBuffer++ = BlockBuffer[j];
		}
		break;
	case 1:
		lpMCUBuffer = MCUBuffer;
		funcret = HufBlock(YDcIndex, YAcIndex);
		if (funcret != FUNC_OK)
			return funcret;
		BlockBuffer[0] = BlockBuffer[0] + ycoef;
		ycoef = BlockBuffer[0];
		for (j = 0; j<64; j++)
			*lpMCUBuffer++ = BlockBuffer[j];
		for (i = 0; i<128; i++)
			*lpMCUBuffer++ = 0;
		break;
	default:
		return FUNC_FORMAT_ERROR;
	}
	return FUNC_OK;
}
//////////////////////////////////////////////////////////////////
int HufBlock(BYTE dchufindex, BYTE achufindex)
{
	short count = 0;
	short i;
	int funcret;

	//dc
	HufTabIndex = dchufindex;
	funcret = DecodeElement();
	if (funcret != FUNC_OK)
		return funcret;

	BlockBuffer[count++] = vvalue;
	//ac
	HufTabIndex = achufindex;
	while (count<64){
		funcret = DecodeElement();
		if (funcret != FUNC_OK)
			return funcret;
		if ((rrun == 0) && (vvalue == 0)){
			for (i = count; i<64; i++)
				BlockBuffer[i] = 0;
			count = 64;
		}
		else{
			for (i = 0; i<rrun; i++)
				BlockBuffer[count++] = 0;
			BlockBuffer[count++] = vvalue;
		}
	}
	return FUNC_OK;
}
//////////////////////////////////////////////////////////////////////////////
int DecodeElement()
{
	int thiscode, tempcode;
	unsigned short temp, valueex;
	short codelen;
	BYTE hufexbyte, runsize, tempsize, sign;
	BYTE newbyte, lastbyte;

	if (BitPos >= 1){
		BitPos--;
		thiscode = (BYTE)CurByte >> BitPos;
		CurByte = CurByte&And[BitPos];
	}
	else{
		lastbyte = ReadByte();
		BitPos--;
		newbyte = CurByte&And[BitPos];
		thiscode = lastbyte >> 7;
		CurByte = newbyte;
	}
	codelen = 1;
	while ((thiscode<huf_min_value[HufTabIndex][codelen - 1]) ||
		(code_len_table[HufTabIndex][codelen - 1] == 0) ||
		(thiscode>huf_max_value[HufTabIndex][codelen - 1]))
	{
		if (BitPos >= 1){
			BitPos--;
			tempcode = (BYTE)CurByte >> BitPos;
			CurByte = CurByte&And[BitPos];
		}
		else{
			lastbyte = ReadByte();
			BitPos--;
			newbyte = CurByte&And[BitPos];
			tempcode = (BYTE)lastbyte >> 7;
			CurByte = newbyte;
		}
		thiscode = (thiscode << 1) + tempcode;
		codelen++;
		if (codelen>16)
			return FUNC_FORMAT_ERROR;
	}  //while
	temp = thiscode - huf_min_value[HufTabIndex][codelen - 1] + code_pos_table[HufTabIndex][codelen - 1];
	hufexbyte = (BYTE)code_value_table[HufTabIndex][temp];
	rrun = (short)(hufexbyte >> 4);
	runsize = hufexbyte & 0x0f;
	if (runsize == 0){
		vvalue = 0;
		return FUNC_OK;
	}
	tempsize = runsize;
	if (BitPos >= runsize){
		BitPos -= runsize;
		valueex = (BYTE)CurByte >> BitPos;
		CurByte = CurByte&And[BitPos];
	}
	else{
		valueex = CurByte;
		tempsize -= BitPos;
		while (tempsize>8){
			lastbyte = ReadByte();
			valueex = (valueex << 8) + (BYTE)lastbyte;
			tempsize -= 8;
		}  //while
		lastbyte = ReadByte();
		BitPos -= tempsize;
		valueex = (valueex << tempsize) + (lastbyte >> BitPos);
		CurByte = lastbyte&And[BitPos];
	}  //else
	sign = valueex >> (runsize - 1);
	if (sign)
		vvalue = valueex;
	else{
		valueex = valueex ^ 0xffff;
		temp = 0xffff << runsize;
		vvalue = -(short)(valueex^temp);
	}
	return FUNC_OK;
}
/////////////////////////////////////////////////////////////////////////////////////
void IQtIZzMCUComponent(short flag)
{
	short H, VV;
	short i, j;
	int *pQtZzMCUBuffer;
	short  *pMCUBuffer;
	pMCUBuffer = MCUBuffer;
	pQtZzMCUBuffer = QtZzMCUBuffer;
	switch (flag){
	case 0:
		H = SampRate_Y_H;
		VV = SampRate_Y_V;
		pMCUBuffer = MCUBuffer;
		pQtZzMCUBuffer = QtZzMCUBuffer;
		break;
	case 1:
		H = SampRate_U_H;
		VV = SampRate_U_V;
		pMCUBuffer = MCUBuffer + Y_in_MCU * 64;
		pQtZzMCUBuffer = QtZzMCUBuffer + Y_in_MCU * 64;
		break;
	case 2:
		H = SampRate_V_H;
		VV = SampRate_V_V;
		pMCUBuffer = MCUBuffer + (Y_in_MCU + U_in_MCU) * 64;
		pQtZzMCUBuffer = QtZzMCUBuffer + (Y_in_MCU + U_in_MCU) * 64;
		break;
	}
	for (i = 0; i<VV; i++)
	for (j = 0; j<H; j++)
		IQtIZzBlock(pMCUBuffer + (i*H + j) * 64, pQtZzMCUBuffer + (i*H + j) * 64, flag);
}
//////////////////////////////////////////////////////////////////////////////////////////
void IQtIZzBlock(short  *s, int * d, short flag)
{
	short i, j;
	short tag;
	short *pQt;
	int buffer2[8][8];
	int *buffer1;
	short offset;
	pQt = YQtTable;
	switch (flag){
	case 0:
		pQt = YQtTable;
		offset = 128;
		break;
	case 1:
		pQt = UQtTable;
		offset = 0;
		break;
	case 2:
		pQt = VQtTable;
		offset = 0;
		break;
	}

	for (i = 0; i<8; i++)
	for (j = 0; j<8; j++){
		tag = Zig_Zag[i][j];
		buffer2[i][j] = (int)s[tag] * (int)pQt[tag];
	}
	buffer1 = (int *)buffer2;
	Fast_IDCT(buffer1);
	for (i = 0; i<8; i++)
	for (j = 0; j<8; j++)
		d[i * 8 + j] = buffer2[i][j] + offset;
}
///////////////////////////////////////////////////////////////////////////////
void Fast_IDCT(int * block)
{
	short i;

	for (i = 0; i<8; i++)
		idctrow(block + 8 * i);

	for (i = 0; i<8; i++)
		idctcol(block + i);
}
///////////////////////////////////////////////////////////////////////////////
BYTE  ReadByte()
{
	BYTE  i;

	i = *(lp++);
	if (i == 0xff)
		lp++;
	BitPos = 8;
	CurByte = i;
	return i;
}
///////////////////////////////////////////////////////////////////////
void Initialize_Fast_IDCT()
{
	short i;

	iclp = iclip + 512;
	for (i = -512; i<512; i++)
		iclp[i] = (i<-256) ? -256 : ((i>255) ? 255 : i);
}
////////////////////////////////////////////////////////////////////////
void idctrow(int * blk)
{
	int x0, x1, x2, x3, x4, x5, x6, x7, x8;
	//intcut
	if (!((x1 = blk[4] << 11) | (x2 = blk[6]) | (x3 = blk[2]) |
		(x4 = blk[1]) | (x5 = blk[7]) | (x6 = blk[5]) | (x7 = blk[3])))
	{
		blk[0] = blk[1] = blk[2] = blk[3] = blk[4] = blk[5] = blk[6] = blk[7] = blk[0] << 3;
		return;
	}
	x0 = (blk[0] << 11) + 128; // for proper rounding in the fourth stage 
	//first stage
	x8 = W7*(x4 + x5);
	x4 = x8 + (W1 - W7)*x4;
	x5 = x8 - (W1 + W7)*x5;
	x8 = W3*(x6 + x7);
	x6 = x8 - (W3 - W5)*x6;
	x7 = x8 - (W3 + W5)*x7;
	//second stage
	x8 = x0 + x1;
	x0 -= x1;
	x1 = W6*(x3 + x2);
	x2 = x1 - (W2 + W6)*x2;
	x3 = x1 + (W2 - W6)*x3;
	x1 = x4 + x6;
	x4 -= x6;
	x6 = x5 + x7;
	x5 -= x7;
	//third stage
	x7 = x8 + x3;
	x8 -= x3;
	x3 = x0 + x2;
	x0 -= x2;
	x2 = (181 * (x4 + x5) + 128) >> 8;
	x4 = (181 * (x4 - x5) + 128) >> 8;
	//fourth stage
	blk[0] = (x7 + x1) >> 8;
	blk[1] = (x3 + x2) >> 8;
	blk[2] = (x0 + x4) >> 8;
	blk[3] = (x8 + x6) >> 8;
	blk[4] = (x8 - x6) >> 8;
	blk[5] = (x0 - x4) >> 8;
	blk[6] = (x3 - x2) >> 8;
	blk[7] = (x7 - x1) >> 8;
}
//////////////////////////////////////////////////////////////////////////////
void idctcol(int * blk)
{
	int x0, x1, x2, x3, x4, x5, x6, x7, x8;
	//intcut
	if (!((x1 = (blk[8 * 4] << 8)) | (x2 = blk[8 * 6]) | (x3 = blk[8 * 2]) |
		(x4 = blk[8 * 1]) | (x5 = blk[8 * 7]) | (x6 = blk[8 * 5]) | (x7 = blk[8 * 3])))
	{
		blk[8 * 0] = blk[8 * 1] = blk[8 * 2] = blk[8 * 3] = blk[8 * 4] = blk[8 * 5]
			= blk[8 * 6] = blk[8 * 7] = iclp[(blk[8 * 0] + 32) >> 6];
		return;
	}
	x0 = (blk[8 * 0] << 8) + 8192;
	//first stage
	x8 = W7*(x4 + x5) + 4;
	x4 = (x8 + (W1 - W7)*x4) >> 3;
	x5 = (x8 - (W1 + W7)*x5) >> 3;
	x8 = W3*(x6 + x7) + 4;
	x6 = (x8 - (W3 - W5)*x6) >> 3;
	x7 = (x8 - (W3 + W5)*x7) >> 3;
	//second stage
	x8 = x0 + x1;
	x0 -= x1;
	x1 = W6*(x3 + x2) + 4;
	x2 = (x1 - (W2 + W6)*x2) >> 3;
	x3 = (x1 + (W2 - W6)*x3) >> 3;
	x1 = x4 + x6;
	x4 -= x6;
	x6 = x5 + x7;
	x5 -= x7;
	//third stage
	x7 = x8 + x3;
	x8 -= x3;
	x3 = x0 + x2;
	x0 -= x2;
	x2 = (181 * (x4 + x5) + 128) >> 8;
	x4 = (181 * (x4 - x5) + 128) >> 8;
	//fourth stage
	blk[8 * 0] = iclp[(x7 + x1) >> 14];
	blk[8 * 1] = iclp[(x3 + x2) >> 14];
	blk[8 * 2] = iclp[(x0 + x4) >> 14];
	blk[8 * 3] = iclp[(x8 + x6) >> 14];
	blk[8 * 4] = iclp[(x8 - x6) >> 14];
	blk[8 * 5] = iclp[(x0 - x4) >> 14];
	blk[8 * 6] = iclp[(x3 - x2) >> 14];
	blk[8 * 7] = iclp[(x7 - x1) >> 14];
}

int main()
{
	long time = clock();
	LoadJpegFile("0.jpg");
	printf("%d\n", clock() - time);
	return 0;
}