aboutsummaryrefslogtreecommitdiff
path: root/content/go-imagedraw-package.article
diff options
context:
space:
mode:
Diffstat (limited to 'content/go-imagedraw-package.article')
-rw-r--r--content/go-imagedraw-package.article85
1 files changed, 43 insertions, 42 deletions
diff --git a/content/go-imagedraw-package.article b/content/go-imagedraw-package.article
index a28bc5d..9e24c14 100644
--- a/content/go-imagedraw-package.article
+++ b/content/go-imagedraw-package.article
@@ -1,12 +1,13 @@
-The Go image/draw package
+# The Go image/draw package
29 Sep 2011
Tags: draw, image, libraries, technical
+Summary: [Package image/draw](https://golang.org/pkg/image/draw/) defines only one operation: drawing a source image onto a destination image, through an optional mask image. This one operation is surprisingly versatile and can perform a number of common image manipulation tasks elegantly and efficiently.
Nigel Tao
-* Introduction
+## Introduction
-[[https://golang.org/pkg/image/draw/][Package image/draw]] defines only one operation:
+[Package image/draw](https://golang.org/pkg/image/draw/) defines only one operation:
drawing a source image onto a destination image,
through an optional mask image.
This one operation is surprisingly versatile and can perform a number of
@@ -16,12 +17,12 @@ Composition is performed pixel by pixel in the style of the Plan 9 graphics
library and the X Render extension.
The model is based on the classic "Compositing Digital Images" paper by Porter and Duff,
with an additional mask parameter:
-`dst`=`(src`IN`mask)`OP`dst`.
-For a fully opaque mask, this reduces to the original Porter-Duff formula: `dst`=`src`OP`dst`.
+`dst = (src IN mask) OP dst`.
+For a fully opaque mask, this reduces to the original Porter-Duff formula: `dst = src OP dst`.
In Go, a nil mask image is equivalent to an infinitely sized,
fully opaque mask image.
-The Porter-Duff paper presented [[http://www.w3.org/TR/SVGCompositing/examples/compop-porterduff-examples.png][12 different composition operators]],
+The Porter-Duff paper presented [12 different composition operators](http://www.w3.org/TR/SVGCompositing/examples/compop-porterduff-examples.png),
but with an explicit mask, only 2 of these are needed in practice:
source-over-destination and source.
In Go, these operators are represented by the `Over` and `Src` constants.
@@ -34,7 +35,7 @@ for the destination image's original content.
For fully opaque source and mask images, the two operators produce the same output,
but the `Src` operator is usually faster.
-* Geometric Alignment
+## Geometric Alignment
Composition requires associating destination pixels with source and mask pixels.
Obviously, this requires destination, source and mask images,
@@ -59,10 +60,10 @@ respective co-ordinate space.
.image go-imagedraw-package_20.png
-The [[https://golang.org/pkg/image/draw/#DrawMask][`DrawMask`]] function
+The [`DrawMask`](https://golang.org/pkg/image/draw/#DrawMask) function
takes seven arguments,
but an explicit mask and mask-point are usually unnecessary,
-so the [[https://golang.org/pkg/image/draw/#Draw][`Draw`]] function takes five:
+so the [`Draw`](https://golang.org/pkg/image/draw/#Draw) function takes five:
// Draw calls DrawMask with a nil mask.
func Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point, op Op)
@@ -70,14 +71,14 @@ so the [[https://golang.org/pkg/image/draw/#Draw][`Draw`]] function takes five:
mask image.Image, mp image.Point, op Op)
The destination image must be mutable, so the image/draw package defines
-a [[https://golang.org/pkg/image/draw/#Image][`draw.Image`]] interface which has a `Set` method.
+a [`draw.Image`](https://golang.org/pkg/image/draw/#Image) interface which has a `Set` method.
type Image interface {
image.Image
Set(x, y int, c color.Color)
}
-* Filling a Rectangle
+## Filling a Rectangle
To fill a rectangle with a solid color, use an `image.Uniform` source.
The `ColorImage` type re-interprets a `Color` as a practically infinite-sized
@@ -86,42 +87,42 @@ For those familiar with the design of Plan 9's draw library,
there is no need for an explicit "repeat bit" in Go's slice-based image types;
the concept is subsumed by `Uniform`.
- // image.ZP is the zero point -- the origin.
- draw.Draw(dst, r, &image.Uniform{c}, image.ZP, draw.Src)
+ // image.ZP is the zero point -- the origin.
+ draw.Draw(dst, r, &image.Uniform{c}, image.ZP, draw.Src)
To initialize a new image to all-blue:
- m := image.NewRGBA(image.Rect(0, 0, 640, 480))
- blue := color.RGBA{0, 0, 255, 255}
- draw.Draw(m, m.Bounds(), &image.Uniform{blue}, image.ZP, draw.Src)
+ m := image.NewRGBA(image.Rect(0, 0, 640, 480))
+ blue := color.RGBA{0, 0, 255, 255}
+ draw.Draw(m, m.Bounds(), &image.Uniform{blue}, image.ZP, draw.Src)
To reset an image to transparent (or black,
if the destination image's color model cannot represent transparency),
use `image.Transparent`, which is an `image.Uniform`:
- draw.Draw(m, m.Bounds(), image.Transparent, image.ZP, draw.Src)
+ draw.Draw(m, m.Bounds(), image.Transparent, image.ZP, draw.Src)
.image go-imagedraw-package_2a.png
-* Copying an Image
+## Copying an Image
To copy from a rectangle `sr` in the source image to a rectangle starting
at a point `dp` in the destination,
convert the source rectangle into the destination image's co-ordinate space:
- r := image.Rectangle{dp, dp.Add(sr.Size())}
- draw.Draw(dst, r, src, sr.Min, draw.Src)
+ r := image.Rectangle{dp, dp.Add(sr.Size())}
+ draw.Draw(dst, r, src, sr.Min, draw.Src)
Alternatively:
- r := sr.Sub(sr.Min).Add(dp)
- draw.Draw(dst, r, src, sr.Min, draw.Src)
+ r := sr.Sub(sr.Min).Add(dp)
+ draw.Draw(dst, r, src, sr.Min, draw.Src)
-To copy the entire source image, use `sr`=`src.Bounds()`.
+To copy the entire source image, use `sr = src.Bounds()`.
.image go-imagedraw-package_2b.png
-* Scrolling an Image
+## Scrolling an Image
Scrolling an image is just copying an image to itself,
with different destination and source rectangles.
@@ -129,16 +130,16 @@ Overlapping destination and source images are perfectly valid,
just as Go's built-in copy function can handle overlapping destination and source slices.
To scroll an image m by 20 pixels:
- b := m.Bounds()
- p := image.Pt(0, 20)
- // Note that even though the second argument is b,
- // the effective rectangle is smaller due to clipping.
- draw.Draw(m, b, m, b.Min.Add(p), draw.Src)
- dirtyRect := b.Intersect(image.Rect(b.Min.X, b.Max.Y-20, b.Max.X, b.Max.Y))
+ b := m.Bounds()
+ p := image.Pt(0, 20)
+ // Note that even though the second argument is b,
+ // the effective rectangle is smaller due to clipping.
+ draw.Draw(m, b, m, b.Min.Add(p), draw.Src)
+ dirtyRect := b.Intersect(image.Rect(b.Min.X, b.Max.Y-20, b.Max.X, b.Max.Y))
.image go-imagedraw-package_2c.png
-* Converting an Image to RGBA
+## Converting an Image to RGBA
The result of decoding an image format might not be an `image.RGBA`:
decoding a GIF results in an `image.Paletted`,
@@ -146,13 +147,13 @@ decoding a JPEG results in a `ycbcr.YCbCr`,
and the result of decoding a PNG depends on the image data.
To convert any image to an `image.RGBA`:
- b := src.Bounds()
- m := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
- draw.Draw(m, m.Bounds(), src, b.Min, draw.Src)
+ b := src.Bounds()
+ m := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
+ draw.Draw(m, m.Bounds(), src, b.Min, draw.Src)
.image go-imagedraw-package_2d.png
-* Drawing Through a Mask
+## Drawing Through a Mask
To draw an image through a circular mask with center `p` and radius `r`:
@@ -181,21 +182,21 @@ To draw an image through a circular mask with center `p` and radius `r`:
.image go-imagedraw-package_2e.png
-* Drawing Font Glyphs
+## Drawing Font Glyphs
To draw a font glyph in blue starting from a point `p`,
-draw with an `image.ColorImage` source and an `image.Alpha`mask`.
+draw with an `image.ColorImage` source and an `image.Alpha mask`.
For simplicity, we aren't performing any sub-pixel positioning or rendering,
or correcting for a font's height above a baseline.
- src := &image.Uniform{color.RGBA{0, 0, 255, 255}}
- mask := theGlyphImageForAFont()
- mr := theBoundsFor(glyphIndex)
- draw.DrawMask(dst, mr.Sub(mr.Min).Add(p), src, image.ZP, mask, mr.Min, draw.Over)
+ src := &image.Uniform{color.RGBA{0, 0, 255, 255}}
+ mask := theGlyphImageForAFont()
+ mr := theBoundsFor(glyphIndex)
+ draw.DrawMask(dst, mr.Sub(mr.Min).Add(p), src, image.ZP, mask, mr.Min, draw.Over)
.image go-imagedraw-package_2f.png
-* Performance
+## Performance
The image/draw package implementation demonstrates how to provide an image
manipulation function that is both general purpose,