⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jpegdec.c

📁 非常不错的jpeg压缩/解压代码,可以实现常用的JPEG压缩/解
💻 C
📖 第 1 页 / 共 2 页
字号:
	tmp7 = z11 + z13;
	tmp11= (z11 - z13) * 1.414213562f;

	z5 = (z10 + z12) * 1.847759065f; // 2*c2
	tmp10 = 1.082392200f * z12 - z5;  // 2*(c2-c6)
	tmp12 = -2.613125930f * z10 + z5; // -2*(c2+c6)

	tmp6 = tmp12 - tmp7;
	tmp5 = tmp11 - tmp6;
	tmp4 = tmp10 + tmp5;

 // Final output stage: scale down by a factor of 8
	outptr[0] = range_limit[(DESCALE((int) (tmp0 + tmp7), 3)) & 1023L];
	outptr[7] = range_limit[(DESCALE((int) (tmp0 - tmp7), 3)) & 1023L];
	outptr[1] = range_limit[(DESCALE((int) (tmp1 + tmp6), 3)) & 1023L];
	outptr[6] = range_limit[(DESCALE((int) (tmp1 - tmp6), 3)) & 1023L];
	outptr[2] = range_limit[(DESCALE((int) (tmp2 + tmp5), 3)) & 1023L];
	outptr[5] = range_limit[(DESCALE((int) (tmp2 - tmp5), 3)) & 1023L];
	outptr[4] = range_limit[(DESCALE((int) (tmp3 + tmp4), 3)) & 1023L];
	outptr[3] = range_limit[(DESCALE((int) (tmp3 - tmp4), 3)) & 1023L];

	wsptr+=8;//advance pointer to the next row
	outptr+=8;
  }
}

void precalculate_Cr_Cb_tables()
{
 WORD k;
 WORD Cr_v,Cb_v;
 for (k=0;k<=255;k++) Cr_tab[k]=(SWORD)((k-128.0)*1.402);
 for (k=0;k<=255;k++) Cb_tab[k]=(SWORD)((k-128.0)*1.772);

 for (Cr_v=0;Cr_v<=255;Cr_v++)
  for (Cb_v=0;Cb_v<=255;Cb_v++)
   Cr_Cb_green_tab[((WORD)(Cr_v)<<8)+Cb_v]=(int)(-0.34414*(Cb_v-128.0)-0.71414*(Cr_v-128.0));

}

void convert_8x8_YCbCr_to_RGB(BYTE *Y, BYTE *Cb, BYTE *Cr, DWORD im_loc, DWORD X_image_bytes, BYTE *im_buffer)
// Functia (ca optimizare) poate fi apelata si fara parametrii Y,Cb,Cr
// Stim ca va fi apelata doar in cazul 1x1
{
  DWORD x,y;
  BYTE im_nr;
  BYTE *Y_val = Y, *Cb_val = Cb, *Cr_val = Cr;
  BYTE *ibuffer = im_buffer + im_loc;

  for (y=0;y<8;y++)
   {
	im_nr=0;
	for (x=0;x<8;x++)
	  {
	   ibuffer[im_nr++] = rlimit_table[*Y_val + Cb_tab[*Cb_val]]; //B
	   ibuffer[im_nr++] = rlimit_table[*Y_val + Cr_Cb_green_tab[WORD_hi_lo(*Cr_val,*Cb_val)]]; //G
	   ibuffer[im_nr++] = rlimit_table[*Y_val + Cr_tab[*Cr_val]]; // R
/*
// Monochrome display
	   im_buffer[im_nr++] = *Y_val;
	   im_buffer[im_nr++] = *Y_val;
	   im_buffer[im_nr++] = *Y_val;
*/
	   Y_val++; Cb_val++; Cr_val++; im_nr++;
	  }
	ibuffer+=X_image_bytes;
   }
}

void convert_8x8_YCbCr_to_RGB_tab(BYTE *Y, BYTE *Cb, BYTE *Cr, BYTE *tab, DWORD im_loc, DWORD X_image_bytes, BYTE *im_buffer)
// Functia (ca optimizare) poate fi apelata si fara parametrii Cb,Cr
{
  DWORD x,y;
  BYTE nr, im_nr;
  BYTE Y_val,Cb_val,Cr_val;
  BYTE *ibuffer = im_buffer + im_loc;

  nr=0;
  for (y=0;y<8;y++)
   {
	im_nr=0;
	for (x=0;x<8;x++)
	  {
	   Y_val=Y[nr];
	   Cb_val=Cb[tab[nr]]; Cr_val=Cr[tab[nr]]; // reindexare folosind tabelul
	   // de supraesantionare precalculat
	   ibuffer[im_nr++] = rlimit_table[Y_val + Cb_tab[Cb_val]]; //B
	   ibuffer[im_nr++] = rlimit_table[Y_val + Cr_Cb_green_tab[WORD_hi_lo(Cr_val,Cb_val)]]; //G
	   ibuffer[im_nr++] = rlimit_table[Y_val + Cr_tab[Cr_val]]; // R
	   nr++; im_nr++;
	  }
	ibuffer+=X_image_bytes;
   }
}

