画像を使っていると使いたい関数の関係でimage
をio.Reader
に変換したいことがあったので、その辺のコーディングメモ。
最終的にはPipe
を使います。
画像読み込みを使う
ファイル読み込みしたもの(*os.File
)はio.Reader
インターフェース実装しているため、テンポラリ画像を保存して読み込むことでio.Reader
として使えます。
実際には関数を分けているので違和感がなかったのですが、1つにまとめるとこんな感じでした。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
file_out, err := os.Create("./tmp.png") defer file_out.Close() if err != nil { fmt.Println("error:file\n",err) return } if err := png.Encode(file_out, rgba); err != nil { fmt.Println("error:png\n",err) return } file, err := os.Open("./tmp.png") defer file.Close() if err != nil { fmt.Println("error:file\n",err) return nil } //... //Use file as io.Reader |
違和感凄いですが特に問題なく使えます。
file
じゃなくてfile_out
をそのままio.Reader
として使えば読み込みはいらない気もしますが、エラーは出ないけど0byteファイルとして認識されてしまいました。
画像のデコードが2回目できないのと同じ理由だろうか。
ちゃんとやる
bytes.Buffer
はio.Writer
も持っているのでimage.Encode
に渡せる。
これで無駄なファイルを作らずに画像のio.Reader
を使える。
1 2 3 4 5 6 7 8 |
buf := new(bytes.Buffer) if err := png.Encode(buf, img); err != nil { fmt.Println("error:png\n",err) return } //... //Use buf as io.Reader |
bytes.Buffer
は便利ですがio.Pipe
を使った方が省メモリでいいよと見かける。
1 2 3 4 5 6 7 8 9 10 11 |
pr, pw := io.Pipe() go func() { if err := png.Encode(pw, rgba); err != nil { fmt.Println("error:png\n",err) return } pw.Close() }() //... //Use pr as io.Reader |
どちらでも問題なく使えた。
画像を使う以上はメモリを気にしたほうが良さそうなのでPipe
を使うことにする。