ImageMagick 範例 --
動畫優化
這些範例開始使用 基本動畫處理,嘗試優化動畫的最終顯示效果和檔案大小。這對於複雜的 GIF 動畫特別重要,因為可以使用較小的子幀覆蓋,以及三種類型的處置方法來控制動畫的處理方式。
如您所見,「
使用背景處置完美地對動畫進行了影格最佳化。此運算子適用於所有 GIF 動畫,並且通常會返回可能的最簡單「處置和影格最佳化」。
現在來談談任何類型的簡單影格最佳化的一些壞消息,例如 IM 提供的... 雖然「
有時候,對圖像最佳化的最佳方法是根本不覆蓋任何像素!例如,右邊是一個簡單的動畫,由 nixscripter 貢獻。如果我們看一下它的幀,您會發現它沒有得到很好的優化。但請注意,動畫的每隔一幀都會重複。
在對其進行幀優化之後,我們得到了一個非常特殊的 GIF 處置序列。
發生的事情是,IM 並沒有覆蓋原始幀,而是選擇使用「先前」GIF 處置來恢復第一個圖像。由於恢復的幀保持原樣,因此沒有更改的像素。所以子幀疊加減少到沒有。不幸的是,IM 或 GIF 格式都不允許您擁有零大小的圖像,因此改用一個特殊的單一透明像素最小圖像。此圖像稱為「遺漏圖像」,因為當「
字節的動畫文件。那麼讓我們嘗試對此動畫進行直接的幀優化。
等等,什麼都沒發生!IM 可以實現的最佳優化是根本沒有變化!這個動畫的上述合併版本是它的最佳選擇嗎?好吧,就動畫的現狀而言……是的,這確實是通過純幀處置優化可以實現的最佳簡單優化!不太好。問題在於,GIF 動畫要“清除”或“擦除”先前幀繪製的像素,它需要使用“背景”處置方法。儘管在某些特殊情況下,也可以使用“先前”處置方法。但是,“背景”處置只能清除剛剛覆蓋的區域。由於第一幀是整個圖像的完整覆蓋,因此整個圖像將被清除。即使動畫中只有一小部分需要清除其像素。因此,需要覆蓋整個第二幀,即使該幀的大部分內容之前都已顯示!這種可怕的兩難境地一直持續到動畫的其餘部分,沒有產生基本的幀優化。我確實說過這個動畫很難進行幀優化。
通過將第一個幀加倍,動畫大小從
位元組減少到
位元組。因此,即使動畫現在有五個幀,但由於子幀圖像疊加層的大小大幅減少,因此整體大小現在要小得多。加倍本質上是將處置方法的像素清除功能與下一幀執行的像素疊加功能分開了。GIF 動畫程式將處置和疊加都作為同一幀更新的一部分來完成,因此速度或質量應該不會有任何明顯的損失。這是一種複雜而棘手的技術,GIF 動畫設計人員或 GIF 優化程式很少看到或理解這種技術,但當需要時,它的好處是值得的。然而,子幀圖像大小的減少只持續很短的時間,因為後面的幀也必須清除下一幀的像素,所以幀又會變大,以繼續清除後面的像素。也就是說,因為像素清除總是導致更大的幀,永遠不會更小。那麼,讓我們嘗試將*所有*幀加倍(最後一個幀不需要加倍除外),看看這對最終圖像有什麼影響...
如您所見,雖然我們的幀數幾乎是原來的兩倍,但所有圖像的大小都要小得多,生成的動畫大小為
位元組,結果更小,但節省的空間不如我們執行第一次單幀加倍時那麼大。為了讓您了解發生了什麼,「
也就是說,IM 產生了與我們先前影格加倍範例相同的結果。 因此 GIF 檔案大小仍然是
位元組。 然而,「
現在我們有了合併形式的原始動畫。 如需移除額外影格的另一種方法,請參閱下面的「
請記住,添加的中间影格與周圍使用者顯示的影格(具有非零時間延遲的影格)不同。 這不是簡單的「影格加倍」,而是將兩個遙遠的小變化分開。 這種添加中间影格的操作並非可以自動化的簡單步驟。 雖然可以開發一種智能啟發式演算法來生成這些中间影格,但並不總是那麼明顯應該怎麼做,更不用說是否應該這樣做了。 *如果您想嘗試生成這樣的啟發式演算法,請給我發郵件*。 因此,讓我們在添加這些額外影格後嘗試標準的影格優化...
透過加入這些「零延遲中間影格」,此動畫影格可以比原始未最佳化的動畫更好地進行最佳化,產生
位元組的動畫。然而,對於此特定情況,它不如使用自動化的 影格加倍 技術(請參閱上方的「OptimizePlus」圖層方法)。但是,加入「零延遲中間影格」並不會阻止您同時使用「影格加倍」技術…
此動畫現在每個影格更新都有兩個額外的「零延遲中間影格」。第一個填補舊的孔洞,第二個清除將包含透明像素的區域,最後恢復不應被清除的像素。結果是針對此特定問題動畫的最佳影格最佳化,最終檔案大小為
位元組。也就是說,我們透過加入 6 個額外的零時間延遲影格,使 4 個影格的動畫變得更小!比原始影格數量多出一倍以上。很奇怪但千真萬確!當然,如果 GIF 動畫程式實際上可以將 零延遲中間影格 識別為它們的本質,即真實動畫影格之間的中間更新,那就更好了。但即使如此,當更新高度分離且非常小時,額外影格造成的輕微停頓也很難察覺。
當然,如果動畫的兩個分離部分實際上並無關聯,則它們不需要時間同步。另一種選擇是,您可以將動畫分割成兩個完全獨立的動畫,而不是加入額外的影格,以便在網頁上同時顯示。請參閱 分割動畫。然而,這個特定的動畫不能分割成獨立的時間分離動畫。首先,遠處的變化需要時間同步。其次,確實發生變化的四個區域在水平和垂直方向上重疊。這意味著簡單的 HTML「表格」無法將子動畫重新組合成一個完整的整體,除非使用某種 CSS 技巧。*你能證明我錯了嗎?* *未來:在「動畫處理」中參考一個更好的「兩個遙遠物體」動畫範例,例如涉及兩個獨立移動物體的動畫。*
這將再次使動畫返回到僅供使用者觀看的影格,從而簡化動畫。當然,在移除 零延遲中間影格 之後,很難重新加入它們,因為變更資訊會遺失。因此,動畫之後可能無法很好地最佳化影格。畢竟,最佳化是此類影格的主要目的之一。
我特意將動畫保留為 IM 內部 MIFF:檔案格式,因為這確保了原始影像在沒有修改的情況下被保留,並使用 PNG:檔案格式來顯示影格,以便您可以看到其中包含的所有半透明像素!這不僅對於具有半透明像素的動畫很重要,對於具有大量顏色的動畫也很重要。一旦將影像序列儲存為 GIF,您產生良好顏色最佳化的機會就會從良好變為困難。
結果看起來與我們想要的完全不同。默認的 50% 透明度處理會使動畫看起來像一個正在縮小的「雞蛋」。這絕對不是我想要通過這個動畫實現的效果.. 如果這種透明度處理方式可以接受,那麼在繼續進行其他優化之前,請按照以下方式應用...
但是,對像這樣的動畫應用閾值並不是一個好的解決方案,因為它實際上破壞了我想要實現的透明效果。
這將移除動畫中的所有透明度,但代價是只能在特定背景顏色上運作。但是,如果您是為特定網頁創建動畫,那可能是完全可以接受的。但是請注意,對於具有銳利輪廓的圖像,使用這樣的抖動模式可能會在銳利邊緣產生「點狀」輪廓。因此,不建議在一般情況下使用。另一種解決方案是嘗試生成某種透明和不透明像素的模式,以嘗試保留圖像的半透明度。為此,IM 提供了大量的抖動選項來解決這個問題。未來:一些指向待創建的透明度抖動部分的連結,例如量化和抖動。請注意,使用單色抖動作為 alpha 通道的顯而易見的第一個解決方案並不簡單,可能需要一些高級的多圖像合成才能正確執行。
結果還算合理,但看起來像是一個正在溶解的物體,而不是瞬間移動。
因此,您可以看到,在 GIF 動畫中處理半透明有很多可能性。
請注意,我沒有將動畫直接保存為 GIF 格式,而是先將其保存為 MIFF 格式文件「
如您所見,動畫中的每個圖像都有非常多的顏色。不僅每一幀的顏色數量都不同,而且第一幀和第三幀在顏色上也非常相似,儘管不完全相同。但是 GIF 文件格式每幀最多只能保存 256 種顏色,ImageMagick 將其保存為 GIF 格式時,它採用了最快、最笨拙的方式...它減少了動畫中每一幀的顏色數量(一個稱為顏色量化的過程)...
由於每幀減少的顏色數量略有不同,因此 IM 還需要為動畫中的每一幀提供單獨的調色板。這表示 GIF 文件有一個「全局顏色表」,而且它始終存在,但還有三個獨立的「局部顏色表」。「
個局部調色盤,比圖像中的影格數少一個,正如我預測的那樣。不僅每個影格都有一組不同的顏色,而且還有一種稍微不同的顏色模式(圖像抖動模式),如 錯誤校正抖動的問題 中所述。通常,IM 顏色量化和抖動 的這種預設操作非常好,並且非常適合圖片,尤其是真實照片。事實上,動畫的單個影格通常看起來很棒。所有問題都在於我們稍後嘗試將這些單獨減色的影格串成一個單一的動畫序列時。
上面示例中的紅色區域顯示了兩個不同的實心正方形區域,正如您所期望的那樣。但它也顯示了圍繞兩個影格背景的顏色差異帶。這些表示背景漸變邊緣處的“攪動”抖動模式,其中使用了不同的顏色像素來表示完全相同的背景。這也是顯示由使用不同顏色集和抖動模式引起的背景干擾最少的影格對。實際的連續影格差異要糟糕得多,產生的差異幾乎是純紅色。
由於動畫中的許多像素在相鄰影格之間都不同,因此當我們嘗試對動畫進行 影格優化 時,卻沒有得到任何優化,這也就不足為奇了……
然而,動畫影格中不變部分之間的大多數像素顏色差異實際上相當小。如果不是這種情況,那就不是很好的 減色。這意味著通過要求 IM 稍微放鬆其顏色比較,您可以要求它忽略微小的顏色差異。這是通過設置適當的 模糊係數 來完成的。
如您所見,添加一點點的顏色誤差值後,IM 現在會忽略那些僅有些微差異的像素,從而產生合理的影格最佳化。您需要多少顏色誤差值取決於 IM 在減少原始圖像顏色時遇到了多少麻煩。在這種情況下,並沒有很多麻煩,所以只需要一個非常小的值。如果一個小的顏色誤差值能產生可接受的結果,那麼就為您的影格最佳化和透明度最佳化設定它。請記住,您仍然需要為每個影格處理一個獨立的顏色表,這是下一個討論的重點。另請注意,影格最佳化決定對第二個影格使用「先前處置」。也就是說,在顯示第二個影格後,在覆蓋之前,將圖像返回到先前的影格處置(第一個圖像)。與始終不使用任何處置相比,這會產生更小的覆蓋圖像大小。如果您只想要一個簡單的覆蓋動畫,並且只使用無處置,則可以使用舊的解構運算子(也稱為圖層比較任意)來生成它。
現在,如果您使用「
為了更容易做到這一點,IM 還提供了一個特殊的選項 "
這會導致
結果圖像中出現「局部」(或額外不需要的)顏色表。在接下來的優化部分中,我將使用動畫的單一顏色表版本,不過您實際上可以在動畫優化的任何時候執行此操作,尤其是在最終保存之前。通過顏色表優化,我們直接轉換的 GIF 動畫從
位元組,在使用 "
位元組。動畫的幀數(和「局部顏色表」)越多,節省的空間就越大。由於對動畫的任何修改通常都會移除每個圖像的已保存調色板,因此在將動畫保存為 GIF 之前,"
建設中
但請注意,到目前為止,我們所看到的所有技術都可能產生從一個疊加層到另一個疊加層變化的抖動模式。像素的劇烈變化看起來像電視靜電。
現在讓我們使用 "
您可以看到子影格現在具有較大的透明區域,這些區域不會影響最終的動畫結果。需要更改像素的區域仍然會被覆蓋,但未更改的區域則會變為透明。這也包括動畫物件內部,留下了相當可怕的「孔洞」。由於較大的恆定透明彩色區域(理論上)可以更好地壓縮,因此產生的「雜亂」動畫會小得多,從影格優化結果將檔案大小從
位元組減少到
位元組。只需付出極少的努力,就能節省大量的空間。請注意,優化方法不需要是 合併動畫,並且子影格的大小保持不變,以便保留此影格和後續影格的處置需求。因此,任何節省都只是在動畫中相同像素數的改進壓縮率方面,而不是在實際儲存到檔案中的像素數方面。因此,它應該在您完成任何需要的 影格優化 之後進行,作為您的最後一個優化步驟。
動畫優化簡介
優化動畫並不容易,尤其是具有色彩限制的 GIF 動畫,以及選擇不同的幀處置技術,以及使用較小的「子幀」覆蓋從一幀到下一幀的能力。當您優化動畫時,您應該嘗試按照以下順序進行優化。然而,這並不是我們將要查看這些優化技術的順序。對於 GIF 動畫,幀優化是最基本的優化技術,也是可以獲得最大收益的地方。因此,我們將首先關注它。使用者在優化方面可能遇到的最困難的問題是 色彩優化,這是由 GIF 動畫的色彩限制造成的。其中一個方面 單一全域色彩表 必須在儲存為 GIF 之前的最後一步完成,否則您可能會失去運算符對最終 GIF 檔案儲存的影響。ImageMagick 的通用 GIF 優化器
「-layers
」方法「Optimize
」將使用我們將在下面詳細討論的一些技術,嘗試以單一合理的步驟優化 GIF 動畫。目前,此選項等效於(按順序)...在這一點上,您可以立即保存 GIF 動畫。這些是合理安全的優化步驟,可以應用於大多數動畫序列,但不能保證它會產生更小的 GIF 動畫。對於原始視訊序列尤其如此,因為 透明度優化 通常會導致 LZW 壓縮比變差。但是,對於大多數涉及卡通圖像的 GIF 動畫,'Optimize
' 運算符應該會產生一個優化良好的動畫。但是,該運算符仍在開發中,並且將來可能會包含額外的標準優化步驟,例如...- Alpha 色版的 50% 門檻值,就像 IM 在保存為 GIF 文件格式時通常所做的那樣,用於移除半透明像素。如果您願意,您仍然可以事先自己處理半透明度以覆蓋此設定。有關更多詳細信息,請參閱 GIF 布林透明度。
- 某種 顏色優化 技術。具體是什麼,還有待決定,並且可能會根據動畫和涉及的顏色數量進行選擇。*歡迎提出建議*。
- 一個 單一全局顏色表,“
+map
” 操作。
Optimize
' 最終會成為 IM 通用 GIF 動畫優化器,供 IM 用戶快速輕鬆地使用。在那之前,請謹慎使用它,尤其是在腳本中,因為它會發生變化。當然,對於特定的動畫來說,許多優化步驟可能不值得付出努力。此選項也可能會變得非常慢。這就是計劃,也是此 IM 範例部分的目標。幀優化
影格優化基於覆蓋較小的子圖像,而不是覆蓋整個圖像。這顯然會產生較少的像素,從而減少磁盤上的文件大小,以便通過網路發送。此外,覆蓋較小的影格意味著客戶端電腦不必在更改屏幕上的像素方面做那麼多工作。但是,GIF 格式中提供了不同的處置方法來處理顯示的最後一個影格,這可能會導致不同大小的覆蓋。不僅如此,還可以將覆蓋區域分成多個部分,或者更新動作,帶來更複雜但更優化的動畫。由於執行影格優化的複雜性,任何現有的影格優化通常都會通過使用“-coalesce
”操作首先刪除。請參閱 合併範例。當然,這意味著任何可能存在的hand優化也將被刪除,因此建議謹慎行事。 基本幀優化
「-deconstruct
」方法會對 GIF 動畫產生基本的影格最佳化。然而,如上一節的解構範例所示,當涉及透明像素時,此運算子不適用於所有 GIF 動畫。特別是當動畫將任何彩色像素清除為透明時。也就是說,它只適用於覆蓋動畫。「-layers
」方法「OptimizeFrame
」旨在成為 GIF 影格最佳化器,它將嘗試使用任何 GIF 處置方法找到最小的子影格覆蓋影像。結果通常是混合處置動畫,但如果確定這是特定動畫的最佳解決方案,它通常也會產生清除影格動畫或純覆蓋動畫。請記住,輸入動畫必須是「合併動畫」,因此它由一系列完整的影像影格組成,所有影格的大小都相同,沒有任何畫布偏移。當然,合併動畫中任何現有的處置方法都完全不相關,並且將被「OptimizeFrame
」方法忽略。例如,讓我們嘗試使用上一節中建立的處置先前動畫。
|
![]() |
||
![]() ![]() ![]() ![]() |
-layers OptimizeFrame
」使用先前處置正確地將我們的動畫返回到其原始的影格最佳化形式。這種最佳化甚至適用於更難處理的背景處置動畫...
|
![]() |
||
![]() |
現在來談談任何類型的簡單影格最佳化的一些壞消息,例如 IM 提供的... 雖然「
OptimizeFrame
」為 IM 可以計算出的給定動畫返回最佳可能的影格最佳化,但仍有一些特殊情況下它表現不佳。這些包括...- 需要像素清除(返回透明度)但影格覆蓋太大而無法有效清除需要清除的小區域像素的動畫(請參閱下面的移動孔動畫)。
- 涉及兩個或多個相距很遠的小區域變化的動畫。這些實際上很常見,並且對影格最佳化來說很可怕。(請參閱下面的拆分影格更新)
- 具有非常複雜背景的動畫,這些背景長時間保持靜態(超過 3 個影格),然後略有變化,然後再次長時間保持靜態,等等,等等... 或者在很短的時間內變得非常模糊的靜態背景。任何電腦演算法幾乎不可能在這種複雜情況下找出「最佳」影格最佳化(即:什麼應該被視為靜態背景?)。只有人類憑藉對所見事物的直觀掌握,才能在這些情況下產生良好的最佳影格覆蓋順序。
無像素覆蓋- 每隔一幀重複圖像
![[動畫]](../images/paddleball.gif)
在對其進行幀優化之後,我們得到了一個非常特殊的 GIF 處置序列。
|
![]() |
||
![]() |
-crop
」“遺漏”實際圖像數據時,也會廣泛使用它,從而產生相同的結果。實際上,此圖像僅保留幀元數據,例如:處置方法、時間延遲 和 循環迭代。因此,即使它是「空的」,它也是動畫的重要組成部分。因此,通過覆蓋一個最小的單一透明像素,IM 在此動畫中節省了大量的空間(和時間)。移動孔動畫- 難以進行幀優化
這是 GIF 動畫的一個極端案例,任何普通的優化方法都無法很好地對其進行幀優化。此動畫基本上由一個簡單不變的背景圖像組成,但在該背景中有一個透明的“孔”,該孔的位置會逐幀變化。為了創建它,我需要創建一個合併的圖像序列,在該序列中,我使用 圖層 Alpha 合成 在固定背景圖像中切出一個孔。我還使用了「+antialias
」開關來確保僅使用四種顏色:三種藍色和透明色。所以我們不需要處理 顏色優化問題。![[IM 文字]](moving_hole_size.txt.gif)
|
![]() |
||
![]() |
幀加倍- 一種幀優化“孔”的方法
不過,並非一切都失去了。通過在動畫中添加一些額外的幀,您可以為「OptimizeFrame
」方法提供一些空間,以便更好地利用可用的 GIF 處置方法。例如,在這裡,我們通過將第一個圖像加倍來添加一個額外的幀,但給它一個零時間延遲,以免改變動畫的整體時序。
|
![]() |
||
![]() |
![[IM 文字]](moving_hole_size.txt.gif)
![[IM 文字]](moving_hole_dup_size.txt.gif)
|
![]() |
||
![]() |
![[IM 文字]](moving_hole_double_size.txt.gif)
背景
」幀是上一幀的精確副本,不會改變正在顯示的內容。但是,它定義了在疊加下一幀圖像之前需要清除的動畫區域。然後,以下「無
」幀填充需要更改的像素,以及先前幀處置也清除的像素。在上面的動畫中,這意味著需要塑造新孔的像素,以及用於填充先前「孔」的像素。結果更小,但沒有那麼多,因為添加額外的幀確實有其自身的成本。至少每個添加的幀也沒有自己的調色盤,否則由於額外調色盤的大小,此動畫實際上會變得更大!圖層優化 Plus- 自動幀加倍優化
我很高興地說,從 6.2.7 版開始,IM 現在可以自動執行幀加倍優化,作為其正常幀優化處理的一部分。但是,由於添加幀以使動畫更小是一個非常激進的舉措,因此它被賦予了自己獨立的「-layers
」方法「OptimizePlus
」。例如,讓我們讓 IM 執行幀加倍優化...
|
![]() |
||
![]() |
![[IM 文字]](moving_hole_oplus_size.txt.gif)
OptimizePlus
」只會在結果動畫(3 個影格)的當前和下一影格中的像素數量減少時才會進行影格加倍,因此我們可以让 IM 決定是否要進行影格加倍。 由於「-layers
」方法「OptimizePlus
」在建立影格最佳化的 GIF 動畫時會新增額外的影格,因此它也會移除對最終動畫沒有任何變化的任何不必要或額外的影格(適當合併延遲時間)。 也就是說,它也會自動執行「RemoveDups
」(請參閱下一項)。 「OptimizeFrame
」方法不會這樣做。 移除重複的幀- 合併連續的重複影像
遺憾的是,如果您將此動畫「合併」,您也會得到以上新增的所有額外影格。為了讓您從合併的動畫中移除此類無用的重複影格,我們提供了一個「RemoveDups
」方法。 此方法會將動畫中的每個影格與下一影格進行比較,如果它們相同(具有由目前模糊因素設定的色彩相似度),則移除第一個影格。 此外,為了確保動畫中的任何時間設定都不會遺失,也會合併兩個影格的時間延遲。 例如..
magick moving_hole_oplus.gif -coalesce -layers RemoveDups gif:- |\ gif_anim_montage - moving_hole_oplus_rmdups_frames.gif |
![[IM Output]](moving_hole_oplus_rmdups_frames.gif)
RemoveZero
」方法。 分割幀更新- 分別更新兩個遙遠的變化
正如您在影格加倍中所見,通過將「清除像素」與疊加新像素分開,我們可以減少單個影格疊加的整體大小。 然而,此動畫仍然會產生一些非常大的疊加,這些疊加主要由實際上從一影格到下一影格沒有變化的像素組成。 也就是說,主疊加影格僅更新兩個彼此相距很遠的小區域,從而產生單個大疊加影像。 與其嘗試同時更新兩個變化,同時還要包含兩個區域之間所有未更改的像素,不如我們分別更新每個區域。 也就是說,我們將*影格更新拆分為兩個階段*,每個階段对应一個已更改的區域。 在這種情況下,我們可以先填充孔洞,然後將新孔洞創建為單獨的更新。 兩個單獨的更改以哪個順序發生實際上並不重要(可能與處置有關),但您應該嘗試使其符合邏輯。 也可能一個更改比另一個更改更容易創建。 例如,在這裡我插入了額外的影格,以將舊孔洞的填充作為「挖掘」新孔洞的單獨更新。 這是最容易生成的中间影格,也是最合乎邏輯的操作順序。 當然,您不需要為最後一個影格執行此操作,因為該影格在動畫循環之前就被丟棄了。
|
![]() |
||
![]() |
|
![]() |
||
![]() |
![[IM 文字]](moving_hole_split_opt_size.txt.gif)
|
![]() |
||
![]() |
![[IM 文字]](moving_hole_split_oplus_size.txt.gif)
當然,如果動畫的兩個分離部分實際上並無關聯,則它們不需要時間同步。另一種選擇是,您可以將動畫分割成兩個完全獨立的動畫,而不是加入額外的影格,以便在網頁上同時顯示。請參閱 分割動畫。然而,這個特定的動畫不能分割成獨立的時間分離動畫。首先,遠處的變化需要時間同步。其次,確實發生變化的四個區域在水平和垂直方向上重疊。這意味著簡單的 HTML「表格」無法將子動畫重新組合成一個完整的整體,除非使用某種 CSS 技巧。*你能證明我錯了嗎?* *未來:在「動畫處理」中參考一個更好的「兩個遙遠物體」動畫範例,例如涉及兩個獨立移動物體的動畫。*
移除零延遲幀- 移除中間更新
當然,有時您不感興趣或想要從動畫中移除這些加入的中間影格,只留下實際上會向使用者顯示一段時間的影格。您不能只是將動畫 合併 並使用「RemoveDups
」方法,因為並非所有「中間影格」都與周圍的影格相似,因此不是重複的。但是,由於這些類型的影格具有 零時間延遲,因此您可以使用另一個特殊的「-layers
」方法,「RemoveZero
」,它將移除任何具有零時間延遲的影格。此方法也會移除使用 影格加倍 和「OptimizePlus
」技術加入的影格。例如…
magick moving_hole_split_oplus.gif -coalesce -layers RemoveZero gif:- |\ gif_anim_montage - moving_hole_split_rmzero_frames.gif |
![[IM Output]](moving_hole_split_rmzero_frames.gif)
幀優化結果與摘要
讓我們總結一下我們對移動孔洞動畫的最佳化… 正如您所見,透過使用一些複雜的影格處理,並借助 IM 和一些人工介入,我們能夠將「移動孔洞」動畫的影格最佳化至接近其原始大小的一半,儘管其影格數幾乎是原始動畫的三倍。當然,結果會因動畫而異,但我們用於影格最佳化的技術是相同的。它只需要一點點的關注和預先思考,而這些是人類擅長而電腦不擅長的。![]() ![]() |
有一點是,IM 在決定如何最佳化影像影格時,不僅應該考慮當前正在查看的影格集中像素的數量,還應該考慮新增的額外影格的整體大小,以及可能獲得的整體壓縮結果。 另一方面,IM 也不會考慮到可能導致的像素數量減少,超出直接涉及的影格。也就是說,由於影格加倍或使用的處理方法,後續影格大小也可能會更小。當選擇是使用「前一影像處置」方法時,尤其如此,這種方法可以在動畫序列的後期大幅減少像素數量,而不是緊接著的下一影格。在這裡做出好的選擇通常需要人工輸入。 因此,我不能保證 IM 會為特定的動畫產生最佳的最佳化選擇。但是,它肯定會在不使用遞迴的情況下,盡力做出選擇。也就是說,僅使用立即像素數量來做出決策。 遞迴演算法,一種做出選擇,然後查看由該選擇產生的動畫的最佳最終大小(包括沿途的遞迴選擇)可以產生有保證的最佳最佳化。然而,它也可能是一個極其緩慢的運算子,對於大型動畫,可能需要數年的時間才能做出最終決定。它還需要包含壓縮最佳化選擇,因為這些選擇可能會影響最終結果。換句話說,雖然這樣的演算法可以保證最佳的最佳化,但它是以沉重的計算成本為代價的。 當然,正如您在上面使用分割影格更新時所見,對動畫試圖實現的目標有深入了解的人,通常在複雜的動畫中會做得更好。 如果您想嘗試建立一個遞迴 GIF 最佳化運算子,請務必嘗試。我會盡我所能提供幫助。它將擊敗市面上幾乎所有其他 GIF 最佳化程式。此外,大多數 GIF 動畫開發人員可能會非常感謝您的努力(金錢方面)。 |
半透明處理
GIF 檔案格式不允許使用半透明像素(請參閱GIF 布林透明度)。這是一個事實,在您可以正確最佳化動畫,甚至將其儲存為 GIF 格式之前,您需要以適合動畫的方式處理可能存在的任何半透明像素。默認情況下,如果您不處理這些像素,IM 將使用 50% 的閾值將這些像素神奇地轉換為完全透明或完全不透明。然而,這可能不是處理問題的最佳方法,特別是在包含大面積半透明像素的影像中,例如陰影效果。例如,我想建立一個星際之門阿斯嘉特傳送動畫,它可以將幾乎任何子影像作為被傳送的物件。
magick -channel RGBA -fill white \ \( medical.gif -repage 100x100+34+65 -coalesce -set delay 200 \) \ \( +clone -motion-blur 0x20+90 -blur 0x3 -colorize 100% \ +clone -colorize 30% +swap -composite -set delay 10 \) \ \( +clone -roll +0-20 -blur 0x3 -colorize 30% \ -motion-blur 0x15+90 -motion-blur 0x15-90 -set delay 10 \) \ \( +clone -colorize 30% \ -motion-blur 0x30+90 -blur 0x5 -crop +0+10\! \) \ \( +clone -motion-blur 0x50+90 -blur 0x2 -crop +0+20\! \) \ \( +page -size 100x100 xc:none -set delay 200 \) \ -set dispose background -coalesce -loop 0 teleport.miff gif_anim_montage teleport.miff teleport_frames.png |
![[IM Output]](teleport_frames.png)
好的,我有一個動畫序列。如果我嘗試直接將其保存為 GIF,IM 將會對所有半透明像素進行閾值處理。
|
![]() |
magick teleport.miff -channel A -threshold 50% +channel \ ...do further processing now... teleport.gif |
使用上述 DIY 方法的一個額外優點是,您可以控制閾值級別。例如,設置為「10% 」會移除幾乎所有存在的半透明像素,而設置為「90% 」會使它們全部變為不透明。
|
![]() |
保留上述動畫中所有特殊效果的最佳整體解決方案是添加純色背景。
|
![]() |
一個簡單的解決方案是使用擴散像素有序抖動技術,該技術可以限制在僅適用於 alpha 通道,以移除半透明像素。
|
![]() |
使用半色調將通過使透明度模式更加粗體來產生更好的效果。
|
![]() |
但對於這個特定的動畫,我發現使用用戶設計的抖動圖來產生垂直線(從水平線抖動模式)會產生一種效果,可以在移除半透明像素的同時增強瞬間移動動畫。
|
![]() |
色彩優化
處理半透明像素只是 GIF 文件格式的第一個限制。下一個限制是動畫中每個顏色表的顏色限制為 256 色。您可以為每一幀使用單獨的顏色表。這意味著單個動畫可以具有超過 256 種顏色。但是,即使這樣也不一定是一個好主意。如果您只想快速了解可用的顏色優化選項,我建議您跳到有關視頻轉 GIF的示例,其中動畫的顏色問題最為嚴重。GIF 色彩問題
GIF 動畫在處理顏色方面尤其存在問題,首先它不允許半透明顏色,然後每幀只有 256 色的限制,或者全局 256 色的限制。最後,除非在一幀中用於像素的顏色與下一幀中圖像該部分未更改時使用的顏色相同,否則您的最佳幀優化將無法很好地工作!這似乎是一個簡單的問題,但色彩減少本身就是一個極其複雜的領域,在 IM 範例中需要用一整個章節來講解。顏色問題實際上是您在全球資訊網上找到的大多數 GIF 動畫都是卡通風格或看起來很糟糕的原因,尤其是從較大版本的動畫調整大小時。在調整動畫大小中,顏色優化可能需要比實際調整大小過程本身付出更多努力。在這裡,我假設您擁有動畫的原始來源。但這並非總是可行,因此如果您要優化修改後的 GIF 動畫,則可能需要格外小心。但是,如果您的動畫顏色過多,首先需要記住的是...
不要直接保存為 GIF 格式,
請使用 MIFF 文件格式 或 分開的 PNG 圖像。
一旦保存為 GIF,您就無法控制 GIF 顏色優化工作,並且您可能會得到一個看起來很糟糕的 GIF 動畫,它使用各種幀優化技術無法很好地優化。請使用 MIFF 文件格式 或 分開的 PNG 圖像。
速度動畫- 顏色過多的動畫
首先,我們需要生成一個顏色非常多的 GIF 動畫,以便我們可以真正測試顏色優化中涉及的問題。
|
![]() |
||
![]() |
speed.miff
」。這保留了原始創建(或修改)動畫的所有方面,包括 GIF 元數據、時間延遲以及圖像的所有顏色,而不會失真。只有在保留原始動畫後,我才將原始動畫直接轉換為 GIF 格式。這樣我就可以展示上述代碼旨在實現的目標,以及為什麼我將其稱為「速度」。這樣做也是為了提供一個基準 GIF 動畫,以便於研究和後續比較。那麼讓我們來看看我們原始動畫的各種細節。
|
![]() |
|
![]() |
|
![]() |
|
![]() |
magick identify
」命令無法告訴您 GIF 文件使用了多少個這樣的局部顏色表,因為該信息過於特定於格式,並且與 IM 通常執行的圖像處理無關。但是,更具體的「Giftrans
」程序可以告訴您使用了多少個低級局部顏色表...如您所見,此動畫具有 ![[IM 文字]](speed_ctables.txt.gif)
在顏色優化之前進行影格優化?
正如您在上面看到的,將動畫直接保存為 GIF 格式是可行的,但您會在相鄰影格之間看到相當多的顏色差異,這對以後的 影格優化 不利(您稍後會看到)。為防止顏色差異導致此類問題,您可以在保存動畫之前執行 影格優化,從而避免引入相鄰影格之間的顏色差異。但是請注意,在減色之前進行影格優化會改變減色的動態。通常,優化的子影格中出現的靜態不動區域較少,這意味著該影格的顏色量化可以降低這些顏色的重要性,從而減少顏色數量。模糊色彩優化
但是,有時您在將原始動畫保存為 GIF 格式之前無法訪問它。如果您從 WWW 下載了原始動畫,則尤其如此。這意味著您已經擁有具有所有這些 GIF 顏色失真的動畫,這會給以後的優化帶來問題。現在,由於相鄰影格使用了一組稍微不同的顏色,並且動畫中的每個影格都使用了不同的像素模式,因此每個影格都可以被視為完全不同的圖像。例如,讓我們比較一下第一個和第三個影格,它們共享了大量的相同背景圖像……。
|
![]() |
![]() ![]() |
如果您的源圖像使用 JPEG 圖像格式存儲,則此類圖像差異也是一個問題。此格式使用有損壓縮方法,即使在 100% 的質量下,也會導致圖像中出現輕微的顏色差異。但是,差異通常僅限於實際差異區域周圍的光暈,而不是遍及整個圖像。 我只能說,除非您打算將單個圖像用作所有影格的靜態背景圖像,否則請避免在動畫中使用 JPEG 圖像。 |
magick speed.gif -layers OptimizeFrame speed_opt2.gif gif_anim_montage speed_opt2.gif speed_opt2_frames.gif |
![[IM Output]](speed_opt2_frames.gif)
magick speed.gif -fuzz 5% -layers OptimizeFrame speed_opt3.gif gif_anim_montage speed_opt3.gif speed_opt3_frames.gif |
![[IM Output]](speed_opt3_frames.gif)
magick speed.gif -fuzz 5% -deconstruct speed_opt4.gif gif_anim_montage speed_opt4.gif speed_opt4_frames.gif |
![[IM Output]](speed_opt4_frames.gif)
生成單一全域顏色表
現在,由於每個影格都有一組不同的顏色,因此 IM 被迫保存圖像,每個影格都有獨立的顏色表:第一個影格使用一個全域顏色表,後面的影格使用 3 個局部顏色表。例如,在這裡,我使用了非常簡單的程式「Giftrans
」程式來報告建立了多少個影格顏色表。對於一個完全融合的(或像電影膠片一樣的)動畫,為每一幀使用獨立的顏色表是完全可以接受且合理的,而且在這種情況下,這並不是問題。也就是說,對於差異很大的圖像幻燈片,獨立的顏色表將產生最佳效果。因此,這是 IM 的正常工作行為。然而,所有這些額外的顏色表都非常消耗資源,因為每個顏色表都可能使用大量空間。每個顏色表最多可以使用 768 位元組(256 色 × 每色 3 位元組,或 3/4 KB)來儲存圖像中的每一幀。不僅如此,GIF 壓縮不會壓縮這些顏色表,只會壓縮像素數據!如果為獨立的顏色表分配這麼多檔案空間是個問題,特別是對於顏色變化不大的圖像(例如大多數 GIF 動畫),那麼您可以讓 IM 只使用所需的全局顏色表,而不添加任何局部顏色表。---要移除局部顏色映射表,所有圖像都必須變成調色板類型,並使用相同的調色板。在命令列中,您可以透過設定「+map
」來定義命令調色板,您不能使用 -colors,因為它作用於單個圖像。命令列解決方案是一個特殊的「+map
」選項,它會對添加到所有圖像的通用調色板執行全局顏色縮減。注意,對圖像的任何更改都可能會使調色板失效,因此,雖然顏色縮減應該在執行 GIF 幀和/或壓縮最佳化之前完成,但通用調色板需要最後執行,就在保存之前。如果「+map
」不需要減少圖像中的顏色數量,它就不會執行顏色縮減或抖動顏色,而只是在所有圖像中添加一個通用的調色板。---如果所有幀都使用相同的顏色調色板,則 IM 可以生成單個全局顏色表。在 IM 中,顏色調色板只能透過從使用這種調色板的圖像格式讀取,或透過使用「-map
」顏色縮減運算符分配一個顏色調色板來分配給圖像。有關詳細信息,請參閱使用預定義顏色映射表進行抖動。生成此單個顏色表的一種方法是簡單地將所有幀「-append
」在一起,然後使用「-colors
」命令將顏色數量減少到最小集合(小於 256,如果您想要更小的顏色表,則可以更小)。然後,可以使用「-map
」將生成的顏色表應用於原始圖像。例如,這裡將圖像縮減為單個 64 色集合。這使用特殊的MPR 內存寄存器將生成的顏色映射表分配給「-map
」命令。
|
![]() |
Giftrans
」檢查生成的動畫,您會發現該圖像現在使用單個「全局」顏色表,而不是為每一幀使用獨立的顏色表。![]() ![]() |
我在將圖像附加在一起之前使用「None 」的「-background 」顏色,允許您在未融合的動畫上使用它,並且不會添加額外的、不需要的顏色。使用了特殊的「 -quantize 」設置「transparent 」色彩空間,以確保 IM 不會嘗試在其顏色映射表中生成半透明顏色。這一點毫無用處,因為我們正在將結果保存為 GIF,而 GIF 無法處理半透明度。最後,我將顏色減少到 63 種,為透明顏色留出空間。有些動畫需要透明度,而其他動畫(比如這個)稍後可能仍然需要透明度來進行壓縮優化。 |
+map
",它將在所有幀上生成一個通用的顏色表(256 色),並全局應用它。這比上面的 DIY 方法簡單得多。
|
![]() |
![[IM 文字]](speed_map_ctables.txt.gif)
![[IM 文字]](speed_size.txt.gif)
+map
" 運算符後,現在變為![[IM 文字]](speed_map_size.txt.gif)
+map
" 運算符應該是最後一個操作。請記住
移除局部顏色表應該是最後的優化,在保存為 GIF 格式之前。
有序抖動,移除「靜態」


... small number of colors ...通過對較小的靜止區域進行幀優化,您甚至可以獲得看起來更糟的矩形靜態區域。... 有序抖動 ... 現在請參閱更實用、更詳細的視頻轉 GIF 優化摘要。
壓縮優化
通過處理半透明像素並使用顏色和幀優化,將動畫保存為 GIF 格式後,您還可以通過迎合 GIF 壓縮算法來進一步減小文件大小。如果 GIF 文件格式可以使用的 LZW 壓縮或行程編碼找到較大面積的恆定顏色或反覆出現的像素序列,則壓縮效果會更好。透明度優化
正如您在幀優化中所見,疊加圖像通常只會重複顯示的內容。也就是說,它會疊加在 GIF 處理方法應用後已經存在的相同顏色的像素。但是,為什麼要費心重複這些像素呢?如果您已經在圖像中使用了透明度,那麼您就可以使用透明像素顏色。但是,將這些區域轉換為透明度後,會得到更大面積的均勻透明像素。與使用混合不同顏色來匹配要疊加的相同區域相比,這種方式可以更好地壓縮。例如,以下是一個簡單的幀優化、疊加動畫...
![]() |
![]() |
-layers
" 方法 'OptimizeTransparency
'(IM v6.3.4-4 中添加)將任何不會改變顯示結果的像素替換為透明像素。
|
![]() |
||
![]() |
![[IM 文字]](bunny_bgnd_size.txt.gif)
![[IM 文字]](bunny_bgnd_opttrans_size.txt.gif)
FUTURE: link to a 'remove background' from animation當然,就像大多數其他「
-layers
」方法(比較或優化)一樣,您可以指定一個 模糊因子 來調整顏色被認為「多麼相似」。這讓您可以處理顏色抖動很糟糕的動畫,不過如果您已經研究過上面的 顏色優化,您應該不會遇到這個問題。免費的動畫 GIF 工具「InterGIF
」也提供了與上面顯示的相同的透明度壓縮優化,但它無法支援「模糊因子」來使「接近」的顏色變化也變得透明。我不推薦它,除非在 IM 不可用的情況下作為替代方案。 LZW 優化- (非 IM)
某些應用程式可以進一步最佳化動畫中影像的壓縮率,使其更小。然而,要做到這一點,需要對 GIF 影像檔案格式通常使用的 LZW 壓縮有專門的了解。基本上,如果 LZW 壓縮演算法已經處理了特定的像素序列,它就不會費心將其轉換為透明像素,因為這樣做不會改善影像壓縮。這聽起來很奇怪,但它確實有效。不幸的是,*ImageMagick 不會這樣做*,因為這是一個非常複雜的過程,需要大量的技巧和資源才能獲得一個合理良好的啟發式方法,以便在一般情況下產生良好的結果。不過,我可以使用「Gifsicle
」應用程式在其最高「-O2
」優化級別下,為您提供此技術的實際示例。
|
![]() |
LZW 壓縮最佳化將圖片從使用簡單透明度最佳化後的 ![]() ![]() 失真 LZW 優化- (非 IM)另一種壓縮改進方法涉及稍微修改像素顏色本身以達到「接近的顏色匹配」,以便增加影像中顏色參考的重複次數。重複的模式自然會壓縮得更好,因此可以產生更高的壓縮率。先前「Gifsicle」應用程式的分支,稱為 giflossy,也產生了一個「gifsicle 」程式,但該程式可以選擇以較小的方式修改影像(它是「有損的」)以進一步減小 GIF 影像的大小,尤其是在動畫中。
|