画像作成
とある授業で画像変換機能実装の課題が出ました。
何から手をつければ良いかよくわからなかったが、とりあえず image パッケージなるものが golang.org を眺めていたところ見つかったので、
手始めに何か触ってみようと思った。
個人的には、いきなり 画像変換 Go とかでググるより 一次情報にアクセスした方がモテるという話を聞いたので、
小一時間に渡り公式ドキュメントというなの樹海(僕にとって)をさまようことになる…
だらだらとパッケージのドキュメントをみていると、 image/png というパッケージの中に、Encode なる関数が見つかった。
なんかこいつを使えば、簡単な画像とか生成できるんじゃね? と思った。
Encode関数はこんな感じだ。
type.Encode
func Encode(w io.Writer, m image.Image) error
第一引数に io.Writer がきているので、どこかしらに画像を書き込める匂いがプンプンしている。
これだ! と思った はいいものの、第二引数の image.Image というものがわからん。
リンクを飛んでみると、どうやら 画像情報を保持しているインターフェースのようだ。
type Image interface {
ColorModel() color.Model
Bounds() Rectangle
At(x, y int) color.Color
}
よくわからん。
だが golang.org のサイトはありがたいことに、多くの関数に対して 使用例exampleを用意してくれている。
func Encode の使用例は以下。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
// Create a colored image of the given width and height.
img := image.NewNRGBA(image.Rect(0, 0, width, height))
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
img.Set(x, y, color.NRGBA{
R: uint8((x + y) & 255),
G: uint8((x + y) << 1 & 255),
B: uint8((x + y) << 2 & 255),
A: 255,
})
}
}
f, err := os.Create("image.png")
if err != nil {
log.Fatal(err)
}
if err := png.Encode(f, img); err != nil {
f.Close()
log.Fatal(err)
}
|
この例をみると、 png.Encode(f, img) のところで io.Writer と img を渡している。
この img が上記であげた image.Image インターフェースに当たるわけだが、
こいつは
1
|
img := image.NewNRGBA(image.Rect(0, 0, width, height))
|
というように NewNRGBAという機能で生成されている。
(New… という名前が完全に生成っぽい)
この関数は 返り値に RGBA 型を当てている。
RGBA型ってなんだ?って思ってリンクを辿ってみたところ、下記のようなメンバ(表現として合っていたかな?)を保持しているようだ。
1
2
3
4
5
6
7
8
9
|
type RGBA struct {
// Pix holds the image's pixels, in R, G, B, A order. The pixel at
// (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4].
Pix []uint8
// Stride is the Pix stride (in bytes) between vertically adjacent pixels.
Stride int
// Rect is the image's bounds.
Rect Rectangle
}
|
よくわからんが、 png.Encode 関数の引数として渡せれる img は、Imageインターフェースを満たしている必要があり、
image.NewNRGBA関数で作成される RGBA型 はこのImageインターフェースを満たしている、ということのようだ。
png を作成
これ前の内容をずらずらとコードにまとめる。
以下のコードを実行すると、真っ黒なpngが生成される。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
package main
import (
"image"
"image/color"
"image/png"
"log"
"os"
)
func main() {
min := image.Point{X: 10, Y: 10}
max := image.Point{X: 110, Y: 110}
r := image.Rectangle{Min: min, Max: max}
// NRGBA を作成
n := image.NewNRGBA(r)
// 描画
for h := r.Min.Y; h < r.Max.Y; h++ {
for v := r.Min.X; v < r.Max.X; v++ {
n.Set(v, h, color.RGBA{
R: uint8(0),
G: uint8(0),
B: uint8(0),
A: uint8(255),
})
}
}
// io.Writer 作成
f, err := os.Create("img.png")
if err != nil {
log.Fatal(err)
}
defer f.Close()
// エンコード
if err := png.Encode(f, n); err != nil {
log.Fatal(err)
}
}
|