diff options
Diffstat (limited to 'content/go-imagedraw-package.article')
-rw-r--r-- | content/go-imagedraw-package.article | 85 |
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, |