The Go image package
21 Sep 2011
Tags: image, libraries, technical

Nigel Tao

* Introduction

The [[https://golang.org/pkg/image/][image]] and [[https://golang.org/pkg/image/color/][image/color]]
packages define a number of types:
`color.Color` and `color.Model` describe colors,
`image.Point` and `image.Rectangle` describe basic 2-D geometry,
and `image.Image` brings the two concepts together to represent a rectangular grid of colors.
A [[https://golang.org/doc/articles/image_draw.html][separate article]]
covers image composition with the [[https://golang.org/pkg/image/draw/][image/draw]] package.

* Colors and Color Models

[[https://golang.org/pkg/image/color/#Color][Color]] is an interface that
defines the minimal method set of any type that can be considered a color:
one that can be converted to red, green, blue and alpha values.
The conversion may be lossy, such as converting from CMYK or YCbCr color spaces.

	type Color interface {
	    // RGBA returns the alpha-premultiplied red, green, blue and alpha values
	    // for the color. Each value ranges within [0, 0xFFFF], but is represented
	    // by a uint32 so that multiplying by a blend factor up to 0xFFFF will not
	    // overflow.
	    RGBA() (r, g, b, a uint32)
	}

There are three important subtleties about the return values.
First, the red, green and blue are alpha-premultiplied:
a fully saturated red that is also 25% transparent is represented by RGBA returning a 75% r.
Second, the channels have a 16-bit effective range:
100% red is represented by RGBA returning an r of 65535,
not 255, so that converting from CMYK or YCbCr is not as lossy.
Third, the type returned is `uint32`, even though the maximum value is 65535,
to guarantee that multiplying two values together won't overflow.
Such multiplications occur when blending two colors according to an alpha
mask from a third color,
in the style of [[https://en.wikipedia.org/wiki/Alpha_compositing][Porter and Duff's]] classic algebra:

	dstr, dstg, dstb, dsta := dst.RGBA()
	srcr, srcg, srcb, srca := src.RGBA()
	_, _, _, m := mask.RGBA()
	const M = 1<<16 - 1
	// The resultant red value is a blend of dstr and srcr, and ranges in [0, M].
	// The calculation for green, blue and alpha is similar.
	dstr = (dstr*(M-m) + srcr*m) / M

The last line of that code snippet would have been more complicated if we
worked with non-alpha-premultiplied colors,
which is why `Color` uses alpha-premultiplied values.

The image/color package also defines a number of concrete types that implement
the `Color` interface.
For example, [[https://golang.org/pkg/image/color/#RGBA][`RGBA`]] is a struct
that represents the classic "8 bits per channel" color.

	type RGBA struct {
	    R, G, B, A uint8
	}

Note that the `R` field of an `RGBA` is an 8-bit alpha-premultiplied color
in the range [0, 255].
`RGBA` satisfies the `Color` interface by multiplying that value by 0x101
to generate a 16-bit alpha-premultiplied color in the range [0, 65535].
Similarly, the [[https://golang.org/pkg/image/color/#NRGBA][`NRGBA`]] struct
type represents an 8-bit non-alpha-premultiplied color,
as used by the PNG image format.
When manipulating an `NRGBA`'s fields directly,
the values are non-alpha-premultiplied, but when calling the `RGBA` method,
the return values are alpha-premultiplied.

A [[https://golang.org/pkg/image/color/#Model][`Model`]] is simply something
that can convert `Color`s to other `Color`s, possibly lossily.
For example, the `GrayModel` can convert any `Color` to a desaturated [[https://golang.org/pkg/image/color/#Gray][`Gray`]].
A `Palette` can convert any `Color` to one from a limited palette.

	type Model interface {
	    Convert(c Color) Color
	}

	type Palette []Color

* Points and Rectangles

A [[https://golang.org/pkg/image/#Point][`Point`]] is an (x,
y) co-ordinate on the integer grid, with axes increasing right and down.
It is neither a pixel nor a grid square. A `Point` has no intrinsic width,
height or color, but the visualizations below use a small colored square.

	type Point struct {
	    X, Y int
	}

.image go-image-package_image-package-01.png

	    p := image.Point{2, 1}

A [[https://golang.org/pkg/image/#Rectangle][`Rectangle`]] is an axis-aligned
rectangle on the integer grid,
defined by its top-left and bottom-right `Point`.
A `Rectangle` also has no intrinsic color,
but the visualizations below outline rectangles with a thin colored line,
and call out their `Min` and `Max` `Point`s.

	type Rectangle struct {
	    Min, Max Point
	}

For convenience, `image.Rect(x0,`y0,`x1,`y1)` is equivalent to `image.Rectangle{image.Point{x0,`y0},`image.Point{x1,`y1}}`,
but is much easier to type.

A `Rectangle` is inclusive at the top-left and exclusive at the bottom-right.
For a `Point`p` and a `Rectangle`r`, `p.In(r)` if and only if `r.Min.X`<=`p.X`&&`p.X`<`r.Max.X`,
and similarly for `Y`.
This is analogous to how a slice `s[i0:i1]` is inclusive at the low end
and exclusive at the high end.
(Unlike arrays and slices, a `Rectangle` often has a non-zero origin.)

.image go-image-package_image-package-02.png

	    r := image.Rect(2, 1, 5, 5)
	    // Dx and Dy return a rectangle's width and height.
	    fmt.Println(r.Dx(), r.Dy(), image.Pt(0, 0).In(r)) // prints 3 4 false

Adding a `Point` to a `Rectangle` translates the `Rectangle`.
Points and Rectangles are not restricted to be in the bottom-right quadrant.

.image go-image-package_image-package-03.png

	    r := image.Rect(2, 1, 5, 5).Add(image.Pt(-4, -2))
	    fmt.Println(r.Dx(), r.Dy(), image.Pt(0, 0).In(r)) // prints 3 4 true

Intersecting two Rectangles yields another Rectangle, which may be empty.

.image go-image-package_image-package-04.png

	    r := image.Rect(0, 0, 4, 3).Intersect(image.Rect(2, 2, 5, 5))
	    // Size returns a rectangle's width and height, as a Point.
	    fmt.Printf("%#v\n", r.Size()) // prints image.Point{X:2, Y:1}

Points and Rectangles are passed and returned by value.
A function that takes a `Rectangle` argument will be as efficient as a function
that takes two `Point` arguments,
or four `int` arguments.

* Images

An [[https://golang.org/pkg/image/#Image][Image]] maps every grid square
in a `Rectangle` to a `Color` from a `Model`.
"The pixel at (x, y)" refers to the color of the grid square defined by the points (x,
y), (x+1, y), (x+1, y+1) and (x, y+1).

	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
	}

A common mistake is assuming that an `Image`'s bounds start at (0, 0).
For example, an animated GIF contains a sequence of Images,
and each `Image` after the first typically only holds pixel data for the area that changed,
and that area doesn't necessarily start at (0, 0).
The correct way to iterate over an `Image` m's pixels looks like:

	b := m.Bounds()
	for y := b.Min.Y; y < b.Max.Y; y++ {
	 for x := b.Min.X; x < b.Max.X; x++ {
	  doStuffWith(m.At(x, y))
	 }
	}

`Image` implementations do not have to be based on an in-memory slice of pixel data.
For example, a [[https://golang.org/pkg/image/#Uniform][`Uniform`]] is an
`Image` of enormous bounds and uniform color,
whose in-memory representation is simply that color.

	type Uniform struct {
	    C color.Color
	}

Typically, though, programs will want an image based on a slice.
Struct types like [[https://golang.org/pkg/image/#RGBA][`RGBA`]] and [[https://golang.org/pkg/image/#Gray][`Gray`]]
(which other packages refer to as `image.RGBA` and `image.Gray`) hold slices
of pixel data and implement the `Image` interface.

	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
	}

These types also provide a `Set(x,`y`int,`c`color.Color)` method that allows modifying the image one pixel at a time.

	    m := image.NewRGBA(image.Rect(0, 0, 640, 480))
	    m.Set(5, 5, color.RGBA{255, 0, 0, 255})

If you're reading or writing a lot of pixel data,
it can be more efficient, but more complicated,
to access these struct type's `Pix` field directly.

The slice-based `Image` implementations also provide a `SubImage` method,
which returns an `Image` backed by the same array.
Modifying the pixels of a sub-image will affect the pixels of the original image,
analogous to how modifying the contents of a sub-slice `s[i0:i1]` will affect
the contents of the original slice `s`.

.image go-image-package_image-package-05.png

	    m0 := image.NewRGBA(image.Rect(0, 0, 8, 5))
	    m1 := m0.SubImage(image.Rect(1, 2, 5, 5)).(*image.RGBA)
	    fmt.Println(m0.Bounds().Dx(), m1.Bounds().Dx()) // prints 8, 4
	    fmt.Println(m0.Stride == m1.Stride)             // prints true

For low-level code that works on an image's `Pix` field,
be aware that ranging over `Pix` can affect pixels outside an image's bounds.
In the example above, the pixels covered by `m1.Pix` are shaded in blue.
Higher-level code, such as the `At` and `Set` methods or the [[https://golang.org/pkg/image/draw/][image/draw package]],
will clip their operations to the image's bounds.

* Image Formats

The standard package library supports a number of common image formats,
such as GIF, JPEG and PNG.
If you know the format of a source image file,
you can decode from an [[https://golang.org/pkg/io/#Reader][`io.Reader`]] directly.

	import (
	 "image/jpeg"
	 "image/png"
	 "io"
	)

	// convertJPEGToPNG converts from JPEG to PNG.
	func convertJPEGToPNG(w io.Writer, r io.Reader) error {
	 img, err := jpeg.Decode(r)
	 if err != nil {
	  return err
	 }
	 return png.Encode(w, img)
	}

If you have image data of unknown format,
the [[https://golang.org/pkg/image/#Decode][`image.Decode`]] function can detect the format.
The set of recognized formats is constructed at run time and is not limited
to those in the standard package library.
An image format package typically registers its format in an init function,
and the main package will "underscore import" such a package solely for
the side effect of format registration.

	import (
	 "image"
	 "image/png"
	 "io"

	 _ "code.google.com/p/vp8-go/webp"
	 _ "image/jpeg"
	)

	// convertToPNG converts from any recognized format to PNG.
	func convertToPNG(w io.Writer, r io.Reader) error {
	 img, _, err := image.Decode(r)
	 if err != nil {
	  return err
	 }
	 return png.Encode(w, img)
	}
