青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

c++初學(xué)者

專注技術(shù)開發(fā)

[轉(zhuǎn)]GIF文檔

1.概述
~~~~~~~~

  GIF(Graphics Interchange Format,圖形交換格式)文件是由 CompuServe公司開發(fā)的圖形文件格式,版權(quán)所有,任何商業(yè)目的使用均須 CompuServe公司授權(quán)。
  GIF圖象是基于顏色列表的(存儲(chǔ)的數(shù)據(jù)是該點(diǎn)的顏色對(duì)應(yīng)于顏色列表的索引值),最多只支持8位(256色)。GIF文件內(nèi)部分成許多存儲(chǔ)塊,用來存儲(chǔ)多幅圖象或者是決定圖象表現(xiàn)行為的控制塊,用以實(shí)現(xiàn)動(dòng)畫和交互式應(yīng)用。GIF文件還通過LZW壓縮算法壓縮圖象數(shù)據(jù)來減少圖象尺寸(關(guān)于LZW算法和GIF數(shù)據(jù)壓縮>>...)。
 

2.GIF文件存儲(chǔ)結(jié)構(gòu)
~~~~~~~~~~~~~~~~~~~

  GIF文件內(nèi)部是按塊劃分的,包括控制塊( Control Block )和數(shù)據(jù)塊(Data Sub-blocks)兩種。控制塊是控制數(shù)據(jù)塊行為的,根據(jù)不同的控制塊包含一些不同的控制參數(shù);數(shù)據(jù)塊只包含一些8-bit的字符流,由它前面的控制塊來決定它的功能,每個(gè)數(shù)據(jù)塊大小從0到255個(gè)字節(jié),數(shù)據(jù)塊的第一個(gè)字節(jié)指出這個(gè)數(shù)據(jù)塊大小(字節(jié)數(shù)),計(jì)算數(shù)據(jù)塊的大小時(shí)不包括這個(gè)字節(jié),所以一個(gè)空的數(shù)據(jù)塊有一個(gè)字節(jié),那就是數(shù)據(jù)塊的大小0x00。下表是一個(gè)數(shù)據(jù)塊的結(jié)構(gòu):

BYTE 7 6 5 4 3 2 1 0 BIT
0

塊大小

Block Size - 塊大小,不包括這個(gè)這個(gè)字節(jié)(不計(jì)算塊大小自身)
1   Data Values - 塊數(shù)據(jù),8-bit的字符串
2  
...  
254  
255  

  一個(gè)GIF文件的結(jié)構(gòu)可分為文件頭(File Header)、GIF數(shù)據(jù)流(GIF Data Stream)和文件終結(jié)器(Trailer)三個(gè)部分。文件頭包含GIF文件署名(Signature)和版本號(hào)(Version);GIF數(shù)據(jù)流由控制標(biāo)識(shí)符、圖象塊(Image Block)和其他的一些擴(kuò)展塊組成;文件終結(jié)器只有一個(gè)值為0x3B的字符(';')表示文件結(jié)束。下表顯示了一個(gè)GIF文件的組成結(jié)構(gòu):

  GIF署名 文件頭  
  版本號(hào)
  邏輯屏幕標(biāo)識(shí)符 GIF數(shù)據(jù)流  
  全局顏色列表  
  ...  
  圖象標(biāo)識(shí)符 圖象塊                              
  圖象局部顏色列表圖
                            基于顏色列表的圖象數(shù)據(jù)  
 
  ...  
  GIF結(jié)尾 文件結(jié)尾  

  下面就具體介紹各個(gè)部分:

文件頭部分(Header)
~~~~~~~~~~~~~~~~~

GIF署名(Signature)和版本號(hào)(Version)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
GIF署名用來確認(rèn)一個(gè)文件是否是GIF格式的文件,這一部分由三個(gè)字符組成:"GIF";文件版本號(hào)也是由三個(gè)字節(jié)組成,可以為"87a"或"89a".具體描述見下表:

BYTE 7 6 5 4 3 2 1 0 BIT
1 'G' GIF文件標(biāo)識(shí)
2 'I'
3 'F'
4 '8' GIF文件版本號(hào):87a - 1987年5月
        89a - 1989年7月
5 '7'或'9'
6 'a'

GIF數(shù)據(jù)流部分(GIF Data Stream)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

邏輯屏幕標(biāo)識(shí)符(Logical Screen Descriptor)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
這一部分由7個(gè)字節(jié)組成,定義了GIF圖象的大小(Logical Screen Width & Height)、顏色深度(Color Bits)、背景色(Blackground Color Index)以及有無全局顏色列表(Global Color Table)和顏色列表的索引數(shù)(Index Count),具體描述見下表:

BYTE 7 6 5 4 3 2 1 0 BIT  
1 邏輯屏幕寬度 像素?cái)?shù),定義GIF圖象的寬度
2
3 邏輯屏幕高度 像素?cái)?shù),定義GIF圖象的高度
4
5 m cr s pixel 具體描述見下...
6 背景色 背景顏色(在全局顏色列表中的索引,如果沒有全局顏色列表,該值沒有意義)
7 像素寬高比 像素寬高比(Pixel Aspect Radio)

