1. 程式人生 > >GIF影象格式(二)——基礎演算法(下)

GIF影象格式(二)——基礎演算法(下)

initialze_string_table(root_number);                                                          
last_code = -1;                                                                               
current_string = '';         // 空字串                                                       
    while (能夠從Code Stream中取出一個Code: this_code) {                                        
    if (last_code==-1) {     // first code                                                    
        把Code對應的string輸出到Char Stream;                                                    
    } else {                                                                                  
        if (this_code在string_table中存在) {                                                   
            current_string = string(last_code);                                               
            current_string += string(this_code)[0];  //this_code對應的string的第一個字元        
            把current_string插入到string_table的末尾;                                           
            把this_code對應的string輸出到Char Stream;                                           
        } else {                                                                              
            current_string = string(last_code);                                               
            current_string += string(last_code)[0];  //last_code對應的string的第一個字元        
            把current_string插入到string_table的末尾;                                           
            把current_string輸出到Char stream;                                                 
        }                                                                                     
    }                                                                                         
    last_code = this_code;                                                                    
}                                                                                             

這個演算法有幾個地方不好理解,首先就是last_code等於-1的時候,我們的做法就是簡單的把Code對應的字串輸出來,這就有了一個問題:這個Code對應的string一定存在嗎?讓我們仔細想想編碼的過程,第一個Code一定是root的index,因此這個string是一定存在的。第二個問題就是對this_code的處理。我們知道,在初始化string table的時候,它只有root_number個項,隨著編碼的過程,這個table一隻增長,但是仍然可能存在得到了一個code卻發現它在string table種對應的字串還沒有生成的情況。結合編碼過程應該不難理解,如果不存在的話,那麼這個Code也應當比當前的table中的最大的一個index僅僅大一,也就是說,如果我們可以用某種方法得到這個應當加入的項,那麼它就是我們要找得項。第三個問題就是為什麼我們總要在讀出一個Code後就要把一個string插入到string_table中,仍然是參考編碼過程,我們總是在輸出了一個Code的同時生成一個string插入到table中,也就是說,在我們進行解碼的時候,如果要讓string_table和我們編碼時同步,也要在讀入一個Code後生成一個string插入到table中。最後一個問題就是對於“Code在string_table中不存在”這種情況的解決方法。從偽碼中可以看到,如果Code存在,構造current_string和輸出的方式都很好理解,但是如果不存在,似乎很無恥的使用了last_code萊得到current_string,其實仔細聯絡編碼方式可以理解:這種方式是必然的。

還是看一個例子:仍然是剛才的例子,我們把我們編出來的碼解回去。

第一步仍然是初始化string_table:
-----------------------
index            string
00                'A'
01                'B'
02                'C'
-----------------------
第二步開始解碼:
Step        last_code        this_code       exist?         current_string                           Insert         output
01                -1                01                -                    -                                        -               'B'
02                01                03               no            string(01)+string(01)[0]=BB           'BB'            'BB'
03                03                02               yes           string(03)+string(02)[0]=BBC        'BBC'            'C'
04                02                03               yes           string(02)+string(03)[0]=CB           'CB'            'BB'
05                03                00               yes           string(03)+string(00)[0]=BBA        'BBA'            'A'
解碼結束,輸出為:BBBCBBA,成功地解為原字串。
我們再看看現在的string_table:
-------------------------
index            string
00                'A'
01                'B'
02                'C'
03                'BB'
04                'BBC'
05                'CB'
06                'BBA'
-------------------------
與編碼方式比較一下,是完全一樣的。
由此可見,解碼過程基本上是編碼的逆過程,而且這兩個過程之間的交流僅僅需要三個元素:Root Items的數目(字符集的大小)、字符集、字符集中各個字元的排列約定。而這三個東西其實是很容易指定的,這就決定了GIF影象可以不需要花太大空間儲存這些東西,大大減小了檔案大小。

相關推薦

GIF影象格式——基礎演算法

initialze_string_table(root_number);                                                          last_code = -1;                                              

GIF影象格式——基礎演算法

現在我們看看每一步是怎麼做的:第一步:初始化我們的編碼表。剛才說了,初始化編碼表只需要一個引數:root_number,也就是根項的數目。其實他就是我們要編碼的Char Stream中的字符集的數目。初始化也很簡單:根據一個事先的約定對所有的Char進行排序,然後從零開始對其編上一個index,形成一個ite

基礎演算法:Kmeans聚類演算法的基本原理與應用

Kmeans聚類演算法的基本原理與應用       內容說明:主要介紹Kmeans聚類演算法的數學原理,並使用matlab程式設計實現Kmeans的簡單應用,不對之處還望指正。 一、Km

基礎演算法篩法求素數

1.基本思想        把從1開始的、某一範圍內的正整數從小到大順序排列, 1不是素數,首先把它篩掉。剩下的數中選擇最小的數是素數,然後去掉它的倍數。依次類推,直到篩子為空時結束。 2.示例 1           2          3           4

NOIP複賽複習十一基礎演算法鞏固與提高

一、倍增演算法:   定義:用f[i][j]表示從i位置出發的2j個位置的資訊綜合(狀態) 一個小小的問題:為什麼是2j而不是3j,5j,…?因為,假設為kj,整個演算法的時間複雜度為(k-1)logk,當k=2時,時間複雜度最小。 這個演算法的三個應用:

Python基礎演算法持續更新~~

一: 建立一個包含1-100之間所有素數的列表,排序後列印顯示該列表; 隨後只保留該列表前5個數字,刪除其餘內容並列印輸出相應結果; 再將每個元素值加上100,顯示列表內容;把列表轉化為字串。 思路分析: 1.建立一個空列表,用來儲存1-100之間的素

《組合語言第3版王爽 著》學習筆記基礎知識2

1.7 CPU 對儲存器的讀寫 以上講到,儲存器被劃分成多個儲存單元,儲存單元從零開始編號。這些編號可以看作儲存單元在儲存器中的地址。就想一條街,每個房子都有門牌號碼。 CPU 要從記憶體中讀資料,

Java 學習—— 基礎語法

Java 基礎語法 一個Java程式可以認為是一系列物件的集合,而這些物件通過呼叫彼此的方法來協同工作。下面簡要介紹下類、物件、方法和例項變數的概念。 物件:物件是類的一個例項,有狀態和行為。例如,一條狗是一個物件,它的狀態有:顏色、名字、品種;行為有:搖尾巴、叫、吃等。 類:類是

從零開始學USB基礎知識2

1.USB相關的硬體 USB裝置,從物理上的邏輯結構來說,包含了主機Host端和裝置Device端。 其中,主機Host端,有對應的硬體的USB的主機控制器Host Controller,而裝置端,連線的是對應的USB裝置。 1.1. USB控制器型別:OHCI,UHCI,

藍橋杯練習系統試題集--基礎練習含C/C++答案

藍橋杯練習系統試題集(二)–基礎練習(含C/C++答案) 1 基礎練習 閏年判斷 時間限制:1.0s 記憶體限制:256.0MB 提交此題 錦囊1 錦囊2 問題描述 給定一個年份,判斷這一年是不是閏年。 當以下情況之一滿足時

決策樹——基礎演算法

決策樹 定義 根據wikipedia的定義,決策樹學習方法是一種通過決策樹實現從某幾個特徵屬性(分枝)到目標值(葉節點)的預測模型。 一種實現方法是貪心演算法:資料來源按照屬性測試條件分割為子集,然後在生成的每個子集上遞迴執行遞迴分割過程,直到該節點所有子集具有相同的目標變數。

STL基礎--演算法不修改資料的演算法

不修改資料的演算法 count, min and max, compare, linear search, attribute // 演算法中Lambda函式很常用: num = count_if(vec.begin(), vec.end(), [](int x){return x<10;

STL基礎--演算法修改資料的演算法

修改元素的演算法 copy, move, transform, swap, fill, replace, remove vector<int> vec = {9,60,70,8,45,87,90}; // 7 items vector<int> vec2 = {0

資料結構--叉樹--輸出樹中從根到每個葉子節點的路徑樹遍歷演算法的應用 .

void AllPath(Bitree T, Stack &S)//輸出二叉樹上從根到所有葉子結點的路徑 { if(T) { Push(S,T->data); if(!T->Left&&!T->Right)/

STL基礎--演算法排序

STL排序演算法 排序演算法要求隨機訪問迭代器 vector, deque, container array, native array 例子 vector<int> vec = {9,1,10,2,45,3,90,4,9,5,8}; sort(vec.begin()

STL基礎--演算法已排序資料的演算法,數值演算法

已排序資料的演算法 Binary search, merge, set operations 每個已排序資料演算法都有一個同名的更一般的形式 vector 1. 二分法搜尋 // 搜尋元素 bool found = binary_search(vec.begin(), vec.end()

基礎演算法---深度優先搜尋DFS

深度優先搜尋演算法(Depth-First-Search),是搜尋演算法的一種。 它沿著樹的深度遍歷樹的節點,儘可能深的搜尋樹的分支。 當節點v的所有邊都己被探尋過,搜尋將回溯到發現節點v的那條邊的起始節點。這一過程一直進行到已發現從源節點可達

Go 的面試基礎演算法

兩個陣列求交集 思路,把兩個數組合併成一個數組,然後通過 hash 表找出陣列中重複的元素 package main import "fmt" func ArrayIntersection(arr []int, arr1 []int)

keras面向小資料集的影象分類VGG-16基礎上fine-tune實現附程式碼

參考譯文地址:http://keras-cn.readthedocs.io/en/latest/blog/image_classification_using_very_little_data/ 本文作者:Francois Chollet 概述 在本文中,將使用VGG-16模型提供一種面向小資料集(幾百

最短路徑—Dijkstra演算法通過邊實現鬆弛:鄰接矩陣

上一節通過Floyd-Warshall演算法寫了多源節點最短路徑問題: 這一節來學習指定一個點(源點)到其餘各個頂點的最短路徑。也叫做“單源最短路徑”Dijkstra。 例如求下圖中1號頂點到2、3、4、5、6號頂點的最短路徑。 用二維陣列e儲存頂點之間邊的關係,初