1
\$\begingroup\$

The "Images" exercise in A Tour of Go asks for an implementation of image.Image. I wrote two solutions, one easy and one harder (just for practice in dealing with interfaces).

SOLUTION 1: (HARD WAY)

package main

import (
    "golang.org/x/tour/pic"
    "image"
    "image/color"
)

type Image struct{
    // one array for x value, one array for y values, array of integer for pixel RGBA values
    image_ [][][]uint8
    x0, y0, x1, y1 int
}

func (i *Image) NewImage(x, y int) *Image {
    image := make([][][]uint8, y)
    for i := 0; i < x; i++ {
        image[i] = make([][]uint8, x)
        for j := 0; j < y; j++ {
            image[i][j] = make([]uint8, 4)
        }
    }
    return &Image{image, 0, 0, x, y}
}

func (p *Image) ColorModel() color.Model { return color.RGBAModel }

func (p *Image) At(x, y int) color.Color {
    var c color.Color
    rgba := color.RGBA{
        p.image_[x][y][0],
        p.image_[x][y][1],
        p.image_[x][y][2],
        p.image_[x][y][3],
    }
    c = rgba
    return c
}

func (p *Image) Bounds() image.Rectangle {
    rectangle := image.Rect(p.x0, p.y0, p.x1, p.y1)
    return rectangle
}

func (p *Image) crazyColors() *Image {
    for i := 0; i < len(p.image_) - 1; i++ {
        for j := 0; j < len(p.image_[i]) - 1; j++ {
            p.image_[i][j][0] = uint8(i + j / 2)
            p.image_[i][j][1] = uint8(i + j * 2)
            p.image_[i][j][2] = uint8(i + j * 2)
            p.image_[i][j][3] = uint8(255)
        }
    }
    return p
}

func main() {
    var i *Image
    i = i.NewImage(255, 255)
    i.crazyColors()
    pic.ShowImage(i)
}

SOLUTION 2: (EASY WAY)

package main

import (
    "golang.org/x/tour/pic"
    "image"
)

type Image struct{
    image.RGBA
}

func (i Image) crazyColors() Image {
    for p := 0; p < len(i.Pix); p += 4 {
        i.Pix[p] = uint8(p + p*2)
        i.Pix[p+1] = uint8(p + p*2)
        i.Pix[p+2] = uint8(p + p*2)
        i.Pix[p+3] = uint8(p + p*2)
    }
    return i
}

func main() {
    rect := image.Rect(0,0,255,255)
    m := Image{*image.NewRGBA(rect)}
    m.crazyColors()
    pic.ShowImage(&m)
}
\$\endgroup\$
  • \$\begingroup\$ I'm not sure what your question is? would it be performance? or better solution? \$\endgroup\$ – Siobhan Oct 12 '16 at 16:35
  • \$\begingroup\$ The second program looks broken. Where does Pix come from? \$\endgroup\$ – janos Oct 12 '16 at 16:45
  • \$\begingroup\$ Also, it would be good to include a description of what you're actually trying to solve here. \$\endgroup\$ – janos Oct 12 '16 at 16:47
1
\$\begingroup\$

Storing a rectangle

The Image stores the parameters to create a rectangle. Those values are not used for anything else in the lifetime of the object, except to create the bounding rectangle when needed. You could instead just store the rectangle itself, so could simply return it when needed.

Pointless local variables

Many of the local variables are pointless, you could skip declaring and assigning to them and simply return values directly, for example:

func (p *Image) At(x, y int) color.Color {
    return color.RGBA{
        p.image_[x][y][0],
        p.image_[x][y][1],
        p.image_[x][y][2],
        p.image_[x][y][3],
    }
}

Naming

The _ suffix in Image.image_ is unusual. I suggest to simply drop the suffix.

The name i is most often used in simple counting loops, I suggest to avoid using it for other purposes. A good short name for an image instance could be img, for example.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.