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


/*************************************************************/ 
/* FILENAME    : ENCODE.C                                    */ 
/* FUNCTION    : This program is for encoding image file     */ 
/* INPUT FORMAT: DECODE       */ 
/*                   <0/1> [Q]                */ 
/* PARAMETERS  :              */ 
/* OUTPUT      :                              */ 
/* COMPILING & | TCC CODE.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   : 2-17-1993/5:00pm                            */ 
/*************************************************************/ 
 
#include  
#include "stdlib.h" 
#include  
#include "math.h" 
#include "errno.h" 
#include "alloc.h" 
#include  
#include  
#include "jpeg.h" 
 
#define PI 3.14159265359 
 
unsigned char 
      ac_ehuffsi[256],dc_ehuffsi[16],dc_huffsize[13],ac_huffsize[165]; 
 
unsigned char 
      buffer[2048]; 
 
unsigned int 
      ac_ehuffco[256],dc_ehuffco[16],dc_huffcode[13],ac_huffcode[165]; 
 
double 
	    dct_coe[8][8]; 
 
int 
      si_data[8][8]; 
 
int 
      result[8][8],bit_last_left=8,code_stream_length=0; 
 
long 
      dc_pre,diff,zz[64]; 
 
unsigned char 
	  far *code_stream; 
 
 
/******************************************************/ 
/*                                                    */ 
/* Function:   Procedure for loading DCT coefficients */ 
/*                                                    */ 
/* Format:     load_dct_coe()                         */ 
/*                                                    */ 
/* Parametre:  None.                                  */ 
/*                                                    */ 
/* Return value: None.                                */ 
/*                                                    */ 
/******************************************************/ 
 
load_dct_coe() 
   { 
   int i,j; 
   for(i=0;i<8;i++) 
      dct_coe[i][0]=0.5/sqrt((double)2.0); 
   for(j=1;j<8;j++) 
      for(i=0;i<8;i++) 
	 dct_coe[i][j]=0.5*cos((2.0*(double)i+1.0)*(double)j*PI/16.0); 
   } 
 
 
 
/******************************************************/ 
/*                                                    */ 
/* Function:   Procedure for  calculating FDCT        */ 
/*                                                    */ 
/* Format:     dct_tran()                             */ 
/*                                                    */ 
/* Parametre:  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]+dct_coe[k][j]*(double)(si_data[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]+dct_coe[k][i]*re1[k][j]; 
    for(i=0;i<8;i++) 
       for(j=0;j<8;j++) 
	  result[i][j]=re2[i][j]; 
    } 
 
 
/*********************************************************/ 
/*                                                       */ 
/* Function:   Procedure for getting the real            */ 
/*              quantization table.                      */ 
/*                                                       */ 
/* Format:     get_a_table(int q_value,                  */ 
/*                         unsigned char *table)         */ 
/*                                                       */ 
/* Parametre:  q_value---parametre Q for quantization.   */ 
/*             table-----pointer of quantization table.  */ 
/*                                                       */ 
/* Return Value: None.                                   */ 
/*                                                       */ 
/*********************************************************/ 
 
void get_q_table(q,table) 
    int q; 
    unsigned char table[8][8]; 
    { 
    unsigned i,j,tmp; 
    for(i=0;i<8;i++) 
       for(j=0;j<8;j++) 
	    { 
	    tmp=table[i][j]*q; 
	    table[i][j]=tmp/50.0+0.5; 
	    } 
    } 
 
 
/***************************************************/ 
/*                                                 */ 
/* Function:   Procedure for Quantize the DCT      */ 
/*                coefficients                     */ 
/*                                                 */ 
/* Format:     quant(unsigned char *table)         */ 
/*                                                 */      
/* Parametre: table---pointer of quantization      */ 
/*                      table.                     */ 
/*                                                 */ 
/* Return value: None.                             */      
/*                                                 */ 
/***************************************************/ 
 
