📄 enc.c
字号:
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
dataptr[0] = tmp10 + tmp11; /* phase 3 */
dataptr[4] = tmp10 - tmp11;
z1 = (tmp12 + tmp13) * ((float) 0.707106781); /* c4 */
dataptr[2] = tmp13 + z1; /* phase 5 */
dataptr[6] = tmp13 - z1;
/* Odd part */
tmp10 = tmp4 + tmp5; /* phase 2 */
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
z5 = (tmp10 - tmp12) * ((float) 0.382683433); /* c6 */
z2 = ((float) 0.541196100) * tmp10 + z5; /* c2-c6 */
z4 = ((float) 1.306562965) * tmp12 + z5; /* c2+c6 */
z3 = tmp11 * ((float) 0.707106781); /* c4 */
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
dataptr[5] = z13 + z2; /* phase 6 */
dataptr[3] = z13 - z2;
dataptr[1] = z11 + z4;
dataptr[7] = z11 - z4;
dataptr += 8; /* advance pointer to next row */
}
/* Pass 2: process columns. */
dataptr = datafloat;
for (ctr = 7; ctr >= 0; ctr--) {
tmp0 = dataptr[0] + dataptr[56];
tmp7 = dataptr[0] - dataptr[56];
tmp1 = dataptr[8] + dataptr[48];
tmp6 = dataptr[8] - dataptr[48];
tmp2 = dataptr[16] + dataptr[40];
tmp5 = dataptr[16] - dataptr[40];
tmp3 = dataptr[24] + dataptr[32];
tmp4 = dataptr[24] - dataptr[32];
/* Even part */
tmp10 = tmp0 + tmp3; /* phase 2 */
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
dataptr[0] = tmp10 + tmp11; /* phase 3 */
dataptr[32] = tmp10 - tmp11;
z1 = (tmp12 + tmp13) * ((float) 0.707106781); /* c4 */
dataptr[16] = tmp13 + z1; /* phase 5 */
dataptr[48] = tmp13 - z1;
/* Odd part */
tmp10 = tmp4 + tmp5; /* phase 2 */
tmp11 = tmp5 + tmp6;
tmp12 = tmp6 + tmp7;
/* The rotator is modified from fig 4-8 to avoid extra negations. */
z5 = (tmp10 - tmp12) * ((float) 0.382683433); /* c6 */
z2 = ((float) 0.541196100) * tmp10 + z5; /* c2-c6 */
z4 = ((float) 1.306562965) * tmp12 + z5; /* c2+c6 */
z3 = tmp11 * ((float) 0.707106781); /* c4 */
z11 = tmp7 + z3; /* phase 5 */
z13 = tmp7 - z3;
dataptr[40] = z13 + z2; /* phase 6 */
dataptr[24] = z13 - z2;
dataptr[8] = z11 + z4;
dataptr[56] = z11 - z4;
dataptr++; /* advance pointer to next column */
}
// Quantize/descale the coefficients, and store into output array
for (i = 0; i < 64; i++) {
/* Apply the quantization and scaling factor */
temp = datafloat[i] * fdtbl[i];
/* Round to nearest integer.
Since C does not specify the direction of rounding for negative
quotients, we have to force the dividend positive for portability.
The maximum coefficient size is +-16K (for 12-bit data), so this
code should work for either 16-bit or 32-bit ints.
*/
outdata[i] = (SWORD) ((SWORD)(temp + 16384.5) - 16384);
}
}
void process_DU(SBYTE *ComponentDU,float *fdtbl,SWORD *DC,
bitstring *HTDC,bitstring *HTAC)
{
bitstring EOB=HTAC[0x00];
bitstring M16zeroes=HTAC[0xF0];
BYTE i;
BYTE startpos;
BYTE end0pos;
BYTE nrzeroes;
BYTE nrmarker;
SWORD Diff;
fdct_and_quantization(ComponentDU,fdtbl,DU_DCT);
//zigzag reorder
for (i=0;i<=63;i++) DU[zigzag[i]]=DU_DCT[i];
Diff=DU[0]-*DC;
*DC=DU[0];
//Encode DC
if (Diff==0) writebits(HTDC[0]); //Diff might be 0
else {writebits(HTDC[category[Diff]]);
writebits(bitcode[Diff]);
}
//Encode ACs
for (end0pos=63;(end0pos>0)&&(DU[end0pos]==0);end0pos--) ;
//end0pos = first element in reverse order !=0
if (end0pos==0) {writebits(EOB);return;}
i=1;
while (i<=end0pos)
{
startpos=i;
for (; (DU[i]==0)&&(i<=end0pos);i++) ;
nrzeroes=i-startpos;
if (nrzeroes>=16) {
for (nrmarker=1;nrmarker<=nrzeroes/16;nrmarker++) writebits(M16zeroes);
nrzeroes=nrzeroes%16;
}
writebits(HTAC[nrzeroes*16+category[DU[i]]]);writebits(bitcode[DU[i]]);
i++;
}
if (end0pos!=63) writebits(EOB);
}
void load_data_units_from_RGB_buffer(WORD xpos,WORD ypos)
{
BYTE x,y;
BYTE pos=0;
DWORD location;
BYTE R,G,B;
location=ypos*Ximage+xpos;
for (y=0;y<8;y++)
{
for (x=0;x<8;x++)
{
R=RGB_buffer[location].R;G=RGB_buffer[location].G;B=RGB_buffer[location].B;
YDU[pos]=Y(R,G,B);
CbDU[pos]=Cb(R,G,B);
CrDU[pos]=Cr(R,G,B);
location++;pos++;
}
location+=Ximage-8;
}
}
void main_encoder()
{
SWORD DCY=0,DCCb=0,DCCr=0; //DC coefficients used for differential encoding
WORD xpos,ypos;
for (ypos=0;ypos<Yimage;ypos+=8)
for (xpos=0;xpos<Ximage;xpos+=8)
{
load_data_units_from_RGB_buffer(xpos,ypos);
process_DU(YDU,fdtbl_Y,&DCY,YDC_HT,YAC_HT);
process_DU(CbDU,fdtbl_Cb,&DCCb,CbDC_HT,CbAC_HT);
process_DU(CrDU,fdtbl_Cb,&DCCr,CbDC_HT,CbAC_HT);
}
}
void load_bitmap(char *bitmap_name, WORD *Ximage_original, WORD *Yimage_original)
{
WORD Xdiv8,Ydiv8;
BYTE nr_fillingbytes;//The number of the filling bytes in the BMP file
// (the dimension in bytes of a BMP line on the disk is divisible by 4)
colorRGB lastcolor;
WORD column;
BYTE TMPBUF[256];
WORD nrline_up,nrline_dn,nrline;
WORD dimline;
colorRGB *tmpline;
FILE *fp_bitmap=fopen(bitmap_name,"rb");
if (fp_bitmap==NULL) exitmessage("Cannot open bitmap file.File not found ?");
if (fread(TMPBUF,1,54,fp_bitmap)!=54)
exitmessage("Need a truecolor BMP to encode.");
if ((TMPBUF[0]!='B')||(TMPBUF[1]!='M')||(TMPBUF[28]!=24))
exitmessage("Need a truecolor BMP to encode.");
Ximage=(WORD)TMPBUF[19]*256+TMPBUF[18];Yimage=(WORD)TMPBUF[23]*256+TMPBUF[22];
*Ximage_original=Ximage;*Yimage_original=Yimage; //Keep the old dimensions
// of the image
if (Ximage%8!=0) Xdiv8=(Ximage/8)*8+8;
else Xdiv8=Ximage;
if (Yimage%8!=0) Ydiv8=(Yimage/8)*8+8;
else Ydiv8=Yimage;
// The image we encode shall be filled with the last line and the last column
// from the original bitmap, until Ximage and Yimage are divisible by 8
// Load BMP image from disk and complete X
RGB_buffer=(colorRGB *)(malloc(3*Xdiv8*Ydiv8));
if (RGB_buffer==NULL) exitmessage("Not enough memory for the bitmap image.");
if (Ximage%4!=0) nr_fillingbytes=4-(Ximage%4);
else nr_fillingbytes=0;
for (nrline=0;nrline<Yimage;nrline++)
{
fread(RGB_buffer+nrline*Xdiv8,1,Ximage*3,fp_bitmap);
fread(TMPBUF,1,nr_fillingbytes,fp_bitmap);
memcpy(&lastcolor,RGB_buffer+nrline*Xdiv8+Ximage-1,3);
for (column=Ximage;column<Xdiv8;column++)
{memcpy(RGB_buffer+nrline*Xdiv8+column,&lastcolor,3);}
}
Ximage=Xdiv8;
dimline=Ximage*3;tmpline=(colorRGB *)malloc(dimline);
if (tmpline==NULL) exitmessage("Not enough memory.");
//Reorder in memory the inversed bitmap
for (nrline_up=Yimage-1,nrline_dn=0;nrline_up>nrline_dn;nrline_up--,nrline_dn++)
{
memcpy(tmpline,RGB_buffer+nrline_up*Ximage, dimline);
memcpy(RGB_buffer+nrline_up*Ximage,RGB_buffer+nrline_dn*Ximage,dimline);
memcpy(RGB_buffer+nrline_dn*Ximage,tmpline,dimline);
}
// Y completion:
memcpy(tmpline,RGB_buffer+(Yimage-1)*Ximage,dimline);
for (nrline=Yimage;nrline<Ydiv8;nrline++)
{memcpy(RGB_buffer+nrline*Ximage,tmpline,dimline);}
Yimage=Ydiv8;
free(tmpline);fclose(fp_bitmap);
}
void init_all()
{
set_DQTinfo();
set_DHTinfo();
init_Huffman_tables();
set_numbers_category_and_bitcode();
precalculate_YCbCr_tables();
prepare_quant_tables();
}
void main(int argc,char *argv[])
{
char BMP_filename[64];
char JPG_filename[64];
WORD Ximage_original,Yimage_original; //the original image dimensions,
// before we made them divisible by 8
BYTE len_filename;
bitstring fillbits; //filling bitstring for the bit alignment of the EOI marker
if (argc>1) { strcpy(BMP_filename,argv[1]);
if (argc>2) strcpy(JPG_filename,argv[2]);
else { strcpy(JPG_filename,BMP_filename);
len_filename=strlen(BMP_filename);
strcpy(JPG_filename+(len_filename-3),"jpg");
}
}
else exitmessage("Syntax: enc fis.bmp [fis.jpg]");
load_bitmap(BMP_filename, &Ximage_original, &Yimage_original);
fp_jpeg_stream=fopen(JPG_filename,"wb");
init_all();
SOF0info.width=Ximage_original;
SOF0info.height=Yimage_original;
writeword(0xFFD8); //SOI
write_APP0info();
// write_comment("Cris made this JPEG with his own encoder");
write_DQTinfo();
write_SOF0info();
write_DHTinfo();
write_SOSinfo();
bytenew=0;bytepos=7;
main_encoder();
//Do the bit alignment of the EOI marker
if (bytepos>=0) {
fillbits.length=bytepos+1;
fillbits.value=(1<<(bytepos+1))-1;
writebits(fillbits);
}
writeword(0xFFD9); //EOI
free(RGB_buffer); free(category_alloc);free(bitcode_alloc);
fclose(fp_jpeg_stream);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -