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;i ac_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;i code_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