quant(table) 
    unsigned char table[8][8]; 
    { 
    int i,j; 
    for(i=0;i<8;i++) 
       for(j=0;j<8;j++) 
	   { 
	   if(result[i][j]>=0) 
	       result[i][j] = 
		  result[i][j]/(float)(table[i][j])+0.5; 
	   else 
	       result[i][j] = 
		  result[i][j]/(float)(table[i][j])-0.5; 
	   } 
    } 
 
 
/***********************************************************/ 
/*                                                         */ 
/*  Function:      Procedure for zigzag scan of the        */ 
/*                 coefficients                            */ 
/*                                                         */      
/*  Format:        zigzag()                                */ 
/*                                                         */ 
/*  Parametre:     None.                                   */      
/*                                                         */      
/*  Return value:  None.                                   */ 
/*                                                         */ 
/***********************************************************/ 
 
zigzag() 
    { 
    int i,j; 
    for(i=0;i<8;i++) 
       for(j=0;j<8;j++) 
	  /*  
	  **  reorder the coefficients in zigzag sequence  
	  */ 
	  zz[zz_index[i*8+j]]=result[i][j];   /* reorder the coefficients in zigzag sequence */ 
    } 
 
 
/*****************************************************************/ 
/*                                                               */ 
/* Function:      Procedure for generation of the Huffman        */ 
/*                Codes  &  SIzes.                               */ 
/*                                                               */ 
/* Format:        loadhuf(unsigned char *DC_bit,                 */ 
/*                        unsigned char *DC_huffval,             */ 
/*                        unsigned char *AC_bit,                 */ 
/*                        unsigned char *AC_huffval)             */ 
/*                                                               */ 
/* Parametre:     DC_bit---------pointer of table used to        */                                                                    
/*                               generate huffman code size      */ 
/*                               for DC coefficents.             */ 
/*                DC_huffval-----pointer of table used to        */  
/*                               generate huffman code           */ 
/*                               for DC coefficients.            */ 
/*                DC_bit---------pointer of table used to        */                                                                    
/*                               generate huffman code size      */ 
/*                               for AC coefficents.             */ 
/*                DC_huffval-----pointer of table used to        */  
/*                               generate huffman code           */        
/*                               for AC coefficients.            */ 
/*                                                               */ 
/* Return value:  None.                                          */ 
/*                                                               */ 
/*****************************************************************/ 
 
loadhuf(d_bit,d_huffval,a_bit,a_huffval) 
    unsigned char d_bit[16],a_bit[16]; 
    unsigned char d_huffval[12],a_huffval[162]; 
    { 
    unsigned code; 
    int i,j,p,dc_lastp,ac_lastp,si; 
 
    /*  
    **  Generation of table of Huffman code sizes  
    */ 
 
    i=0; 
    j=1; 
    p=0; 
 
    while(i<16) 
       { 
       if(j>d_bit[i]) 
	  { 
	  i++; 
	  j=1; 
	  } 
       else 
	  { 
	  /*  
	  **  Generate DC Huffman code sizes  
	  */ 
	  dc_huffsize[p]=i+1;   
	  p++; 
	  j++; 
	  } 
       } 
    dc_huffsize[p]=0; 
    dc_lastp=p; 
 
    i=0; 
    j=1; 
    p=0; 
 
    while(i<16) 
       { 
       if(j>a_bit[i]) 
	  { 
	  i++; 
	  j=1; 
	  } 
       else 
	  { 
	  /* 
	  ** Generate AC Huffman code sizes 
	  */ 
	  ac_huffsize[p]=i+1; 
	  p++; 
	  j++; 
	  } 
       } 
    ac_huffsize[p]=0; 
    ac_lastp=p; 
 
    /* 
    **  Generation of table of Huffman codes 
    */ 
 
    p=0; 
    code=0; 
    si=dc_huffsize[0]; 
 
y1: do 
       { 
       /* 
       ** Generation of DC Huffman code 
       */ 
       dc_huffcode[p]=code; 
       code++; 
       p++; 
       } while(dc_huffsize[p]==si); 
     
    if(dc_huffsize[p]!=0) 
       { 
       do 
	  { 
	  code=code<<1; 
	  si++; 
	  } while(dc_huffsize[p]!=si); 
       goto y1; 
       } 
 
    p=0; 
    code=0; 
    si=ac_huffsize[0]; 
 
y2: do 
       { 
	/* 
       **  Generation of AC Huffman code 
       */ 
       ac_huffcode[p]=code; 
       code++; 
       p++; 
       } while(ac_huffsize[p]==si); 
     
    if(ac_huffsize[p]!=0) 
       { 
       do 
	  { 
	  code=code<<1; 
	  si++; 
	  } while(ac_huffsize[p]!=si); 
       goto y2; 
       } 
 
    /* 
    **   Reorder the values in HUFFCODE and HUFFSIZE according 
    **   to the values in HUFFVAL. 
    */ 
    p=0; 
 
    do 
       { 
       i=d_huffval[p]; 
       /* 
       **  dc code & size reorder 
       */ 
       dc_ehuffco[i]=dc_huffcode[p]; 
       dc_ehuffsi[i]=dc_huffsize[p]; 
       p++; 
       } while(p=0) 
	  tmp[j]=tmp1>>k; 
       else 
	  tmp[j]=tmp1<<(-k); 
        
       if((code_stream[code_stream_length]|=tmp[j])==0xff) 
	   { 
	   code_stream_length++; 
	   code_stream[code_stream_length]=0; 
	   } 
        
       if(k>=0) 
	  code_stream_length++; 
       code_si-=8; 
       } 
 
    if(k==0) 
       bit_last_left=8; 
    else 
	/* 
	**  encode category 
	*/ 
       bit_last_left= -k; 
 
    if(i==0) 
       return; 
     
    if(i<0) 
       { 
       i--; 
       tmp1=0xffff; 
       tmp1>>=16-ssss; 
       tmp1&=i; 
       } 
    else 
       tmp1=i; 
    num_of_byte=(ssss-bit_last_left+15)/8; 
     
    for(j=0;j=0) 
	  tmp[j]=tmp1>>k; 
       else 
	  tmp[j]=tmp1<<(-k); 
        
       if((code_stream[code_stream_length]|=tmp[j])==0xff) 
	   { 
	   code_stream_length++; 
	   code_stream[code_stream_length]=0; 
	   } 
        
       if(k>=0) 
	  code_stream_length++; 
       ssss-=8; 
       } 
     
    if(k==0) 
       bit_last_left=8; 
    else 
       bit_last_left= -k; 
    } 
 
 
/****************************************************************/ 
/*                                                              */ 
/* Function:    Send code of AC coefficient to the code stream  */ 
/*                                                              */ 
/* Format:      ac_send(int number,long ac_data)                */ 
/*                                                              */ 
/* Parameter:   number-----length  of 0 sequence                */ 
/*              ac_data----AC data to be encoded into code      */ 
/*                         stream.                              */ 
/*                                                              */ 
/* Return value: None.                                          */ 
/*                                                              */ 
/****************************************************************/ 
 
void ac_send(r,z) 
int r; 
long z; 
    { 
    int j,k,ssss,rs,code_si,num_of_byte; 
    unsigned int tmp1; 
    unsigned char tmp[3]; 
    ssss=log_of_int(z); 
    rs=(r<<4)+ssss; 
    code_si=ac_ehuffsi[rs]; 
    tmp1=ac_ehuffco[rs]; 
    num_of_byte=(code_si-bit_last_left+15)/8; 
     
    for(j=0;j=0) 
	  tmp[j]=tmp1>>k; 
       else 
	  tmp[j]=tmp1<<(-k); 
        
       if((code_stream[code_stream_length]|=tmp[j])==0xff) 
	   { 
	   code_stream_length++; 
	   code_stream[code_stream_length]=0; 
	   } 
        
       if(k>=0) 
	  code_stream_length++; 
       code_si-=8; 
       } 
     
    if(k==0) 
       bit_last_left=8; 
    else 
       /* 
       **       encode Run/Size 
       */ 
       bit_last_left= -k; 
 
    if(z<0) 
       { 
       z--; 
       tmp1=0xffff; 
       tmp1>>=16-ssss; 
       tmp1&=z; 
       } 
    else 
       tmp1=z; 
    num_of_byte=(ssss-bit_last_left+15)/8; 
     
    for(j=0;j=0) 
	  tmp[j]=tmp1>>k; 
       else 
	  tmp[j]=tmp1<<(-k); 
        
       if((code_stream[code_stream_length]|=tmp[j])==0xff) 
	   { 
	   code_stream_length++; 
	   code_stream[code_stream_length]=0; 
	   } 
        
       if(k>=0) 
	  code_stream_length++; 
       ssss-=8; 
       } 
 
    if(k==0) 
       bit_last_left=8; 
    else 
       bit_last_left= -k; 
    } 
 
 
/****************************************************************/ 
/*                                                              */ 
/*  Function:   Send code of AC coefficient(0 or F0) to the     */ 
/*              code stream                                     */ 
/*                                                              */ 
/* Format:      ac_send0f0(int ac_data)                         */ 
/*                                                              */ 
/* Parameter:   ac_data-----AC data (0 or F0) to encoded into   */ 
/*                          code  stream.                       */ 
/*                                                              */ 
/* Return value:  None.                                         */ 
/*                                                              */ 
/****************************************************************/ 
 
void ac_send0f0(rs) 
int rs; 
    { 
    int j,k,code_si,num_of_byte; 
    unsigned int tmp1; 
    unsigned char tmp[3]; 
    code_si=ac_ehuffsi[rs]; 
    tmp1=ac_ehuffco[rs]; 
    num_of_byte=(code_si-bit_last_left+15)/8; 
     
    for(j=0;j=0) 
	  tmp[j]=tmp1>>k; 
       else 
	  tmp[j]=tmp1<<(-k); 
        
       if((code_stream[code_stream_length]|=tmp[j])==0xff) 
	   { 
	   code_stream_length++; 
	   code_stream[code_stream_length]=0; 
	   } 
        
       if(k>=0) 
	  code_stream_length++; 
       code_si-=8; 
       } 
     
    if(k==0) 
       bit_last_left=8; 
    else 
	/* 
	 **   encode Run/Size 
	 */ 
       bit_last_left= -k; 
    } 
 
 
/*************************************************/ 
/*                                               */ 
/* Function:    Huffman encoding                 */ 
/*                                               */ 
/* Format:      encode()                         */ 
/*                                               */ 
/* Parametre:   None                             */ 
/*                                               */ 
/* Return value:  None                           */ 
/*                                               */ 
/*************************************************/ 
 
void encode() 
    { 
    int k=0,r=0; 
    diff=zz[0]-dc_pre; 
    dc_pre=zz[0]; 
    dc_send(diff); 
 
t1: k++; 
     
    if(zz[k]==0) 
       { 
       if(k==63) 
	  { 
	  /* 
	  **  Code EHUFSI(0) bits of EHUFCO(0) 
	  */ 
	  ac_send0f0(0); 
	  goto e1; 
	  } 
       else 
	  { 
	  r++; 
	  goto t1; 
	  } 
       } 
    else 
       { 
        
       while(r>15) 
	  { 
	  /* 
	  **  Code EHUFSI(240) bits of EHUFCO(240) 
	  */ 
	  ac_send0f0(240); 
	  r-=16; 
	  } 
       /* 
       **  Encode_R,zz[k] 
       */ 
       ac_send(r,zz[k]); 
       r=0; 
       if(k!=63) 
	  goto t1; 
       } 
e1: ; 
    } 
 
 
 
/**************************************************/ 
/*                                                */ 
/*      PROGRAM MAIN                              */ 
/*                                                */ 
/**************************************************/ 
 
main(int argc,char **argv) 
    { 
    FILE *fp_so,*fp_tar; 
    struct timeb start_time, end_time ; 
    int second_d ; 
    unsigned char byte_last,pad,n=0; 
    long i,j,k,l; 
    int q,block_count=0; 
    int color; 
    unsigned int img_width,img_height,tmp; 
 
    union { 
	  unsigned int restart; 
	  unsigned char rh_rl[2]; 
	  } interval; 
 
 
    ftime( &start_time ) ; 
 
    if(argc<6) 
       { 
       printf(" Error of Insufficient   Parameter!!\n"); 
       printf(" \n Usage: encode imgfile jpgfile color imgwidth imgheight [q]\n"); 
       exit(0); 
       } 
 
	if((code_stream=(unsigned char far *)farcalloc(64000l,1))==NULL) 
    { 
	printf("No Enough Memory!\n") ; 
	exit(0) ; 
    } 
 
    if((fp_so=fopen(argv[1],"rb"))==NULL) 
    { 
	printf(" Image file open error ! \n"); 
	exit(0); 
	} 
 
    if((fp_tar=fopen(argv[2],"wb"))==NULL) 
    { 
	printf( "Target file open error ! \n"); 
	exit(0); 
	} 
 
    /* 
    **  set default Q value for encode 
    */ 
 
    q=20; 
 
    if(argc==7) 
	q=atoi(argv[6]); 
 
    /* 
    **  get parametres from command line 
    */ 
 
    color=atoi(argv[3]); 
    img_height=atoi(argv[5]); 
    img_width=atoi(argv[4]); 
 
    tmp=((img_width>>3)<<3); 
    fwrite(&img_width, sizeof(int),1,fp_tar); 
 
    tmp=((img_height>>3)<<3); 
    fwrite(&img_height,sizeof(int),1,fp_tar); 
 
    interval.restart=img_width>>3; 
 
    if(color==0) 
    { 
	get_q_table(q,qu_table); 
	loadhuf(dc_bits,dc_huffval,ac_bits,ac_huffval); 
	} 
    else 
    { 
	get_q_table(q,co_qu_table); 
	loadhuf(co_dc_bits,co_dc_huffval,co_ac_bits,co_ac_huffval); 
	} 
     
    load_dct_coe(); 
     
    code_stream[code_stream_length++]=0xff; 
    /* 
    **  Add Start Of Image mark 
    */ 
    code_stream[code_stream_length++]=0xd8; 
    code_stream[code_stream_length++]=0xff; 
    /* 
    **  Define Quantization tables 
    */ 
    code_stream[code_stream_length++]=0xdb; 
    code_stream[code_stream_length++]=0x00; 
    /* 
    **  Length of Quantization tables is 67 
    */ 
    code_stream[code_stream_length++]=0x43; 
    /* 
    ** Y-Quantization table 
    */ 
    code_stream[code_stream_length++]=0x00; 
     
    if(color==0) 
    { 
	for(i=0;i<64;i++) 
		code_stream[code_stream_length++]=qu_table[i/8][i%8]; 
    } 
    else 
    { 
	for(i=0;i<64;i++) 
		code_stream[code_stream_length++]=co_qu_table[i/8][i%8]; 
    } 
 
    code_stream[code_stream_length++]=0xff; 
    /* 
    **  Define Huffman tables 
    */ 
    code_stream[code_stream_length++]=0xc4; 
    code_stream[code_stream_length++]=0x00; 
    /* 
    **  Huffman tables length=0xd2=210=2+1+16+12+1+16+162 
    */ 
    code_stream[code_stream_length++]=0xd2; 
    /* 
    **  Y-DC table 
    */ 
    code_stream[code_stream_length++]=0x00; 
     
    if(color==0) 
    { 
	for(i=0;i<16;i++) 
		/* 
		**  Y-DC BITS 
		*/ 
		code_stream[code_stream_length++]=dc_bits[i]; 
 
	 for(i=0;i<12;i++) 
		/* 
		**  DC-Huffman values 
		*/ 
		code_stream[code_stream_length++]=dc_huffval[i]; 
    } 
    else 
    { 
	for(i=0;i<16;i++) 
		/* 
		**  Y-DC BITS 
		*/ 
		code_stream[code_stream_length++]=co_dc_bits[i]; 
 
	for(i=0;i<12;i++) 
		/* 
		**   DC-Huffman values 
		*/ 
		code_stream[code_stream_length++]=co_dc_huffval[i]; 
    } 
 
    /* 
    **   Y-AC table 
    */ 
    code_stream[code_stream_length++]=0x10; 
     
    if(color==0) 
    { 
	for(i=0;i<16;i++) 
		code_stream[code_stream_length++]=ac_bits[i]; 
	for(i=0;i<162;i++) 
		code_stream[code_stream_length++]=ac_huffval[i]; 
    } 
    else 
    { 
	for(i=0;i<16;i++) 
		code_stream[code_stream_length++]=co_ac_bits[i]; 
	for(i=0;i<162;i++) 
		code_stream[code_stream_length++]=co_ac_huffval[i]; 
    } 
 
    /* 
    **  Define Restart Interval 
    */ 
    code_stream[code_stream_length++]=0xff; 
    code_stream[code_stream_length++]=0xdd; 
    code_stream[code_stream_length++]=0x00; 
    code_stream[code_stream_length++]=0x04; 
    code_stream[code_stream_length++]=interval.rh_rl[1]; 
	code_stream[code_stream_length++]=interval.rh_rl[0]; 
	/* 
    ** Define Restart Interval 
    */ 
 
    for(i=0;i<(img_height>>3);i++) 
       { 
 
       /* 
       **read 8 lines from the source imgfile 
       */ 
        
       for(j=0;j<8;j++) 
       { 
	   fread(buffer+j*((img_width>>3)<<3),1,((img_width>>3)<<3),fp_so); 
	   fseek(fp_so,img_width-((img_width>>3)<<3),SEEK_CUR); 
	   } 
 
       for(j=0;j<(img_width>>3);j++) 
	  { 
	   
	  /* 
	  ** read one 8x8 block to si_data[][] 
	  */ 
 
	  for(k=0;k<8;k++) 
	     for(l=0;l<8;l++) 
		si_data[k][l]=(int)(buffer[k*((img_width>>3)<<3)+j*8+l])-128; 
 
	  /* 
	  **  DCT transform 
	  */ 
 
	  dct_tran(); 
	   
	  /*   
	  **  Quantization 
	  */ 
 
	  if(color==0) 
	  { 
		quant(qu_table); 
	  } 
	  else 
	  { 
		quant(co_qu_table); 
	  } 
	   
	  /* 
	  **   chage to zigzag sequence 
	  */ 
 
	  zigzag(); 
	   
	  encode(); 
 
	  block_count++; 
	   
	  if((block_count%interval.restart)==0) 
	     { 
	     if(bit_last_left!=8) 
		{ 
		pad=0xff; 
		pad>>=(8-bit_last_left); 
		code_stream[code_stream_length++]|=pad; 
		bit_last_left=8; 
		if(code_stream[code_stream_length-1]==0xff) 
		   { 
		   code_stream[code_stream_length]=0; 
		   code_stream_length++; 
		   } 
		/* 
		**  byte padding 
		*/ 
		} 
	     code_stream[code_stream_length++]=0xff; 
	     code_stream[code_stream_length++]=((n++)&7)+0xd0; 
	     dc_pre=0; 
	     /* 
	     **  Init before a new interval 
	     */ 
	     } 
	  } 
       } 
     
    code_stream[code_stream_length++]=0xff; 
    /* 
    ** End Of Image 
    */ 
    code_stream[code_stream_length++]=0xd9; 
     
    fwrite(code_stream,1,code_stream_length,fp_tar); 
    fclose(fp_so); 
    fclose(fp_tar); 
    ftime( &end_time ) ; 
    second_d = end_time.millitm - start_time.millitm ; 
    second_d = second_d + 
		  (end_time.time-start_time.time) * 1000 ; 
    printf( " The encoding costs: %.3f second.\n", (float)second_d/1000.0 ) ; 
    }