Help us understand the problem. What is going on with this article?

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

はじめに

先日、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作成の際は参考にさせてもらいました。

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away