Skip to content

Instantly share code, notes, and snippets.

@koyachi
Last active August 15, 2019 01:29
Show Gist options
  • Save koyachi/3335f68985d21612ad82233eed8cf0a8 to your computer and use it in GitHub Desktop.
Save koyachi/3335f68985d21612ad82233eed8cf0a8 to your computer and use it in GitHub Desktop.

Revisions

  1. koyachi revised this gist Dec 2, 2018. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions _how-to-interpret-the-loop-count-in-gif.md
    Original file line number Diff line number Diff line change
    @@ -46,7 +46,7 @@ macos上で動作するメジャーなブラウザでのループ回数を調べ

    ## Netscape Looping Application Extensionが存在しない場合(iOS)
    ここで、Netscape Looping Application Extensionが存在しない場合のiOSアプリ上でのループ回数を確認してみます。
    ブラウザで見ると1回再生されるGIFのループ回数をkCGImagePropertyGIFLoopCountで参照すると0ということは、kCGImagePropertyGIFLoopCountでの解釈はB派のように見えます。これは想像ですがNetscape Looping Application Extension内に記されているループ回数を取得する、という用途に使うためのものだからだと思われます。これはこれでアリだけどブラウザの挙動に似せたい場合は困ります
    ブラウザで見ると1回再生されるGIFのループ回数をkCGImagePropertyGIFLoopCountで参照すると0ということは、kCGImagePropertyGIFLoopCountでの解釈はB派のように見えます。これは想像ですがNetscape Looping Application Extension内に記されているループ回数を取得する、という用途に使うためのものだからだと思われます。ただ、ブラウザの挙動に似せたい場合は困ります

    そもそも、Netscape Looping Application Extensionが存在しなく、複数画像フレームのみが存在するGIF画像はありえるのでしょうか?結果から言うとありえます。あるWebサービスにアップロードしたループ回数1回のGIFをダウンロードするとそうなっていました。あってもなくてもブラウザの解釈が同じならファイルから削ってしまって、ファイルサイズ圧縮手法の一つとして使われているのではないかと思われます。

    @@ -58,7 +58,7 @@ Netscape Looping Application Extensionが存在しなく複数画像フレーム

    このライブラリではループ回数以外の要素は真面目に解析していません。実装にあたってはいろんな言語のGIF解析ライブラリを参考にしました。GIFMetadataを使うことでUIImageView等に適切なループ回数を設定することができるようになりました。

    GIFMetadataを作るにあたって初めてSwiftでバイナリ解析のコードを書きましたが、他の言語でバイナリ解析するのと遜色ない感じで書けました。[Kaitai Struct](https://kaitai.io/)も気になりましたが、素直な実装としました
    GIFMetadataを作るにあたって初めてSwiftでバイナリ解析のコードを書きましたが、他の言語でバイナリ解析するのと遜色ない感じで書けました。このライブラリ実装時には[Kaitai Struct](https://kaitai.io/)も気になりましたが、decode対象部分も限定されているので素直な実装としました

    ## リンク
    - [kCGImagePropertyGIFLoopCount - Image I/O | Apple Developer Documentation](https://developer.apple.com/documentation/imageio/kcgimagepropertygifloopcount)
  2. koyachi revised this gist Dec 2, 2018. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion _how-to-interpret-the-loop-count-in-gif.md
    Original file line number Diff line number Diff line change
    @@ -34,7 +34,7 @@ GIF内にNetscape Looping Application Extensionが存在しない場合の2つ

    macos上で動作するメジャーなブラウザでのループ回数を調べてみました(2017-06-07, コヤチ調べ)

    | data in GIF | Chrome | Safari | Firefox |
    | GIF内のNetscape Looping Application Extensionブロック有無、画像フレームの有無、Extension内loop回数 | Chrome | Safari | Firefox |
    |:------------|:-------|:-------|:--------|
    | ブロックなし、複数フレームなし | 静止画 | 静止画 | 静止画 |
    | ブロックなし、複数フレームあり | 1回再生 | 1回再生 | 1回再生 |
  3. koyachi revised this gist Dec 2, 2018. 1 changed file with 4 additions and 3 deletions.
    7 changes: 4 additions & 3 deletions _how-to-interpret-the-loop-count-in-gif.md
    Original file line number Diff line number Diff line change
    @@ -7,7 +7,8 @@ iOSアプリでGIFアニメーションを再生してみたところ、PCのブ
    ## Netscape Looping Application Extensionをどう解釈するか
    GIFのフォーマットについて調べてみると、GIF内にはNetscape Looping Application Extension (GIF Unofficial Specification)という領域があり、ここにGIFのループ回数が記されていることがわかりました。
    ![](https://gist.github.com/koyachi/3335f68985d21612ad82233eed8cf0a8/raw/201e407c8d9d4d52e96a22869ae74312cbe244d5/netscape-looping-application-extension.png)
    - http://www.vurdalakov.net/misc/gif/netscape-looping-application-extension
    - [Netscape Looping Application Extension (GIF Unofficial Specification) - vurdalakov.net](http://www.vurdalakov.net/misc/gif/netscape-looping-application-extension)

    更に調べてみると、このNetscape Looping Application ExtensionはApplication Extensionを利用してNetscape社が入れた仕様で、明確なGIFの仕様ではなさそうでした。

    - 関連: [loop回数 = 2で記録されているのにChromeだと3回ループするのはなぜ?というChromiumのissue](https://bugs.chromium.org/p/chromium/issues/detail?id=592735)
    @@ -55,9 +56,9 @@ macos上で動作するメジャーなブラウザでのループ回数を調べ
    Netscape Looping Application Extensionが存在しなく複数画像フレームのみが存在する画像のループ回数を、ブラウザと同様に解釈したいので、以下のSwiftライブラリを作りました。
    - [koyachi/swift-GIFMetadata: Wrokaround for getting preferred loop count of Animation GIFs without Application Extension Blocks.](https://github.com/koyachi/swift-GIFMetadata)

    このライブラリではループ回数以外の要素は真面目に解析していません。実装にあたってはいろんな言語のGIF解析ライブラリを参考にしました。GIFMetadataを使うことでUIImageView等に適切なループ回数を設定することができました
    このライブラリではループ回数以外の要素は真面目に解析していません。実装にあたってはいろんな言語のGIF解析ライブラリを参考にしました。GIFMetadataを使うことでUIImageView等に適切なループ回数を設定することができるようになりました

    GIFMetadataを作るにあたってSwiftを使って初めてバイナリ解析のコードを書きましたが、他の言語でバイナリ解析するのと遜色ない感じでかけました[Kaitai Struct](https://kaitai.io/)も気になりましたが、素直な実装としました。
    GIFMetadataを作るにあたって初めてSwiftでバイナリ解析のコードを書きましたが、他の言語でバイナリ解析するのと遜色ない感じで書けました[Kaitai Struct](https://kaitai.io/)も気になりましたが、素直な実装としました。

    ## リンク
    - [kCGImagePropertyGIFLoopCount - Image I/O | Apple Developer Documentation](https://developer.apple.com/documentation/imageio/kcgimagepropertygifloopcount)
  4. koyachi renamed this gist Dec 2, 2018. 1 changed file with 2 additions and 0 deletions.
    Original file line number Diff line number Diff line change
    @@ -49,6 +49,8 @@ macos上で動作するメジャーなブラウザでのループ回数を調べ

    そもそも、Netscape Looping Application Extensionが存在しなく、複数画像フレームのみが存在するGIF画像はありえるのでしょうか?結果から言うとありえます。あるWebサービスにアップロードしたループ回数1回のGIFをダウンロードするとそうなっていました。あってもなくてもブラウザの解釈が同じならファイルから削ってしまって、ファイルサイズ圧縮手法の一つとして使われているのではないかと思われます。

    ![](https://gist.github.com/koyachi/3335f68985d21612ad82233eed8cf0a8/raw/038a8fe13a936ddc1fe419d5a6be38915478c776/dump-gif-header.png)

    ## Netscape Looping Application Extensionが存在しなく複数画像フレームのみが存在する画像のループを、iOSでもブラウザ同様に解釈したい
    Netscape Looping Application Extensionが存在しなく複数画像フレームのみが存在する画像のループ回数を、ブラウザと同様に解釈したいので、以下のSwiftライブラリを作りました。
    - [koyachi/swift-GIFMetadata: Wrokaround for getting preferred loop count of Animation GIFs without Application Extension Blocks.](https://github.com/koyachi/swift-GIFMetadata)
  5. koyachi revised this gist Dec 2, 2018. 1 changed file with 0 additions and 0 deletions.
    Binary file added dump-gif-header.png
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
  6. koyachi revised this gist Dec 2, 2018. 1 changed file with 5 additions and 1 deletion.
    6 changes: 5 additions & 1 deletion how-to-interpret-the-loop-count-in-gif.md
    Original file line number Diff line number Diff line change
    @@ -6,7 +6,7 @@ iOSアプリでGIFアニメーションを再生してみたところ、PCのブ

    ## Netscape Looping Application Extensionをどう解釈するか
    GIFのフォーマットについて調べてみると、GIF内にはNetscape Looping Application Extension (GIF Unofficial Specification)という領域があり、ここにGIFのループ回数が記されていることがわかりました。
    - (ここに図)
    ![](https://gist.github.com/koyachi/3335f68985d21612ad82233eed8cf0a8/raw/201e407c8d9d4d52e96a22869ae74312cbe244d5/netscape-looping-application-extension.png)
    - http://www.vurdalakov.net/misc/gif/netscape-looping-application-extension
    更に調べてみると、このNetscape Looping Application ExtensionはApplication Extensionを利用してNetscape社が入れた仕様で、明確なGIFの仕様ではなさそうでした。

    @@ -19,6 +19,8 @@ GIFのフォーマットについて調べてみると、GIF内にはNetscape Lo

    このAとBの解釈では、GIF上に同じループ回数が記されていても再生回数が1回分ズレることになります。

    ![](https://gist.github.com/koyachi/3335f68985d21612ad82233eed8cf0a8/raw/201e407c8d9d4d52e96a22869ae74312cbe244d5/loop-ccount-when-netscape-looping-application-extension-is-exist.png)

    GIF内にNetscape Looping Application Extensionが存在しない場合の2つの解釈方法は次の通りです:
    - A: 記録されている画像フレームたちをとりあえず展開(再生)し、更にloop回数分ループする派
    - => loop回数(今回はextensionブロック無しなので0) + 1回ループしてるように見える
    @@ -27,6 +29,8 @@ GIF内にNetscape Looping Application Extensionが存在しない場合の2つ
    - => loop回数(今回はextensionブロック無しなので0)
    - = 0

    ![](https://gist.github.com/koyachi/3335f68985d21612ad82233eed8cf0a8/raw/201e407c8d9d4d52e96a22869ae74312cbe244d5/loop-count-when-netscape-looping-application-extension-is-NOT-exist.png)

    macos上で動作するメジャーなブラウザでのループ回数を調べてみました(2017-06-07, コヤチ調べ)

    | data in GIF | Chrome | Safari | Firefox |
  7. koyachi revised this gist Dec 2, 2018. 4 changed files with 64 additions and 1 deletion.
    65 changes: 64 additions & 1 deletion how-to-interpret-the-loop-count-in-gif.md
    Original file line number Diff line number Diff line change
    @@ -1 +1,64 @@
    a
    # iOSアプリ上でGIFのループ回数をいい感じに解釈する
    iOSアプリでGIFアニメーションを再生してみたところ、PCのブラウザ上でのループ再生回数と異なるケースがあることがわかりました。PCのブラウザ上で動作するWebアプリケーションと同等のGIFループ再生機能を提供したかったので、なぜループ再生回数が違うのか調査し、その違いを吸収することを試みました。

    具体的な事象としては、ブラウザで表示すると1回アニメーションするGIFのループ回数が、[kCGImagePropertyGIFLoopCount](https://developer.apple.com/documentation/imageio/kcgimagepropertygifloopcount) を使ってGIFファイル中のループ回数を取得すると0が返ってきていました。
    [UIImageViewのanimationRepeatCount](https://developer.apple.com/documentation/uikit/uiimageview/1621070-animationrepeatcount)ではrepeat count == 0は無限ループを意味し、このまま解釈するとiOS上では無限ループしてしまい、ブラウザと同様に再生できません。

    ## Netscape Looping Application Extensionをどう解釈するか
    GIFのフォーマットについて調べてみると、GIF内にはNetscape Looping Application Extension (GIF Unofficial Specification)という領域があり、ここにGIFのループ回数が記されていることがわかりました。
    - (ここに図)
    - http://www.vurdalakov.net/misc/gif/netscape-looping-application-extension
    更に調べてみると、このNetscape Looping Application ExtensionはApplication Extensionを利用してNetscape社が入れた仕様で、明確なGIFの仕様ではなさそうでした。

    - 関連: [loop回数 = 2で記録されているのにChromeだと3回ループするのはなぜ?というChromiumのissue](https://bugs.chromium.org/p/chromium/issues/detail?id=592735)

    明確なGIFの仕様ではないので、GIFプレイヤーの実装で解釈が異なることがありえそうです。GIF内にNetscape Looping Application Extensionが存在する場合の2つの解釈方法を考えてみます:
    - A: 記録されている画像フレームたちをとりあえず展開(再生)し、更にloop回数分ループする派
    - (ここでいう「画像フレーム」とは、Animation用の各フレームのことです)
    - B: loop回数分だけループする派

    このAとBの解釈では、GIF上に同じループ回数が記されていても再生回数が1回分ズレることになります。

    GIF内にNetscape Looping Application Extensionが存在しない場合の2つの解釈方法は次の通りです:
    - A: 記録されている画像フレームたちをとりあえず展開(再生)し、更にloop回数分ループする派
    - => loop回数(今回はextensionブロック無しなので0) + 1回ループしてるように見える
    - = 1
    - B: loop回数分だけループする派
    - => loop回数(今回はextensionブロック無しなので0)
    - = 0

    macos上で動作するメジャーなブラウザでのループ回数を調べてみました(2017-06-07, コヤチ調べ)

    | data in GIF | Chrome | Safari | Firefox |
    |:------------|:-------|:-------|:--------|
    | ブロックなし、複数フレームなし | 静止画 | 静止画 | 静止画 |
    | ブロックなし、複数フレームあり | 1回再生 | 1回再生 | 1回再生 |
    | ブロックあり、loop回数=0 | 無限ループ | 無限ループ | 無限ループ |
    | ブロックあり、loop回数=1 | 2回再生 | 1回再生 | 1回再生 |
    | ブロックあり、loop回数=2 | 3回再生 | 2回再生 | 2回再生 |

    現在のブラウザではB派に近い(loop回数分だけループする派 + 0の場合だけ無限ループ)解釈が多いようです。

    ## Netscape Looping Application Extensionが存在しない場合(iOS)
    ここで、Netscape Looping Application Extensionが存在しない場合のiOSアプリ上でのループ回数を確認してみます。
    ブラウザで見ると1回再生されるGIFのループ回数をkCGImagePropertyGIFLoopCountで参照すると0ということは、kCGImagePropertyGIFLoopCountでの解釈はB派のように見えます。これは想像ですがNetscape Looping Application Extension内に記されているループ回数を取得する、という用途に使うためのものだからだと思われます。これはこれでアリだけどブラウザの挙動に似せたい場合は困ります。

    そもそも、Netscape Looping Application Extensionが存在しなく、複数画像フレームのみが存在するGIF画像はありえるのでしょうか?結果から言うとありえます。あるWebサービスにアップロードしたループ回数1回のGIFをダウンロードするとそうなっていました。あってもなくてもブラウザの解釈が同じならファイルから削ってしまって、ファイルサイズ圧縮手法の一つとして使われているのではないかと思われます。

    ## Netscape Looping Application Extensionが存在しなく複数画像フレームのみが存在する画像のループを、iOSでもブラウザ同様に解釈したい
    Netscape Looping Application Extensionが存在しなく複数画像フレームのみが存在する画像のループ回数を、ブラウザと同様に解釈したいので、以下のSwiftライブラリを作りました。
    - [koyachi/swift-GIFMetadata: Wrokaround for getting preferred loop count of Animation GIFs without Application Extension Blocks.](https://github.com/koyachi/swift-GIFMetadata)

    このライブラリではループ回数以外の要素は真面目に解析していません。実装にあたってはいろんな言語のGIF解析ライブラリを参考にしました。GIFMetadataを使うことでUIImageView等に適切なループ回数を設定することができました。

    GIFMetadataを作るにあたってSwiftを使って初めてバイナリ解析のコードを書きましたが、他の言語でバイナリ解析するのと遜色ない感じでかけました。[Kaitai Struct](https://kaitai.io/)も気になりましたが、素直な実装としました。

    ## リンク
    - [kCGImagePropertyGIFLoopCount - Image I/O | Apple Developer Documentation](https://developer.apple.com/documentation/imageio/kcgimagepropertygifloopcount)
    - [animationRepeatCount - UIImageView | Apple Developer Documentation](https://developer.apple.com/documentation/uikit/uiimageview/1621070-animationrepeatcount)
    - [Netscape Looping Application Extension (GIF Unofficial Specification) - vurdalakov.net](http://www.vurdalakov.net/misc/gif/netscape-looping-application-extension)
    - [592735 - GIF animation loops once more than it should - chromium - Monorail](https://bugs.chromium.org/p/chromium/issues/detail?id=592735)
    - [koyachi/swift-GIFMetadata: Wrokaround for getting preferred loop count of Animation GIFs without Application Extension Blocks.](https://github.com/koyachi/swift-GIFMetadata)
    - [Kaitai Struct](https://kaitai.io/)
    - [Goodpatch Advent Calendar 2018 - Qiita](https://qiita.com/advent-calendar/2018/goodpatch)
    - [ちょうど10年前にもバイナリのこと書いてました](http://perl-users.jp/articles/advent-calendar/2008/)
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
    Binary file added netscape-looping-application-extension.png
    Loading
    Sorry, something went wrong. Reload?
    Sorry, we cannot display this file.
    Sorry, this file is invalid so it cannot be displayed.
  8. koyachi renamed this gist Dec 2, 2018. 1 changed file with 0 additions and 0 deletions.
  9. koyachi created this gist Dec 2, 2018.
    1 change: 1 addition & 0 deletions how-to-interpret-the-loop-count-in.gif.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    a