LoginSignup
16
12

More than 3 years have passed since last update.

Re:ゼロから始めないAPNGエンコーダ

Last updated at Posted at 2017-03-21

はじめに

先日、ChromiumでAPNG(Animated PNG)がサポートされたというニュースを聞いて、Golang製のAPNGエンコーダgoapngを作って見ました。
ただ、現状APNGが対応しているブラウザはFirefoxとSafariくらいであまり使い道がないんですよね・・・(ChromeはExtentionを入れる2017年の6月まで待てばと動きます。Chromeはバージョン59になりAPNGに対応しました。)。24bit+α値のアニメーションも作れるし、今後対応するブラウザが増えていってほしいですね。
また、ブラウザじゃないですがLINEスタンプはAPNGに対応しているらしいので、スタンプ作成自動化なんかに使ってみてもいいかもしれませんね。

goapngで生成した動くGopherはこんな感じ。
(画像は「本物の golang を... 本物の Gopher を、お見せしますよ。 - Qiita」からお借りしました。)

animated_gopher.png

コイツ・・・動くぞ(動かないかも)

インストール

go getで一発。そうGolangならね

$ go get github.com/cia-rana/goapng

使い方

使い方はいたってシンプル
goapngをimportして、goapng.APNGに画像データと遅延情報(delay)をつっこみエンコードするだけ!
インターフェースはアニメーションgifの作り方と同じにしたので、APNGとアニメーションgifと出力を切り替えるのも簡単です。

package main

import (
    "github.com/cia-rana/goapng"
    "image/png"
    "os"
    "fmt"
)

func main() {
    inPaths := []string{
        "res/gopher01.png",
        "res/gopher02.png",
        "res/gopher03.png",
    }
    outPath := "res/animated_gopher.png"

    // Assemble output image.
    outApng := &goapng.APNG{}
    for _, inPath := range inPaths {
        // Read image file.
        f, err := os.Open(inPath)
        if err != nil {
            fmt.Println(err)
            f.Close()
            return
        }
        inPng, err := png.Decode(f)
        if err != nil {
            fmt.Println(err)
            f.Close()
            return
        }
        f.Close()

        // Append a frame(type: *image.Image). First frame used as the default image.
        outApng.Image = append(outApng.Image, &inPng)

        // Append a delay time(type: uint32) per frame in 10 milliseconds.
        // If it is 0, the decoder renders the next frame as quickly as possible.
        outApng.Delay = append(outApng.Delay, 0)
    }

    // Encode images to APNG image.
    f, err := os.Create(outPath)
    if err != nil {
        fmt.Println(err)
        f.Close()

        return
    }
    if err = goapng.EncodeAll(f, outApng); err != nil {
        fmt.Println(err)
        f.Close()
        os.Remove(outPath)
        return
    }
    f.Close()
}

エンコーダの簡単な概要

APNG仕様はただのPNG仕様の拡張なので(補助チャンクが3つ増えただけ)、めんどうくさい圧縮処理はimage/pngに任せて、image/pngを使って吐いたバイナリに補助チャンクを挿入するといった処理をしています。APNGの詳しい概要はこちらをご覧ください。

対応画像

しっかりテストはしていませんが、画像内部でパレットを使っている場合を除き、image.Imageに変換できればどんな画像でもいけるはずです。また、APNGの仕様では、2フレーム目以降の画像の幅・高さは、1フレーム目の画像のそれ以内に収まっていればどんな大きさでも構わないことになっています。

ソース

MITで公開しています。煮るなり焼くなり好きにしてください。

その他APNG関連ツール

ココにCLIやらGUIやらいっぱい載ってます。特にapngasmはコードがGitHubで公開されているので、goapng作成の際は参考にさせてもらいました。

参考

16
12
1

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
16
12