Upgrade to Pro — share decks privately, control downloads, hide ads and more …

GoならわかるGIF

 GoならわかるGIF

GIFアニメーションの仕様・構造をimage/gifの実装を読みながら理解する話。

decafe09

April 19, 2019
Tweet

More Decks by decafe09

Other Decks in Programming

Transcript

  1. Go
    ならわかるGIF
    Umeda.go 2019 Spring 2019.04.20
    @decafe09

    View Slide

  2. 自己紹介
    @decafe09
    小野寺 俊也
    シナジー
    マー
    ケティング株式会社
    最近、
    サー
    バー
    サイドKotlin
    をはじめました。

    View Slide

  3. 今日の話
    Umeda.go 2018 Autumn
    であまり話せなかった
    GIF
    アニメー
    ションについて話します。
    よくあるWeb
    サー
    ビスのAPI
    を作ったらいろいろ勉強になった話
    https://speakerdeck.com/decafe09/webapplicationapitips?slide=20

    View Slide

  4. 今日の話
    GIF
    アニメー
    ションの仕様を
    image/gif
    のコー
    ドを読みながら
    理解する話。

    View Slide

  5. 広告で使うGIF
    の入稿規定の例
    GIF89a
    であること。
    幅●px
    以内、
    高さ●px
    以内であること。
    無限ルー
    プしないこと。
    再生秒数が●
    秒以内であること。(
    今回は割愛)

    View Slide

  6. t
    y
    p
    e G
    I
    F s
    t
    r
    u
    c
    t {
    I
    m
    a
    g
    e [
    ]
    *
    i
    m
    a
    g
    e
    .
    P
    a
    l
    e
    t
    t
    e
    d
    D
    e
    l
    a
    y [
    ]
    i
    n
    t
    s
    e
    c
    o
    n
    d
    .
    L
    o
    o
    p
    C
    o
    u
    n
    t i
    n
    t /
    / ★
    ルー
    プ回数
    D
    i
    s
    p
    o
    s
    a
    l [
    ]
    b
    y
    t
    e
    C
    o
    n
    f
    i
    g i
    m
    a
    g
    e
    .
    C
    o
    n
    f
    i
    g
    B
    a
    c
    k
    g
    r
    o
    u
    n
    d
    I
    n
    d
    e
    x b
    y
    t
    e
    }
    t
    y
    p
    e C
    o
    n
    f
    i
    g s
    t
    r
    u
    c
    t {
    C
    o
    l
    o
    r
    M
    o
    d
    e
    l c
    o
    l
    o
    r
    .
    M
    o
    d
    e
    l
    W
    i
    d
    t
    h
    , H
    e
    i
    g
    h
    t i
    n
    t /
    / ★
    幅,
    高さ
    }

    View Slide

  7. f
    u
    n
    c D
    e
    c
    o
    d
    e
    A
    l
    l
    (
    r i
    o
    .
    R
    e
    a
    d
    e
    r
    ) (
    *
    G
    I
    F
    , e
    r
    r
    o
    r
    ) {
    v
    a
    r d d
    e
    c
    o
    d
    e
    r
    i
    f e
    r
    r :
    = d
    .
    d
    e
    c
    o
    d
    e
    (
    r
    , f
    a
    l
    s
    e
    , t
    r
    u
    e
    )
    ; e
    r
    r !
    = n
    i
    l {
    r
    e
    t
    u
    r
    n n
    i
    l
    , e
    r
    r
    }
    g
    i
    f :
    = &
    G
    I
    F
    {
    I
    m
    a
    g
    e
    : d
    .
    i
    m
    a
    g
    e
    ,
    L
    o
    o
    p
    C
    o
    u
    n
    t
    : d
    .
    l
    o
    o
    p
    C
    o
    u
    n
    t
    , /
    / ★
    ルー
    プ回数
    D
    e
    l
    a
    y
    : d
    .
    d
    e
    l
    a
    y
    ,
    D
    i
    s
    p
    o
    s
    a
    l
    : d
    .
    d
    i
    s
    p
    o
    s
    a
    l
    ,
    C
    o
    n
    f
    i
    g
    : i
    m
    a
    g
    e
    .
    C
    o
    n
    f
    i
    g
    {
    C
    o
    l
    o
    r
    M
    o
    d
    e
    l
    : d
    .
    g
    l
    o
    b
    a
    l
    C
    o
    l
    o
    r
    T
    a
    b
    l
    e
    ,
    W
    i
    d
    t
    h
    : d
    .
    w
    i
    d
    t
    h
    , /
    / ★

    H
    e
    i
    g
    h
    t
    : d
    .
    h
    e
    i
    g
    h
    t
    , /
    / ★
    高さ
    }
    ,
    B
    a
    c
    k
    g
    r
    o
    u
    n
    d
    I
    n
    d
    e
    x
    : d
    .
    b
    a
    c
    k
    g
    r
    o
    u
    n
    d
    I
    n
    d
    e
    x
    ,
    }
    r
    e
    t
    u
    r
    n g
    i
    f
    , n
    i
    l
    }

    View Slide

  8. 使うだけならほぼここまで。
    今日の話はここから
    GIF
    アニメー
    ションの仕様を
    image/gif
    のコー
    ドを読みながら
    理解する話。
    v
    a
    r d d
    e
    c
    o
    d
    e
    r
    i
    f e
    r
    r :
    = d
    .
    d
    e
    c
    o
    d
    e
    (
    r
    , f
    a
    l
    s
    e
    , t
    r
    u
    e
    )
    ; e
    r
    r !
    = n
    i
    l {
    r
    e
    t
    u
    r
    n n
    i
    l
    , e
    r
    r
    }

    View Slide

  9. t
    y
    p
    e d
    e
    c
    o
    d
    e
    r s
    t
    r
    u
    c
    t {
    r r
    e
    a
    d
    e
    r
    /
    / F
    r
    o
    m h
    e
    a
    d
    e
    r
    .
    v
    e
    r
    s s
    t
    r
    i
    n
    g /
    / ★
    バー
    ジョン
    w
    i
    d
    t
    h i
    n
    t /
    / ★

    h
    e
    i
    g
    h
    t i
    n
    t /
    / ★
    高さ
    l
    o
    o
    p
    C
    o
    u
    n
    t i
    n
    t /
    / ★
    ルー
    プ回数
    d
    e
    l
    a
    y
    T
    i
    m
    e i
    n
    t
    b
    a
    c
    k
    g
    r
    o
    u
    n
    d
    I
    n
    d
    e
    x b
    y
    t
    e
    d
    i
    s
    p
    o
    s
    a
    l
    M
    e
    t
    h
    o
    d b
    y
    t
    e
    /
    / F
    r
    o
    m i
    m
    a
    g
    e d
    e
    s
    c
    r
    i
    p
    t
    o
    r
    .
    i
    m
    a
    g
    e
    F
    i
    e
    l
    d
    s b
    y
    t
    e
    /
    / F
    r
    o
    m g
    r
    a
    p
    h
    i
    c
    s c
    o
    n
    t
    r
    o
    l
    .
    t
    r
    a
    n
    s
    p
    a
    r
    e
    n
    t
    I
    n
    d
    e
    x b
    y
    t
    e
    h
    a
    s
    T
    r
    a
    n
    s
    p
    a
    r
    e
    n
    t
    I
    n
    d
    e
    x b
    o
    o
    l
    /
    / C
    o
    m
    p
    u
    t
    e
    d
    .
    g
    l
    o
    b
    a
    l
    C
    o
    l
    o
    r
    T
    a
    b
    l
    e c
    o
    l
    o
    r
    .
    P
    a
    l
    e
    t
    t
    e
    /
    / U
    s
    e
    d w
    h
    e
    n d
    e
    c
    o
    d
    i
    n
    g
    .
    d
    e
    l
    a
    y [
    ]
    i
    n
    t
    d
    i
    s
    p
    o
    s
    a
    l [
    ]
    b
    y
    t
    e
    i
    m
    a
    g
    e [
    ]
    *
    i
    m
    a
    g
    e
    .
    P
    a
    l
    e
    t
    t
    e
    d
    t
    m
    p [
    1
    0
    2
    4
    ]
    b
    y
    t
    e /
    / m
    u
    s
    t b
    e a
    t l
    e
    a
    s
    t 7
    6
    8 s
    o w
    e c
    a
    n r
    e
    a
    d c
    o
    l
    o
    r t
    a
    b
    l
    e
    }

    View Slide

  10. GIF
    アニメー
    ションのバイトコー
    ド例
    0
    0
    0
    0
    0
    0
    0
    0
    : 4
    7
    4
    9 4
    6
    3
    8 3
    9
    6
    1 c
    8
    0
    0 c
    8
    0
    0 0
    0
    0
    0 0
    0
    2
    1 f
    f
    0
    b G
    I
    F
    8
    9
    a
    .
    .
    .
    .
    .
    .
    .
    !
    .
    .
    0
    0
    0
    0
    0
    0
    1
    0
    : 4
    e
    4
    5 5
    4
    5
    3 4
    3
    4
    1 5
    0
    4
    5 3
    2
    2
    e 3
    0
    0
    3 0
    1
    0
    3 0
    0
    0
    0 N
    E
    T
    S
    C
    A
    P
    E
    2
    .
    0
    .
    .
    .
    .
    .
    0
    0
    0
    0
    0
    0
    2
    0
    : 2
    1
    f
    9 0
    4
    0
    0 0
    a
    0
    0 0
    0
    0
    0 2
    c
    0
    0 0
    0
    0
    0 0
    0
    c
    8 0
    0
    c
    8 !
    .
    .
    .
    .
    .
    .
    .
    ,
    .
    .
    .
    .
    .
    .
    .
    :
    :
    0
    0
    0
    0
    6
    7
    5
    0
    : 9
    b
    0
    2 0
    4
    7
    5 d
    e
    c
    7 9
    3
    2
    f 7
    f
    3
    2 2
    0
    0
    0 3
    b .
    .
    .
    u
    .
    .
    .
    /
    .
    2 .
    ;

    View Slide

  11. GIF
    アニメー
    ションの構成例
    意味 ブロック
    ヘッダー Header, Logical Screen Descriptor
    GIF
    アニ&
    繰り返し回数 Application Extention
    ‑‑‑ ‑‑‑
    遅延、
    透過など* Graphic Control Extension
    画像* Image Descriptor, Local Color Table, Table Based Image Data
    ‑‑‑ ‑‑‑
    ファイル終端 Trailer

    遅延、
    透過など*,
    画像*
    は繰り返し。

    再生秒数は、Graphic Control Extension
    の情報を使います。

    View Slide

  12. f
    u
    n
    c (
    d *
    d
    e
    c
    o
    d
    e
    r
    ) d
    e
    c
    o
    d
    e
    (
    r i
    o
    .
    R
    e
    a
    d
    e
    r
    , c
    o
    n
    f
    i
    g
    O
    n
    l
    y
    , k
    e
    e
    p
    A
    l
    l
    F
    r
    a
    m
    e
    s b
    o
    o
    l
    ) e
    r
    r
    o
    r {
    i
    f r
    r
    , o
    k :
    = r
    .
    (
    r
    e
    a
    d
    e
    r
    )
    ; o
    k { d
    .
    r = r
    r } e
    l
    s
    e { d
    .
    r = b
    u
    f
    i
    o
    .
    N
    e
    w
    R
    e
    a
    d
    e
    r
    (
    r
    ) }
    d
    .
    l
    o
    o
    p
    C
    o
    u
    n
    t = -
    1 /
    / ★
    ルー
    プ回数の初期化
    e
    r
    r :
    = d
    .
    r
    e
    a
    d
    H
    e
    a
    d
    e
    r
    A
    n
    d
    S
    c
    r
    e
    e
    n
    D
    e
    s
    c
    r
    i
    p
    t
    o
    r
    (
    ) /
    /
    その1
    ヘッダー
    f
    o
    r {
    c
    , e
    r
    r :
    = r
    e
    a
    d
    B
    y
    t
    e
    (
    d
    .
    r
    )
    s
    w
    i
    t
    c
    h c {
    c
    a
    s
    e s
    E
    x
    t
    e
    n
    s
    i
    o
    n
    :
    i
    f e
    r
    r = d
    .
    r
    e
    a
    d
    E
    x
    t
    e
    n
    s
    i
    o
    n
    (
    ) /
    /
    その2 G
    I
    F
    アニ&
    繰り返し回数
    c
    a
    s
    e s
    I
    m
    a
    g
    e
    D
    e
    s
    c
    r
    i
    p
    t
    o
    r
    :
    i
    f e
    r
    r = d
    .
    r
    e
    a
    d
    I
    m
    a
    g
    e
    D
    e
    s
    c
    r
    i
    p
    t
    o
    r
    (
    k
    e
    e
    p
    A
    l
    l
    F
    r
    a
    m
    e
    s
    )
    c
    a
    s
    e s
    T
    r
    a
    i
    l
    e
    r
    :
    i
    f l
    e
    n
    (
    d
    .
    i
    m
    a
    g
    e
    ) =
    = 0 { r
    e
    t
    u
    r
    n f
    m
    t
    .
    E
    r
    r
    o
    r
    f
    (
    "
    g
    i
    f
    : m
    i
    s
    s
    i
    n
    g i
    m
    a
    g
    e d
    r
    e
    t
    u
    r
    n n
    i
    l
    d
    e
    f
    a
    u
    l
    t
    :
    r
    e
    t
    u
    r
    n f
    m
    t
    .
    E
    r
    r
    o
    r
    f
    (
    "
    g
    i
    f
    : u
    n
    k
    n
    o
    w
    n b
    l
    o
    c
    k t
    y
    p
    e
    : 0
    x
    %
    .
    2
    x
    "
    , c
    )
    }
    }
    }

    View Slide

  13. こぼれ話
    Go 1.10
    まではLoopCount
    の初期化が正しくされていなかったため、
    未指定で作成しようとすると、
    無限ルー
    プ(loopCount = 0)
    となっていました。
    Go 1.11
    で修正されています。
    Non‑looping animated GIFs are now supported. They are denoted by having a LoopCount of
    ‑1.
    https://golang.org/doc/go1.11#image/gif
    https://go‑review.googlesource.com/c/go/+/93076/4/src/image/gif/reader.go#b563

    View Slide

  14. ヘッダー
    項目 詳細 内容 Byte/Bit
    Header Signature GIF 3 Bytes
    Version 87a、89a 3 Bytes
    Logical Screen Descriptor Logical Screen Width ●px 2 Bytes
    Logical Screen Height ●px 2 Bytes
    Global Color Table Flag ‑ 1 Bit
    Color Resolution ‑ 3 Bits
    Sort Flag ‑ 1 Bit
    Size of Global Color Table ‑ 3 Bits
    Background Color Index ‑ 1 Byte
    Pixel Aspect Ratio ‑ 1 Byte
    0
    0
    0
    0
    0
    0
    0
    0
    : [
    4
    7
    4
    9 4
    6
    ]
    [
    3
    8 3
    9
    6
    1
    ] [
    c
    8
    0
    0
    ] [
    c
    8
    0
    0
    ] [
    0
    0
    ]
    [
    0
    0
    ] [
    0
    0
    ]
    2
    1 f
    f
    0
    b G
    I
    F
    8
    9
    a
    .
    .
    .
    .
    .
    .
    .
    !
    .
    .

    View Slide

  15. f
    u
    n
    c (
    d *
    d
    e
    c
    o
    d
    e
    r
    ) r
    e
    a
    d
    H
    e
    a
    d
    e
    r
    A
    n
    d
    S
    c
    r
    e
    e
    n
    D
    e
    s
    c
    r
    i
    p
    t
    o
    r
    (
    ) e
    r
    r
    o
    r {
    e
    r
    r :
    = r
    e
    a
    d
    F
    u
    l
    l
    (
    d
    .
    r
    , d
    .
    t
    m
    p
    [
    :
    1
    3
    ]
    )
    i
    f e
    r
    r !
    = n
    i
    l {
    r
    e
    t
    u
    r
    n f
    m
    t
    .
    E
    r
    r
    o
    r
    f
    (
    "
    g
    i
    f
    : r
    e
    a
    d
    i
    n
    g h
    e
    a
    d
    e
    r
    : %
    v
    "
    , e
    r
    r
    )
    }
    d
    .
    v
    e
    r
    s = s
    t
    r
    i
    n
    g
    (
    d
    .
    t
    m
    p
    [
    :
    6
    ]
    ) /
    / ★
    バー
    ジョン
    i
    f d
    .
    v
    e
    r
    s !
    = "
    G
    I
    F
    8
    7
    a
    " &
    & d
    .
    v
    e
    r
    s !
    = "
    G
    I
    F
    8
    9
    a
    " {
    r
    e
    t
    u
    r
    n f
    m
    t
    .
    E
    r
    r
    o
    r
    f
    (
    "
    g
    i
    f
    : c
    a
    n
    '
    t r
    e
    c
    o
    g
    n
    i
    z
    e f
    o
    r
    m
    a
    t %
    q
    "
    , d
    .
    v
    e
    r
    s
    )
    }
    d
    .
    w
    i
    d
    t
    h = i
    n
    t
    (
    d
    .
    t
    m
    p
    [
    6
    ]
    ) + i
    n
    t
    (
    d
    .
    t
    m
    p
    [
    7
    ]
    )
    <
    <
    8 /
    / ★

    d
    .
    h
    e
    i
    g
    h
    t = i
    n
    t
    (
    d
    .
    t
    m
    p
    [
    8
    ]
    ) + i
    n
    t
    (
    d
    .
    t
    m
    p
    [
    9
    ]
    )
    <
    <
    8 /
    / ★
    高さ
    i
    f f
    i
    e
    l
    d
    s :
    = d
    .
    t
    m
    p
    [
    1
    0
    ]
    ; f
    i
    e
    l
    d
    s
    &
    f
    C
    o
    l
    o
    r
    T
    a
    b
    l
    e !
    = 0 {
    d
    .
    b
    a
    c
    k
    g
    r
    o
    u
    n
    d
    I
    n
    d
    e
    x = d
    .
    t
    m
    p
    [
    1
    1
    ]
    /
    / r
    e
    a
    d
    C
    o
    l
    o
    r
    T
    a
    b
    l
    e o
    v
    e
    r
    w
    r
    i
    t
    e
    s t
    h
    e c
    o
    n
    t
    e
    n
    t
    s o
    f d
    .
    t
    m
    p
    , b
    u
    t t
    h
    a
    t
    '
    s O
    K
    .
    i
    f d
    .
    g
    l
    o
    b
    a
    l
    C
    o
    l
    o
    r
    T
    a
    b
    l
    e
    , e
    r
    r = d
    .
    r
    e
    a
    d
    C
    o
    l
    o
    r
    T
    a
    b
    l
    e
    (
    f
    i
    e
    l
    d
    s
    )
    ; e
    r
    r !
    = n
    i
    l
    r
    e
    t
    u
    r
    n e
    r
    r
    }
    }
    /
    / d
    .
    t
    m
    p
    [
    1
    2
    ] i
    s t
    h
    e P
    i
    x
    e
    l A
    s
    p
    e
    c
    t R
    a
    t
    i
    o
    , w
    h
    i
    c
    h i
    s i
    g
    n
    o
    r
    e
    d
    .
    r
    e
    t
    u
    r
    n n
    i
    l
    }

    View Slide

  16. 項目 詳細 内容 Byte/Bit
    Application
    Extension
    Extension Introducer 0x21 1 Byte
    Extension Label 0xFF 1 Byte
    Block Size ‑ 1 Byte
    Application Identifier NETSCAPE 8 Bytes
    Application Authentication
    Code
    2.0 3 Bytes
    Block Size* 3 1 Byte
    Data Value*
    0x01 +
    ルー
    プ回数(2
    Bytes)
    3 Bytes
    Block Terminator ‑ 1 Byte
    0
    0
    0
    0
    0
    0
    0
    0
    : 4
    7
    4
    9 4
    6
    3
    8 3
    9
    6
    1 c
    8
    0
    0 c
    8
    0
    0 0
    0
    0
    0 0
    0
    [
    2
    1
    ] [
    f
    f
    ]
    [
    0
    b
    ] G
    I
    F
    8
    9
    a
    .
    .
    .
    .
    .
    .
    .
    !
    .
    .
    0
    0
    0
    0
    0
    0
    1
    0
    : [
    4
    e
    4
    5 5
    4
    5
    3 4
    3
    4
    1 5
    0
    4
    5
    ] [
    3
    2
    2
    e 3
    0
    ]
    [
    0
    3
    ] [
    0
    1
    0
    3
    ] 0
    0
    0
    0 N
    E
    T
    S
    C
    A
    P
    E
    2
    .
    0
    .
    .
    .
    .
    .

    View Slide

  17. f
    u
    n
    c (
    d *
    d
    e
    c
    o
    d
    e
    r
    ) r
    e
    a
    d
    E
    x
    t
    e
    n
    s
    i
    o
    n
    (
    ) e
    r
    r
    o
    r {
    e
    x
    t
    e
    n
    s
    i
    o
    n
    , e
    r
    r :
    = r
    e
    a
    d
    B
    y
    t
    e
    (
    d
    .
    r
    )
    i
    f e
    r
    r !
    = n
    i
    l { r
    e
    t
    u
    r
    n f
    m
    t
    .
    E
    r
    r
    o
    r
    f
    (
    "
    g
    i
    f
    : r
    e
    a
    d
    i
    n
    g e
    x
    t
    e
    n
    s
    i
    o
    n
    : %
    v
    "
    , e
    r
    r
    ) }
    s
    i
    z
    e :
    = 0
    s
    w
    i
    t
    c
    h e
    x
    t
    e
    n
    s
    i
    o
    n {
    c
    a
    s
    e e
    T
    e
    x
    t
    :
    s
    i
    z
    e = 1
    3
    c
    a
    s
    e e
    G
    r
    a
    p
    h
    i
    c
    C
    o
    n
    t
    r
    o
    l
    :
    r
    e
    t
    u
    r
    n d
    .
    r
    e
    a
    d
    G
    r
    a
    p
    h
    i
    c
    C
    o
    n
    t
    r
    o
    l
    (
    )
    c
    a
    s
    e e
    C
    o
    m
    m
    e
    n
    t
    :
    /
    / n
    o
    t
    h
    i
    n
    g t
    o d
    o b
    u
    t r
    e
    a
    d t
    h
    e d
    a
    t
    a
    .
    c
    a
    s
    e e
    A
    p
    p
    l
    i
    c
    a
    t
    i
    o
    n
    :
    b
    , e
    r
    r :
    = r
    e
    a
    d
    B
    y
    t
    e
    (
    d
    .
    r
    )
    i
    f e
    r
    r !
    = n
    i
    l { r
    e
    t
    u
    r
    n f
    m
    t
    .
    E
    r
    r
    o
    r
    f
    (
    "
    g
    i
    f
    : r
    e
    a
    d
    i
    n
    g e
    x
    t
    e
    n
    s
    i
    o
    n
    : %
    v
    "
    , e
    r
    r
    ) }
    /
    / T
    h
    e s
    p
    e
    c r
    e
    q
    u
    i
    r
    e
    s s
    i
    z
    e b
    e 1
    1
    , b
    u
    t A
    d
    o
    b
    e s
    o
    m
    e
    t
    i
    m
    e
    s u
    s
    e
    s 1
    0
    .
    s
    i
    z
    e = i
    n
    t
    (
    b
    )
    d
    e
    f
    a
    u
    l
    t
    :
    r
    e
    t
    u
    r
    n f
    m
    t
    .
    E
    r
    r
    o
    r
    f
    (
    "
    g
    i
    f
    : u
    n
    k
    n
    o
    w
    n e
    x
    t
    e
    n
    s
    i
    o
    n 0
    x
    %
    .
    2
    x
    "
    , e
    x
    t
    e
    n
    s
    i
    o
    n
    )
    }
    i
    f s
    i
    z
    e > 0 {
    i
    f e
    r
    r :
    = r
    e
    a
    d
    F
    u
    l
    l
    (
    d
    .
    r
    , d
    .
    t
    m
    p
    [
    :
    s
    i
    z
    e
    ]
    )
    ; e
    r
    r !
    = n
    i
    l {
    r
    e
    t
    u
    r
    n f
    m
    t
    .
    E
    r
    r
    o
    r
    f
    (
    "
    g
    i
    f
    : r
    e
    a
    d
    i
    n
    g e
    x
    t
    e
    n
    s
    i
    o
    n
    : %
    v
    "
    , e
    r
    r
    )
    }
    }

    View Slide

  18. /
    / A
    p
    p
    l
    i
    c
    a
    t
    i
    o
    n E
    x
    t
    e
    n
    s
    i
    o
    n w
    i
    t
    h "
    N
    E
    T
    S
    C
    A
    P
    E
    2
    .
    0
    " a
    s s
    t
    r
    i
    n
    g a
    n
    d 1 i
    n d
    a
    t
    a m
    e
    a
    n
    s
    /
    / t
    h
    i
    s e
    x
    t
    e
    n
    s
    i
    o
    n d
    e
    f
    i
    n
    e
    s a l
    o
    o
    p c
    o
    u
    n
    t
    .
    i
    f e
    x
    t
    e
    n
    s
    i
    o
    n =
    = e
    A
    p
    p
    l
    i
    c
    a
    t
    i
    o
    n &
    & s
    t
    r
    i
    n
    g
    (
    d
    .
    t
    m
    p
    [
    :
    s
    i
    z
    e
    ]
    ) =
    = "
    N
    E
    T
    S
    C
    A
    P
    E
    2
    .
    0
    " {
    n
    , e
    r
    r :
    = d
    .
    r
    e
    a
    d
    B
    l
    o
    c
    k
    (
    )
    i
    f e
    r
    r !
    = n
    i
    l {
    r
    e
    t
    u
    r
    n f
    m
    t
    .
    E
    r
    r
    o
    r
    f
    (
    "
    g
    i
    f
    : r
    e
    a
    d
    i
    n
    g e
    x
    t
    e
    n
    s
    i
    o
    n
    : %
    v
    "
    , e
    r
    r
    )
    }
    i
    f n =
    = 0 {
    r
    e
    t
    u
    r
    n n
    i
    l
    }
    i
    f n =
    = 3 &
    & d
    .
    t
    m
    p
    [
    0
    ] =
    = 1 {
    d
    .
    l
    o
    o
    p
    C
    o
    u
    n
    t = i
    n
    t
    (
    d
    .
    t
    m
    p
    [
    1
    ]
    ) | i
    n
    t
    (
    d
    .
    t
    m
    p
    [
    2
    ]
    )
    <
    <
    8 /
    / ★
    ルー
    プ回数
    }
    }
    f
    o
    r {
    n
    , e
    r
    r :
    = d
    .
    r
    e
    a
    d
    B
    l
    o
    c
    k
    (
    )
    i
    f e
    r
    r !
    = n
    i
    l {
    r
    e
    t
    u
    r
    n f
    m
    t
    .
    E
    r
    r
    o
    r
    f
    (
    "
    g
    i
    f
    : r
    e
    a
    d
    i
    n
    g e
    x
    t
    e
    n
    s
    i
    o
    n
    : %
    v
    "
    , e
    r
    r
    )
    }
    i
    f n =
    = 0 {
    r
    e
    t
    u
    r
    n n
    i
    l
    }
    }
    }

    View Slide

  19. 今日はここまで。
    続きは image/gif
    で!

    View Slide

  20. まとめ
    GIF
    アニメー
    ションもGo
    ならわかる。
    バイトコー
    ドをGo
    の実装と一緒に読んでいける。
    読み取りで使うときは、DecodeAll()
    で GIF
    を取得すればOK。
    GIF87a
    と GIF89a
    などのバー
    ジョンは GIF
    には入っていないので、
    バイトコー
    ドで。

    View Slide

  21. ご静聴ありがとうございました。
    参考: https://www.w3.org/Graphics/GIF/spec‑gif89a.txt

    View Slide