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函数结束
转载于:https://www.cnblogs.com/QuentinYo/archive/2012/11/13/2767325.html
相关资源:JPEG_encoder