]> Cypherpunks repositories - gostls13.git/commitdiff
doc: add Go image/draw package article and convert code snippets to Go1.
authorJohan Euphrosine <proppy@google.com>
Wed, 14 Mar 2012 00:27:41 +0000 (11:27 +1100)
committerAndrew Gerrand <adg@golang.org>
Wed, 14 Mar 2012 00:27:41 +0000 (11:27 +1100)
Originally published on The Go Programming Language Blog, September 29, 2011.

http://blog.golang.org/2011/09/go-imagedraw-package.html

Update #2547.

R=golang-dev, adg, rsc
CC=golang-dev
https://golang.org/cl/5755057

12 files changed:
doc/Makefile
doc/articles/image-20.png [new file with mode: 0644]
doc/articles/image-2a.png [new file with mode: 0644]
doc/articles/image-2b.png [new file with mode: 0644]
doc/articles/image-2c.png [new file with mode: 0644]
doc/articles/image-2d.png [new file with mode: 0644]
doc/articles/image-2e.png [new file with mode: 0644]
doc/articles/image-2f.png [new file with mode: 0644]
doc/articles/image_draw.html [new file with mode: 0644]
doc/docs.html
doc/progs/image_draw.go [new file with mode: 0644]
src/pkg/image/draw/draw.go

index 60e1ef369c1fb8e4ce89d701d084422ddb6ccef3..b275dfe4ddd1aa92325415a22bd949fa92e315ec 100644 (file)
@@ -7,13 +7,14 @@ RAWHTML=\
        articles/error_handling.rawhtml\
        articles/slices_usage_and_internals.rawhtml\
        articles/laws_of_reflection.rawhtml\
+       articles/image_draw.rawhtml\
        effective_go.rawhtml\
        go1.rawhtml\
 
 all: $(RAWHTML)
 
 %.rawhtml: %.html
-       godoc -url /doc/$* >$@
+       godoc -url /doc/$< >$@
 
 clean:
        rm -f $(RAWHTML) 
diff --git a/doc/articles/image-20.png b/doc/articles/image-20.png
new file mode 100644 (file)
index 0000000..063e430
Binary files /dev/null and b/doc/articles/image-20.png differ
diff --git a/doc/articles/image-2a.png b/doc/articles/image-2a.png
new file mode 100644 (file)
index 0000000..3f1c0af
Binary files /dev/null and b/doc/articles/image-2a.png differ
diff --git a/doc/articles/image-2b.png b/doc/articles/image-2b.png
new file mode 100644 (file)
index 0000000..32b2470
Binary files /dev/null and b/doc/articles/image-2b.png differ
diff --git a/doc/articles/image-2c.png b/doc/articles/image-2c.png
new file mode 100644 (file)
index 0000000..f9abce5
Binary files /dev/null and b/doc/articles/image-2c.png differ
diff --git a/doc/articles/image-2d.png b/doc/articles/image-2d.png
new file mode 100644 (file)
index 0000000..ed0a9f9
Binary files /dev/null and b/doc/articles/image-2d.png differ
diff --git a/doc/articles/image-2e.png b/doc/articles/image-2e.png
new file mode 100644 (file)
index 0000000..483b208
Binary files /dev/null and b/doc/articles/image-2e.png differ
diff --git a/doc/articles/image-2f.png b/doc/articles/image-2f.png
new file mode 100644 (file)
index 0000000..3dce02d
Binary files /dev/null and b/doc/articles/image-2f.png differ
diff --git a/doc/articles/image_draw.html b/doc/articles/image_draw.html
new file mode 100644 (file)
index 0000000..848b659
--- /dev/null
@@ -0,0 +1,222 @@
+<!--{
+       "Title": "The Go image/draw package",
+       "Template": true
+}-->
+
+<p>
+<a href="http://golang.org/pkg/image/draw/">Package image/draw</a> 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.  
+</p>
+
+<p>
+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: <code>dst = (src IN mask) OP dst</code>.
+For a fully opaque mask, this reduces to the original Porter-Duff
+formula: <code>dst = src OP dst</code>. In Go, a nil mask image is equivalent
+to an infinitely sized, fully opaque mask image.
+</p>
+
+<p>
+The Porter-Duff paper presented
+<a href="http://www.w3.org/TR/SVGCompositing/examples/compop-porterduff-examples.png">12 different composition operators</a>,
+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 <code>Over</code> and <code>Src</code> constants. The <code>Over</code> operator
+performs the natural layering of a source image over a destination
+image: the change to the destination image is smaller where the
+source (after masking) is more transparent (that is, has lower
+alpha). The <code>Src</code> operator merely copies the source (after masking)
+with no regard for the destination image's original content. For
+fully opaque source and mask images, the two operators produce the
+same output, but the <code>Src</code> operator is usually faster.
+</p>
+
+<p><b>Geometric Alignment</b></p>
+
+<p>  
+Composition requires associating destination pixels with source and
+mask pixels. Obviously, this requires destination, source and mask
+images, and a composition operator, but it also requires specifying
+what rectangle of each image to use. Not every drawing should write
+to the entire destination: when updating an animating image, it is
+more efficient to only draw the parts of the image that have
+changed. Not every drawing should read from the entire source: when
+using a sprite that combines many small images into one large one,
+only a part of the image is needed. Not every drawing should read
+from the entire mask: a mask image that collects a font's glyphs is
+similar to a sprite. Thus, drawing also needs to know three
+rectangles, one for each image. Since each rectangle has the same
+width and height, it suffices to pass a destination rectangle `r`
+and two points <code>sp</code> and <code>mp</code>: the source rectangle is equal to <code>r</code>
+translated so that <code>r.Min</code> in the destination image aligns with 
+<code>sp</code> in the source image, and similarly for <code>mp</code>. The effective
+rectangle is also clipped to each image's bounds in their
+respective co-ordinate space.
+</p>
+
+<p>
+<img src="image-20.png">
+</p>
+
+<p>
+The <a href="http://golang.org/pkg/image/draw/#DrawMask"><code>DrawMask</code></a>
+function takes seven arguments, but an explicit mask and mask-point
+are usually unnecessary, so the
+<a href="http://golang.org/pkg/image/draw/#Draw"><code>Draw</code></a> function takes five:
+</p>
+
+<pre>
+// Draw calls DrawMask with a nil mask.
+func Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point, op Op)
+func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point,
+       mask image.Image, mp image.Point, op Op)
+</pre>
+
+<p>
+The destination image must be mutable, so the image/draw package
+defines a <a href="http://golang.org/pkg/image/draw/#Image"><code>draw.Image</code></a>
+interface which has a <code>Set</code> method.
+</p>
+
+{{code "../src/pkg/image/draw/draw.go" `/type Image/` `/}/`}}
+  
+<p><b>Filling a Rectangle</b></p>
+
+<p>
+To fill a rectangle with a solid color, use an <code>image.Uniform</code>
+source. The <code>ColorImage</code> type re-interprets a <code>Color</code> as a
+practically infinite-sized <code>Image</code> of that color. 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 <code>Uniform</code>.
+</p>
+
+{{code "/doc/progs/image_draw.go" `/ZERO/` `/STOP/`}}
+
+<p>
+To initialize a new image to all-blue:
+</p>
+
+{{code "/doc/progs/image_draw.go" `/BLUE/` `/STOP/`}}
+
+<p>
+To reset an image to transparent (or black, if the destination
+image's color model cannot represent transparency), use
+<code>image.Transparent</code>, which is an <code>image.Uniform</code>:
+</p>
+
+{{code "/doc/progs/image_draw.go" `/RESET/` `/STOP/`}}
+  
+<p>
+<img src="image-2a.png">
+</p>
+
+<p><b>Copying an Image</b></p>
+
+<p>
+To copy from a rectangle <code>sr</code> in the source image to a rectangle
+starting at a point <code>dp</code> in the destination, convert the source
+rectangle into the destination image's co-ordinate space:
+</p>
+
+{{code "/doc/progs/image_draw.go" `/RECT/` `/STOP/`}}
+  
+<p>
+Alternatively:
+</p>
+
+{{code "/doc/progs/image_draw.go" `/RECT2/` `/STOP/`}}
+  
+<p>
+To copy the entire source image, use <code>sr = src.Bounds()</code>.
+</p>
+  
+<p>
+<img src="image-2b.png">
+</p>
+<p><b>Scrolling an Image</b></p>
+
+<p>
+Scrolling an image is just copying an image to itself, with
+different destination and source rectangles. 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:
+</p>
+
+{{code "/doc/progs/image_draw.go" `/SCROLL/` `/STOP/`}}
+  
+<p><img src="image-2c.png"></p>
+<p><b>Converting an Image to RGBA</b></p>
+
+<p>
+The result of decoding an image format might not be an
+<code>image.RGBA</code>: decoding a GIF results in an <code>image.Paletted</code>,
+decoding a JPEG results in a <code>ycbcr.YCbCr</code>, and the result of
+decoding a PNG depends on the image data. To convert any image to
+an <code>image.RGBA</code>:
+</p>
+
+{{code "/doc/progs/image_draw.go" `/CONV/` `/STOP/`}}
+  
+<p>
+<img src="image-2d.png">
+</p>
+
+<p><b>Drawing Through a Mask</b></p>
+
+<p>
+To draw an image through a circular mask with center <code>p</code> and radius
+<code>r</code>:
+</p>
+
+{{code "/doc/progs/image_draw.go" `/CIRCLE/` `/STOP/`}}
+{{code "/doc/progs/image_draw.go" `/CIRCLE2/` `/STOP/`}}
+  
+<p>
+<img src="image-2e.png">
+</p>
+
+<p><b>Drawing Font Glyphs</b></p>
+
+<p> 
+To draw a font glyph in blue starting from a point <code>p</code>, draw with
+an <code>image.ColorImage</code> source and an <code>image.Alpha mask</code>. For
+simplicity, we aren't performing any sub-pixel positioning or
+rendering, or correcting for a font's height above a baseline.
+</p>
+
+{{code "/doc/progs/image_draw.go" `/GLYPH/` `/STOP/`}}
+
+<p>
+<img src="image-2f.png">
+</p>
+  
+<p><b>Performance</b></p>
+
+<p>
+The image/draw package implementation demonstrates how to provide
+an image manipulation function that is both general purpose, yet
+efficient for common cases. The <code>DrawMask</code> function takes arguments
+of interface types, but immediately makes type assertions that its
+arguments are of specific struct types, corresponding to common
+operations like drawing one <code>image.RGBA</code> image onto another, or
+drawing an <code>image.Alpha</code> mask (such as a font glyph) onto an
+<code>image.RGBA</code> image. If a type assertion succeeds, that type
+information is used to run a specialized implementation of the
+general algorithm. If the assertions fail, the fallback code path
+uses the generic <code>At</code> and <code>Set</code> methods. The fast-paths are purely
+a performance optimization; the resultant destination image is the
+same either way. In practice, only a small number of special cases
+are necessary to support typical applications.  
+</p>
+
+
index 4b40bfe4b36919c39c38f09df2413fa2e9355488..cc637b038a6d2e2858030c179f19f4cd5315b6b0 100644 (file)
@@ -117,7 +117,7 @@ Guided tours of Go programs.
 <li><a href="http://blog.golang.org/2011/03/gobs-of-data.html">Gobs of data</a> - the design and use of the <a href="/pkg/encoding/gob/">gob</a> package.</li>
 <li><a href="/doc/articles/laws_of_reflection.html">The Laws of Reflection</a> - the fundamentals of the <a href="/pkg/reflect/">reflect</a> package.</li>
 <li><a href="http://blog.golang.org/2011/09/go-image-package.html">The Go image package</a> - the fundamentals of the <a href="/pkg/image/">image</a> package.</li>
-<li><a href="http://blog.golang.org/2011/09/go-imagedraw-package.html">The Go image/draw package</a> - the fundamentals of the <a href="/pkg/image/draw/">image/draw</a> package.</li>
+<li><a href="/doc/articles/image_draw.html">The Go image/draw package</a> - the fundamentals of the <a href="/pkg/image/draw/">image/draw</a> package.</li>
 </ul>
 
 <h4>Tools</h4>
diff --git a/doc/progs/image_draw.go b/doc/progs/image_draw.go
new file mode 100644 (file)
index 0000000..f3400b6
--- /dev/null
@@ -0,0 +1,142 @@
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file contains the code snippets included in "The Go image/draw package."
+
+package main
+
+import (
+       "image"
+       "image/color"
+       "image/draw"
+)
+
+func main() {
+       Color()
+       Rect()
+       RectAndScroll()
+       ConvAndCircle()
+       Glyph()
+}
+
+func Color() {
+       c := color.RGBA{255, 0, 255, 255}
+       r := image.Rect(0, 0, 640, 480)
+       dst := image.NewRGBA(r)
+
+       // ZERO OMIT
+       // image.ZP is the zero point -- the origin.
+       draw.Draw(dst, r, &image.Uniform{c}, image.ZP, draw.Src)
+       // STOP OMIT
+
+       // BLUE OMIT
+       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)
+       // STOP OMIT
+
+       // RESET OMIT
+       draw.Draw(m, m.Bounds(), image.Transparent, image.ZP, draw.Src)
+       // STOP OMIT
+}
+
+func Rect() {
+       dst := image.NewRGBA(image.Rect(0, 0, 640, 480))
+       sr := image.Rect(0, 0, 200, 200)
+       src := image.Black
+       dp := image.Point{100, 100}
+
+       // RECT OMIT
+       r := image.Rectangle{dp, dp.Add(sr.Size())}
+       draw.Draw(dst, r, src, sr.Min, draw.Src)
+       // STOP OMIT
+}
+
+func RectAndScroll() {
+       dst := image.NewRGBA(image.Rect(0, 0, 640, 480))
+       sr := image.Rect(0, 0, 200, 200)
+       src := image.Black
+       dp := image.Point{100, 100}
+
+       // RECT2 OMIT
+       r := sr.Sub(sr.Min).Add(dp)
+       draw.Draw(dst, r, src, sr.Min, draw.Src)
+       // STOP OMIT
+
+       m := dst
+
+       // SCROLL OMIT
+       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))
+       // STOP OMIT
+
+       _ = dirtyRect // noop
+}
+
+func ConvAndCircle() {
+       src := image.NewRGBA(image.Rect(0, 0, 640, 480))
+       dst := image.NewRGBA(image.Rect(0, 0, 640, 480))
+
+       // CONV OMIT
+       b := src.Bounds()
+       m := image.NewRGBA(image.Rect(0, 0, b.Dx(), b.Dy()))
+       draw.Draw(m, m.Bounds(), src, b.Min, draw.Src)
+       // STOP OMIT
+
+       p := image.Point{100, 100}
+       r := 50
+
+       // CIRCLE2 OMIT
+       draw.DrawMask(dst, dst.Bounds(), src, image.ZP, &circle{p, r}, image.ZP, draw.Over)
+       // STOP OMIT
+}
+
+func theGlyphImageForAFont() image.Image {
+       return image.NewRGBA(image.Rect(0, 0, 640, 480))
+}
+
+func theBoundsFor(index int) image.Rectangle {
+       return image.Rect(0, 0, 32, 32)
+}
+
+func Glyph() {
+       p := image.Point{100, 100}
+       dst := image.NewRGBA(image.Rect(0, 0, 640, 480))
+       glyphIndex := 42
+
+       // GLYPH OMIT
+       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)
+       // STOP OMIT
+}
+
+//CIRCLE OMIT
+type circle struct {
+       p image.Point
+       r int
+}
+
+func (c *circle) ColorModel() color.Model {
+       return color.AlphaModel
+}
+
+func (c *circle) Bounds() image.Rectangle {
+       return image.Rect(c.p.X-c.r, c.p.Y-c.r, c.p.X+c.r, c.p.Y+c.r)
+}
+
+func (c *circle) At(x, y int) color.Color {
+       xx, yy, rr := float64(x-c.p.X)+0.5, float64(y-c.p.Y)+0.5, float64(c.r)
+       if xx*xx+yy*yy < rr*rr {
+               return color.Alpha{255}
+       }
+       return color.Alpha{0}
+}
+
+//STOP
index 3b6679f7c7eb5c38083a6844f5fcd8b9a0243009..bef325c0c9df5960937e69b50e2f2f7f9e91a64b 100644 (file)
@@ -5,7 +5,7 @@
 // Package draw provides image composition functions.
 //
 // See "The Go image/draw package" for an introduction to this package:
-// http://blog.golang.org/2011/09/go-imagedraw-package.html
+// http://golang.org/doc/articles/image_draw.html
 package draw
 
 import (