简单的JPEG解码程序

// simplejpeg.cpp : Defines the entry point for the console application.
//
//header file
//#include "bmp.h"


//*************************************************************************************
//#include "jpeg.h"
#pragma pack(1)
#define M_SOF0  0xc0
#define M_DHT   0xc4
#define M_EOI   0xd9
#define M_SOS   0xda
#define M_DQT   0xdb
#define M_DRI   0xdd
#define M_APP0  0xe0

static int Zig_Zag[8][8]={{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,37,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}
       };

#define W1 2841 /* 2048*sqrt(2)*cos(1*pi/16) */
#define W2 2676 /* 2048*sqrt(2)*cos(2*pi/16) */
#define W3 2408 /* 2048*sqrt(2)*cos(3*pi/16) */
#define W5 1609 /* 2048*sqrt(2)*cos(5*pi/16) */
#define W6 1108 /* 2048*sqrt(2)*cos(6*pi/16) */
#define W7 565  /* 2048*sqrt(2)*cos(7*pi/16) */


//*************************************************************************************
typedef char CHAR;
typedef short SHORT;
typedef long LONG;

 

typedef unsigned long       DWORD;
typedef int                 BOOL;
typedef unsigned char       BYTE;
typedef unsigned short      WORD;

 

typedef int HFILE;
typedef CHAR *LPSTR, *PSTR;

#define FALSE 0
#define TRUE 1


typedef struct tagBITMAPINFOHEADER{
        DWORD      biSize;
        LONG       biWidth;
        LONG       biHeight;
        WORD       biPlanes;
        WORD       biBitCount;
        DWORD      biCompression;
        DWORD      biSizeImage;
        LONG       biXPelsPerMeter;
        LONG       biYPelsPerMeter;
        DWORD      biClrUsed;
        DWORD      biClrImportant;
} BITMAPINFOHEADER, * LPBITMAPINFOHEADER,*PBITMAPINFOHEADER;

typedef struct tagBITMAPFILEHEADER {
        WORD    bfType;
        DWORD   bfSize;
        WORD    bfReserved1;
        WORD    bfReserved2;
        DWORD   bfOffBits;
}  BITMAPFILEHEADER,  * LPBITMAPFILEHEADER,*PBITMAPFILEHEADER;

/* constants for the biCompression field */
#define BI_RGB        0L
#define BI_RLE8       1L
#define BI_RLE4       2L
#define BI_BITFIELDS  3L


typedef struct tagRGBQUAD {
        BYTE    rgbBlue;
        BYTE    rgbGreen;
        BYTE    rgbRed;
        BYTE    rgbReserved;
} RGBQUAD;
typedef RGBQUAD * LPRGBQUAD;


#define MAKEWORD(a, b)      ((WORD)(((BYTE)(a)) | ((WORD)((BYTE)(b))) << 8))
#define MAKELONG(a, b)      ((LONG)(((WORD)(a)) | ((DWORD)((WORD)(b))) << 16))
#define LOWORD(l)           ((WORD)(l))
#define HIWORD(l)           ((WORD)(((DWORD)(l) >> 16) & 0xFFFF))
#define LOBYTE(w)           ((BYTE)(w))
#define HIBYTE(w)           ((BYTE)(((WORD)(w) >> 8) & 0xFF))

//---yk--- add

 


#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


//
//Jpeg functions
BOOL LoadJpegFile(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;
char *            hImgData=NULL;
DWORD              NumColors;
DWORD              LineBytes;
DWORD              ImgWidth=0 , ImgHeight=0;
char*             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;

 


BOOL LoadJpegFile (char *JpegFileName)
{
 FILE*      hfjpg;
 DWORD          ImgSize;
 DWORD              BufSize,JpegBufSize;
 FILE*              hfbmp;
 FILE*              IMGdata;
 void *      hJpegBuf;
 int       funcret;
 DWORD i;
 LPBITMAPINFOHEADER lpImgData;

 char * hImgData256;

 if((hfjpg=fopen(JpegFileName,"rb"))==NULL)
 {
  showerror(FUNC_FILE_ERROR);
  return FALSE;
 }
/*SEEK_CUR
Current position of file pointer.
SEEK_END
End of file.
SEEK_SET
Beginning of file.*/


 //get jpg file length
 fseek(hfjpg,0L,SEEK_END);
 JpegBufSize=ftell(hfjpg);
 //rewind to the beginning of the file
 fseek(hfjpg,0L,SEEK_SET);

 if((hJpegBuf=malloc(JpegBufSize))==NULL)
 {
  fclose(hfjpg);
  showerror(FUNC_MEMORY_ERROR);
  
  return FALSE;
 }
 lpJpegBuf=(unsigned char  *)hJpegBuf;
 fread((unsigned char  *)hJpegBuf,sizeof( char ),JpegBufSize,hfjpg);
 fclose(hfjpg);
 
 InitTable();

 if((funcret=InitTag())!=FUNC_OK)
 {
 // GlobalUnlock(hJpegBuf);
  free(hJpegBuf);
  showerror(funcret);
  return FALSE;
 }
 //create new bitmapfileheader and bitmapinfoheader
 memset((char *)&bf,0,sizeof(BITMAPFILEHEADER)); 
 memset((char *)&bi,0,sizeof(BITMAPINFOHEADER));

 bi.biSize=(DWORD)sizeof(BITMAPINFOHEADER);
 bi.biWidth=(LONG)(ImgWidth);
 bi.biHeight=(LONG)(ImgHeight);
 bi.biPlanes=1;
 bi.biBitCount=24;
 bi.biClrUsed=0;
 bi.biClrImportant=0;
 bi.biCompression=BI_RGB;
 NumColors=0;
 printf("bi.biWidth is %ld/n",bi.biWidth);
printf("bi.biBitCount is %ld/n",bi.biBitCount);
 LineBytes=(DWORD)WIDTHBYTES(bi.biWidth*bi.biBitCount);
 printf("LineBytes is %ld/n",LineBytes);
 ImgSize=(DWORD)LineBytes*bi.biHeight;//???????
 printf("size is %ld/n",ImgSize);
 bf.bfType=0x4d42;
int a= sizeof(BITMAPFILEHEADER);
int b= sizeof(BITMAPINFOHEADER);
//注意字节对齐问题!!!!!!!!!!!!!!!!!!!!!!!!1
//如果没有#pragma pack(1),a是16~~~~~~~
int c=NumColors*sizeof(RGBQUAD);

 bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD)+ImgSize;
 bf.bfOffBits=54;//(DWORD)(NumColors*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER));
 BufSize=bf.bfSize-sizeof(BITMAPFILEHEADER);
// printf("size is %ld/n",BufSize);
 if((hImgData=(char*)malloc(BufSize))==NULL)
 {
  //GlobalUnlock(hJpegBuf);
  free(hJpegBuf);
  showerror(FUNC_MEMORY_ERROR);
  showerror(FUNC_MEMORY_ERROR);
  return FALSE;
 }
// lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);
 lpImgData=(LPBITMAPINFOHEADER)hImgData;
 memcpy(lpImgData,(char *)&bi,sizeof(BITMAPINFOHEADER));
 lpPtr=(char *)lpImgData+sizeof(BITMAPINFOHEADER);

 if((SampRate_Y_H==0)||(SampRate_Y_V==0))
 {
 // GlobalUnlock(hJpegBuf);
  free(hJpegBuf);
  //GlobalUnlock(hImgData);
  free(hImgData);
  hImgData=NULL;
  showerror(FUNC_FORMAT_ERROR);
  return FALSE ;
 }

 funcret=Decode();
 if(funcret==FUNC_OK)
 {
  //hDc=GetDC(hWnd);
/*  hBitmap=CreateDIBitmap(hDc, (LPBITMAPINFOHEADER)lpImgData, (LONG)CBM_INIT,
      (LPSTR)lpImgData+sizeof(BITMAPINFOHEADER) +NumColors*sizeof(RGBQUAD),
         (LPBITMAPINFO)lpImgData, DIB_RGB_COLORS);
*/
 // hfbmp=fopen("c://jpeg2-bmp.bmp","Wb");

  if((hfbmp=fopen("jpeg2-bmp.bmp","wb"))==NULL)
  {
   showerror(FUNC_FILE_ERROR);
   return FALSE;
  }

  // hfbmp=fopen("c://jpeg2-bmp.bmp","Wb");

 

  fwrite((LPSTR)&bf,sizeof(BITMAPFILEHEADER),1,hfbmp);
  fwrite((LPSTR)lpImgData,sizeof(char),BufSize,hfbmp);

  if((IMGdata=fopen("111.txt","wb"))==NULL)
  {
   showerror(FUNC_FILE_ERROR);
   return FALSE;
  }
  DWORD xx = ImgWidth*ImgHeight;
  if(( hImgData256=(char *)malloc(xx))==NULL)
  {
   //GlobalUnlock(hJpegBuf);
   free(hImgData256);
   showerror(FUNC_MEMORY_ERROR);
   showerror(FUNC_MEMORY_ERROR);
   showerror(FUNC_MEMORY_ERROR);
   return FALSE;
  }

  char * temp=hImgData256;
  for(i=0; i < xx; i++)
  {
   i;
   char t3=*lpPtr;
   t3 &= 0xE0;
   char t1=*(lpPtr+1);
   t1 = t1>>3;
   t1 &= 0x1c;
   char t2=*(lpPtr+2);
   t2=t2>>6;
   t2 &= 0x03;
   char t4 = t3 + t1 + t2 ;
   *temp++=t4;
   lpPtr=lpPtr+ 3;
   //不能使用temp+=3;
  }
  int count=fwrite(hImgData256,sizeof(char),xx,IMGdata);
  //free((void*)hImgData256);
  fclose(IMGdata);

  fclose(hfbmp);
  
//  ReleaseDC(hWnd,hDc);
//  GlobalUnlock(hJpegBuf);
  free(hJpegBuf);
  //GlobalUnlock(hImgData);
  return TRUE;
 }
 else
 {
  //GlobalUnlock(hJpegBuf);
  free(hJpegBuf);
 // GlobalUnlock(hImgData);
  free(hImgData);
  hImgData=NULL;
  showerror(funcret);
  return FALSE;
 }
}
/
void showerror(int funcret)
{
 switch(funcret)
 {
 case FUNC_MEMORY_ERROR:
     printf("Error alloc memory/n!");
  break;
 case FUNC_FILE_ERROR:
     printf("File not found!/n");
  break;
 case FUNC_FORMAT_ERROR:
  printf("File format error!/n");
  break;
 }
}

