📄 chp9.htm
字号:
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span lang=ZH-CN style='font-size:10.5pt'>源程序就不给出了,有兴趣的读者可以自己实现。</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'><o:p></o:p></span></p>
<h2 style='text-align:justify;text-justify:inter-ideograph'><span
style='font-family:"Times New Roman"'>9.2 </span><span lang=ZH-CN
style='mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman"'>行程编码</span><span
style='font-family:"Times New Roman"'><o:p></o:p></span></h2>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span lang=ZH-CN style='font-size:10.5pt'>行程编码</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>(Run Length Coding)</span><span
lang=ZH-CN style='font-size:10.5pt'>的原理也很简单:将一行中颜色值相同的相邻象素用一个计数值和该颜色值来代替。例如</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>aaabccccccddeee</span><span
lang=ZH-CN style='font-size:10.5pt'>可以表示为</span><span style='font-size:10.5pt;
font-family:"Times New Roman"'>3a1b6c2d3e</span><span lang=ZH-CN
style='font-size:10.5pt'>。如果一幅图象是由很多块颜色相同的大面积区域组成,那么采用行程编码的压缩效率是惊人的。然而,该算法也导致了一个致命弱点,如果图象中每两个相邻点的颜色都不同,用这种算法不但不能压缩,反而数据量增加一倍。所以现在单纯采用行程编码的压缩算法用得并不多,</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>PCX</span><span
lang=ZH-CN style='font-size:10.5pt'>文件算是其中的一种。</span><span style='font-size:
10.5pt;font-family:"Times New Roman"'><o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>PCX</span><span lang=ZH-CN style='font-size:10.5pt'>文件最早是</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>PC Paintbrush</span><span
lang=ZH-CN style='font-size:10.5pt'>软件所采用的一种文件格式,由于压缩比不高,现在用的并不是很多了。它也是由头信息、调色板、实际的图象数据三个部分组成。其中头信息的结构为:</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'><o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>typedef struct{<o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>
char manufacturer;<o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>
char version;<o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>
char encoding;<o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>
char bits_per_pixel;<o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>
WORD xmin,ymin;<o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>
WORD xmax,ymax;<o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>
WORD hres;<o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>
WORD vres;<o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>
char palette[48];<o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>
char reserved;<o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>
char colour_planes;<o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>
WORD bytes_per_line;<o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>
WORD palette_type;<o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>
char filler[58];<o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span style='font-size:10.5pt;font-family:
"Times New Roman"'> } PCXHEAD;<o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span lang=ZH-CN style='font-size:10.5pt'>其中值得注意的是以下几个数据:</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>manufacturer</span><span
lang=ZH-CN style='font-size:10.5pt'>为</span><span style='font-size:10.5pt;
font-family:"Times New Roman"'>PCX</span><span lang=ZH-CN style='font-size:
10.5pt'>文件的标识,必须为</span><span style='font-size:10.5pt;font-family:"Times New Roman"'>0x0a</span><span
lang=ZH-CN style='font-size:10.5pt'>;</span><span style='font-size:10.5pt;
font-family:"Times New Roman"'>xmin</span><span lang=ZH-CN style='font-size:
10.5pt'>为最小的</span><span style='font-size:10.5pt;font-family:"Times New Roman"'>x</span><span
lang=ZH-CN style='font-size:10.5pt'>坐标,</span><span style='font-size:10.5pt;
font-family:"Times New Roman"'>xmax</span><span lang=ZH-CN style='font-size:
10.5pt'>最大的</span><span style='font-size:10.5pt;font-family:"Times New Roman"'>x</span><span
lang=ZH-CN style='font-size:10.5pt'>坐标,所以图象的宽度为</span><span style='font-size:
10.5pt;font-family:"Times New Roman"'>xmax-xmin+1</span><span lang=ZH-CN
style='font-size:10.5pt'>,同样图象的高度为</span><span style='font-size:10.5pt;
font-family:"Times New Roman"'>ymax-yin+1</span><span lang=ZH-CN
style='font-size:10.5pt'>;</span><span style='font-size:10.5pt;font-family:
"Times New Roman"'>bytes_per_line</span><span lang=ZH-CN style='font-size:10.5pt'>为每个编码行所占的字节数,下面将详细介绍。</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'><o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span style='font-size:10.5pt;font-family:
"Times New Roman"'>PCX</span><span lang=ZH-CN style='font-size:10.5pt'>的调色板在文件的最后。以</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>256</span><span
lang=ZH-CN style='font-size:10.5pt'>色</span><span style='font-size:10.5pt;
font-family:"Times New Roman"'>PCX</span><span lang=ZH-CN style='font-size:
10.5pt'>文件为例,倒数第</span><span style='font-size:10.5pt;font-family:"Times New Roman"'>769</span><span
lang=ZH-CN style='font-size:10.5pt'>个字节为颜色数的标识,</span><span style='font-size:
10.5pt;font-family:"Times New Roman"'>256</span><span lang=ZH-CN
style='font-size:10.5pt'>时该字节必须为</span><span style='font-size:10.5pt;
font-family:"Times New Roman"'>12</span><span lang=ZH-CN style='font-size:10.5pt'>,剩下的</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>768(256</span><span
lang=ZH-CN style='font-size:10.5pt'>×</span><span style='font-size:10.5pt;
font-family:"Times New Roman"'>3)</span><span lang=ZH-CN style='font-size:10.5pt'>为调色板的</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>RGB</span><span
lang=ZH-CN style='font-size:10.5pt'>值。</span><span style='font-size:10.5pt;
font-family:"Times New Roman"'><o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span lang=ZH-CN style='font-size:10.5pt'>为了叙述方便,我们针对</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>256</span><span
lang=ZH-CN style='font-size:10.5pt'>色</span><span style='font-size:10.5pt;
font-family:"Times New Roman"'>PCX</span><span lang=ZH-CN style='font-size:
10.5pt'>文件,介绍一下它的解码过程。编码是解码的逆过程,有兴趣的读者可以试着自己来完成。</span><span style='font-size:
10.5pt;font-family:"Times New Roman"'><o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span lang=ZH-CN style='font-size:10.5pt'>解码是以行为单位的,该行所占的字节数由</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>bytes_per_line</span><span
lang=ZH-CN style='font-size:10.5pt'>给定。为此,我们开一个大小为</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>bytes_per_line</span><span
lang=ZH-CN style='font-size:10.5pt'>的解码缓冲区。一开始,将缓冲区的所有内容清零。从文件中读出一个字节</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>C</span><span
lang=ZH-CN style='font-size:10.5pt'>,若</span><span style='font-size:10.5pt;
font-family:"Times New Roman"'>C>0xc0</span><span lang=ZH-CN
style='font-size:10.5pt'>,说明是行程</span><span style='font-size:10.5pt;font-family:
"Times New Roman"'>(Run Length)</span><span lang=ZH-CN style='font-size:10.5pt'>信息,即</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>C</span><span
lang=ZH-CN style='font-size:10.5pt'>的低</span><span style='font-size:10.5pt;
font-family:"Times New Roman"'>6</span><span lang=ZH-CN style='font-size:10.5pt'>位表示后面连续的字节个数</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>(</span><span
lang=ZH-CN style='font-size:10.5pt'>所以最多</span><span style='font-size:10.5pt;
font-family:"Times New Roman"'>63</span><span lang=ZH-CN style='font-size:10.5pt'>个连续颜色相同的象素,若还有颜色相同的象素,将在下一个行程处理</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>)</span><span
lang=ZH-CN style='font-size:10.5pt'>,文件的下一个字节就是实际的图象数据</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>(</span><span
lang=ZH-CN style='font-size:10.5pt'>即该颜色在调色板中的索引值</span><span style='font-size:
10.5pt;font-family:"Times New Roman"'>)</span><span lang=ZH-CN
style='font-size:10.5pt'>。若</span><span style='font-size:10.5pt;font-family:
"Times New Roman"'>C<0xc0</span><span lang=ZH-CN style='font-size:10.5pt'>,则表示</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>C</span><span
lang=ZH-CN style='font-size:10.5pt'>是实际的图象数据。如此反复,直到这</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>bytes_per_line</span><span
lang=ZH-CN style='font-size:10.5pt'>个字节处理完,这一行的解码完成。</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>PCX</span><span
lang=ZH-CN style='font-size:10.5pt'>就是有若干个这样的解码行组成。</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'><o:p></o:p></span></p>
<p style='margin:0cm;margin-bottom:.0001pt;text-align:justify;text-justify:
inter-ideograph;line-height:18.0pt'><span lang=ZH-CN style='font-size:10.5pt'>下面是实现</span><span
style='font-size:10.5pt;font-family:"Times New Roman"'>256</span><span
lang=ZH-CN style='font-size:10.5pt'>色</span><span style='font-size:10.5pt;
font-family:"Times New Roman"'>PCX</span><span lang=ZH-CN style='font-size:
10.5pt'>文件解码的源程序,其中第二个函数对一行进行解码,应该把阅读的重点放在这个函数上。要注意的是,执行时文件</span><span
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -