📄 jpg2bmp.c
字号:
// jpg2bmp.c
// Seloo luo
// seloo@tom.com
// 2008-10-10
//header file
#include <string.h>
#include <stdlib.h>
#include "math.h"
#include "stdio.h"
#include "DEF.H"
#include "BMP.H"
#include "JPEG.H"
#define MAKEWORD(a,b) ((WORD)(((BYTE)(a))|((WORD)((BYTE)(b)))<<8))
//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);
void InitTable(void);
int Decode(void);
int DecodeMCUBlock(void);
int HufBlock(BYTE dchufindex,BYTE achufindex);
int DecodeElement(void);
void IQtIZzMCUComponent(short flag);
void IQtIZzBlock(short*s,int*d,short flag);
void GetYUV(short flag);
void StoreBuffer(void);
BYTE ReadByte(void);
void Initialize_Fast_IDCT(void);
void Fast_IDCT(int*block);
void idctrow(int*blk);
void idctcol(int*blk);
//////////////////////////////////////////////////
//global variable declaration
BITMAPFILEHEADER bf ;
BITMAPINFOHEADER bi ;
char *hImgData=NULL ;
void *hJpegBuf=NULL ;
DWORD NumColors ;
DWORD LineBytes ;
DWORD ImgWidth=0,ImgHeight=0 ;
//////////////////////////////////////////////////
//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 ,JpegBufSize ;
FILE *hfbmp ;
int funcret ;
//BITMAPINFOHEADER *lpImgData ;
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);
printf("Jpegfile size is %ld\n",JpegBufSize);
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)
{
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("ImgWidth is %ld\n",bi.biWidth);
printf("bi.biBitCount is %d\n",bi.biBitCount);
LineBytes=(unsigned long)WIDTHBYTES(bi.biWidth*bi.biBitCount);
printf("ImgHeight is %ld\n",bi.biHeight);
ImgSize=(DWORD)LineBytes*bi.biHeight ;
printf("Image size is %ld\n",ImgSize);
bf.bfType=0x4d42 ;
bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD)+ImgSize ;
printf("sizeof(BITMAPFILEHEADER) is %d\n",sizeof(BITMAPFILEHEADER));
printf("sizeof(BITMAPINFOHEADER) is %d\n",sizeof(BITMAPINFOHEADER));
bf.bfOffBits=(DWORD)(NumColors*sizeof(RGBQUAD)+(sizeof(BITMAPFILEHEADER))+sizeof(BITMAPINFOHEADER)) ;
if((hImgData=(char*)malloc(ImgSize))==NULL)
{
free(hJpegBuf);
showerror(FUNC_MEMORY_ERROR);
return FALSE ;
}
if((SampRate_Y_H==0)||(SampRate_Y_V==0))
{
free(hJpegBuf);
free(hImgData);
hImgData=NULL ;
showerror(FUNC_FORMAT_ERROR);
return FALSE ;
}
funcret=Decode();
if(funcret==FUNC_OK)
{
if((hfbmp=fopen("c:\\test.bmp","wb"))==NULL)
{
showerror(FUNC_FILE_ERROR);
return FALSE ;
}
fwrite((char *)&bf,sizeof(BITMAPFILEHEADER),1,hfbmp);
fwrite((char *)&bi,sizeof(BITMAPINFOHEADER),1,hfbmp);
fwrite((char *)hImgData,sizeof(char),ImgSize,hfbmp);
fclose(hfbmp);
free(hJpegBuf);
return TRUE ;
}
else
{
free(hJpegBuf);
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(void)
{
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 ;
default :
if((id&0xf0)!=0xd0)
{
llength=MAKEWORD(*(lp+1),*lp);
lp+=llength ;
}
else lp+=2 ;
break ;
}//switch
}//while
return FUNC_OK ;
}
/////////////////////////////////////////////////////////////////
void InitTable(void)
{
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -