?? ezw.c
字號(hào):
/*
EZW編碼器
數(shù)據(jù)掃描的方式如下:
Morton order scan:
==================
1 | 2 | 5 6 | 17 18 21 22
---+---| |
3 | 4 | 7 8 | 19 20 23 24
-------+--------|
9 10 | 13 14 | 25 26 29 30
| |
11 12 | 15 16 | 27 28 31 32
----------------+---------------
33 34 37 38 | 49 50 53 54
|
35 36 39 40 | 51 52 55 56
|
41 42 45 46 | 57 58 61 62
|
43 44 47 48 | 59 60 63 64
Raster scan:
============
1 | 2 | 5 6 | 17 18 19 20
---+---| |
3 | 4 | 7 8 | 21 22 23 24
-------+--------|
9 10 | 13 14 | 25 26 27 28
| |
11 12 | 15 16 | 29 30 31 32
----------------+---------------
33 34 35 36 | 49 50 51 52
|
37 38 39 40 | 53 54 55 56
|
41 42 43 44 | 57 58 59 60
|
45 46 47 48 | 61 62 63 64
數(shù)據(jù)平面的頻帶分布如下:
Subband distribution:
=====================
LL | HL | HL HL | HL HL HL HL
---+--- | |
LH | HH | HL HL | HL HL HL HL
--------+---------|
LH LH | HH HH | HL HL HL HL
| |
LH LH | HH HH | HL HL HL HL
------------------+------------------
LH LH LH LH | HH HH HH HH
|
LH LH LH LH | HH HH HH HH
|
LH LH LH LH | HH HH HH HH
|
LH LH LH LH | HH HH HH HH
*/
#define debug
#include "ezw.h"
#include "fifo.h"
#include "list.h"
#include "matrix2d.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//工作矩陣
matrix_2d *M;
//誤差值
char error;
//用于統(tǒng)計(jì)某一數(shù)據(jù)流中1和0的個(gè)數(shù)
int zeroes, ones;
//編碼數(shù)據(jù)流的輸出文件
FILE *ezw_file;
//輸出字節(jié)及編碼標(biāo)志位
unsigned char output_byte, mask;
//建立一個(gè)數(shù)據(jù)流輸出的文件頭
ezw_file_header header;
void load_data(matrix_2d *m)
{
int row, col;
for (row=0; row<8; row++)
{
for (col=0; col<8; col++)
{
//進(jìn)行工作矩陣的賦值
m->m[row][col] = example[row][col];
}
}
}
/*
* Puts a bit in the output stream.
*/
void put_bit(char bit)
{
//如果放入的比特為是1,統(tǒng)計(jì)1的個(gè)數(shù);反之統(tǒng)計(jì)0的個(gè)數(shù)
if (bit=='1')
{
output_byte |= mask;
ones++;
}
else zeroes++;
mask >>= 1;
if (mask==0)
{
fwrite(&output_byte,sizeof(output_byte),1,ezw_file);
output_byte = 0;
mask = 0x80;
}
}
/*
* Puts dominant-pass and subordinate-pass codes in the output stream.
*/
void output_code(int code)
{
//對(duì)于一個(gè)已經(jīng)量化且編碼后的數(shù)據(jù),來(lái)判斷它的類型。其類型有6種,正如在頭文件中定義的那樣
switch (code)
{
case ZERO:
put_bit('0'); //如果是二進(jìn)制數(shù)0,則輸出一個(gè)比特位,值不變
#ifdef debug
printf("0");
#endif
break;
case ONE:
put_bit('1'); //如果是二進(jìn)制數(shù)1, 則輸出一個(gè)比特位,值不變
#ifdef debug
printf("1");
#endif
break;
case POS:
put_bit('0'); //如果是正大系數(shù),則按順序輸出兩個(gè)比特位,值依次為0,1
put_bit('1');
#ifdef debug
printf("p");
#endif
break;
case NEG:
put_bit('1'); //如果是負(fù)大系數(shù),則按順序輸出兩個(gè)比特位,值依次為1,1
put_bit('1');
#ifdef debug
printf("n");
#endif
break;
case ZTR:
put_bit('0'); //如果是零樹(shù)根,則按順序輸出兩個(gè)比特位,值依次為0,0
put_bit('0');
#ifdef debug
printf("t");
#endif
break;
case IZ:
put_bit('1'); //如果是孤獨(dú)零,則按順序輸出兩個(gè)比特位,值依次為1,0
put_bit('0');
#ifdef debug
printf("z");
#endif
break;
}
}
/*
* Returns the largest value in a descendance tree.
*/
element_type max_descendant(matrix_2d *m, int x, int y)
{
int i, j, min_x, max_x, min_y, max_y;
//max為函數(shù)輸出值
element_type temp, max;
//假如是第一個(gè)節(jié)點(diǎn),返回矩陣得元素最大值
if ((x==0) && (y==0))
{
temp = m->m[0][0];
m->m[0][0] = min_element_type;
max = matrix_2d_abs_max(m);
m->m[0][0] = temp;
}
//否則,掃描繼續(xù)
else
{
min_x = x << 1;
min_y = y << 1;
max_x = (x+1) << 1;
max_y = (y+1) << 1;
//整幅圖像掃描完畢仍沒(méi)有結(jié)構(gòu),退出
if ((min_x==m->col) || (min_y==m->row))
{
return (0);
}
//初始化最大值
max = 0;
while ((max_y<=m->row) && (max_x<=m->col))
{
//掃描進(jìn)行
for (i=min_y; i<max_y; i++)
{
for (j=min_x; j<max_x; j++)
{
temp = abs(m->m[i][j]);
if (temp>max) max = temp;
}
}
//起始點(diǎn)坐標(biāo)值左移1位后,繼續(xù)
min_x <<= 1;
max_x <<= 1;
min_y <<= 1;
max_y <<= 1;
}
}
//返回最大值
return (max);
}
/*
* Returns 1 if descendance tree is a zerotree.
*/
char zerotree(matrix_2d *m, int x, int y, int threshold)
{
int i, j, min_x, max_x, min_y, max_y;
element_type temp, max;
char stop;
stop = 0;
if ((x==0) && (y==0))
{
//將當(dāng)前系數(shù)放入緩存區(qū)
temp = m->m[0][0];
m->m[0][0] = min_element_type;
//取矩陣中元素的最大絕對(duì)值
max = matrix_2d_abs_max(m);
m->m[0][0] = temp;
//如果最大值大于當(dāng)前閾值,停止
if (max>=threshold)
stop = 1;
}
//如果不是矩陣的第一個(gè)元素,坐標(biāo)值將左移1位
else
{
//橫坐標(biāo)最小值左移1位
min_x = x << 1;
//縱坐標(biāo)最小值左移1位
min_y = y << 1;
//橫坐標(biāo)最大值左移1位
max_x = (x+1) << 1;
//縱坐標(biāo)最大值左移1位
max_y = (y+1) << 1;
//如果掃描起始點(diǎn)坐標(biāo)值超過(guò)圖像的邊界坐標(biāo)值,返回真值
if ((min_x==m->col) || (min_y==m->row))
{
return (1);
}
max = 0;
while ((max_y<=m->row) && (max_x<=m->col))
{
//逐個(gè)系數(shù)掃描
for (i=min_y; i<max_y; i++)
{
for (j=min_x; j<max_x; j++)
{
temp = abs(m->m[i][j]);
//如果出現(xiàn)大系數(shù),停止
if (temp>=threshold)
{
stop = 1;
break;
}
}
if (stop==1) break;
}
if (stop==1) break;
//坐標(biāo)值再左移1位,
//循環(huán)仍在繼續(xù)
min_x <<= 1;
max_x <<= 1;
min_y <<= 1;
max_y <<= 1;
}
}
if (stop==1) return (0);
//返回真值
return (1);
}
/*
* Returns a dominant-pass code from the alphabet [POS,NEG,ZTR,IZ].
*/
int code(matrix_2d *m, int x, int y, element_type threshold)
{
element_type temp;
//將欲處理的數(shù)據(jù)暫存到一塊區(qū)域
temp = m->m[y][x];
//如果該小波系數(shù)的幅值大于當(dāng)前閾值,則是大系數(shù)(但是不知道正負(fù))
if (abs(temp)>=threshold)
{
//如果它大于0,則返回為POS(即"正大系數(shù)")
if (temp>=0)
return (POS);
else
//否則返回為NEG("負(fù)大系數(shù)")
return (NEG);
}
//如果它的幅值小于當(dāng)前閾值,則是小系數(shù)(但不知道是否"零樹(shù)根")
else
{
//如果零樹(shù)判斷為真,則返回ZTR("零樹(shù)根")
if (zerotree(m,x,y,threshold)==1)
return (ZTR);
//否則返回IZ("孤獨(dú)零")
else return (IZ);
}
}
/*
* Appends a value to the subordinate list.
*/
void to_sub_list(element_type value)
{
list_type d;
//僅僅往樹(shù)添加系數(shù)的幅度值的大小,系數(shù)的符號(hào)已經(jīng)編碼
d.x = abs(value);
d.y = 0;
append_to_list(d);
}
/*
* Builds a dominant pass EZW-element from a matrix element and a threshold.
*/
void process_element(matrix_2d *m, element_type threshold, ezw_element *s)
{
//將小波數(shù)據(jù),系數(shù)坐標(biāo)和量化閾值作為輸入,進(jìn)行編碼(即符號(hào)化)
s->code = code(m,s->x,s->y,threshold);
//假如編碼為大系數(shù)(無(wú)論正負(fù)),將編碼放入子表中
if ((s->code==POS) || (s->code==NEG))
{
to_sub_list(m->m[s->y][s->x]);
//編碼位置復(fù)位
m->m[s->y][s->x] = 0;
}
}
/*
* Performs one complete dominant pass. Dominant-pass-codes are sent to the
* output stream and the subordinate list is updated.
*/
void dominant_pass(matrix_2d *m, element_type threshold)
{
ezw_element s;
int min_x, max_x, min_y, max_y;
//將當(dāng)前掃描位置移至example[0][0]處,并進(jìn)行判斷、量化
s.x = 0;
s.y = 0;
//將該系數(shù)與當(dāng)前閾值進(jìn)行比較,符號(hào)化
process_element(m,threshold,&s);
//將上一步的結(jié)果進(jìn)行輸出編碼
output_code(s.code);
//對(duì)example[1][0],example[0][1],example[1][1]進(jìn)行判斷、量化
s.x = 1;
s.y = 0;
//將該系數(shù)與當(dāng)前閾值進(jìn)行比較,符號(hào)化
process_element(m,threshold,&s);
//將上一步的結(jié)果放到掃描序列中
put_in_fifo(s);
s.x = 0;
s.y = 1;
//將該系數(shù)與當(dāng)前閾值進(jìn)行比較,符號(hào)化
process_element(m,threshold,&s);
//將上一步的結(jié)果放到掃描序列中
put_in_fifo(s);
s.x = 1;
s.y = 1;
//將該系數(shù)與當(dāng)前閾值進(jìn)行比較,符號(hào)化
process_element(m,threshold,&s);
//將上一步的結(jié)果放到掃描序列中
put_in_fifo(s);
//從掃描序列中取出一個(gè)系數(shù)
s = get_from_fifo();
//假如序列為空,直接將其送輸出編碼
if (fifo_empty==0)
output_code(s.code);
while (fifo_empty==0)
{
//如果當(dāng)前編碼不為ZTR,則將當(dāng)前掃描移至下一頻段
if (s.code!=ZTR)
{
//橫坐標(biāo)最小值左移1位,即加倍
min_x = s.x << 1;
//橫坐標(biāo)最大值為最小值加1
max_x = min_x+1;
//縱坐標(biāo)最小值左移1位,即加倍
min_y = s.y << 1;
//縱坐標(biāo)最大值為最小值加1
max_y = min_y+1;
if ((max_x<=m->col) && (max_y<=m->row))
{
for (s.y=min_y; s.y<max_y+1; s.y++)
{
for (s.x=min_x; s.x<max_x+1; s.x++)
{
process_element(m,threshold,&s);
put_in_fifo(s);
}
}
}
}
s = get_from_fifo();
if (fifo_empty==0) output_code(s.code);
}
}
/*
* Performs one subordinate pass.
*/
void subordinate_pass(element_type threshold)
{
list_type d; //定義一顆零樹(shù)
int i;
char found;
if (threshold>0)
{
for (i=0; i<list_length; i++)
{
d = get_list_element(i,&found);
if (found==1)
{
if ((d.x&threshold)!=0)
output_code(ONE);
else
output_code(ZERO);
}
}
}
}
/*
* EZW-codes matrix m, returns initial threshold.
*/
void EZW_code(matrix_2d *m, element_type threshold)
{
while (threshold!=0) //初始化量化閾值為0
{
dominant_pass(m,threshold);
#ifdef debug
printf("\n");
#endif
//將量化閾值右移1位,即數(shù)值為原來(lái)的1/2
//主表掃描結(jié)束后,閾值減半繼續(xù)子表的掃描
subordinate_pass(threshold>>1);
#ifdef debug
printf("\n");
#endif
//本次主表、子表掃描結(jié)束
//將量化閾值右移1位,即數(shù)值為原來(lái)的1/2
threshold >>= 1;
}
}
int EZW(void)
{
printf("\n");
//工作矩陣的高度為8
header.height = 8;
//工作矩陣的寬度為8
header.width = 8;
//創(chuàng)建一個(gè)用于運(yùn)算的工作矩陣
M = matrix_2d_create(header.height,header.width);
if (M==NULL)
//如果工作矩陣分配不成功,退出
exit(1);
//將實(shí)驗(yàn)小波系數(shù)轉(zhuǎn)存到工作矩陣中
load_data(M);
#ifdef debug
matrix_2d_write(M);
#endif
//準(zhǔn)備編碼后的數(shù)據(jù)流輸出的文件
header.threshold = 1 << (int)(floor(log10(matrix_2d_abs_max(M))/log10(2)));
if ((ezw_file=fopen("out.ezw","wb"))==NULL)
{
printf("Could not open output file.\n");
//如果輸出文件沒(méi)有打開(kāi),退出
exit(1);
};
//往輸出文件中寫入文件頭
fwrite(&header,sizeof(header),1,ezw_file);
//進(jìn)行EZW編碼運(yùn)算
zeroes = 0; //初始數(shù)據(jù)流中沒(méi)有比特位,所以置0
ones = 0;
//初始輸出字節(jié)數(shù)為0
output_byte = 0;
//最高位為1的標(biāo)志位
mask = 0x80;
//將工作矩陣作為輸入,給定閾值進(jìn)行編碼
EZW_code(M,header.threshold);
//刷新輸出區(qū)域
if (mask!=0)
{
fwrite(&output_byte,sizeof(output_byte),1,ezw_file);
}
#ifdef debug
printf("\n");
printf(" bits: %d, %d zeroes, %d ones.\n",zeroes+ones,zeroes,ones);
#endif
//清除所有的臨時(shí)文件和內(nèi)存占用
fclose(ezw_file);
//釋放工作矩陣所占的空間
matrix_2d_destroy(M);
//釋放主表掃描過(guò)程中的臨時(shí)數(shù)據(jù)
destroy_fifo();
//清除零樹(shù)掃描過(guò)程中的臨時(shí)數(shù)據(jù)
destroy_list();
//返回
return 0;
}
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -