はじめに
Go 言語基礎文法最速マスターにて出題されている演習課題「Exercise: Images(イメージ)」の答えに辿り着くまでの手順と解答例の解説を記事にしてみました。
課題
課題の目的は Exercise: Slices 解答例 で作成した画像ジェネレーターを参考にして、データのスライスの代わりに image.Image
インタフェースの実装を返すようにすることです。
package main
import "golang.org/x/tour/pic"
type Image struct{}
func main() {
m := Image{}
pic.ShowImage(m)
}
解答例
package main
import (
"golang.org/x/tour/pic"
"image"
"image/color"
)
type Image struct {}
func (m *Image) ColorModel() color.Model {
return color.RGBAModel
}
func (m *Image) Bounds() image.Rectangle {
return image.Rect(0, 0, 128, 128)
}
func (m *Image) At(x, y int) color.Color {
v := uint8(x ^ y)
return color.RGBA{v, v, 255, 255}
}
func main() {
m := Image{}
pic.ShowImage(&m)
}
実行結果は下記のようになります。
解説
初めに、課題のソースコードを読み解きます。
ほぼ Exercise: Slices と同じなので差分だけ説明します。
5 行目、type
で struct{}
型を Image
という名前で 型宣言 していますね。
type Image struct{}
課題の文章より、この Image
型に インタフェースを満たすのに必要なメソッド を実装して pic.ShowImage
関数を呼び出してねとあります。
下記の Image
インターフェースのソースコードを見てわかる通り、必要なメソッドとは ColorModel()
, Bounds()
, At(x, y int)
の 3 つのことです。
type Image interface {
// ColorModel returns the Image's color model.
ColorModel() color.Model
// Bounds returns the domain for which At can return non-zero color.
// The bounds do not necessarily contain the point (0, 0).
Bounds() Rectangle
// At returns the color of the pixel at (x, y).
// At(Bounds().Min.X, Bounds().Min.Y) returns the upper-left pixel of the grid.
// At(Bounds().Max.X-1, Bounds().Max.Y-1) returns the lower-right one.
At(x, y int) color.Color
}
7 – 10 行目、main
関数では Image{}
型を変数 m
に格納、pic.ShowImage
関数に渡して画像を出力しています。
func main() {
m := Image{}
pic.ShowImage(m)
}
さて、実装を進めます。
やることは Image
インターフェースの ColorModel()
, Bounds()
, At(x, y int)
を実装することですね、ひとつずつやっていきます。
まずは ColorModel()
を実装します。
ColorModel() color.Model
課題の文章より「ColorModel
は、color.RGBAModel
を返すようにします。」とあるので、下記のように書けば良いだけですね。
func (m *Image) ColorModel() color.Model {
return color.RGBAModel
}
image/color
パッケージのインポートも忘れずに。
import (
"golang.org/x/tour/pic"
"image/color"
)
次は Bounds()
を実装します。
Bounds() Rectangle
課題の文章より「Bounds
は、image.Rect(0, 0, w, h)
のようにして image.Rectangle
を返すようにします。」とあります。
変数 w
, h
は出力する画像の width(横幅)と height(高さ)のことです、今回は適当に 128 で設定しました。
func (m *Image) Bounds() image.Rectangle {
return image.Rect(0, 0, 128, 128)
}
image
パッケージのインポートも忘れずに。
import (
"golang.org/x/tour/pic"
"image"
"image/color"
)
次は At(x, y int)
を実装します。
At(x, y int) color.Color
課題の文章より「At
は、ひとつの色を返します。 生成する画像の色の値 v
を color.RGBA{v, v, 255, 255}
を利用して返すようにします。」とあります。
変数 v
には前に Exercise: Slices でやったように uint8(intValue) を使うと良いです。
func (m *Image) At(x, y int) color.Color {
v := uint8((x + y) / 2)
return color.RGBA{v, v, 255, 255}
}
3 つのメソッドの実装が完了しました、纏めると下記のようになります。
package main
import (
"golang.org/x/tour/pic"
"image"
"image/color"
)
type Image struct {}
func (m *Image) ColorModel() color.Model {
return color.RGBAModel
}
func (m *Image) Bounds() image.Rectangle {
return image.Rect(0, 0, 128, 128)
}
func (m *Image) At(x, y int) color.Color {
v := uint8((x + y) / 2)
return color.RGBA{v, v, 255, 255}
}
func main() {
m := Image{}
pic.ShowImage(&m)
}
実行結果は下記のようになります。
大丈夫だ、問題ない。
以上です。
おわりに
インターフェースの実装の御浚いといった内容の課題でした。