void calculate_tabs()
{
 BYTE tab_temp[256];
 BYTE x,y;

 // Tabelul de supraesantionare 16x16
 for (y=0;y<16;y++)
	 for (x=0;x<16;x++)
	   tab_temp[y*16+x] = (y/YV)* 8 + x/YH;

 // Din el derivam tabelele corespunzatoare celor 4 blocuri de 8x8 pixeli
 for (y=0;y<8;y++)
	{
	 for (x=0;x<8;x++)
	  tab_1[y*8+x]=tab_temp[y*16+x];
	 for (x=8;x<16;x++)
	  tab_2[y*8+(x-8)]=tab_temp[y*16+x];
	}
 for (y=8;y<16;y++)
	{
	 for (x=0;x<8;x++)
	  tab_3[(y-8)*8+x]=tab_temp[y*16+x];
	 for (x=8;x<16;x++)
	  tab_4[(y-8)*8+(x-8)]=tab_temp[y*16+x];
	}
}


int init_JPG_decoding()
{
 byte_pos=0;
 init_QT();
 calculate_mask();
 prepare_range_limit_table();
 precalculate_Cr_Cb_tables();
 return 1; //for future error check
}

DWORD filesize(FILE *fp)
{
 DWORD pos;
 DWORD pos_cur;
 pos_cur=ftell(fp);
 fseek(fp,0,SEEK_END);
 pos=ftell(fp);
 fseek(fp,pos_cur,SEEK_SET);
 return pos;
}

int load_JPEG_header(FILE *fp, DWORD *X_image, DWORD *Y_image)
{
 DWORD length_of_file;
 BYTE vers,units;
 WORD Xdensity,Ydensity,Xthumbnail,Ythumbnail;
 WORD length;
 float *qtable;
 DWORD old_byte_pos;
 Huffman_table *htable;
 DWORD j;
 BYTE precision,comp_id,nr_components;
 BYTE QT_info,HT_info;
 BYTE SOS_found,SOF_found;

 length_of_file=filesize(fp);
 buf=(BYTE *)malloc(length_of_file+4);
 if (buf==NULL) exit_func("Not enough memory for loading file");
 fread(buf,length_of_file,1,fp);

 if ((buf[0]!=0xFF)||(buf[1]!=SOI)) exit_func("Not a JPG file ?\n");
 if ((buf[2]!=0xFF)||(buf[3]!=APP0)) exit_func("Invalid JPG file.");
 if ( (buf[6]!='J')||(buf[7]!='F')||(buf[8]!='I')||(buf[9]!='F')||
	  (buf[10]!=0) ) exit_func("Invalid JPG file.");

 init_JPG_decoding();
 byte_pos=11;

 BYTE_p(byte_pos);vers=bp;
 if (vers!=1) exit_func("JFIF version not supported");
 BYTE_p(byte_pos); // vers_lo=bp;
 BYTE_p(byte_pos);  units=bp;
 if (units!=0) //exit_func("JPG format not supported");
	;//	printf("units = %d\n", units);
 WORD_p(byte_pos); Xdensity=wp; WORD_p(byte_pos); Ydensity=wp;
 if ((Xdensity!=1)||(Ydensity!=1)) //exit_func("JPG format not supported");
	 ;  //{printf("X density = %d\n",Xdensity); printf("Y density = %d\n",Ydensity);}
 BYTE_p(byte_pos);Xthumbnail=bp;BYTE_p(byte_pos);Ythumbnail=bp;
 if ((Xthumbnail!=0)||(Ythumbnail!=0))
	exit_func(" Cannot process JFIF thumbnailed files\n");
 // Start decoding process
 SOS_found=0; SOF_found=0; Restart_markers=0;
 while ((byte_pos<length_of_file)&&!SOS_found)
 {
  BYTE_p(byte_pos);
  if (bp!=0xFF) continue;
  // A marker was found
  BYTE_p(byte_pos);
  switch(bp)
  {
   case DQT: WORD_p(byte_pos); length=wp; // length of the DQT marker
			 for (j=0;j<wp-2;)
				{
				 old_byte_pos=byte_pos;
				 BYTE_p(byte_pos); QT_info=bp;
				 if ((QT_info>>4)!=0)
				 exit_func("16 bit quantization table not supported");
				 qtable=QT[QT_info&0xF];
				 load_quant_table(qtable);
				 j+=byte_pos-old_byte_pos;
				}
			 break;
   case DHT: WORD_p(byte_pos); length=wp;
			 for (j=0;j<wp-2;)
				{
				 old_byte_pos=byte_pos;
				 BYTE_p(byte_pos); HT_info=bp;
				 if ((HT_info&0x10)!=0) htable=&HTAC[HT_info&0xF];
				 else htable=&HTDC[HT_info&0xF];
				 load_Huffman_table(htable);
				 j+=byte_pos-old_byte_pos;
				}
			 break;
   case COM: WORD_p(byte_pos); length=wp;
			 byte_pos+=wp-2;
			 break;
   case DRI: Restart_markers=1;
			 WORD_p(byte_pos); length=wp; //should be = 4
			 WORD_p(byte_pos);  MCU_restart=wp;
			 if (MCU_restart==0) Restart_markers=0;
			 break;
   case SOF: WORD_p(byte_pos); length=wp; //should be = 8+3*3=17
			 BYTE_p(byte_pos); precision=bp;
			 if (precision!=8) exit_func("Only 8 bit precision supported");
			 WORD_p(byte_pos); *Y_image=wp; WORD_p(byte_pos); *X_image=wp;
			 BYTE_p(byte_pos); nr_components=bp;
			 if (nr_components!=3) exit_func("Only truecolor JPGS supported");
			 for (j=1;j<=3;j++)
				{
				 BYTE_p(byte_pos); comp_id=bp;
				 if ((comp_id==0)||(comp_id>3)) exit_func("Only YCbCr format supported");
				 switch (comp_id)
					{
					 case 1: // Y
							BYTE_p(byte_pos); YH=bp>>4;YV=bp&0xF;
							BYTE_p(byte_pos); YQ_nr=bp;
							break;
					 case 2: // Cb
							BYTE_p(byte_pos); CbH=bp>>4;CbV=bp&0xF;
							BYTE_p(byte_pos); CbQ_nr=bp;
							break;
					 case 3: // Cr
							BYTE_p(byte_pos); CrH=bp>>4;CrV=bp&0xF;
							BYTE_p(byte_pos); CrQ_nr=bp;
							break;
					}
				}
			 SOF_found=1;
			 break;
   case SOS: WORD_p(byte_pos); length=wp; //should be = 6+3*2=12
		 BYTE_p(byte_pos); nr_components=bp;
		 if (nr_components!=3) exit_func("Invalid SOS marker");
		 for (j=1;j<=3;j++)
		   {
			BYTE_p(byte_pos); comp_id=bp;
			if ((comp_id==0)||(comp_id>3)) exit_func("Only YCbCr format supported");
			switch (comp_id)
			{
			 case 1: // Y
					BYTE_p(byte_pos); YDC_nr=bp>>4;YAC_nr=bp&0xF;
					break;
			 case 2: // Cb
					BYTE_p(byte_pos); CbDC_nr=bp>>4;CbAC_nr=bp&0xF;
					break;
			 case 3: // Cr
					BYTE_p(byte_pos); CrDC_nr=bp>>4;CrAC_nr=bp&0xF;
					break;
			}
		   }
		 BYTE_p(byte_pos); BYTE_p(byte_pos); BYTE_p(byte_pos); // Skip 3 bytes
		 SOS_found=1;
		 break;
   case 0xFF:
		 break; // do nothing for 0xFFFF, sequence of consecutive 0xFF are for
			// filling purposes and should be ignored
   default:  WORD_p(byte_pos); length=wp;
		 byte_pos+=wp-2; //skip unknown marker
		 break;
  }
 }
 if (!SOS_found) exit_func("Invalid JPG file. No SOS marker found.");
 if (!SOF_found) exit_func("Progressive JPEGs not supported");

 if ((CbH>YH)||(CrH>YH)) exit_func("Vertical sampling factor for Y should be >= sampling factor for Cb,Cr");
 if ((CbV>YV)||(CrV>YV)) exit_func("Horizontal sampling factor for Y should be >= sampling factor for Cb,Cr");

 if ((CbH>=2)||(CbV>=2)) exit_func("Cb sampling factors should be = 1");
 if ((CrV>=2)||(CrV>=2)) exit_func("Cr sampling factors should be = 1");

// Restricting sampling factors for Y,Cb,Cr should give us 4 possible cases for sampling factors
// YHxYV,CbHxCbV,CrHxCrV: 2x2,1x1,1x1;  1x2,1x1,1x1; 2x1,1x1,1x1;
// and 1x1,1x1,1x1 = no upsampling needed

 Hmax=YH,Vmax=YV;
 if ( *X_image%(Hmax*8)==0) X_round=*X_image; // X_round = Multiple of Hmax*8
 else X_round=(*X_image/(Hmax*8)+1)*(Hmax*8);
 if ( *Y_image%(Vmax*8)==0) Y_round=*Y_image; // Y_round = Multiple of Vmax*8
 else Y_round=(*Y_image/(Vmax*8)+1)*(Vmax*8);

 im_buffer=(BYTE *)malloc(X_round*Y_round*4);
 if (im_buffer==NULL) exit_func("Not enough memory for storing the JPEG image");

 return 1;
}

