1 #include "Windows.h"
  2 #include <stdio.h>
  3 #include <iostream.h>
  4 #include <fstream.h>
  5 #include <stdlib.h>
  6 #include <math.h>
  7 #include <string.h>
  8 
  9 int OUTBYTES=0;
 10 
 11 //读入和存储bmp文件
 12 unsigned char *pBmpBuf;//读入图像数据的指针
 13 int bmpWidth;
 14 int bmpHeight;
 15 int bmpBlockcount;//视频的帧数
 16 int biBitCount;//图像类型
 17 RGBQUAD *pColorTable;//颜色表指针n
 18 bool readbmp(char *bmpname);
 19 bool saveBmp(char *bmpName, unsigned char *imgBuf, int width, int height,int biBitCount, RGBQUAD *pColorTable);
 20 
 21 bool readbmp(char *bmpname)
 22 {
 23     
 24     FILE *fp=fopen(bmpname,"rb");//二进制读方式打开指定的图像文件
 25     if(fp==0) return 0;    
 26     fseek(fp, sizeof(BITMAPFILEHEADER),0);//跳过位图文件头结构BITMAPFILEHEADER
 27     BITMAPINFOHEADER head;  //定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中
 28     fread(&head, sizeof(BITMAPINFOHEADER), 1,fp); 
 29     
 30     bmpWidth = head.biWidth;
 31     bmpHeight = head.biHeight;
 32     biBitCount = head.biBitCount;
 33     
 34     int lineByte=(bmpWidth * biBitCount/8+3)/4*4;//定义变量,计算图像每行像素所占的字节数(必须是4的倍数)
 35     if(biBitCount==8)
 36     {
 37         pColorTable=new RGBQUAD[256];
 38         fread(pColorTable,sizeof(RGBQUAD),256,fp);
 39     }
 40 
 41     pBmpBuf=new unsigned char[lineByte * bmpHeight];
 42     fread(pBmpBuf,1,lineByte * bmpHeight,fp);
 43     fclose(fp);
 44     return 1;
 45 }
 46 
 47 
 48 
 49 bool saveBmp(char *bmpName, unsigned char *imgBuf, int width, int height, 
 50              int biBitCount, RGBQUAD *pColorTable)
 51 {
 52 
 53     if(!imgBuf)
 54         return 0;
 55     int colorTablesize=0;//颜色表大小,以字节为单位,灰度图像颜色表为1024字节,彩色图像颜色表大小为0
 56     if(biBitCount==8)
 57         colorTablesize=1024;
 58     
 59     int lineByte=(width * biBitCount/8+3)/4*4;//待存储图像数据每行字节数为4的倍数
 60     FILE *fp=fopen(bmpName,"wb");
 61     if(fp==0) return 0;
 62     
 63     BITMAPFILEHEADER fileHead;
 64     fileHead.bfType = 0x4D42;//bmp类型
 65     
 66     fileHead.bfSize= sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
 67         + colorTablesize + lineByte*height;//bfSize是图像文件4个组成部分之和
 68     fileHead.bfReserved1 = 0;
 69     fileHead.bfReserved2 = 0;
 70     
 71     fileHead.bfOffBits=54+colorTablesize;//bfOffBits是图像文件前三个部分所需空间之和
 72     fwrite(&fileHead, sizeof(BITMAPFILEHEADER),1, fp);//写文件头进文件
 73     
 74     BITMAPINFOHEADER head; 
 75     head.biBitCount=biBitCount;
 76     head.biClrImportant=0;
 77     head.biClrUsed=0;
 78     head.biCompression=0;
 79     head.biHeight=height;
 80     head.biPlanes=1;
 81     head.biSize=40;
 82     head.biSizeImage=lineByte*height;
 83     head.biWidth=width;
 84     head.biXPelsPerMeter=0;
 85     head.biYPelsPerMeter=0;
 86     
 87     fwrite(&head, sizeof(BITMAPINFOHEADER),1, fp);//写位图信息头进内存
 88     
 89     if(biBitCount==8)
 90         fwrite(pColorTable, sizeof(RGBQUAD),256, fp);
 91     fwrite(imgBuf, height*lineByte, 1, fp);//写位图数据进文件
 92     
 93     fclose(fp);
 94     return 1;
 95 }
 96 //声明和定义bmp读写完成
 97 
 98 
 99 //声明和定义DCT
100 
101 #define N 8
102 double C[N][N];    //使用C*X*Ct得到DCT变换,而不是最原始的变换式
103 double Ct[N][N];
104 int OutputRunLength=0;
105 int InputRunLength=0;
106 
107 double qk=1;
108 int Quantum[N][N]=
109     {
110         {16,11,10,16, 24, 40, 51, 61},
111         {12,12,14,19, 26, 58, 60, 55},
112         {14,13,16,24, 40, 57, 69, 56},
113         {14,17,22,29, 51, 87, 80, 62},
114         {18,22,37,56, 68,109,103, 77},
115         {24,35,55,64, 81,104,113, 92},
116         {49,64,78,87,103,121,120, 101},
117         {72,92,95,98,112,100,103, 99}  
118     };
119 struct zigzag
120 { 
121     int row;
122     int col;
123 }
124 ZigZag[N*N]=
125 {
126     {0,0},
127     {0,1},{1,0},
128     {2,0},{1,1},{0,2},
129     {0,3},{1,2},{2,1},{3,0},
130     {4,0},{3,1},{2,2},{1,3},{0,4},
131     {0,5},{1,4},{2,3},{3,2},{4,1},{5,0},
132     {6,0},{5,1},{4,2},{3,3},{2,4},{1,5},{0,6},
133     {0,7},{1,6},{2,5},{3,4},{4,3},{5,2},{6,1},{7,0},
134     {7,1},{6,2},{5,3},{4,4},{3,5},{2,6},{1,7},
135     {2,7},{3,6},{4,5},{5,4},{6,3},{7,2},
136     {7,3},{6,4},{5,5},{4,6},{3,7},
137     {4,7},{5,6},{6,5},{7,4},
138     {7,5},{6,6},{5,7},
139     {6,7},{7,6},
140     {7,7}
141 };
142 void InitializeDCT();//define C[][] and Ct[][]
143 void ForwardDCT(int input[N][N],int output[N][N]);
144 void WriteDCTData(ofstream outcode,int output_data[N][N]);
145 
146 void InitializeDCT()
147  {
148      
149      int i,j;
150      double pi=atan(1.0)*4.0;
151 
152 
153      for(j=0;j<N;j++)
154      {
155          C[0][j]=1.0/sqrt((double)N);
156          Ct[j][0]=C[0][j];
157      }
158 
159      for(i=1;i<N;i++)   
160         {
161             for(j=0;j<N;j++)
162             {
163              C[i][j]= sqrt(2.0/(double)N)  *  cos(   pi*i*  (2*j+1) / (2.0*(double)N) );
164              Ct[j][i]=C[i][j];
165             }
166      }
167  }
168 
169 void ForwardDCT(int input[N][N],int output[N][N])
170 {//output = C*input*Ct
171      double temp[N][N];
172     double temp1;
173     int i,j,k;
174 
175     for(i=0;i<N;i++)
176     {
177         for(j=0;j<N;j++)
178         {
179             temp[i][j]=0.0;
180             for(k=0;k<N;k++)
181                 temp[i][j]+=(input[i][k]-128)*Ct[k][j];
182         }
183     }
184 
185     for(i=0;i<N;i++)
186     {
187         for(j=0;j<N;j++)
188         {
189             temp1=0.0;
190             for(k=0;k<N;k++)
191                 temp1+=C[i][k]*temp[k][j];
192             if(temp1>=0)
193                 output[i][j]=temp1+0.5;
194             else
195                 output[i][j]=temp1-0.5;
196         }
197     }
198 }
199 
200 void WriteDCTData(ofstream outcode,int output_data[N][N])
201 {
202     int i=0;
203     int j=0;
204     int k=0;
205     int row1=0;
206     int col1=0;
207     unsigned int bitcount;
208     double result=0.0;
209     unsigned int abs=0;
210     int zero16count=0;//出现连续的16个零的次数
211     unsigned int OutputRunL=0;
212     unsigned int tempint;
213     unsigned char tempchar;
214 
215     for(i=0;i<(N*N);i++)
216     {
217         row1=ZigZag[i].row;
218         col1=ZigZag[i].col;
219         result=(double)output_data[row1][col1]/(double)Quantum[row1][col1];
220 
221         if(result>255&&result<-255)
222             cout<<"result:"<<result<<endl;
223 
224         if(result>=0)
225             abs=result+0.5;
226          if(result<0)
227             abs=-(result-0.499999); 
228 
229          if(abs>0xff)
230             cout<<"wrong!"<<endl;
231 
232          if(abs==0)
233         {
234             OutputRunL++;
235             if(OutputRunL==16)
236             {  
237                 OutputRunL=0;
238                 zero16count++;
239             }
240         }
241 
242         if(abs>0)
243         {   
244             
245             for(j=1;j<16;j++)//找到abs是几位的
246             { 
247                 if( (abs>>j)==0)
248                 {    
249                     bitcount=j;
250                     break;
251                 }
252             }
253             for(k=0; k<zero16count ;k++)
254             {
255                 tempchar=0xf0;
256                 outcode.put(tempchar);
257             }
258             zero16count=0;
259             if(result>0)
260             {
261                 tempint=(  (OutputRunL<<4) | bitcount );
262                 tempchar=tempint;
263                 outcode.put(tempchar);
264 
265                 if(abs>0xff)             
266                 {
267                    tempchar=(abs>>8);
268                    outcode.put(tempchar);
269                    
270                    tempchar=( abs&0xff);
271                    outcode.put(tempchar);
272                    OutputRunL=0;
273                 }
274                    else
275                    {
276                        tempchar=abs;
277                    outcode.put(tempchar);
278                    OutputRunL=0;
279                    }
280 
281 
282 
283 
284             }
285             if(result<0)
286             {
287                     if(bitcount>8)
288                 {
289                    tempint=(  (OutputRunL<<4)|bitcount );
290                    tempchar=tempint;
291                    outcode.put(tempchar);
292 
293                    tempint=(  (unsigned int)(  (1<<bitcount) -1-abs) );
294                    tempchar= (tempint>>8);
295                    outcode.put(tempchar);
296 
297                    
298                     tempchar= (tempint&0xff);
299                    outcode.put(tempchar);
300 
301 
302                    OutputRunL=0;
303                 }
304                     else{
305 
306 
307                 tempint=(  (OutputRunL<<4)|bitcount );
308                 tempchar=tempint;
309                 outcode.put(tempchar);
310                 tempint=(  (unsigned int)(  (1<<bitcount) -1-abs) );
311                 tempchar= tempint;
312 
313                 outcode.put(tempchar);
314                 OutputRunL=0;
315                     }
316             }
317         }
318     }
319 
320     outcode.put((unsigned char)0);
321 
322 }
323 
324 
325 //声明和定义DCT完成
326 
327 
328 //声明和定义Huffman
329 
330 unsigned char mask=0x80;   
331 int rack=0;             //从文件读入或者要写入文件的数据字节
332 
333 typedef struct treenode{
334     unsigned int count;        //权值 
335     unsigned int saved_count; 
336     int child0;                
337     int child1;
338 }NODE;
339  
340 typedef struct code {      
341     unsigned int codes; 
342     int code_bits;
343 }CODE;
344 
345 #define ENDofSTREAM 256
346 int InputBit(ifstream input);
347 void OutputBits(ofstream output,unsigned long code,int count);
348 void count_bytes(ifstream  input,unsigned long counts[256]);
349 void output_counts(ofstream output,unsigned long counts[256]);
350 int build_tree(NODE * nodes,unsigned long counts[256]);
351 void convert_tree_to_code(NODE *nodes,CODE * codes, unsigned long code_so_far,int bits,int node);
352 void encode(ifstream input, ofstream output, CODE * codes) ;
353 
354 int InputBit(ifstream input)
355 {
356     int value;
357     
358     if(0x80==mask)
359     {
360         rack=input.get();
361         if(rack==EOF)
362         {  
363            return    0xff;   
364         }
365         
366     }
367         value=rack&mask;
368         mask>>=1;
369         if(    0==mask)
370            mask=0x80;
371         return value?1:0;
372 }
373 
374 void OutputBits(ofstream output,unsigned long code,int count)
375 {
376     unsigned long masktemp;
377     masktemp=1L<<(count-1);   
378     while(masktemp!=0)
379     {
380         if(masktemp&code)     
381             rack|=mask;
382         mask>>=1;
383         if(mask==0)
384         {
385             output.put(  (unsigned char)rack);
386             OUTBYTES++;
387             rack=0;
388             mask=0x80;
389         }
390         masktemp>>=1;
391     }
392 }
393 
394 void count_bytes(ifstream input ,unsigned long  counts[256])
395 {
396     input.seekg(0,ios::beg);  
397     int c;
398     
399     while (  ( c=input.get() ) !=EOF)
400     {
401         counts[c]++; 
402         if( ( c!=0x0f0) && (c!=0) )
403             input.get();    
404     }
405 
406     input.seekg(0,ios::beg);  
407 }
408 
409 void output_counts(ofstream output,unsigned long counts[256])
410 {
411     unsigned int first,last,next,i;
412     output.seekp(0,ios::beg);
413     unsigned int templ=0;
414     templ=10*qk;
415     output.put((unsigned char)templ);
416 
417     first=0;
418 
419     while(first<256 && counts[first]==0)
420         first++;
421     
422     for( ; first<256; first=next)     
423     {
424         last=first+1;
425         for(;;)   
426         {
427             for(; last<256;last++)
428                 if (counts[last]==0)
429                     break; 
430             last--;  
431 
432             for(next=last+1;next<256;next++)  
433             {
434                 if(counts[next]!=0)
435                     break;  
436             }
437             
438             if(next>255)
439                     break;
440             if((next-last)>3)
441                     break;
442                 last=next;  
443         }
444     
445         output.put( (unsigned char)first );
446         OUTBYTES++;
447         output.put( (unsigned char)last );
448         OUTBYTES++;
449         for(i=first;i<= last;i++)
450         {
451             if(counts[i]!=1)
452                 counts[i]=counts[i]/2;
453             output.put( (unsigned char)counts[i] );
454             OUTBYTES++;
455         }
456     }
457             output.put( (unsigned char)0 );
458             OUTBYTES++;
459 }
460 
461 int build_tree(NODE * nodes,unsigned long counts[256])
462 {
463     int nextfree;
464     int  i;
465     int min1;
466     int min2;
467     
468     for(i=0;i<256;i++)
469         nodes[i].count=counts[i];
470     nodes[511].count=0xffffffff;  
471     for (nextfree=ENDofSTREAM ;  ; nextfree++)  
472     {
473         min1=min2=511;
474 
475         for(i=0;i<nextfree;i++)
476         {
477             if (nodes[i].count!=0)
478             {
479                 if(nodes[i].count<nodes[min1].count)
480                 {
481                     min2=min1;
482                     min1=i;
483                 }
484                 else if (nodes[i].count<nodes[min2].count)
485                     min2=i;
486             }
487         }  
488             if(511==min2)  
489                 break;
490         
491             nodes[nextfree].count=nodes[min1].count+nodes[min2].count;
492             nodes[min1].saved_count=nodes[min1].count;
493             nodes[min1].count=0;
494             nodes[min2].saved_count=nodes[min2].count;
495             nodes[min2].count=0;
496             nodes[nextfree].child0=min1;
497             nodes[nextfree].child1=min2;
498         }
499 
500         nextfree--;
501 
502         nodes[nextfree].saved_count=nodes[nextfree].count;
503 
504         return(nextfree);
505 }
506 
507 void convert_tree_to_code(NODE *nodes,CODE * codes, unsigned long code_so_far,int bits,int node)
508 {
509     if (node<ENDofSTREAM)       
510     {
511         codes[node].codes=code_so_far;
512         codes[node].code_bits=bits;
513         return;
514     }
515      code_so_far<<=1;
516      bits++;
517      convert_tree_to_code(nodes,codes,code_so_far,bits,nodes[node].child0);
518      convert_tree_to_code(nodes,codes,code_so_far | 1,bits,nodes[node].child1);
519 }
520 
521 
522 void encode(ifstream  input,ofstream output, CODE * codes)
523 {
524     unsigned int c;
525     int bit_count;
526     input.seekg(0,ios::beg);
527     while (  ( c=input.get() ) !=EOF  )
528     {        OutputBits(output,(unsigned long ) codes[c].codes, codes[c].code_bits);
529             bit_count=( c & 0x0f);
530             if(  ( c!=0xf0) &&  (c!=0) ) 
531             {
532                 c=input.get();  
533                 OutputBits(output,(unsigned long) c,bit_count);
534             }
535     }
536     
537 }
538 
539 //声明和定义Huffman完成
540 
541 
542 //main函数开始
543 void main()
544 {
545     cout<<"使用JPEG进行静止图像的编码:\n\n";
546 
547     int i,j;
548     char readPath[30];
549     int bmpheight,bmpwidth;
550     sprintf(readPath, "test.bmp");
551     readbmp(readPath);
552 
553     bmpheight=bmpHeight;
554     bmpwidth=bmpWidth;
555     int **bmpin=new int*[bmpheight];
556     for(i=0;i<bmpheight;i++)
557             bmpin[i]=new int[bmpwidth];
558     for(i=0;i<bmpheight;i++)
559     { 
560         for(j=0;j<bmpwidth;j++)            
561       {
562           bmpin[i][j]=int(*(pBmpBuf+i*bmpwidth+j));
563       }
564     }
565     cout<<"量化矩阵为qk*Q,qk用于控制压缩比\n";
566     cout<<"请输入参数qk:"<<endl;
567     cin>>qk;
568     for(i=0;i<8;i++)
569     { 
570         for(j=0;j<8;j++) 
571             Quantum[i][j]*=qk;
572     
573     }//量化矩阵的设置
574 
575 //DCT
576     int row,col;
577     int idct,jdct;
578     int input[N][N];
579     int output[N][N];
580 
581     ofstream dctout;
582     dctout.open("DCTCodes.dat",ios::out|ios::trunc|ios::binary);
583 
584     InitializeDCT();
585     for(row=0;row<bmpheight;row+=N)
586     {
587         for(col=0;col<bmpwidth;col+=N)
588         {
589             {    for(idct=0;idct<N;idct++)
590                     for(jdct=0;jdct<N;jdct++)
591                        input[idct][jdct]=bmpin[row+idct][col+jdct];
592             }
593             ForwardDCT(input,output);  
594             WriteDCTData(dctout,output);
595         }
596     }
597    dctout.close();
598 
599    for(i=0;i<bmpheight;i++)
600         delete[]bmpin[i];
601      delete[]bmpin;
602   
603 
604 //Huffman
605 
606     unsigned long counts[256]={0};
607     NODE * nodes;
608     CODE * codes;
609     int root_node;
610     ifstream PreHuff("DCTCodes.dat",ios::in|ios::binary);
611     ofstream Huff("compressed.bin",ios::out|ios::trunc|ios::binary);
612 
613     if(NULL==(nodes= new NODE[512]))  
614     {
615        cout<<"Huffman :new NODE fail"<<endl;
616     }
617     if(NULL==(codes= new CODE [256]))
618     {
619         cout<<"Huffman :new CODE fail"<<endl;
620     }
621 
622     int ias;
623     for(ias=0;ias<512;ias++)
624     {
625         nodes[ias].count=0;
626         nodes[ias].saved_count=0;
627         nodes[ias].child0=0;
628         nodes[ias].child1=0;
629     }
630     for(ias=0;ias<256;ias++)
631     {
632         codes[ias].codes=0;
633         codes[ias].code_bits=0;
634     }
635     count_bytes(PreHuff, counts);
636     output_counts(Huff,counts);     
637     root_node =build_tree(nodes,counts);
638     convert_tree_to_code(nodes,codes,0,0,root_node);
639 
640     PreHuff.seekg(0,ios::beg);
641     encode(PreHuff,Huff, codes);
642     PreHuff.close();
643     Huff.close();
644     
645     cout<<"\n";
646     cout<<"输出:"<<OUTBYTES<<" Bytes"<<endl;
647     cout<<"压缩比:64*64/"<<OUTBYTES<<"="<<(64*64)/(double)OUTBYTES<<"\n"<<endl<<endl;
648     delete []nodes;
649     delete []codes;
650 
651     int finish;
652     cout<<"请输入“Finish”:";
653     cin>>finish;
654 }
655 //main函数结束