int InitTag()
{
 BOOL finish=FALSE;
 BYTE id;
 short  llength;
 short  i,j,k;
 short  huftab1,huftab2;
 short  huftabindex;
 BYTE hf_table_index;
 BYTE qt_table_index;
 BYTE comnum;

 unsigned char  *lptemp;
 short  ccount;

 lp=lpJpegBuf+2;

 while (!finish){
  id=*(lp+1);
  lp+=2;
  switch (id){
  case M_APP0:
   llength=MAKEWORD(*(lp+1),*lp);
   lp+=llength;
   break;
  case M_DQT:
   llength=MAKEWORD(*(lp+1),*lp);
   qt_table_index=(*(lp+2))&0x0f;
   lptemp=lp+3;
   if(llength<80){
    for(i=0;i<64;i++)
     qt_table[qt_table_index][i]=(short)*(lptemp++);
   }
   else{
    for(i=0;i<64;i++)
     qt_table[qt_table_index][i]=(short)*(lptemp++);
                qt_table_index=(*(lptemp++))&0x0f;
      for(i=0;i<64;i++)
     qt_table[qt_table_index][i]=(short)*(lptemp++);
     }
     lp+=llength;  
   break;
  case M_SOF0:
    llength=MAKEWORD(*(lp+1),*lp);
    ImgHeight=MAKEWORD(*(lp+4),*(lp+3));
    ImgWidth=MAKEWORD(*(lp+6),*(lp+5));
            comp_num=*(lp+7);
      if((comp_num!=1)&&(comp_num!=3))
      return FUNC_FORMAT_ERROR;
   if(comp_num==3){
    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+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<code_len_table[huftabindex][i]){
       code_value_table[huftabindex][k+j]=(short)(*(lptemp++));
       k++;
      }
      j+=k; 
     }
    i=0;
    while (code_len_table[huftabindex][i]==0)
      i++;
    for (j=0;j<i;j++){
     huf_min_value[huftabindex][j]=0;
     huf_max_value[huftabindex][j]=0;
    }
    huf_min_value[huftabindex][i]=0;
    huf_max_value[huftabindex][i]=code_len_table[huftabindex][i]-1;
    for (j=i+1;j<16;j++){
     huf_min_value[huftabindex][j]=(huf_max_value[huftabindex][j-1]+1)<<1;
     huf_max_value[huftabindex][j]=huf_min_value[huftabindex][j]+code_len_table[huftabindex][j]-1;
    }
    code_pos_table[huftabindex][0]=0;
    for (j=1;j<16;j++)
       code_pos_table[huftabindex][j]=code_len_table[huftabindex][j-1]+code_pos_table[huftabindex][j-1];
      lp+=llength;
   }  //if
   else{
     hf_table_index=*(lp+2);
    lp+=2;
    while (hf_table_index!=0xff){
     huftab1=(short)hf_table_index>>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<code_len_table[huftabindex][i])
       {
        code_value_table[huftabindex][k+j]=(short)(*(lptemp++));
        k++;
       }
       j+=k;
      }
     i=0;
     while (code_len_table[huftabindex][i]==0)
      i++;
     for (j=0;j<i;j++){
      huf_min_value[huftabindex][j]=0;
      huf_max_value[huftabindex][j]=0;
     }
     huf_min_value[huftabindex][i]=0;
     huf_max_value[huftabindex][i]=code_len_table[huftabindex][i]-1;
     for (j=i+1;j<16;j++){
      huf_min_value[huftabindex][j]=(huf_max_value[huftabindex][j-1]+1)<<1;
      huf_max_value[huftabindex][j]=huf_min_value[huftabindex][j]+code_len_table[huftabindex][j]-1;
     }
     code_pos_table[huftabindex][0]=0;
     for (j=1;j<16;j++)
      code_pos_table[huftabindex][j]=code_len_table[huftabindex][j-1]+code_pos_table[huftabindex][j-1];
     lp+=ccount;
     hf_table_index=*lp;
    }  //while
   }  //else
   break;
  case M_DRI:
   llength=MAKEWORD(*(lp+1),*lp);
   restart=MAKEWORD(*(lp+3),*(lp+2));
   lp+=llength;
   break;
  case M_SOS:
   llength=MAKEWORD(*(lp+1),*lp);
   comnum=*(lp+2);
   if(comnum!=comp_num)
    return FUNC_FORMAT_ERROR;
   lptemp=lp+3;
   for (i=0;i<comp_num;i++){
    if(*lptemp==comp_index[0]){
     YDcIndex=(*(lptemp+1))>>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<VV;i++)
  for(j=0;j<H;j++)
   for(k=0;k<8;k++)
    for(h=0;h<8;h++)
     buf[(i*8+k)*SampRate_Y_H*8+j*8+h]=*pQtZzMCU++;
}
///
void StoreBuffer()
{
 short i,j;
 unsigned char  *lpbmp;
 unsigned char R,G,B;
 int y,u,v,rr,gg,bb;

 for(i=0;i<SampRate_Y_V*8;i++){
  if((sizei+i)<ImgHeight){
   lpbmp=((unsigned char *)lpPtr+(DWORD)(ImgHeight-sizei-i-1)*LineBytes+sizej*3);
   for(j=0;j<SampRate_Y_H*8;j++){
    if((sizej+j)<ImgWidth){
     y=Y[i*8*SampRate_Y_H+j];
     u=U[(i/V_YtoU)*8*SampRate_Y_H+j/H_YtoU];
     v=V[(i/V_YtoV)*8*SampRate_Y_H+j/H_YtoV];
     rr=((y<<8)+18*u+367*v)>>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<SampRate_Y_H*SampRate_Y_V;i++)  //Y
  {
   funcret=HufBlock(YDcIndex,YAcIndex);
   if (funcret!=FUNC_OK)
    return funcret;
   BlockBuffer[0]=BlockBuffer[0]+ycoef;
   ycoef=BlockBuffer[0];
   for (j=0;j<64;j++)
    *lpMCUBuffer++=BlockBuffer[j];
  }
  for (i=0;i<SampRate_U_H*SampRate_U_V;i++)  //U
  {
   funcret=HufBlock(UVDcIndex,UVAcIndex);
   if (funcret!=FUNC_OK)
    return funcret;
   BlockBuffer[0]=BlockBuffer[0]+ucoef;
   ucoef=BlockBuffer[0];
   for (j=0;j<64;j++)
    *lpMCUBuffer++=BlockBuffer[j];
  }
  for (i=0;i<SampRate_V_H*SampRate_V_V;i++)  //V
  {
   funcret=HufBlock(UVDcIndex,UVAcIndex);
   if (funcret!=FUNC_OK)
    return funcret;
   BlockBuffer[0]=BlockBuffer[0]+vcoef;
   vcoef=BlockBuffer[0];
   for (j=0;j<64;j++)
    *lpMCUBuffer++=BlockBuffer[j];
  }
  break;
 case 1:
  lpMCUBuffer=MCUBuffer;
  funcret=HufBlock(YDcIndex,YAcIndex);
  if (funcret!=FUNC_OK)
   return funcret;
  BlockBuffer[0]=BlockBuffer[0]+ycoef;
  ycoef=BlockBuffer[0];
  for (j=0;j<64;j++)
   *lpMCUBuffer++=BlockBuffer[j];
  for (i=0;i<128;i++)
   *lpMCUBuffer++=0;
  break;
 default:
  return FUNC_FORMAT_ERROR;
 }
 return FUNC_OK;
}
//
int HufBlock(BYTE dchufindex,BYTE achufindex)
{
 short count=0;
 short i;
 int funcret;

 //dc
 HufTabIndex=dchufindex;
 funcret=DecodeElement();
 if(funcret!=FUNC_OK)
  return funcret;

 BlockBuffer[count++]=vvalue;
 //ac
 HufTabIndex=achufindex;
 while (count<64){
  funcret=DecodeElement();
  if(funcret!=FUNC_OK)
   return funcret;
  if ((rrun==0)&&(vvalue==0)){
   for (i=count;i<64;i++)
    BlockBuffer[i]=0;
   count=64;
  }
  else{
   for (i=0;i<rrun;i++)
    BlockBuffer[count++]=0;
   BlockBuffer[count++]=vvalue;
  }
 }
 return FUNC_OK;
}
//
int DecodeElement()
{
 int thiscode,tempcode;
 unsigned short temp,valueex;
 short codelen;
 BYTE hufexbyte,runsize,tempsize,sign;
 BYTE newbyte,lastbyte;

 if(BitPos>=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 ((thiscode<huf_min_value[HufTabIndex][codelen-1])||
    (code_len_table[HufTabIndex][codelen-1]==0)||
    (thiscode>huf_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<<tempsize)+(lastbyte>>BitPos);
  CurByte=lastbyte&And[BitPos];
 }  //else
 sign=valueex>>(runsize-1);
 if(sign)
  vvalue=valueex;
 else{
  valueex=valueex^0xffff;
  temp=0xffff<<runsize;
  vvalue=-(short)(valueex^temp);
 }
 return FUNC_OK;
}
/
void IQtIZzMCUComponent(short flag)
{
 short H,VV;
 short i,j;
 int *pQtZzMCUBuffer;
 short  *pMCUBuffer;

 switch(flag){
 case 0:
  H=SampRate_Y_H;
  VV=SampRate_Y_V;
  pMCUBuffer=MCUBuffer;
  pQtZzMCUBuffer=QtZzMCUBuffer;
  break;
 case 1:
  H=SampRate_U_H;
  VV=SampRate_U_V;
  pMCUBuffer=MCUBuffer+Y_in_MCU*64;
  pQtZzMCUBuffer=QtZzMCUBuffer+Y_in_MCU*64;
  break;
 case 2:
  H=SampRate_V_H;
  VV=SampRate_V_V;
  pMCUBuffer=MCUBuffer+(Y_in_MCU+U_in_MCU)*64;
  pQtZzMCUBuffer=QtZzMCUBuffer+(Y_in_MCU+U_in_MCU)*64;
  break;
 }
 for(i=0;i<VV;i++)
  for (j=0;j<H;j++)
   IQtIZzBlock(pMCUBuffer+(i*H+j)*64,pQtZzMCUBuffer+(i*H+j)*64,flag);
}
//
void IQtIZzBlock(short  *s ,int * d,short flag)
{
 short i,j;
 short tag;
 short *pQt;
 int buffer2[8][8];
 int *buffer1;
 short offset;

 switch(flag){
 case 0:
  pQt=YQtTable;
  offset=128;
  break;
 case 1:
  pQt=UQtTable;
  offset=0;
  break;
 case 2:
  pQt=VQtTable;
  offset=0;
  break;
 }

 for(i=0;i<8;i++)
  for(j=0;j<8;j++){
   tag=Zig_Zag[i][j];
   buffer2[i][j]=(int)s[tag]*(int)pQt[tag];
  }
 buffer1=(int *)buffer2;
 Fast_IDCT(buffer1);
 for(i=0;i<8;i++)
  for(j=0;j<8;j++)
   d[i*8+j]=buffer2[i][j]+offset;
}
///
void Fast_IDCT(int * block)
{
 short i;

 for (i=0; i<8; i++)
  idctrow(block+8*i);

 for (i=0; i<8; i++)
  idctcol(block+i);
}
///
BYTE  ReadByte()
{
 BYTE  i;

 i=*(lp++);
 if(i==0xff)
  lp++;
 BitPos=8;
 CurByte=i;
 return i;
}
///
void Initialize_Fast_IDCT()
{
 short i;

 iclp = iclip+512;
 for (i= -512; i<512; i++)
  iclp[i] = (i<-256) ? -256 : ((i>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];
}

int main()
{
 LoadJpegFile("test.jpg");
 return 0;
}
 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
#ifndef JPEGDECODE_H #define JPEGDECODE_H #include "global.h" #include "globalextern.h" typedef unsigned char BYTE; struct ImageComponentData { double value[3]; }; class MBitReader { public: BYTE* Data; int m_currentData; int m_currentDataIndex; int m_currentBitPosition; MBitReader(BYTE* data,int currentDataIndex) { Data=data; m_currentBitPosition=8; m_currentDataIndex=currentDataIndex; m_currentData=Data[m_currentDataIndex]; } public: int ReadNextBit() { if (m_currentBitPosition-1> m_currentBitPosition) & 0x01; } }; class MJpegDecode { public: struct _JFIFAPPOInfo { BYTE APP0[2]; /* 02h Application Use Marker */ BYTE Length[2]; /* 04h Length of APP0 Field */ BYTE Identifier[5]; /* 06h "JFIF" (zero terminated) Id String */ BYTE Version[2]; /* 0Bh JFIF Format Revision */ BYTE Units; /* 0Dh Units used for Resolution */ BYTE Xdensity[2]; /* 0Eh Horizontal Resolution */ BYTE Ydensity[2]; /* 10h Vertical Resolution */ BYTE XThumbnail; /* 12h Thumbnail Horizontal Pixel Count */ BYTE YThumbnail; /* 13h Thumbnail Vertical Pixel Count */ } JFIFAPPOINFO; struct _JFIFDQTInfo { BYTE DQT[2]; // 14h 量化表段标记 BYTE Length[2]; // 16h 量化表段长度 BYTE Identifier; // 18h 量化表ID BYTE QTData[64]; // 19h 量化表数据 } JFIFDQTINFO[2]; struct _JFIFSOFOInfo { BYTE SOFO[2]; // 9Eh 帧开始段标记 BYTE Length[2]; // A0h 帧开始段长度 BYTE BitCount; // A2h 样本精度bit位数 BYTE Height[2]; // A5h 图像像素宽度 BYTE Width[2]; // A3h 图像像素高度 BYTE ComponentsCount; // A7h 图像组件计数 BYTE YIdentifier; // A8h 亮度Y的ID号 BYTE YHVSamplingCoefficient; // A9h 亮度Y垂直和水平采样系数 BYTE YUsedDQTIdentifier; // AAh 亮度Y使用的量化表ID号 BYTE CbIdentifier; // ABh 色度Cb的ID号 BYTE CbHVSamplingCoefficient; // ACh 色度Cb垂直和水平采样系数 BYTE CbUsedDQTIdentifier; // ADh 色度Cb使用的量化表ID号 BYTE CrIdentifier; // AEh 色度Cr的ID号 BYTE CrHVSamplingCoefficient; // AFh 色度Cr垂直和水平采样系数 BYTE CrUsedDQTIdentifier; // B0h 色度Cr使用的量化表ID号 } JFIFSOFOINFO; struct _JFIFDRIInfo { BYTE DRI[2]; BYTE Length[2]; BYTE NMCUReset[2]; //每n个MCU块就有一个 RSTn 标记. } JFIFDRIINFO; struct _JFIFDHTInfo { BYTE DHT[2]; // B1h 哈夫曼表定义段标记 BYTE Length[2]; // B3h 哈夫曼表段长度 BYTE HTIdentifier; // B5h 哈夫曼表号 BYTE NBitsSymbolsCount[16]; // B6h (符号的二进制位长度为n)的符号个数 BYTE SymbolsTable[256]; // C6h 按递增次序代码长度排列的符号表 } JFIFDHTINFO[2][2]; struct _JFIFSOSInfo { BYTE SOS[2]; // 261h 扫描开始段标记 BYTE Length[2]; // 263h 扫描开始段长度 BYTE ComponentsCount; // 265h 扫描行内组件的数量 BYTE YIdentifier; // 266h 亮度Y的ID号 BYTE YHTTableID; // 267h 亮度Y使用的哈夫曼表ID号 BYTE CbIdentifier; // 268h 色度Cb的ID号 BYTE CbHTTableID; // 269h 色度Cb使用的哈夫曼表ID号 BYTE CrIdentifier; // 26Ah 色度Cr的ID号 BYTE CrHTTableID; // 26Bh 色度Cr使用的哈夫曼表ID号 BYTE Reserved[3]; // 26Ch 3个未知保留字节 } JFIFSOSINFO; private: struct HuffmanTable { int CodeOfFirstNLengthSymbol[17]; //长度为N的第一个码字的整数值 int NLengthToSymbolsTableIndex[16]; //查表得到第一个长度为N的符号位于符号表的索引 } HUFFMANTABLE[2][2]; public: int ReadJFIFInfo(const BYTE* const jfifData,int jfifDataSize); void DecodeData(int mcuStartIndex,BYTE* jfifData,int jfifDataSize,ImageComponentData*& targetBitmapData); void SetHuffmanTable(); void DecodeOneDUDC(MBitReader* myBitReader,double* DU,double& lastDC,int index1,int index2); void DecodeOneDUAC(MBitReader* myBitReader,double* DU,int index1,int index2); void DecodeOneMCU(MBitReader* myBitReader,int mcuXn,int mcuYn,int mcuWidth,int mcuHeight,double *DU,ImageComponentData* targetImage); void InverseQuantization(double* du,BYTE* quantizationTable); void InverseZigzag(double* sourceDU,double* targetDU); void IDCT(double* sourceDU,double* targetDU); void YCbCrToRGB(ImageComponentData* sourceImage,ImageComponentData* targetImage); public: int imageHeight; int imageWidth; int alignedImageWidth; int alignedImageHeight; HuffmanTable* HT; double DC[3]; int HSamplingCoefficient[3]; int VSamplingCoefficient[3]; int DQTID[3]; int nMCUReset; }; #endif // JPEGDECODE_H

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值