void resync()
// byte_pos  = pozitionat pe restart marker
{
 byte_pos+=2;
 BYTE_p(byte_pos);
 if (bp==0xFF) byte_pos++; // skip 00
 w1=WORD_hi_lo(bp, 0);
 BYTE_p(byte_pos);
 if (bp==0xFF) byte_pos++; // skip 00
 w1+=bp;
 BYTE_p(byte_pos);
 if (bp==0xFF) byte_pos++; // skip 00
 w2=WORD_hi_lo(bp, 0);
 BYTE_p(byte_pos);
 if (bp==0xFF) byte_pos++; // skip 00
 w2+=bp;
 wordval=w1; d_k=0; // Reinit bitstream decoding
 DCY=0; DCCb=0; DCCr=0; // Init DC coefficients
}

void decode_MCU_1x1(DWORD im_loc)
{
 // Y
 process_Huffman_data_unit(YDC_nr,YAC_nr,&DCY);
 IDCT_transform(DCT_coeff,Y,YQ_nr);
 // Cb
 process_Huffman_data_unit(CbDC_nr,CbAC_nr,&DCCb);
 IDCT_transform(DCT_coeff,Cb,CbQ_nr);
 // Cr
 process_Huffman_data_unit(CrDC_nr,CrAC_nr,&DCCr);
 IDCT_transform(DCT_coeff,Cr,CrQ_nr);

 convert_8x8_YCbCr_to_RGB(Y,Cb,Cr,im_loc,X_image_bytes,im_buffer);
}
void decode_MCU_2x1(DWORD im_loc)
{
 // Y
 process_Huffman_data_unit(YDC_nr,YAC_nr,&DCY);
 IDCT_transform(DCT_coeff,Y_1,YQ_nr);
 process_Huffman_data_unit(YDC_nr,YAC_nr,&DCY);
 IDCT_transform(DCT_coeff,Y_2,YQ_nr);
 // Cb
 process_Huffman_data_unit(CbDC_nr,CbAC_nr,&DCCb);
 IDCT_transform(DCT_coeff,Cb,CbQ_nr);
 // Cr
 process_Huffman_data_unit(CrDC_nr,CrAC_nr,&DCCr);
 IDCT_transform(DCT_coeff,Cr,CrQ_nr);

 convert_8x8_YCbCr_to_RGB_tab(Y_1,Cb,Cr,tab_1,im_loc,X_image_bytes,im_buffer);
 convert_8x8_YCbCr_to_RGB_tab(Y_2,Cb,Cr,tab_2,im_loc+32,X_image_bytes,im_buffer);
}

void decode_MCU_2x2(DWORD im_loc)
{
 // Y
 process_Huffman_data_unit(YDC_nr,YAC_nr,&DCY);
 IDCT_transform(DCT_coeff,Y_1,YQ_nr);
 process_Huffman_data_unit(YDC_nr,YAC_nr,&DCY);
 IDCT_transform(DCT_coeff,Y_2,YQ_nr);
 process_Huffman_data_unit(YDC_nr,YAC_nr,&DCY);
 IDCT_transform(DCT_coeff,Y_3,YQ_nr);
 process_Huffman_data_unit(YDC_nr,YAC_nr,&DCY);
 IDCT_transform(DCT_coeff,Y_4,YQ_nr);
 // Cb
 process_Huffman_data_unit(CbDC_nr,CbAC_nr,&DCCb);
 IDCT_transform(DCT_coeff,Cb,CbQ_nr);
 // Cr
 process_Huffman_data_unit(CrDC_nr,CrAC_nr,&DCCr);
 IDCT_transform(DCT_coeff,Cr,CrQ_nr);

 convert_8x8_YCbCr_to_RGB_tab(Y_1,Cb,Cr,tab_1,im_loc,X_image_bytes,im_buffer);
 convert_8x8_YCbCr_to_RGB_tab(Y_2,Cb,Cr,tab_2,im_loc+32,X_image_bytes,im_buffer);
 convert_8x8_YCbCr_to_RGB_tab(Y_3,Cb,Cr,tab_3,im_loc+y_inc_value,X_image_bytes,im_buffer);
 convert_8x8_YCbCr_to_RGB_tab(Y_4,Cb,Cr,tab_4,im_loc+y_inc_value+32,X_image_bytes,im_buffer);
}

void decode_MCU_1x2(DWORD im_loc)
{
 // Y
 process_Huffman_data_unit(YDC_nr,YAC_nr,&DCY);
 IDCT_transform(DCT_coeff,Y_1,YQ_nr);
 process_Huffman_data_unit(YDC_nr,YAC_nr,&DCY);
 IDCT_transform(DCT_coeff,Y_2,YQ_nr);
 // Cb
 process_Huffman_data_unit(CbDC_nr,CbAC_nr,&DCCb);
 IDCT_transform(DCT_coeff,Cb,CbQ_nr);
 // Cr
 process_Huffman_data_unit(CrDC_nr,CrAC_nr,&DCCr);
 IDCT_transform(DCT_coeff,Cr,CrQ_nr);

 convert_8x8_YCbCr_to_RGB_tab(Y_1,Cb,Cr,tab_1,im_loc,X_image_bytes,im_buffer);
 convert_8x8_YCbCr_to_RGB_tab(Y_2,Cb,Cr,tab_3,im_loc+y_inc_value,X_image_bytes,im_buffer);
}

void decode_JPEG_image()
{
 decode_MCU_func decode_MCU;

 WORD x_mcu_cnt,y_mcu_cnt;
 DWORD nr_mcu;
 WORD X_MCU_nr,Y_MCU_nr; // Nr de MCU-uri
 DWORD MCU_dim_x; //dimensiunea in bufferul imagine a unui MCU pe axa x
 DWORD im_loc_inc; // = 7 * X_round * 4 sau 15*X_round*4;
 DWORD im_loc; //locatia in bufferul imagine

 byte_pos-=2;
 resync();

 y_inc_value = 32*X_round;
 calculate_tabs(); // Calcul tabele de supraesantionare, tinand cont de YH si YV

 if ((YH==1)&&(YV==1)) decode_MCU=decode_MCU_1x1;
 else {
	   if (YH==2)
	   {
		if (YV==2) decode_MCU=decode_MCU_2x2;
		else decode_MCU=decode_MCU_2x1;
	   }
	   else decode_MCU=decode_MCU_1x2;
 }
 MCU_dim_x=Hmax*8*4;

 Y_MCU_nr=Y_round/(Vmax*8); // nr of MCUs on Y axis
 X_MCU_nr=X_round/(Hmax*8); // nr of MCUs on X axis

 X_image_bytes=X_round*4; im_loc_inc = (Vmax*8-1) * X_image_bytes;
 nr_mcu=0; im_loc=0; // memory location of the current MCU
 for (y_mcu_cnt=0;y_mcu_cnt<Y_MCU_nr;y_mcu_cnt++)
 {
  for (x_mcu_cnt=0;x_mcu_cnt<X_MCU_nr;x_mcu_cnt++)
   {
	decode_MCU(im_loc);
	if ((Restart_markers)&&((nr_mcu+1)%MCU_restart==0)) resync();
	nr_mcu++;
	im_loc+=MCU_dim_x;
   }
  im_loc+=im_loc_inc;
 }
}

int get_JPEG_buffer(WORD X_image,WORD Y_image, BYTE **address_dest_buffer)
{
 WORD y;
 DWORD dest_loc=0;
 BYTE *src_buffer=im_buffer;
 BYTE *dest_buffer_start, *dest_buffer;

 DWORD src_bytes_per_line=X_round*4;
 DWORD dest_bytes_per_line=X_image*4;


 if ((X_round==X_image)&&(Y_round==Y_image))
	*address_dest_buffer=im_buffer;
 else
 {
  dest_buffer_start = (BYTE *)malloc(X_image*Y_image*4);
  if (dest_buffer_start==NULL) exit_func("Not enough memory for storing the JPEG image");
  dest_buffer = dest_buffer_start;
  for (y=0;y<Y_image;y++) {
	   memcpy(dest_buffer,src_buffer,dest_bytes_per_line);
	   src_buffer+=src_bytes_per_line;
	   dest_buffer+=dest_bytes_per_line;
  }
 *address_dest_buffer=dest_buffer_start;
 free(im_buffer);
 }
// release the buffer which contains the JPG file
 free(buf);
 return 1;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -