1. 程式人生 > >The Go image/draw package

The Go image/draw package

29 September 2011

Introduction

Package 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.

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

. In Go, a nil mask image is equivalent to an infinitely sized, fully opaque mask image.

The Porter-Duff paper presented 12 different composition operators, 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. The Over 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 Src 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 Src operator is usually faster.

Geometric Alignment

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 sp and mp: the source rectangle is equal to r translated so that r.Min in the destination image aligns with sp in the source image, and similarly for mp. The effective rectangle is also clipped to each image's bounds in their respective co-ordinate space.

The DrawMask function takes seven arguments, but an explicit mask and mask-point are usually unnecessary, so the 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)
func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point,
 mask image.Image, mp image.Point, op Op)

The destination image must be mutable, so the image/draw package defines a draw.Image interface which has a Set method.

type Image interface {
    image.Image
    Set(x, y int, c color.Color)
}

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 Image 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 Uniform.

// 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)

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)

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)

Alternatively:

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().

Scrolling an Image

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:

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))

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, 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)

Drawing Through a Mask

To draw an image through a circular mask with center p and radius r:

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}
}

    draw.DrawMask(dst, dst.Bounds(), src, image.ZP, &circle{p, r}, image.ZP, draw.Over)

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. 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)

Performance

The image/draw package implementation demonstrates how to provide an image manipulation function that is both general purpose, yet efficient for common cases. The DrawMask 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 image.RGBA image onto another, or drawing an image.Alpha mask (such as a font glyph) onto an image.RGBA 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 At and Set 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.

相關推薦

The Go image/draw package

29 September 2011 Introduction Package image/draw defines only one operation: drawing a source image onto a dest

The Go image package

21 September 2011 Introduction The image and image/color packages define a number of types: color.Color and colo

Research Report on the Optical Image Stabilization

電子科技大學 格拉斯哥學院 2017/2018級 席文正 Introduction Image stabilization is the technique of improving image quality by actively removing the apparent mo

Go語言開發者福利 - 國內版 The Go Playground

本文為原創文章,轉載註明出處,歡迎掃碼關注公眾號flysnow_org或者網站www.flysnow.org/,第一時間看後續精彩文章。覺得好的話,順手分享到朋友圈吧,感謝支援。 作為Go語言開發者,我們都知道,Golang為我們提供了一個線上的、可以執行Go語言程式碼的、可以分享Go語言程式碼的

Chapter 8:Automating the Featurizer: Image Feature Extraction and Deep Learning

一、the simplest image features 最簡單的image表徵方法為:pixel matrix。但是,這種表徵方法,沒有將pixel之間的relationship囊括在內,因此,無法capture enough semantic inform

How to Enable the GD Image Library for WordPress?

很久以前還在用 php5 + wordpress 時,文章的縮圖都有自動被產生,某一次升級之後,縮圖功能就不見了。花了2小時Google 終於找到原因。 解法如下: apt-get install php7.0-gd phpenmod gd /etc/init.d/php7.0-fpm restart p

How can i detect the library image is from front camera or back camera

遇到一個奇怪的問題,iOS 前鏡頭拍的照片,被旋轉了 180度。 解法如下: Your code checks for available cameras on the device. What you need to do is read the metadata for the image after

The Go init Function

There are times, when creating applications in Go, that you need to be able to set up some form of state on the initial startup of your program. Th

How the Go runtime implements maps efficiently (without generics)

This post discusses how maps are implemented in Go. It is based on a presentation I gave at the GoCon Spring 2018 conference in Tokyo, Japan. What is a

Updating the Go Code of Conduct

23 May 2018 In November 2015, we introduced the Go Code of Conduct. It was developed in a collaboratio

The empty interface in the Go programming language

One of the most hotly debated topics in the world of the Go programming language, is the lack of generics. Generics are considered a key feature in othe

Use "conda info " to see the dependencies for each package

我這裡使用conda install tensorflow失敗,出現上述問題 我這裡主要是更換conda映象資料來源 1.檢視當前映象資料來源列表 conda config --get channels 2.網路上面均有的清華映象源(使用方式) conda config --

golang基礎--image/draw渲染圖片、利用golang/freetype庫在圖片上生成文字

文章目錄需求安裝依賴邏輯效果圖例項 需求 在一張A4紙上,利用image/draw標準庫生成4張二維碼,和該二維碼的客戶資訊 1、二維碼生成利用到的庫就是image/draw,通過draw.Draw進行寫入 2、然後字型渲染利用了golang/freetype開

A conversation with the Go team

6 June 2013 At Google I/O 2013, several members of the Go team hosted a "Fireside chat." Robert Griese

Introducing the Go Race Detector

26 June 2013 Introduction Race conditions are among the most insidious and elusive programming errors. The

The Go Programming Language turns two

10 November 2011 Two years ago a small team at Google went public with their fledgling project - the Go Prog

Getting to know the Go community

21 December 2011 Over the past couple of years Go has attracted a lot of users and contributors, and I've ha

Introducing the Go Playground

15 September 2010 If you visit golang.org today you'll see our new look. We have given the site a new coat o

Inside the Go Playground

12 December 2013 Introduction In September 2010 we introduced the Go Playground, a web service that compil

論文解析《Deep Convolutional Neural Network Features and the Original Image

這一篇論文詳細分析了人臉識別中CNN網路提取到的features有一些什麼樣的性質,一般人臉識別中CNN出來後面接一個線性層用交叉熵來分類,這裡的features值得就是cnn出來的512或者128維的浮點陣列。文章首先用這個features作為輸入,使用LDA來分類,預測頭