www.pudn.com > bmp2jpeg&jpegcoding.rar > compress.c


////////////////////////////////////////////////////////////// 
//Name:compress.c 
//Purpose: Run length algorithm and Jpeg decoding 
//Author: phoenix, CS, TshingHua, Beijing, P.R.C. 
//Email: bjlufengjun@www.163.net or lufengjun@hotmail.com 
//Date:April 3, 1998 
 
//header file 
#include "bmp.h" 
#include "jpeg.h" 
#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 
 
//function declaration 
int PASCAL WinMain (HANDLE, HANDLE, LPSTR, int); 
LRESULT CALLBACK MainWndProc(HWND , UINT,WPARAM, LPARAM); 
BOOL LoadPcxFile(HWND hWnd,char *BmpFileName); 
void ReadPcxLine(unsigned char *p,FILE *fp); 
////////////////////////////////////////////////// 
//Jpeg functions 
BOOL LoadJpegFile(HWND hWnd,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; 
HGLOBAL            hImgData=NULL; 
DWORD              NumColors; 
DWORD              LineBytes; 
DWORD              ImgWidth=0 , ImgHeight=0; 
unsigned int       PcxBytesPerLine; 
LPSTR              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; 
/////////////////////////////////////////////////////////// 
int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance, 
		    LPSTR lpszCmdLine, int nCmdShow) 
{ 
	MSG       msg; 
	WNDCLASS  wndclass; 
	HWND      hWnd; 
 
	if ( ! hPrevInstance ){ 
		wndclass.style = CS_HREDRAW | CS_VREDRAW; 
		wndclass.lpfnWndProc = MainWndProc; 
		wndclass.cbClsExtra = 0; 
		wndclass.cbWndExtra = 0; 
		wndclass.hInstance = hInstance; 
		wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); 
		wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); 
		wndclass.hbrBackground = GetStockObject (WHITE_BRUSH); 
		wndclass.lpszMenuName =  "BMPMENU"; 
		wndclass.lpszClassName = "phoenix ip system"; 
    } 
 
    if ( ! RegisterClass (&wndclass) ) 
	    return FALSE; 
 
	hWnd = CreateWindow ("phoenix ip system","Run length algorithm and Jpeg decoding", 
						 WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT, 
						 CW_USEDEFAULT,	CW_USEDEFAULT, NULL,NULL, 
						 hInstance,	NULL); 
	if (!hWnd) 
		return FALSE; 
	ShowWindow (hWnd, SW_SHOWMAXIMIZED); 
	UpdateWindow (hWnd); 
	 
	while ( GetMessage (&msg, NULL, 0, 0) ){ 
		TranslateMessage (&msg); 
		DispatchMessage (&msg); 
    } 
	return msg.wParam; 
} 
//////////////////////////////////////////////////////////////// 
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message,WPARAM wParam, LPARAM lParam) 
{ 
    static  HDC    hDC,hMemDC; 
    PAINTSTRUCT    ps; 
 
    switch (message){ 
    case WM_PAINT: 
	{          
		hDC = BeginPaint(hWnd, &ps); 
		if (hBitmap) 
		{  
			hMemDC = CreateCompatibleDC(hDC); 
			if (hPalette) 
			{            
				SelectPalette (hDC, hPalette, FALSE);  
				SelectPalette (hMemDC, hPalette, FALSE); 
				RealizePalette (hDC); 
			}    
			SelectObject(hMemDC, hBitmap);  
			BitBlt(hDC, 0, 0, ImgWidth,ImgHeight, hMemDC, 0, 0, SRCCOPY); 
			DeleteDC(hMemDC); 
		} 
		EndPaint(hWnd, &ps); 
		break; 
	} 
	case WM_DESTROY: //注意释放内存和位图,调色板句柄 
        if(hBitmap!=NULL) 
	        DeleteObject(hBitmap); 
	     
		if(hPalette!=NULL)                      
	        DeleteObject(hPalette); 
		 
		if(hImgData!=NULL){ 
			GlobalUnlock(hImgData); 
			GlobalFree(hImgData); 
		}	         
	    PostQuitMessage (0); 
	    return 0; 
	case WM_COMMAND: 
	    switch (wParam){ 
		case IDM_RUNLENGTH: 
			//注意重新分配内存和调色板,位图句柄时,先释放原来的 
	        if(hBitmap!=NULL){      
				DeleteObject(hBitmap); 
	            hBitmap=NULL; 
	        } 
	        if(hPalette!=NULL){                      
				DeleteObject(hPalette); 
	            hPalette=NULL; 
	        } 
			if(hImgData!=NULL){ 
				GlobalUnlock(hImgData); 
				GlobalFree(hImgData);   
				hImgData=NULL; 
			}	         
			if(LoadPcxFile(hWnd,"c:\\test.pcx")) //成功,则重画窗口 
                InvalidateRect(hWnd,NULL,TRUE); 
	        break; 
		case IDM_JPEG: 
			//注意重新分配内存和调色板,位图句柄时,先释放原来的 
	        if(hBitmap!=NULL){      
				DeleteObject(hBitmap); 
	            hBitmap=NULL; 
	        } 
	        if(hPalette!=NULL){                      
				DeleteObject(hPalette); 
	            hPalette=NULL; 
	        } 
			if(hImgData!=NULL){ 
				GlobalUnlock(hImgData); 
				GlobalFree(hImgData);   
				hImgData=NULL; 
			}	         
			if(LoadJpegFile(hWnd,"c:\\test.jpg")) //成功,则重画窗口 
                InvalidateRect(hWnd,NULL,TRUE); 
	        break; 
		case IDM_EXIT: 
	        SendMessage(hWnd,WM_DESTROY,0,0L); 
	        break; 
	    } 
	break;                 
    } 
    return DefWindowProc (hWnd, message, wParam, lParam); 
} 
//////////////////////////////////////////////////////////////// 
BOOL LoadPcxFile (HWND hWnd,char *PcxFileName) 
{    
//pcx header 
typedef struct{ 
		 char manufacturer; 
		 char version; 
		 char encoding; 
		 char bits_per_pixel; 
		 WORD xmin,ymin; 
		 WORD xmax,ymax; 
		 WORD hres; 
		 WORD vres; 
		 char palette[48]; 
		 char reserved; 
		 char colour_planes; 
		 WORD bytes_per_line; 
		 WORD palette_type; 
		 char filler[58]; 
	      } PCXHEAD; 
	FILE               *PCXfp; 
	PCXHEAD			   header; 
    LOGPALETTE         *pPal; 
    HPALETTE           hPrevPalette;  
    HDC                hDc; 
	HLOCAL             hPal; 
	DWORD 		       ImgSize; 
	DWORD              BufSize; 
	LPBITMAPINFOHEADER lpImgData;	 
	DWORD              i; 
	LONG               x,y; 
	int                PcxTag; 
	unsigned char      LineBuffer[6400]; 
	LPSTR              lpPtr; 
	HFILE              hfbmp; 
 
    if((PCXfp=fopen(PcxFileName,"rb"))==NULL){ 
        MessageBox(hWnd,"File c:\\test.pcx not found!","Error Message",MB_OK|MB_ICONEXCLAMATION); 
        return FALSE; 
	} 
    fread((char*)&header,1,sizeof(PCXHEAD),PCXfp); 
    if(header.manufacturer!=0x0a){ 
	    MessageBox(hWnd,"Not a valid Pcx file!","Error Message",MB_OK|MB_ICONEXCLAMATION); 
	    fclose(PCXfp); 
	    return FALSE; 
	} 
	fseek(PCXfp,-769L,SEEK_END); 
	PcxTag=fgetc(PCXfp)&0xff; 
	if(PcxTag!=12){ 
	    MessageBox(hWnd,"Not a 256 colors Pcx file!","Error Message",MB_OK|MB_ICONEXCLAMATION); 
		fclose(PCXfp); 
		return FALSE; 
	} 
	//create new bitmapfileheader and bitmapinfoheader 
	memset((char *)&bf,0,sizeof(BITMAPFILEHEADER));	 
	memset((char *)&bi,0,sizeof(BITMAPINFOHEADER)); 
 
	bi.biSize=sizeof(BITMAPINFOHEADER); 
	bi.biWidth=header.xmax-header.xmin+1; 
	bi.biHeight=header.ymax-header.ymin+1; 
	bi.biPlanes=1; 
	bi.biBitCount=8; 
	bi.biCompression=BI_RGB; 
	ImgWidth=bi.biWidth; 
	ImgHeight=bi.biHeight; 
	NumColors=256; 
	LineBytes=(DWORD)WIDTHBYTES(bi.biWidth*bi.biBitCount); 
	ImgSize=(DWORD)LineBytes*bi.biHeight; 
 
	bf.bfType=0x4d42; 
	bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD)+ImgSize; 
	bf.bfOffBits=(DWORD)(NumColors*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)); 
	if((hImgData=GlobalAlloc(GHND,(DWORD)(sizeof(BITMAPINFOHEADER)+ 
						     NumColors*sizeof(RGBQUAD)+ImgSize)))==NULL) 
	{ 
    	MessageBox(hWnd,"Error alloc memory!","ErrorMessage",MB_OK| 
                   MB_ICONEXCLAMATION); 
	    fclose(PCXfp); 
		return FALSE; 
	} 
	lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);  
	memcpy(lpImgData,(char *)&bi,sizeof(BITMAPINFOHEADER)); 
	lpPtr=(char *)lpImgData+sizeof(BITMAPINFOHEADER); 
 
    hPal=LocalAlloc(LHND,sizeof(LOGPALETTE) + NumColors* sizeof(PALETTEENTRY)); 
    pPal =(LOGPALETTE *)LocalLock(hPal); 
    pPal->palNumEntries =256; 
	pPal->palVersion    = 0x300; 
	for (i = 0; i < 256; i++) { 
   		pPal->palPalEntry[i].peRed=(BYTE)fgetc(PCXfp); 
		pPal->palPalEntry[i].peGreen=(BYTE)fgetc(PCXfp); 
		pPal->palPalEntry[i].peBlue=(BYTE)fgetc(PCXfp); 
		pPal->palPalEntry[i].peFlags=(BYTE)0; 
		*(lpPtr++)=(unsigned char)pPal->palPalEntry[i].peBlue; 
		*(lpPtr++)=(unsigned char)pPal->palPalEntry[i].peGreen; 
		*(lpPtr++)=(unsigned char)pPal->palPalEntry[i].peRed; 
		*(lpPtr++)=0; 
	} 
	hPalette=CreatePalette(pPal); 
	LocalUnlock(hPal); 
	LocalFree(hPal); 
 
	hDc=GetDC(hWnd); 
	if(hPalette){ 
        hPrevPalette=SelectPalette(hDc,hPalette,FALSE); 
		RealizePalette(hDc); 
	} 
	PcxBytesPerLine=(unsigned int)header.bytes_per_line; 
	fseek(PCXfp,(LONG)sizeof(PCXHEAD),SEEK_SET); 
	BufSize=bf.bfSize-sizeof(BITMAPFILEHEADER); 
 
	for(y=0;y>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>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>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; 
 
	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>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=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 ((thiscodehuf_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<>BitPos); 
		CurByte=lastbyte&And[BitPos]; 
	}  //else 
	sign=valueex>>(runsize-1); 
	if(sign) 
		vvalue=valueex; 
	else{ 
		valueex=valueex^0xffff; 
		temp=0xffff<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]; 
}