m - 全局顏色列表標(biāo)志(Global Color Table Flag),當(dāng)置位時(shí)表示有全局顏色列表,pixel值有意義.
cr - 顏色深度(Color ResoluTion),cr+1確定圖象的顏色深度.
s - 分類標(biāo)志(Sort Flag),如果置位表示全局顏色列表分類排列.
pixel - 全局顏色列表大小,pixel+1確定顏色列表的索引數(shù)(2的pixel+1次方).

全局顏色列表(Global Color Table)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
全局顏色列表必須緊跟在邏輯屏幕標(biāo)識(shí)符后面,每個(gè)顏色列表索引條目由三個(gè)字節(jié)組成,按R、G、B的順序排列。

BYTE 7 6 5 4 3 2 1 0 BIT
1 索引1的紅色值  
2 索引1的綠色值  
3 索引1的藍(lán)色值  
4 索引2的紅色值  
5 索引2的綠色值  
6 索引2的藍(lán)色值  
7 ...                             

圖象標(biāo)識(shí)符(Image Descriptor)
~~~~~~~~~~~~~~~~~~~~~~~~~
一個(gè)GIF文件內(nèi)可以包含多幅圖象,一幅圖象結(jié)束之后緊接著下是一幅圖象的標(biāo)識(shí)符,圖象標(biāo)識(shí)符以0x2C(',')字符開始,定義緊接著它的圖象的性質(zhì),包括圖象相對(duì)于邏輯屏幕邊界的偏移量、圖象大小以及有無局部顏色列表和顏色列表大小,由10個(gè)字節(jié)組成:

BYTE 7 6 5 4 3 2 1 0 BIT  
1 0 0 1 0 1 1 0 0 圖象標(biāo)識(shí)符開始,固定值為','
2 X方向偏移量 必須限定在邏輯屏幕尺寸范圍內(nèi)
3
4 Y方向偏移量
5
6 圖象寬度
7
8 圖象高度
9
10 m i s r pixel m - 局部顏色列表標(biāo)志(Local Color Table Flag)
              置位時(shí)標(biāo)識(shí)緊接在圖象標(biāo)識(shí)符之后有一個(gè)局部顏色列表,供緊跟在它之后的一幅圖象使用;值否時(shí)使用全局顏色列表,忽略pixel值。
i - 交織標(biāo)志(Interlace Flag),置位時(shí)圖象數(shù)據(jù)使用交織方式排列(詳細(xì)描述...),否則使用順序排列。
s - 分類標(biāo)志(Sort Flag),如果置位表示緊跟著的局部顏色列表分類排列.
r - 保留,必須初始化為0.
pixel - 局部顏色列表大小(Size of Local Color Table),pixel+1就為顏色列表的位數(shù)

局部顏色列表(Local Color Table)
~~~~~~~~~~~~~~~~~~~~~~~~~~
如果上面的局部顏色列表標(biāo)志置位的話,則需要在這里(緊跟在圖象標(biāo)識(shí)符之后)定義一個(gè)局部顏色列表以供緊接著它的圖象使用,注意使用前應(yīng)線保存原來的顏色列表,使用結(jié)束之后回復(fù)原來保存的全局顏色列表。如果一個(gè)GIF文件即沒有提供全局顏色列表,也沒有提供局部顏色列表,可以自己創(chuàng)建一個(gè)顏色列表,或使用系統(tǒng)的顏色列表。局部顏色列表的排列方式和全局顏色列表一樣:RGBRGB......

基于顏色列表的圖象數(shù)據(jù)(Table-Based Image Data)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
由兩部分組成:LZW編碼長度(LZW Minimum Code Size)和圖象數(shù)據(jù)(Image Data)。

BYTE 7 6 5 4 3 2 1 0 BIT
1 LZW編碼長度 LZW編碼初始碼表大小的位數(shù),詳細(xì)描述見LZW編碼...
 

 


...
 
圖象數(shù)據(jù),由一個(gè)或幾個(gè)數(shù)據(jù)塊(Data Sub-blocks)組成

數(shù)據(jù)塊
 

...
 

GIF圖象數(shù)據(jù)使用了LZW壓縮算法(詳細(xì)介紹請(qǐng)看后面的『LZW算法和GIF數(shù)據(jù)壓縮』),大大減小了圖象數(shù)據(jù)的大小。圖象數(shù)據(jù)在壓縮前有兩種排列格式:連續(xù)的和交織的(由圖象標(biāo)識(shí)符的交織標(biāo)志控制)。連續(xù)方式按從左到右、從上到下的順序排列圖象的光柵數(shù)據(jù);交織圖象按下面的方法處理光柵數(shù)據(jù):

創(chuàng)建四個(gè)通道(pass)保存數(shù)據(jù),每個(gè)通道提取不同行的數(shù)據(jù):
第一通道(Pass 1)提取從第0行開始每隔8行的數(shù)據(jù);
第二通道(Pass 2)提取從第4行開始每隔8行的數(shù)據(jù);
第三通道(Pass 3)提取從第2行開始每隔4行的數(shù)據(jù);
第四通道(Pass 4)提取從第1行開始每隔2行的數(shù)據(jù);

下面的例子演示了提取交織圖象數(shù)據(jù)的順序:

 通道1   通道2   通道3   通道4   
0  -------------------------------------------------------- 1        
1 --------------------------------------------------------       4  
2  --------------------------------------------------------     3    
3  --------------------------------------------------------       4  
4  --------------------------------------------------------   2      
5  --------------------------------------------------------       4  
6  --------------------------------------------------------     3    
7  --------------------------------------------------------       4  
8  -------------------------------------------------------- 1        
9  --------------------------------------------------------       4  
10 --------------------------------------------------------     3    
11 --------------------------------------------------------       4  
12 --------------------------------------------------------   2      
13 --------------------------------------------------------       4  
14 --------------------------------------------------------     3    
15 --------------------------------------------------------       4  
16 -------------------------------------------------------- 1        
17 --------------------------------------------------------       4  
18 --------------------------------------------------------     3    
19 --------------------------------------------------------       4  
20 --------------------------------------------------------   2      

 

圖形控制擴(kuò)展(Graphic Control Extension)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
這一部分是可選的(需要89a版本),可以放在一個(gè)圖象塊(圖象標(biāo)識(shí)符)或文本擴(kuò)展塊的前面,用來控制跟在它后面的第一個(gè)圖象(或文本)的渲染(Render)形式,組成結(jié)構(gòu)如下:

BYTE 7 6 5 4 3 2 1 0 BIT
1 擴(kuò)展塊標(biāo)識(shí) Extension Introducer - 標(biāo)識(shí)這是一個(gè)擴(kuò)展塊,固定值0x21
2 圖形控制擴(kuò)展標(biāo)簽 Graphic Control Label - 標(biāo)識(shí)這是一個(gè)圖形控制擴(kuò)展塊,固定值0xF9
3 塊大小 Block Size - 不包括塊終結(jié)器,固定值4
4 保留 處置方法

i

t

i - 用戶輸入標(biāo)志;t - 透明色標(biāo)志。詳細(xì)描述見下...
5 延遲時(shí)間 Delay Time - 單位1/100秒,如果值不為1,表示暫停規(guī)定的時(shí)間后再繼續(xù)往下處理數(shù)據(jù)流
6
7 透明色索引 Transparent Color Index - 透明色索引值
8 塊終結(jié)器 Block Terminator - 標(biāo)識(shí)塊終結(jié),固定值0

處置方法(Disposal Method):指出處置圖形的方法,當(dāng)值為:
                        0 - 不使用處置方法
                        1 - 不處置圖形,把圖形從當(dāng)前位置移去
                        2 - 回復(fù)到背景色
                        3 - 回復(fù)到先前狀態(tài)
                      4-7 - 自定義
用戶輸入標(biāo)志(Use Input Flag):指出是否期待用戶有輸入之后才繼續(xù)進(jìn)行下去,置位表示期待,值否表示不期待。用戶輸入可以是按回車鍵、鼠標(biāo)點(diǎn)擊等,可以和延遲時(shí)間一起使用,在設(shè)置的延遲時(shí)間內(nèi)用戶有輸入則馬上繼續(xù)進(jìn)行,或者沒有輸入直到延遲時(shí)間到達(dá)而繼續(xù)
透明顏色標(biāo)志(Transparent Color Flag):置位表示使用透明顏色

注釋擴(kuò)展(Comment Extension)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
這一部分是可選的(需要89a版本),可以用來記錄圖形、版權(quán)、描述等任何的非圖形和控制的純文本數(shù)據(jù)(7-bit ASCII字符),注釋擴(kuò)展并不影響對(duì)圖象數(shù)據(jù)流的處理,解碼器完全可以忽略它。存放位置可以是數(shù)據(jù)流的任何地方,最好不要妨礙控制和數(shù)據(jù)塊,推薦放在數(shù)據(jù)流的開始或結(jié)尾。具體組成:

BYTE 7 6 5 4 3 2 1 0 BIT
1 擴(kuò)展塊標(biāo)識(shí) Extension Introducer - 標(biāo)識(shí)這是一個(gè)擴(kuò)展塊,固定值0x21
2 注釋塊標(biāo)簽 Comment Label - 標(biāo)識(shí)這是一個(gè)注釋塊,固定值0xFE
 
...
 
Comment Data - 一個(gè)或多個(gè)數(shù)據(jù)塊(Data Sub-Blocks)組成

注釋塊
 

...
 
  塊終結(jié)器 Block Terminator - 標(biāo)識(shí)注釋塊結(jié)束,固定值0

圖形文本擴(kuò)展(Plain Text Extension)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

這一部分是可選的(需要89a版本),用來繪制一個(gè)簡單的文本圖象,這一部分由用來繪制的純文本數(shù)據(jù)(7-bit ASCII字符)和控制繪制的參數(shù)等組成。繪制文本借助于一個(gè)文本框(Text Grid)來定義邊界,在文本框中劃分多個(gè)單元格,每個(gè)字符占用一個(gè)單元,繪制時(shí)按從左到右、從上到下的順序依次進(jìn)行,直到最后一個(gè)字符或者占滿整個(gè)文本框(之后的字符將被忽略,因此定義文本框的大小時(shí)應(yīng)該注意到是否可以容納整個(gè)文本),繪制文本的顏色索引使用全局顏色列表,沒有則可以使用一個(gè)已經(jīng)保存的前一個(gè)顏色列表。另外,圖形文本擴(kuò)展塊也屬于圖形塊(Graphic Rendering Block),可以在它前面定義圖形控制擴(kuò)展對(duì)它的表現(xiàn)形式進(jìn)一步修改。圖形文本擴(kuò)展的組成:
 

BYTE 7 6 5 4 3 2 1 0 BIT
1 擴(kuò)展塊標(biāo)識(shí) Extension Introducer - 標(biāo)識(shí)這是一個(gè)擴(kuò)展塊,固定值0x21
2 圖形控制擴(kuò)展標(biāo)簽 Plain Text Label - 標(biāo)識(shí)這是一個(gè)圖形文本擴(kuò)展塊,固定值0x01
3 塊大小 Block Size - 塊大小,固定值12
4 文本框左邊界位置 Text Glid Left Posotion - 像素值,文本框離邏輯屏幕的左邊界距離
5
6 文本框上邊界位置 Text Glid Top Posotion - 像素值,文本框離邏輯屏幕的上邊界距離
7
8 文本框高度 Text Glid Width -像素值
9
10 文本框高度 Text Glid Height - 像素值
11
12 字符單元格寬度 Character Cell Width - 像素值,單個(gè)單元格寬度
13 字符單元格高度 Character Cell Height- 像素值,單個(gè)單元格高度
14 文本前景色索引 Text Foreground Color Index - 前景色在全局顏色列表中的索引
15 文本背景色索引 Text Blackground Color Index - 背景色在全局顏色列表中的索引
N
...
 
Plain Text Data - 一個(gè)或多個(gè)數(shù)據(jù)塊(Data Sub-Blocks)組成,保存要在顯示的字符串。

文本數(shù)據(jù)塊
 

...
 
N+1 塊終結(jié) Block Terminator - 標(biāo)識(shí)注釋塊結(jié)束,固定值0

推薦:1.由于文本的字體(Font)和尺寸(Size)沒有定義,解碼器應(yīng)該根據(jù)情況選擇最合適的;
2.如果一個(gè)字符的值小于0x20或大于0xF7,則這個(gè)字符被推薦顯示為一個(gè)空格(0x20);
3.為了兼容性,最好定義字符單元格的大小為8x8或8x16(寬度x高度)

應(yīng)用程序擴(kuò)展(Application Extension)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

這是提供給應(yīng)用程序自己使用的(需要89a版本),應(yīng)用程序可以在這里定義自己的標(biāo)識(shí)、信息等,組成:
 

BYTE 7 6 5 4 3 2 1 0 BIT
1 擴(kuò)展塊標(biāo)識(shí) Extension Introducer - 標(biāo)識(shí)這是一個(gè)擴(kuò)展塊,固定值0x21
2 圖形控制擴(kuò)展標(biāo)簽 Application Extension Label - 標(biāo)識(shí)這是一個(gè)應(yīng)用程序擴(kuò)展塊,固定值0xFF
3 塊大小 Block Size - 塊大小,固定值11
4 應(yīng)用程序標(biāo)識(shí)符 Application Identifier - 用來鑒別應(yīng)用程序自身的標(biāo)識(shí)(8個(gè)連續(xù)ASCII字符)
5
6
7
8
9
10
11
12 應(yīng)用程序鑒別碼 Application Authentication Code - 應(yīng)用程序定義的特殊標(biāo)識(shí)碼(3個(gè)連續(xù)ASCII字符)
13
14
N
...
 
應(yīng)用程序自定義數(shù)據(jù)塊 - 一個(gè)或多個(gè)數(shù)據(jù)塊(Data Sub-Blocks)組成,保存應(yīng)用程序自己定義的數(shù)據(jù)

應(yīng)用程序數(shù)據(jù)
 

...
 
N+1 塊終結(jié)器 lock Terminator - 標(biāo)識(shí)注釋塊結(jié)束,固定值0

文件結(jié)尾部分
~~~~~~~~~~~

文件終結(jié)器(Trailer)
~~~~~~~~~~~~~~~~

這一部分只有一個(gè)值為0的字節(jié),標(biāo)識(shí)一個(gè)GIF文件結(jié)束.
 

BYTE 7 6 5 4 3 2 1 0  
1

文件終結(jié)

GIF Trailer - 標(biāo)識(shí)GIF文件結(jié)束,固定值0x3B


2.LZW算法和GIF數(shù)據(jù)壓縮
~~~~~~~~~~~~~~~~~~~~~~~~~~~

  GIF文件的圖象數(shù)據(jù)使用了可變長度編碼的LZW壓縮算法(Variable-Length_Code LZW Compression),這是從LZW(Lempel Ziv Compression)壓縮算法演變過來的,通過壓縮原始數(shù)據(jù)的重復(fù)部分來達(dá)到減少文件大小的目的。

