為什麼 GIF 去浮水印比照片難
照片是一張圖,GIF 是一條時間軸。一個 GIF 去浮水印工具必須回答三個靜態圖工具永遠不會碰到的問題:怎麼解碼幀、怎麼讓修復在幀與幀之間保持一致、怎麼在重新編碼時不把顏色搞壞。
解碼:幀不是各自獨立的圖片
很多動圖只存了與上一幀相比發生變化的那塊畫素,外加一條處理指令(disposal),用來說明之後這塊區域該怎麼處理。要正確修復第 12 幀,得先還原第 12 幀實際長什麼樣,也就是從第 0 幀開始把處理鏈重播一次。這個工具用一個串流式合成器來做這件事,最多同時只持有四張畫布,所以 60 幀的 GIF 不會膨脹成 60 張全尺寸點陣圖。
修復:一張遮罩,多個幀
每一幀都單獨畫一次選取範圍太折磨人了,所以你只在第一幀標記,這張遮罩會被重複使用。這也說明了為什麼它最適合位置固定的疊加層 —— 角落的 logo、日期戳記、字幕列。會橫跨畫面滑動的疊加層,是一張遮罩描述不出來的。
順帶一提,每一幀都跑模型也很浪費。修某一幀之前,會先把該幀選取範圍內的區域和上一幀的同一區域比對,幾乎一致就直接沿用上一次結果、跳過模型。一段帶固定浮水印的螢幕錄影裡,相當一部分幀根本不會碰到模型。
重新編碼:為什麼必須共用一張調色盤
GIF 只能放 256 種顏色。如果逐幀各自量化,同一種顏色在不同幀會被對應到不同的調色盤索引,播放時看起來就是顏色閃爍。所以這裡改成:在整段動畫裡取樣最多八幀拼成縮圖,從中算出一張調色盤,所有幀都按它對應。透明色會在這張調色盤裡佔一個專屬位置,而不是搶走某個真實顏色的位置。
正是這條流水線,把一個正經的 GIF 去浮水印工具和「碰巧能匯入 GIF 的圖片編輯器」區分開來:動圖被當成一串彼此相依的幀,而不是一張洗完就壓平匯出的圖片。
