Melchior

バンクーバーで働くエンジニアの備忘録

Image.Decodeでunknown formatになったときの対処法

いまいち条件がわかりませんが、一度Decodeされたデータは再度Decodeしようとするとunknown formatになるようです。 Goのバージョンは1.6.2を使用しています。 依存ファイルは以下のとおりです。

import (
    "bytes"
    "image"
    "image/gif"
    "image/jpeg"
    "image/png"
    "io"
    "os"
)

ダメな例

まずはダメな例です。

file, _ := os.Open("./image.jpg")
img, _ := jpeg.Decode(file)
conf, encode, err := image.DecodeConfig(file) // unknown format

DecodeでもDecodeConfigでも再現します。これは困ります。

対処法1

ファイルを開き直すことで解決します。

file, _ := os.Open("./image.jpg")
img, _ := jpeg.Decode(file)
file, _ = os.Open("./image.jpg")
conf, encode, err := image.DecodeConfig(file)

気持ち悪いです。

対処法2

別の方法を模索したところ、EncodeしてDecodeし直すと解決することがわかりました。

file, _ := os.Open("./image.jpg")
img, _ := jpeg.Decode(file)
buf := new(bytes.Buffer)
jpeg.Encode(buf, img, nil)
conf, encode, err := image.DecodeConfig(file)

気持ち悪さは半減しましたが、まだ気持ち悪いです。

対処法3

事前にいじれる場合はio.Copyでコピーすると良さそうです。

file, _ := os.Open("./image.jpg")
buf := new(bytes.Buffer)
io.Copy(buf, file)
img, encode, _ := image.Decode(file)
conf, encode, err := image.DecodeConfig(buf)

まとめ

最終的にio.Copyに落ち着きました。

func Decode(file io.Reader) {
    buf := new(bytes.Buffer)
    io.Copy(buf, file)
    img, encode, err := image.Decode(file)
    conf, encode, err := image.DecodeConfig(buf)
    ...
}

ソース