標(biāo)準(zhǔn)的LZW壓縮原理:
~~~~~~~~~~~~~~~~~~
先來解釋一下幾個(gè)基本概念:
  LZW壓縮有三個(gè)重要的對(duì)象:數(shù)據(jù)流(CharStream)、編碼流(CodeStream)和編譯表(String Table)。在編碼時(shí),數(shù)據(jù)流是輸入對(duì)象(圖象的光柵數(shù)據(jù)序列),編碼流就是輸出對(duì)象(經(jīng)過壓縮運(yùn)算的編碼數(shù)據(jù));在解碼時(shí),編碼流則是輸入對(duì)象,數(shù)據(jù)流是輸出對(duì)象;而編譯表是在編碼和解碼時(shí)都須要用借助的對(duì)象。

字符(Character):最基礎(chǔ)的數(shù)據(jù)元素,在文本文件中就是一個(gè)字節(jié),在光柵數(shù)據(jù)中就是一個(gè)像素的顏色在指定的顏色列表中的索引值
字符串(String):由幾個(gè)連續(xù)的字符組成;
前綴(Prefix):也是一個(gè)字符串,不過通常用在另一個(gè)字符的前面,而且它的長度可以為0;
(Root):單個(gè)長度的字符串;
編碼(Code):一個(gè)數(shù)字,按照固定長度(編碼長度)從編碼流中取出,編譯表的映射值;
圖案:一個(gè)字符串,按不定長度從數(shù)據(jù)流中讀出,映射到編譯表?xiàng)l目.

  LZW壓縮的原理:提取原始圖象數(shù)據(jù)中的不同圖案,基于這些圖案創(chuàng)建一個(gè)編譯表,然后用編譯表中的圖案索引來替代原始光柵數(shù)據(jù)中的相應(yīng)圖案,減少原始數(shù)據(jù)大小。看起來和調(diào)色板圖象的實(shí)現(xiàn)原理差不多,但是應(yīng)該注意到的是,我們這里的編譯表不是事先創(chuàng)建好的,而是根據(jù)原始圖象數(shù)據(jù)動(dòng)態(tài)創(chuàng)建的,解碼時(shí)還要從已編碼的數(shù)據(jù)中還原出原來的編譯表(GIF文件中是不攜帶編譯表信息的),為了更好理解編解碼原理,我們來看看具體的處理過程:

編碼器(Compressor)
~~~~~~~~~~~~~~~~

  編碼數(shù)據(jù),第一步,初始化一個(gè)編譯表,假設(shè)這個(gè)編譯表的大小是12位的,也就是最多有4096個(gè)單位,另外假設(shè)我們有32個(gè)不同的字符(也可以認(rèn)為圖象的每個(gè)像素最多有32種顏色),表示為a,b,c,d,e...,初始化編譯表:第0項(xiàng)為a,第1項(xiàng)為b,第2項(xiàng)為c...一直到第31項(xiàng),我們把這32項(xiàng)就稱為根。
  開始編譯,先定義一個(gè)前綴對(duì)象Current Prefix,記為[.c.],現(xiàn)在它是空的,然后定義一個(gè)當(dāng)前字符串Current String,標(biāo)記為[.c.]k,[.c.]就為Current Prefix,k就為當(dāng)前讀取字符。現(xiàn)在來讀取數(shù)據(jù)流的第一個(gè)字符,假如為p,那么Current String就等于[.c.]p(由于[.c.]為空,實(shí)際上值就等于p),現(xiàn)在在編譯表中查找有沒有Current String的值,由于p就是一個(gè)根字符,我們已經(jīng)初始了32個(gè)根索引,當(dāng)然可以找到,把p設(shè)為Current Prefix的值,不做任何事繼續(xù)讀取下一個(gè)字符,假設(shè)為q,Current String就等于[.c.]q(也就是pq),看看在編譯表中有沒有該值,當(dāng)然。沒有,這時(shí)我們要做下面的事情:將Current String的值(也就是pq)添加到編譯表的第32項(xiàng),把Current Prefix的值(也就是p)在編譯表中的索引輸出到編碼流,修改Current Prefix為當(dāng)前讀取的字符(也就是q)。繼續(xù)往下讀,如果在編譯表中可以查找到Current String的值([.c.]k),則把Current String的值([.c.]k)賦予Current Prefix;如果查找不到,則添加Current String的值([.c.]k)到編譯表,把Current Prefix的值([.c.])在編譯表中所對(duì)應(yīng)的索引輸出到編碼流,同時(shí)修改Current Prefix為k ,這樣一直循環(huán)下去直到數(shù)據(jù)流結(jié)束。偽代碼看起來就像下面這樣:

編碼器偽代碼

Initialize String Table;
[.c.] = Empty;
[.c.]k = First Character in CharStream;
while ([.c.]k != EOF )
{
  if ( [.c.]k is in the StringTable)
  {
    [.c.] = [.c.]k;
  }
  else
  {
    add [.c.]k to the StringTable;
    Output the Index of [.c.] in the StringTable to the CodeStream;
    [.c.] = k;
  }
  [.c.]k = Next Character in CharStream;
}

Output the Index of [.c.] in the StringTable to the CodeStream;

來看一個(gè)具體的例子,我們有一個(gè)字母表a,b,c,d.有一個(gè)輸入的字符流abacaba。現(xiàn)在來初始化編譯表:#0=a,#1=b,#2=c,#3=d.現(xiàn)在開始讀取第一個(gè)字符a,[.c.]a=a,可以在在編譯表中找到,修改[.c.]=a;不做任何事繼續(xù)讀取第二個(gè)字符b,[.c.]b=ab,在編譯表中不能找,那么添加[.c.]b到編譯表:#4=ab,同時(shí)輸出[.c.](也就是a)的索引#0到編碼流,修改[.c.]=b;讀下一個(gè)字符a,[.c.]a=ba,在編譯表中不能找到:添加編譯表#5=ba,輸出[.c.]的索引#1到編碼流,修改[.c.]=a;讀下一個(gè)字符c,[.c.]c=ac,在編譯表中不能找到:添加編譯表#6=ac,輸出[.c.]的索引#0到編碼流,修改[.c.]=c;讀下一個(gè)字符a,[.c.]c=ca,在編譯表中不能找到:添加編譯表#7=ca,輸出[.c.]的索引#2到編碼流,修改[.c.]=a;讀下一個(gè)字符b,[.c.]b=ab,編譯表的#4=ab,修改[.c.]=ab;讀取最后一個(gè)字符a,[.c.]a=aba,在編譯表中不能找到:添加編譯表#8=aba,輸出[.c.]的索引#4到編碼流,修改[.c.]=a;好了,現(xiàn)在沒有數(shù)據(jù)了,輸出[.c.]的值a的索引#0到編碼流,這樣最后的輸出結(jié)果就是:#0#1#0#2#4#0.

解碼器(Decompressor)
~~~~~~~~~~~~~~~~~~

  好了,現(xiàn)在來看看解碼數(shù)據(jù)。數(shù)據(jù)的解碼,其實(shí)就是數(shù)據(jù)編碼的逆向過程,要從已經(jīng)編譯的數(shù)據(jù)(編碼流)中找出編譯表,然后對(duì)照編譯表還原圖象的光柵數(shù)據(jù)。
  首先,還是要初始化編譯表。GIF文件的圖象數(shù)據(jù)的第一個(gè)字節(jié)存儲(chǔ)的就是LZW編碼的編碼大小(一般等于圖象的位數(shù)),根據(jù)編碼大小,初始化編譯表的根條目(從0到2的編碼大小次方),然后定義一個(gè)當(dāng)前編碼Current Code,記作[code],定義一個(gè)Old Code,記作[old]。讀取第一個(gè)編碼到[code],這是一個(gè)根編碼,在編譯表中可以找到,把該編碼所對(duì)應(yīng)的字符輸出到數(shù)據(jù)流,[old]=[code];讀取下一個(gè)編碼到[code],這就有兩種情況:在編譯表中有或沒有該編碼,我們先來看第一種情況:先輸出當(dāng)前編碼[code]所對(duì)應(yīng)的字符串到數(shù)據(jù)流,然后把[old]所對(duì)應(yīng)的字符(串)當(dāng)成前綴prefix [...],當(dāng)前編碼[code]所對(duì)應(yīng)的字符串的第一個(gè)字符當(dāng)成k,組合起來當(dāng)前字符串Current String就為[...]k,把[...]k添加到編譯表,修改[old]=[code],讀下一個(gè)編碼;我們來看看在編譯表中找不到該編碼的情況,回想一下編碼情況:如果數(shù)據(jù)流中有一個(gè)p[...]p[...]pq這樣的字符串,p[...]在編譯表中而p[...]p不在,編譯器將輸出p[...]的索引而添加p[...]p到編譯表,下一個(gè)字符串p[...]p就可以在編譯表中找到了,而p[...]pq不在編譯表中,同樣將輸出p[...]p的索引值而添加p[...]pq到編譯表,這樣看來,解碼器總比編碼器慢一步』,當(dāng)我們遇到p[...]p所對(duì)應(yīng)的索引時(shí),我們不知到該索引對(duì)應(yīng)的字符串(在解碼器的編譯表中還沒有該索引,事實(shí)上,這個(gè)索引將在下一步添加),這時(shí)需要用猜測(cè)法:現(xiàn)在假設(shè)上面的p[...]所對(duì)應(yīng)的索引值是#58,那么上面的字符串經(jīng)過編譯之后是#58#59,我們?cè)诮獯a器中讀到#59時(shí),編譯表的最大索引只有#58,#59所對(duì)應(yīng)的字符串就等于#58所對(duì)應(yīng)的字符串(也就是p[...])加上這個(gè)字符串的第一個(gè)字符(也就是p),也就是p[...]p。事實(shí)上,這種猜測(cè)法是很準(zhǔn)確(有點(diǎn)不好理解,仔細(xì)想一想吧)。上面的解碼過程用偽代碼表示就像下面這樣:

解碼器偽代碼

Initialize String Table;
[code] = First Code in the CodeStream;
Output the String for [code] to the CharStream;

[old] = [code];
[code] = Next Code in the CodeStream;
while ([code] != EOF )
{
  if ( [code] is in the StringTable)
  {
    Output the String for [code] to the CharStream;
// 輸出[code]所對(duì)應(yīng)的字符串
    [...] = translation for [old]; // [old]所對(duì)應(yīng)的字符串
    k = first character of translation for [code]; // [code]所對(duì)應(yīng)的字符串的第一個(gè)字符
    add [...]k to the StringTable;
    [old] = [code];

  }
  else
  {
    [...] = translation for [old];
    k = first character of [...];
    Output [...]k to CharStream;
    add [...]k to the StringTable;
    [old] = [code];

  }
  [code] = Next Code in the CodeStream;
}

GIF數(shù)據(jù)壓縮
~~~~~~~~~~~

下面是GIF文件的圖象數(shù)據(jù)結(jié)構(gòu):
 

BYTE 7 6 5 4 3 2 1 0 BIT
1

編碼長度

LZW Code Size - LZW壓縮的編碼長度,也就是要壓縮的數(shù)據(jù)的位數(shù)
  ... 數(shù)據(jù)塊
  塊大小 數(shù)據(jù)塊,如果需要可重復(fù)多次
  編碼數(shù)據(jù)
  ... 數(shù)據(jù)塊
  塊終結(jié)器 一個(gè)圖象的數(shù)據(jù)編碼結(jié)束,固定值0

把光柵數(shù)據(jù)序列(數(shù)據(jù)流)壓縮成GIF文件的圖象數(shù)據(jù)(字符流)可以按下面的步驟進(jìn)行:
1.定義編碼長度
GIF圖象數(shù)據(jù)的第一個(gè)字節(jié)就是編碼長度(Code Size),這個(gè)值是指要表現(xiàn)一個(gè)像素所需要的最小位數(shù),通常就等于圖象的色深;
2.壓縮數(shù)據(jù)
通過LZW壓縮算法將圖象的光柵數(shù)據(jù)流壓縮成GIF的編碼數(shù)據(jù)流。這里使用的LZW壓縮算法是從標(biāo)準(zhǔn)的LZW壓縮算法演變過來的,它們之間有如下的差別:
  [1]GIF文件定義了一個(gè)編碼大小(Clear Code),這個(gè)值等于2的『編碼長度』次方,在從新開始一個(gè)編譯表(編譯表溢出)時(shí)均須輸出該值,解碼器遇到該值時(shí)意味著要從新初始化一個(gè)編譯表;
  [2]在一個(gè)圖象的編碼數(shù)據(jù)結(jié)束之前(也就是在塊終結(jié)器的前面),需要輸出一個(gè)Clear Code+1的值,解碼器在遇到該值時(shí)就意味著GIF文件的一個(gè)圖象數(shù)據(jù)流的結(jié)束;
  [3]第一個(gè)可用到的編譯表索引值是Clear Code+2(從0到Clear Code-1是根索引,再上去兩個(gè)不可使用,新的索引從Clare Code+2開始添加);
  [4]GIF輸出的編碼流是不定長的,每個(gè)編碼的大小從Code Size + 1位到12位編碼的最大值就是4095(編譯表需要定義的索引數(shù)就是4096),當(dāng)編碼所須的位數(shù)超過當(dāng)前的位數(shù)時(shí)就把當(dāng)前位數(shù)加1,這就需要在編碼或解碼時(shí)注意到編碼長度的改變。
3.編譯成字節(jié)序列
因?yàn)镚IF輸出的編碼流是不定長的,這就需要把它們編譯成固定的8-bit長度的字符流,編譯順序是從右往左。下面是一個(gè)具體例子:編譯5位長度編碼到8位字符

0 b b b a a a a a
1 d c c c c c b b
2 e e e e d d d d
3 g g f f f f f e
4 h h h h h g g g
  ...
N                

 
4.打包
  前面講過,一個(gè)GIF的數(shù)據(jù)塊的大小從0到255個(gè)字節(jié),第一個(gè)字節(jié)是這個(gè)數(shù)據(jù)塊的大小(字節(jié)數(shù)),這就需要將編譯編后的碼數(shù)據(jù)打包成一個(gè)或幾個(gè)大小不大于255個(gè)字節(jié)的數(shù)據(jù)包。然后寫入圖象數(shù)據(jù)塊中。

posted on 2008-12-26 18:14 大海 閱讀(601) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 圖像

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲盗摄视频| 一区二区不卡在线视频 午夜欧美不卡在| 中文成人激情娱乐网| 免费久久精品视频| 欧美一区免费视频| 久久久亚洲精品一区二区三区 | 亚洲嫩草精品久久| 亚洲免费成人av电影| 日韩午夜免费| 一区二区成人精品| 久久成人资源| 久久精品免费看| 欧美精品亚洲二区| 国产精品人人做人人爽| 国产婷婷97碰碰久久人人蜜臀| 香蕉视频成人在线观看| 欧美一区二区三区在线观看视频| 免费观看成人www动漫视频| 久久人体大胆视频| 亚洲人成小说网站色在线| 一区二区三区 在线观看视频| 久久久久久夜精品精品免费| 麻豆精品91| 国产精品99久久久久久www| 久久久噜噜噜| 欧美色区777第一页| 亚洲成在线观看| 欧美一区二视频| 亚洲高清在线| 性欧美大战久久久久久久免费观看| 亚洲国产导航| 性欧美1819性猛交| 欧美日韩综合另类| 亚洲精品乱码久久久久久久久| 国产一区二区三区高清在线观看| 欧美日精品一区视频| 国产小视频国产精品| 国产精品99久久不卡二区| 免费看亚洲片| 久久精品国产久精国产思思| 国产精品日产欧美久久久久| 日韩视频免费在线| 久久精品网址| 亚洲午夜激情| 欧美—级a级欧美特级ar全黄| 免费一级欧美在线大片| 国产日韩欧美| 亚洲综合色自拍一区| 亚洲欧洲在线观看| 久久躁狠狠躁夜夜爽| 黑人操亚洲美女惩罚| 亚洲欧美一区二区三区久久| 亚洲精品乱码久久久久久日本蜜臀| 亚洲伦理在线观看| 午夜精品美女久久久久av福利| 日韩视频久久| 欧美mv日韩mv国产网站| 性18欧美另类| 韩国三级电影久久久久久| 欧美在线3区| 亚洲一级片在线观看| 国产精品日日做人人爱| 午夜精品久久久久久久久久久| 午夜精品美女自拍福到在线| 99国产精品国产精品久久| 欧美精品色综合| 亚洲精品乱码久久久久久按摩观 | 久久久国产精品亚洲一区| 日韩亚洲欧美精品| 欧美人牲a欧美精品| 一区二区三区国产盗摄| 亚洲最黄网站| 欧美日韩在线一区二区| 亚洲砖区区免费| 亚洲欧美卡通另类91av| 国产亚洲精品久久久久婷婷瑜伽| 最新中文字幕一区二区三区| 亚洲第一狼人社区| 欧美aⅴ一区二区三区视频| 亚洲精品麻豆| 一区二区三区视频在线看| 国产免费亚洲高清| 欧美v国产在线一区二区三区| 亚洲精品免费在线播放| 欧美日韩大片一区二区三区| 亚洲自拍高清| 久久精品国产清自在天天线| 激情婷婷欧美| 最新成人av网站| 国产欧美日韩精品a在线观看| 一区电影在线观看| 亚洲一区二区三区欧美| 在线观看国产成人av片| 91久久精品美女高潮| 国产精品网站一区| 欧美电影资源| 国产乱肥老妇国产一区二| 久久精品综合网| 欧美日韩国产首页在线观看| 久久久www成人免费精品| 欧美精品七区| 久久久久久久综合日本| 欧美人在线视频| 久久频这里精品99香蕉| 欧美日韩另类综合| 美腿丝袜亚洲色图| 国产精一区二区三区| 亚洲激情校园春色| 一区二区三区在线观看欧美| 亚洲一区二区免费在线| 亚洲欧洲日产国产网站| 一区二区三区四区精品| 欧美在线一区二区| 欧美成在线观看| 欧美在线观看视频| 欧美美女视频| 欧美大片免费观看| 国产日韩欧美在线观看| 亚洲免费av片| 亚洲剧情一区二区| 久久成人综合网| 久久久久久久91| 国产亚洲激情在线| 亚洲一级片在线看| 这里只有精品视频| 欧美黑人国产人伦爽爽爽| 女女同性女同一区二区三区91| 久久狠狠久久综合桃花| 亚洲综合大片69999| 欧美日韩亚洲视频一区| 亚洲日本精品国产第一区| 亚洲精品久久嫩草网站秘色| 米奇777在线欧美播放| 免费观看成人www动漫视频| 国产日韩精品一区二区| 亚洲欧美日韩在线综合| 午夜一级在线看亚洲| 国产精品久久久亚洲一区 | 乱中年女人伦av一区二区| 欧美日产在线观看| 99成人精品| 亚洲一区欧美| 国产视频自拍一区| 久久本道综合色狠狠五月| 欧美与欧洲交xxxx免费观看 | 久久综合久色欧美综合狠狠| 午夜天堂精品久久久久| 欧美性大战xxxxx久久久| 中文久久精品| 久久精品国产欧美激情| 尤物精品国产第一福利三区 | 欧美专区福利在线| 久久久www成人免费无遮挡大片| 久久久久国产一区二区三区四区| 影院欧美亚洲| 久久综合伊人| 最新亚洲一区| 亚洲欧美日韩国产综合精品二区| 欧美在线免费视屏| 久久精品在线免费观看| 在线成人h网| 欧美日韩第一页| 亚洲欧美色一区| 欧美成人一区二区三区片免费| 国产精品成人观看视频国产奇米| 久久福利影视| 在线免费观看欧美| 欧美精品亚洲精品| 亚洲一区二区三区色| 久久视频一区二区| 亚洲美女中文字幕| 国产精品视频免费一区| 麻豆精品网站| 亚洲自拍三区| 亚洲国产高清高潮精品美女| 日韩一级精品| 欧美一区午夜精品| 欧美剧在线免费观看网站| 99riav久久精品riav| 久热爱精品视频线路一| 亚洲婷婷国产精品电影人久久| 午夜精品久久久99热福利| 蜜臀av一级做a爰片久久| 亚洲一区二区三区激情| 亚洲福利一区| 国产美女精品免费电影| 欧美国产日韩一区二区三区| 欧美亚洲日本一区| 亚洲老板91色精品久久| 久久久天天操| 午夜激情综合网| 一本色道88久久加勒比精品| 一区二区三区在线观看视频| 国产精品久久久久9999| 欧美日韩999| 欧美成人69| 老司机亚洲精品| 欧美在线观看一区二区| 在线中文字幕日韩| 免费视频最近日韩|