www.pudn.com > jpeg1.zip > ADECODE.C


/*************************************************************/ 
/* FILENAME    : DECODE.C                                    */ 
/* FUNCTION    : This program is for decoding the compressed */ 
/*               image file in JPEG format                   */ 
/* INPUT FORMAT: DECODE       */ 
/* PARAMETERS  :              */ 
/* OUTPUT      :                             */ 
/* COMPILING & | TCC  DECODE.C (PC Computer: Turbo C 2.0)    */ 
/* AUTHOR      : Ai Wei                                      */ 
/* ADDRESS     : Room 248, Dormitory 1                       */ 
/*                Tsing Hua University                       */ 
/*                Beijing 100084, P.R.China                  */ 
/* DATE/TIME   : 1-12-1993/5:00pm                            */ 
/*************************************************************/ 
 
#include "stdio.h" 
#include "stdlib.h" 
#include "alloc.h" 
#include "io.h" 
#include "errno.h" 
#include "math.h" 
#include  
/*#include  
#include  
*/ 
#define  PI 3.14159265359 
 
unsigned char far 
      *image; 
unsigned int 
      dc_maxcode[16],dc_mincode[16],dc_start_p[16]; 
unsigned int 
      ac_maxcode[16],ac_mincode[16],ac_start_p[16]; 
double 
      idct_coe[8][8]; 
unsigned char 
      qu_table[8][8]; 
unsigned char 
      code_stream[20000]; 
 
static int 
      zz_index[64]={ 
			  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,31,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 
			}; 
 
unsigned char 
       dc_bits[16]; 
unsigned char 
       ac_bits[16]; 
unsigned char 
       dc_huffval[12]; 
unsigned char 
       ac_huffval[162]; 
int 
       restore[8][8],data_for_idct[8][8],interval=256; 
long 
       curr_bit_position=0,img_position=0,dc_pre,diff,zz[64]; 
int 
       bit_occupied=0,current_stream_position=0,code_stream_length; 
unsigned int 
       img_width,img_height; 
 
 
/******************************************************/ 
/*                                                    */ 
/*   Function:  Procedure for loading the IDCT        */ 
/*              coefficients                          */ 
/*                                                    */   
/*   Format:    load_idct_coe()                       */ 
/*                                                    */    
/*   Patameter: None.                                 */  
/*                                                    */ 
/*   Return value:  None.                             */   
/*                                                    */   
/******************************************************/ 
 
void load_idct_coe() 
   { 
   int i,j; 
   for(j=0;j<8;j++) 
	  idct_coe[0][j]=0.5/sqrt((double)2.0); 
 
   for(i=1;i<8;i++) 
	  for(j=0;j<8;j++) 
	 idct_coe[i][j]=0.5*cos((2.0*(double)j+1.0)*(double)i*PI/16.0); 
   } 
 
 
/******************************************************/ 
/*                                                    */ 
/* Function:   Procedure for calculating IDCT         */ 
/*                                                    */ 
/* Format:    dct_tran()                              */   
/*                                                    */   
/* Patameter: None.                                   */ 
/*                                                    */ 
/* Return value:  None.                               */   
/*                                                    */   
/******************************************************/ 
 
dct_tran() 
	{ 
	double re1[8][8],re2[8][8]; 
	int i,j,k; 
	for(i=0;i<8;i++) 
	   for(j=0;j<8;j++) 
	   { 
	   re1[i][j]=0.0; 
	   re2[i][j]=0.0; 
	   for(k=0;k<8;k++) 
		  re1[i][j]=re1[i][j]+idct_coe[k][j]*(double)(data_for_idct[i][k]); 
	   } 
	 
	for(i=0;i<8;i++) 
	   for(j=0;j<8;j++) 
	   for(k=0;k<8;k++) 
		  re2[i][j]=re2[i][j]+idct_coe[k][i]*re1[k][j]; 
	 
	for(i=0;i<8;i++) 
	   for(j=0;j<8;j++) 
	  restore[i][j]=re2[i][j]; 
	} 
 
 
 
/*******************************************************/ 
/*                                                     */          
/*   Function: Procedure for generation of MAXCODE,    */ 
/*             MINCODE &  START_POSITION(in huffval)   */ 
/*             by which one  can split the code stream */ 
/*             and decide the   code size and the value*/  
/*             it represents                           */ 
/*                                                     */ 
/*   NOTE: HUFFVAL & BITS must be loaded first         */ 
/*                                                     */          
/*   Format:   init_huffman_table()                    */          
/*                                                     */ 
/*   Patameter:  None.                                 */   
/*                                                     */  
/*   Return value:  None                               */  
/*                                                     */ 
/*******************************************************/ 
 
