This is based on the Picture generator from the Slices exercise.
func Pic(dx, dy int) [][]uint8 {
p := make([][]uint8,dy)
for i := range p {
p[i] = make([]uint8,dx)
}
for y := range p {
for x := range p[y] {
p[y][x]=(uint8(x)*uint8(y))
}
}
return p
}
this time it will return an implementation of
image.Image
instead of a slice of data.
So we need to implement the interfaces defined:
-
ColorModel
-
Bounds
-
At
Let’s start off with one of these to see if we’re on the right lines…
package main
import (
"image/color"
"golang.org/x/tour/pic"
)
type Image struct{}
func (i Image) ColorModel() color.Model {
return color.RGBAModel
}
func main() {
m := Image{}
pic.ShowImage(m)
}
This compiles (🙌) and fails (as we’d expect) with something that may or may not be validating that we’ve not screwed things up yet:
./prog.go:17:15: cannot use m (type Image) as type image.Image in argument to pic.ShowImage:
Image does not implement image.Image (missing At method)
Let’s add in the other fixed value, Bounds
:
package main
import (
"image"
"image/color"
"golang.org/x/tour/pic"
)
type Image struct{}
func (i Image) ColorModel() color.Model {
return color.RGBAModel
}
func (i Image) Bounds() image.Rectangle {
return image.Rect(0, 0, 256, 256)
}
func main() {
m := Image{}
pic.ShowImage(m)
}
Now the final part - At
. Building it up bit by bit, we know what the function definition should look like, based on the above pattern and the interface definition:
func (i Image) At(x,y int) color.Color {
The value returned by this function is the colour (yes, I said colo_u_r! 🇬🇧) at the given coordinates. In the picture we created earlier this was using the expression x*y to describe the strength of the bluescale to plot. The Color
type for the RGBAModel
we’re using is + RGBA
, which returns RGB plus alpha, so let’s try this here:
package main
import (
"image"
"image/color"
"golang.org/x/tour/pic"
)
type Image struct{}
func (i Image) ColorModel() color.Model {
return color.RGBAModel
}
func (i Image) Bounds() image.Rectangle {
return image.Rect(0, 0, 256, 256)
}
func (i Image) At(x,y int) color.Color {
var r,g,b,a uint8 = 25 ,0,0,0
b=uint8(x)*uint8(y)
return color.RGBA{r,g,b,a}
}
func main() {
m := Image{}
pic.ShowImage(m)
}
This not only compiles (🙌) but successfully runs (😅)…but doesn’t display anything 😢 … or does it? 🤔
In the Go execution window the Program exited
is lower down the page:
and if you right-click over the blank space you can see there’s an image there, and inspecting this with developer tools shows it’s a 256x256 transparent image. That alpha thingy… setting it to zero means the image is transparent!
Let’s try again and set the alpha level this time:
package main
import (
"image"
"image/color"
"golang.org/x/tour/pic"
)
type Image struct{}
func (i Image) ColorModel() color.Model {
return color.RGBAModel
}
func (i Image) Bounds() image.Rectangle {
return image.Rect(0, 0, 256, 256)
}
func (i Image) At(x,y int) color.Color {
var r,g,b,a uint8 = 0 ,0,0,0
b=uint8(x)*uint8(y)
a=b
return color.RGBA{r,g,b,a}
}
func main() {
m := Image{}
pic.ShowImage(m)
}
🎉 TADA! 🎉
You can muck about with the other colour values too:
func (i Image) At(x,y int) color.Color {
var r,g,b,a uint8 = 0 ,0,0,0
b=uint8(float64(y)*0.2) * uint8(x)
r=uint8(float64(y)*0.5)
a=b
return color.RGBA{r,g,b,a}
}
func (i Image) At(x,y int) color.Color {
var r,g,b,a uint8 = 0 ,0,0,0
b=uint8(float64(y)*4.25) * uint8(x*2)
r=uint8(float64(y)*16)
a=b
return color.RGBA{r,g,b,a}
}