GIF 轉 Sprite Sheet 轉換器 — 免費、在瀏覽器中執行、免上傳

製作你自己的 GIF 轉 Sprite Sheet
拖入 GIF,取得可直接用於遊戲的 Sprite Sheet — 選擇欄數、列數與 FPS,保留透明度,下載 PNG 圖集。一切都在你的瀏覽器中進行,檔案不會離開你的裝置。
GIF 轉 Sprite Sheet 聽起來很簡單,直到你親手做一次。GIF 本身就是一連串完整影格,帶有調色盤與各影格延遲,所以你真正需要的工具,是能解碼每個影格、正確合成透明度,並把這些影格排列在同一張 PNG 上、以紋理座標定址的網格中。Neta Studio 的轉換器會在瀏覽器的 canvas 元素上本機完成解碼步驟,因此你的檔案會留在瀏覽器中,永遠不會接觸到伺服器。你拖入 GIF、選擇欄數、列數與 FPS,然後下載單一 PNG 圖集。
困難的部分不是繪圖,而是調色盤、時間與網格運算。GIF 將透明度儲存為顏色表的索引,因此一個在圖片檢視器中看起來乾淨的影格,一旦經過合成,到了 canvas 上可能帶著黑色或白色底。GIF 的影格延遲以百分之一秒為單位,而且經常每個影格都不同,這就是為什麼直接匯出會產生一張播放起來會卡頓的 Sprite Sheet。本頁涵蓋真正重要的設定,以及我們在打造這項工具時遇到的失敗模式。
將 GIF 轉換成 Sprite Sheet
轉換器就在頁面最上方:拖放區、影格預覽列,以及四個控制項 — 欄數、列數、FPS,還有一個保留 Alpha 通道的切換開關。當你拖入檔案,瀏覽器會透過 GIF 解碼器為每個影格建立 ImageBitmap,將每個影格以來源尺寸繪製到離屏 canvas,再把它們 blit 到圖集 canvas 中計算好的儲存格位置。來源檔案會以 File API 讀取並保留在記憶體中。不會發出任何攜帶你 GIF 的網路請求。
輸出永遠是 PNG。PNG 提供 8 位元 Alpha 通道,這正是角色製作所需要的;JPEG 會把每個柔和邊緣壓平成底色。如果你的 GIF 沒有透明度,圖集仍會是 RGBA,而未使用的 Alpha 位元組只會增加檔案大小。如果你的 GIF 確實使用了透明度,解碼器必須要求完整套用 disposal 的影格,而不是局部更新,否則移動中的元素會在整張 Sprite Sheet 上拖出殘影。
建構 Sprite Sheet 時,要配合引擎取樣的方式,而不是它在檔案瀏覽器裡看起來的樣子。4x4 的 64x64 影格網格是 256x256 的紋理,第 n 個影格的位置是欄 n mod 4、列 floor(n / 4)。當目標引擎或著色器圖集要求 2 的次方時,請將 Sprite Sheet 尺寸保持在 2 的次方;320x320 的 Sprite Sheet 在某些路徑上會被補齊或重新取樣,Sprite 邊緣就會變柔和。
01
將 GIF 拖放到轉換器上。在你變更任何設定之前,影格數與來源尺寸就會顯示出來。
02
將欄數與列數設為你想要的網格。以 24 個影格的動畫來說,6x4 是常見選擇;單列也可以,而這正是 VRChat 需要的。
03
將 FPS 設為你的遊戲會使用的播放速率。這會決定記錄在 Sprite Sheet 中的名目影格時間;輸出是靜態 PNG,因此實際播放速率由引擎驅動。
04
除非你的目標格式不支援 Alpha,否則請保持開啟。如果你的 GIF 在預覽中顯示黑色背景,表示來源沒有透明索引,那個黑色是真實存在的。
05
下載 PNG 並檢查尺寸是否符合你的目標:寬度等於欄數乘以影格寬度,高度等於列數乘以影格高度。

VRChat 用的 GIF 轉 Sprite Sheet
VRChat 的 flipbook 著色器會將紋理讀取為一條水平長條,而不是網格。如果你給它 6x4 的 Sprite Sheet,你只會得到第一列重複的長條,因為 UV 運算假設每個影格都位於同一列,而影格索引只會在 U 軸上前進。請將欄數設為你的影格數,列數設為 1。24 個影格的動畫就會變成 24x1 的 Sprite Sheet。
讓長條的總寬度成為 2 的次方。24 個影格、每個影格 64 像素的長條寬度是 1536 像素,這不是 2 的次方;下一個能被 64 像素整除的尺寸是 2048,可容納 32 個影格。你可以用透明像素或重複最後一個影格來補滿未使用的儲存格。2 的次方很重要,因為非 PoT 紋理在上傳路徑中經過 mipmap 產生或壓縮時,取樣可能偏移半個 texel,而只有一像素寬的 Sprite 就會顯現出來。
在這裡處理 Alpha,也就是在 Sprite Sheet 中,而不是在著色器裡。著色器中的去背或 alpha-test 路徑是粗糙的工具;GIF 抗鋸齒輪廓產生的柔和邊緣,會依臨界值而保留下來或消失,而你不會想為每個虛擬角色調整那個臨界值。匯出帶有真實 Alpha 且邊緣對預乘安全(premultiplied-safe)的 PNG,著色器只要取樣即可。保持迴圈節奏固定:VRChat 的 flipbook 以固定時間步進前進,所以如果你的來源 GIF 有不等長的各影格延遲,請在匯出前將它們均等化,否則動畫會以統一速率播放,與原始時間不一致。
完整參數清單與紋理設定,請參閱 flipbook 紋理指南。
GIF 轉影格網格(「試算表」)
當人們搜尋 gif to spreadsheet 時,他們幾乎不是指 .xlsx。他們指的是影格網格:影格以列與欄排列,讓每一格都能用索引定址。大家會用這個詞,是因為網格乍看之下很像試算表。這項工具會產生那個網格,而這個網格和 Sprite Sheet 是同一件事 — 差別只在於你怎麼稱呼它。真正重要的是版面規則一致:固定的儲存格大小、固定的欄數,以及從左到右、由上到下的影格順序。
人們有時會嘗試的另一種做法,是在像素藝術編輯器中一格一格繪製影格,疊上洋蔥皮,直到動畫看起來正確。那種工作流程適合原創角色,對於你已經擁有的 GIF 則很糟糕。像素編輯器不會讀取 GIF 的各影格延遲,而手動把 24 個影格匯入 24 個圖層,會完全遺失時間資訊。如果你的來源已經是動畫,轉成網格是更短的路徑。像素藝術工具值得在你原創製作時使用,而不是在轉碼時使用。
若你要手繪影格,像素藝術頁面涵蓋了繪圖與調色盤的部分。
影格尺寸、網格與透明背景
有四件事會破壞大多數轉換。每一件都有特定症狀。
GIF 的透明度會死在調色盤裡。GIF 最多只能使用 256 色,並以調色盤索引標示透明度。當影格以 disposal method 2 解碼時,某個影格中原本透明的區域,可能會被還原成前一張影格的背景色。修正方法是將每個影格合成到透明緩衝區,而不是合成到白色。如果你的預覽在 Sprite 周圍顯示黑色或灰色形狀,那就是調色盤的背景索引,而它現在已經是真實像素。
最後一列不完整。如果你的影格數是 23,而你選擇 6 欄,你會得到三個完整列,以及最後一列只有五格,而不是六格。圖集高度仍會進位到完整列高。如果你的引擎的 flipbook 運算假設網格是完整的,並用總影格數除以欄數來推算影格索引,它會在迴圈結尾讀到空白格。請用透明格把 Sprite Sheet 補成完整矩形,或減少欄數讓影格數能整除。
影格尺寸必須能整除 Sprite Sheet。如果你從寬 320 的 Sprite Sheet 中擷取寬 64 的子矩形,你會剛好得到五欄。從寬 330 的 Sprite Sheet 中,你會得到五欄,以及 10 像素的剩餘區域,而那並不是影格。請讓 Sprite Sheet 的尺寸等於影格尺寸乘以欄數,兩個軸向都一樣。
原點差一。紋理 UV 座標通常從左下角開始,而影格網格則是從左上角排列。如果第 0 個影格被算成最後一個影格,表示你的引擎把 V 反轉了。欄 c、列 r 的 Sprite 儲存格在影像空間中的位置是 x = c * width、y = r * height,而將它轉成翻轉後的 UV,只需要用 1 減去該值。
- 網格控制項欄數、列數與 FPS 都是明確輸入。圖集尺寸由影格尺寸乘以網格計算得出,絕不猜測。
- 保留 Alpha匯出的是 RGBA PNG。透明區域會保持透明,包括最後一列不完整時的補齊格。
- 本機解碼GIF 在瀏覽器中解碼。沒有上傳步驟、沒有伺服器端佇列,也不必等待往返傳輸。
Sprite Sheet 接下來會去哪裡
無論哪種情況,匯出的都是同一張 PNG;差別在於引擎期望如何切割紋理,以及它如何處理 Alpha。將此處當作簡短參考。
針對每個目標,匯出一張該目標無需自訂著色器就能讀取的網格 Sprite Sheet。如果你要支援兩個目標,就匯出兩張:一張給 VRChat 的水平長條,一張給引擎的網格。從同一個 GIF 重新匯出,比撰寫 UV 運算來協調兩者更省時間。
| 目標 | 匯出 |
|---|---|
| Unity | 網格 Sprite Sheet、2 的次方紋理,Sprite Mode 設為 Multiple,並依儲存格大小進行網格切割;像素藝術使用 filter mode Point,平滑則使用 Bilinear。在匯入器上啟用 Alpha Is Transparency。 |
| Godot | 網格或長條,以 AtlasTexture 載入,或在 AnimatedSprite2D 中以 SpriteFrames 資源切割。像素作品請將 filter 設為 Nearest。影格時間來自 SpriteFrames 表,而不是 PNG。 |
| GameMaker | 網格 Sprite Sheet,以 Sprite 匯入,並將影格尺寸設為你的儲存格尺寸。影格數必須與 Sprite Sheet 完全相符;GameMaker 不會替你修剪不完整的最後一列。 |
| VRChat | 單一水平長條,總寬度為 2 的次方,欄數等於影格數,列數等於 1。Alpha 已寫入 PNG,迴圈節奏一致。 |
在 3D 中觀看你的 Sprite Sheet 動起來
大多數轉換器到了 PNG 就停止,讓你到別處驗證結果。3D 遊戲建構器則會繼續下去:你可以將 Sprite Sheet 載入到面向鏡頭的平面上,在真實場景中觀看它動起來,這是唯一能回答網格與時間是否正確的測試。Agent Sprite Forge 是讓 Sprite 變成擁有控制器的角色的地方;Sprite 就是角色,而 3D 世界是它生活的地方。
The Cyclops' Island 就是這個想法的可玩示範 — 一個你可以在其中走動的小型 3D 場景,在瀏覽器中建構,並以 Sprite 作為角色。放入你自己的 Sprite Sheet,驅動示範影格的同一套機制就會取樣你的圖集。如果影格順序錯誤,你立刻就會看到:角色倒退走,或在迴圈結尾跳到空白格。如果 Alpha 錯誤,你會看到身體周圍出現生硬的矩形。這些都是你在引擎中會發現的相同錯誤,大約五秒內就能看見。
試玩可玩的 The Cyclops' Island 場景,並換上你自己的圖集。
更多免費 Sprite 工具
轉換器只是其中一塊。這三項涵蓋 Neta Studio 上其餘的 Sprite 工作流程,而且它們會在同一個瀏覽器工作階段中執行,並採用相同的本機檔案處理方式。
- Sprite Sheet 製作器將個別的影格圖像合併成單一圖集。當你的來源影格是分開的 PNG,而不是一個 GIF,而你仍需要規則網格時,這很實用。
- Sprite 動畫工具在時間軸上播放 Sprite Sheet、調整影格速率,並在不開啟引擎的情況下檢查迴圈節奏。可在匯出前捕捉影格順序差一錯誤。
- Sprite 資源庫關於網格設定、引擎匯入設定,以及各格式反覆出現的透明度陷阱的參考表與筆記。
走進它所屬的世界
Sprite 是一個無處可站的角色。最後一步是別人沒有提供的:把你剛做好的 Sprite Sheet 放進一個有人可以走動的世界 — 一座小島、一顆行星、一個下雨的街角。這個網站上的每個世界,都是從一段文字描述製作出來,並發佈成可遊玩的頁面。
常見問題
有 ezgif 的替代方案嗎? +
有,如果你需要的正好是 GIF 轉 Sprite Sheet。ezgif 處理廣泛的格式轉換;這項工具只做一件事:解碼 GIF、將影格排列成網格或長條,然後以你選擇的 Alpha 匯出 PNG 圖集。不會上傳任何內容,因此沒有伺服器佇列。
透明度會被保留嗎? +
會,前提是來源 GIF 確實使用透明的調色盤索引。匯出的是 RGBA PNG。常見的失敗原因在於來源:許多 GIF 使用的是實心背景色,而不是透明度,那個背景就會以真實像素出現在 Sprite Sheet 中。
為什麼我的 Sprite Sheet 有黑色背景? +
GIF 的調色盤背景索引是黑色,或者影格被合成到錯誤的緩衝區。GIF 影格可以是局部更新,因此解碼時若不遵循 disposal 方法,就會留下前一張影格的像素。在排列網格之前,請將每個影格重新合成到透明 canvas 上。
我要如何選擇欄數與列數? +
如果可以,請選擇能整除影格數的欄數,這樣就不會有最後一列不完整。以 24 個影格的動畫來說,6x4 可行。若要用於 VRChat,請將欄數設為影格數,列數設為 1。
我可以在 Sprite Sheet 中設定影格速率嗎? +
PNG 是靜態圖片,不帶時間資訊。工具中的 FPS 設定會記錄預定速率;實際播放由你的引擎或著色器驅動。VRChat 的 flipbook 以固定步進前進,因此請讓匯出速率與它相符。
為什麼匯出後動畫會卡頓? +
來源 GIF 的各影格延遲可能以百分之一秒為單位且不規則,而引擎正以固定速率前進。請將延遲均等化,或接受統一節奏,並將引擎速率設為平均值。
回到 3D 遊戲建構器
全部 31 個完成的 3D 世界、遊戲與場景都在同一頁 — 每一個都可以遊玩。
瀏覽現成的 Sprite Sheet
這個資源庫中的每項素材都是透明、可直接用於遊戲的 PNG,並附有記錄下來的提示詞 — Sprite Sheet 資源與免費 Sprite Sheet,依動作、風格與主題標記。可免費瀏覽與下載。