• jpegEncode


      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函数结束
  • 相关阅读:
    php 三元运算符简洁用法
    Linux 获取网卡信息
    《构建之法》读后感
    毫秒数据字符串转换为DateTime
    POST请求——HttpWebRequest
    多个不同类对象传输思路
    WCF 大文件传输配置
    WCF配置文件详解
    C# 元组、匿名对象、ref&out
    C#控制台关闭之前做一些操作
  • 原文地址:https://www.cnblogs.com/QuentinYo/p/2767325.html
Copyright © 2020-2023  润新知