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函数结束