loading...

Learning Golang (some rough notes) - S01E08 - Images

rmoff profile image Robin Moffatt Originally published at rmoff.net on ・3 min read

Learning Go (11 Part Series)

1) Learning Golang (some rough notes) - S01E00 2) Learning Golang (some rough notes) - S01E01 - Pointers 3 ... 9 3) Learning Golang (some rough notes) - S01E02 - Slices 4) Learning Golang (some rough notes) - S01E03 - Maps 5) Learning Golang (some rough notes) - S01E04 - Function Closures 6) Learning Golang (some rough notes) - S01E05 - Interfaces 7) Learning Golang (some rough notes) - S01E06 - Errors 8) Learning Golang (some rough notes) - S01E07 - Readers 9) Learning Golang (some rough notes) - S01E08 - Images 10) Learning Golang (some rough notes) - S01E09 - Concurrency (Channels, Goroutines) 11) Learning Golang (some rough notes) - S01E10 - Concurrency (Web Crawler)

👉 A Tour of Go : Exercise: Images

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
}

slice02

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:

image01

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! 🎉

image02

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}
}

image03

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}
}

image04

Learning Go (11 Part Series)

1) Learning Golang (some rough notes) - S01E00 2) Learning Golang (some rough notes) - S01E01 - Pointers 3 ... 9 3) Learning Golang (some rough notes) - S01E02 - Slices 4) Learning Golang (some rough notes) - S01E03 - Maps 5) Learning Golang (some rough notes) - S01E04 - Function Closures 6) Learning Golang (some rough notes) - S01E05 - Interfaces 7) Learning Golang (some rough notes) - S01E06 - Errors 8) Learning Golang (some rough notes) - S01E07 - Readers 9) Learning Golang (some rough notes) - S01E08 - Images 10) Learning Golang (some rough notes) - S01E09 - Concurrency (Channels, Goroutines) 11) Learning Golang (some rough notes) - S01E10 - Concurrency (Web Crawler)

Posted on by:

rmoff profile

Robin Moffatt

@rmoff

Robin Moffatt is a Developer Advocate at Confluent, and regular conference speaker. He also likes writing about himself in the third person, eating good breakfasts, and drinking good beer.

Discussion

markdown guide