void init_huffman_table() 
	{ 
	int i,dc_position=0,ac_position=0; 
	unsigned int dc_start_code=0,ac_start_code=0; 
	 
	for(i=0;i<16;i++) 
	   { 
	   dc_maxcode[i]=0; 
	   ac_maxcode[i]=0; 
	   dc_mincode[i]=0xffff; 
	   /* 
	   **  to avoid wrong entry  
	   */ 
	   ac_mincode[i]=0xffff; dc_start_code<<=1; 
	    
	   if(dc_bits[i]!=0) 
	  { 
	  dc_mincode[i]=dc_start_code; 
	  dc_start_code+=dc_bits[i]; 
	  dc_maxcode[i]=dc_start_code-1; 
	  dc_start_p[i]=dc_position; 
	  dc_position+=dc_bits[i]; 
	  } 
	   ac_start_code<<=1; 
	    
	   if(ac_bits[i]!=0) 
	  { 
	  ac_mincode[i]=ac_start_code; 
	  ac_start_code+=ac_bits[i]; 
	  ac_maxcode[i]=ac_start_code-1; 
	  ac_start_p[i]=ac_position; 
	  ac_position+=ac_bits[i]; 
	  } 
	   } 
	} 
 
 
/**********************************************************************/ 
/*                                                                    */ 
/*  Function:  Procedure for loading information from a JPEG format   */ 
/*             image                                                  */ 
/*                                                                    */   
/*  Format:    load()                                                 */ 
/*                                                                    */ 
/*  Parameter: None                                                   */ 
/*                                                                    */ 
/*  Return value: None                                                */   
/*                                                                    */ 
/**********************************************************************/ 
 
int load() 
	{ 
	unsigned char mark; 
	unsigned int curr_code,code_si; 
	register int i,j; 
	union { unsigned char byte[2]; 
		unsigned int table_length; 
	  } ll; 
	ll.byte[0]=code_stream[current_stream_position++]; 
	mark=code_stream[current_stream_position++]; 
	 
	if((ll.byte[0]!=0xff)||(mark!=0xd8)) 
	   return 0; 
ss1:    ll.byte[0]=code_stream[current_stream_position]; 
	 
	if((ll.byte[0]!=0xff)|| 
	   ((ll.byte[0]==0xff)&&(code_stream[current_stream_position+1]==0))) 
	   return 1; 
	else 
	   { 
	   current_stream_position++; 
	   mark=code_stream[current_stream_position++]; 
	   switch(mark) 
	  { 
	  /*  
	  ** Define Huffman tables  
	  */  
	  case 0xc4:  
		{ 
		ll.byte[1]=code_stream[current_stream_position++]; 
		/*  
		**  table length  
		*/                                                    
		ll.byte[0]=code_stream[current_stream_position++];  
		/*  
		**  load dc bits  
		*/ 
		for(i=1,j=0;i<17;i++,j++) 
		   dc_bits[j]=code_stream[current_stream_position+i]; 
		/*  
		** load dc huffval  
		*/ 
		for(i=17,j=0;i<=28;i++,j++)                  
		   dc_huffval[j]=code_stream[current_stream_position+i]; 
		/*  
		** load ac bits 
		*/ 
		for(i=30,j=0;i<46;i++,j++)                  
		   ac_bits[j]=code_stream[current_stream_position+i]; 
		/*  
		** load ac huffval  
		*/ 
		for(i=46,j=0;i<208;i++,j++) 
		   ac_huffval[j]=code_stream[current_stream_position+i]; 
		current_stream_position+=(ll.table_length-2); 
		break; 
		} 
	   
	  /* 
	  **  Define Quantization tables  
	  */  
	  case 0xdb:     
		{ 
		ll.byte[1]=code_stream[current_stream_position];     
		/*  
		** table length  
		*/ 
		ll.byte[0]=code_stream[current_stream_position+1]; 
		/* 
		** load quantization tables  
		*/ 
		for(i=3,j=0;i<67;i++,j++) 
		   qu_table[j/8][j%8]=code_stream[current_stream_position+i]; 
		current_stream_position+=ll.table_length; 
		break; 
		} 
	   
	  /*  
	  ** Start Of Scan 
	  */ 
	  case 0xda:     
		{ 
		return 1; 
		break; 
		} 
	   
	  /*  
	  ** Define restart interval  
	  */ 
	  case 0xdd:     
		{ 
		/*  
		**  table length  
		*/ 
		current_stream_position+=2;        
		ll.byte[1]=code_stream[current_stream_position++]; 
		ll.byte[0]=code_stream[current_stream_position++]; 
		interval=ll.table_length; 
		break; 
		} 
	   
	  default: 
		{ 
		ll.byte[1]=code_stream[current_stream_position]; 
		/*  
		** table length 
		*/ 
		ll.byte[0]=code_stream[current_stream_position+1];   
		current_stream_position+=ll.table_length; 
		break; 
		} 
	  } 
	   } 
	goto ss1; 
	} 
 
 
 
