0
0

More than 3 years have passed since last update.

【iOS】Pythonista3でGIFアニメのコマごとの表示時間を変更する。

Last updated at Posted at 2020-08-13

はじめに

以前、GIFアニメでハマった記事を書く際にGIFフォーマットの詳細という素晴らしい記事が見つけました。
GIFファイルの中の画像にはそれぞれディレイタイムが2バイトで設定されており、0.01秒単位で設定できるようです。

目標は【Graphic Control Extension】

GIFファイルの中には画像データがあるのは当然ですが、画像データの前にはGraphic Control Extensionという8バイトのブロックがあるそうです。

Graphic Control Extension

  • Extension Introducer(1B) = 0x21   <= 印 1
  • Graphic Control Label(1B) = 0xf9  <= 印 2
  • Block Size(1B) = 0x04       <= 印 3
  • R(3b),DM(3b),UIF(1b),TCF(1b)
  • Delay Time(2B)          <= ここがディレイタイム
  • Transparent Color Index(1B)
  • Block Terminator(1B) = 0x00

バイナリエディタで確認

ディレイタイムを1秒にセットしたGIFアニメをバイナリエディタで確認してみました。

5A681C6A-B727-43D3-BDCA-E817CD2029F7.png
ちゃんと印1~30x21f904に続いてディレイタイム0x6400があります。
1秒で設定してるので0.01で割ると100なので、100 = 0x0064となり、リトルエンディアンで格納すると0x6400で間違いありません。
この値をゴニョゴニョすればコマごとの表示時間を変更できるということですね。

やってみよう

ChangeDelay.py
# GIFファイルをバイナリデータとして開く。
FileName = 'test.gif'
with open(FileName,'rb') as f:
    Bin = f.read()

# Graphic Control Extentionを探して位置とディレイ値をListに記録する。
GCE = b'\x21\xf9\x04'
DelayList = []
point = 0
while point < len(Bin):
    start = Bin.find(GCE,point)
    if start<0:break
    delay = int.from_bytes(Bin[start+4:start+6],byteorder="little")
    DelayList.append([start+4,delay])
    point = start+1

# 最初の1枚を1秒に、半分以降を5倍の長さに変更する。
DelayList[0][1]=100
for i in range(1,len(DelayList)//2):
    DelayList[-i][1]*=5

# バイナリデータを書き換える。
for point,delay in DelayList:
    Bin = Bin[:point] + delay.to_bytes(2,byteorder="little") + Bin[point+2:]


# バイナリデータをGIFとして保存。
with open('temp.gif','wb') as f:
    f.write(Bin)

Before

20枚の画像全てが0.05秒に設定。
90E284C4-F734-4E82-B99E-6F4636142A32.gif

After

最初の1枚を1秒にして、半分以降を5倍に書き換えました。
DEA4F364-7E69-4607-BA68-2711AC552EDF.gif

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0