/***************************************************/ 
/*                                                 */ 
/* Function:   Procedure for fetching the next bit */ 
/*             in the  code_stream                 */ 
/*                                                 */ 
/* Format:      fetch_next_bit()                   */ 
/*                                                 */      
/* Parameter:   None.                              */      
/*                                                 */      
/* Return value: None.                             */ 
/*                                                 */      
/***************************************************/ 
 
unsigned char fetch_next_bit() 
	{ 
	unsigned char tmp; 
	 
	/*  
	** is the next byte of the code stream  
	*/  
	if((curr_bit_position%8)==0)        
	   { 
	   if(code_stream[current_stream_position+curr_bit_position/8-1]==0xff) 
	  { 
	  if(code_stream[current_stream_position+curr_bit_position/8]==0x00) 
		  curr_bit_position+=8; 
	  else 
		  return 0xff; 
	  } 
	   } 
	tmp=code_stream[current_stream_position+curr_bit_position/8]; 
	tmp<<=(curr_bit_position%8); 
	curr_bit_position++; 
	return (tmp>>7); 
	} 
 
 
/****************************************************/ 
/*                                                  */ 
/* Function:   Procedure for calculating 2**N       */ 
/*                                                  */     
/* Format:     pow2(int value)                      */     
/*                                                  */ 
/* Parameter:  value----value according to which    */ 
/*                      the log_data is calculated  */  
/*                                                  */ 
/* Return value: log_data                           */ 
/*                                                  */ 
/****************************************************/ 
 
int pow2(i) 
int i; 
	{ 
	int j,k; 
	for(j=0,k=1;jdc_maxcode[code_length])) 
	   { 
	   code_length++; 
	   if(((next_bit=fetch_next_bit())==0xff)||(code_length>16)) 
	   return -1; 
	   code_guess=(code_guess<<1)+next_bit; 
	   } 
	category=dc_huffval[code_guess-dc_mincode[code_length]+dc_start_p[code_length]]; 
	diff=0; 
 
	for(i=0;iac_maxcode[code_length])) 
	  { 
	  code_length++; 
	  if(((next_bit=fetch_next_bit())==0xff)||(code_length>16)) 
		 return -1; 
	  code_guess=(code_guess<<1)+next_bit; 
	  } 
	   rs=ac_huffval[code_guess-ac_mincode[code_length]+ac_start_p[code_length]]; 
	   if(rs==0x00) 
	  /* 
	  **  That is end of block  
	  */ 
	  return 1;   
	   run=rs/16; 
	   ssss=rs%16; 
	   j+=run; 
	   diff=0; 
	   for(i=0;icode_stream_length) 
	   { 
	   printf(" Unknown JPEG format.\n"); 
	   exit(0); 
	   } 
	 
	decode(); 
 
	i_zigzag(); 
	 
	i_qu(); 
 
	dct_tran(); 
	 
	for(i=0;i<8;i++) 
	   for(j=0;j<8;j++) 
	  { 
	  restore[i][j]+=128; 
	  if(restore[i][j]>255)  
			restore[i][j]=255; 
	  if(restore[i][j]<0)    
			restore[i][j]=0; 
	   
	  *(image+(m/(img_width>>3)*8+i)*img_width+(m%(img_width>>3))*8+j) 
			=restore[i][j]; 
	  } 
 
	m++; 
	/* 
	** a new interval 
	*/ 
	if((m%interval)==0)       
	   { 
	   dc_pre=0; 
 
	   if((code_stream[current_stream_position+curr_bit_position/8]==0xff)&& 
	  (code_stream[current_stream_position+curr_bit_position/8+1]==0x00)) 
		 curr_bit_position=(curr_bit_position/8+4)*8; 
	   else 
	  curr_bit_position=((curr_bit_position+7)/8+2)*8; 
	   } 
 
	i=code_stream[current_stream_position+(curr_bit_position+7)/8]; 
	j=code_stream[current_stream_position+(curr_bit_position+7)/8+1]; 
 
	if((i==0xff)&&(j==0xd9)) 
		goto end_decode; 
		  /* 
		  **  an EOI marker 
		  */ 
 
	if(m>=(img_width>>3)*(img_height>>3)) 
	   { 
	   printf("Stream overflow!\n"); 
	   goto end_decode; 
	   } 
	goto ee; 
 
end_decode: 
	for(i=0;i