image/draw 包僅僅定義了一個操作:通過可選的蒙版圖(mask image),把一個原始圖片繪制到目標圖片上,這個操作是出奇的靈活,可以優雅和高效的執行很多常見的圖像處理任務。
1: // Draw calls DrawMask with a nil mask.
2: func Draw(dst Image, r image.Rectangle, src image.Image, sp image.Point, op Op)
3: func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point,
4: mask image.Image, mp image.Point, op Op)
第一個函數Draw是沒有使用蒙版mask的調用方法,它內部其實就是調用的mask為 nil的方法。
它的參數描述如下:
- dst 繪圖的背景圖。
- r 是背景圖的繪圖區域
- src 是要繪制的圖
- sp 是 src 對應的繪圖開始點(繪制的大小 r變量定義了)
- mask 是繪圖時用的蒙版,控制替換圖片的方式。
- mp 是繪圖時蒙版開始點(繪制的大小 r變量定義了)
- op Op is a Porter-Duff compositing operator. 參考文章:http://blog.csdn.net/ison81/article/details/5468763
Porter-Duff 等式12種規則可以看這篇博客:http://www.blogjava.net/onedaylover/archive/2008/01/16/175675.html
下圖就是幾個相關的例子:
mask 蒙版是漸變
給一個矩形填充顏色
使用 Draw方法的邏輯效果圖:
代碼:
1: m := image.NewRGBA(image.Rect(0, 0, 640, 480))
2: blue := color.RGBA{0, 0, 255, 255}
3: draw.Draw(m, m.Bounds(), &image.Uniform{blue}, image.ZP, draw.Src)
拷貝圖片的一部分
效果特效如下:
相關代碼:
1: r := image.Rectangle{dp, dp.Add(sr.Size())} // 獲得更換區域
2: draw.Draw(dst, r, src, sr.Min, draw.Src)
如果是復制整個圖片,則更簡單:
1: sr = src.Bounds() // 獲取要復制圖片的尺寸
2: r := sr.Sub(sr.Min).Add(dp) // 目標圖的要剪切區域
3: draw.Draw(dst, r, src, sr.Min, draw.Src)
圖片滾動效果
效果如下圖:
假設我們需要把圖片 m 上移20個像素.
相關代碼:
1: b := m.Bounds()
2: p := image.Pt(0, 20)
3: // Note that even though the second argument is b,
4: // the effective rectangle is smaller due to clipping.
5: draw.Draw(m, b, m, b.Min.Add(p), draw.Src)
6: dirtyRect := b.Intersect(image.Rect(b.Min.X, b.Max.Y-20, b.Max.X, b.Max.Y))
把一個圖片轉成RGBA格式
效果圖:
相關代碼:
1: b := src.Bounds()
2: m := image.NewRGBA(b)
3: draw.Draw(m, b, src, b.Min, draw.Src)
通過蒙版畫特效
效果圖
相關代碼
1: type circle struct {
2: p image.Point
3: r int
4: }
5:
6: func (c *circle) ColorModel() color.Model {
7: return color.AlphaModel
8: }
9:
10: func (c *circle) Bounds() image.Rectangle {
11: return image.Rect(c.p.X-c.r, c.p.Y-c.r, c.p.X+c.r, c.p.Y+c.r)
12: }
13:
14: func (c *circle) At(x, y int) color.Color {
15: xx, yy, rr := float64(x-c.p.X)+0.5, float64(y-c.p.Y)+0.5, float64(c.r)
16: if xx*xx+yy*yy < rr*rr {
17: return color.Alpha{255}
18: }
19: return color.Alpha{0}
20: }
21:
22:
23: draw.DrawMask(dst, dst.Bounds(), src, image.ZP, &circle{p, r}, image.ZP, draw.Over)
注意,一個image對象只需要實現下面幾個就可,這也就是Go接口強大的地方.
1: type Image interface {
2: // ColorModel returns the Image's color model.
3: ColorModel() color.Model
4: // Bounds returns the domain for which At can return non-zero color.
5: // The bounds do not necessarily contain the point (0, 0).
6: Bounds() Rectangle
7: // At returns the color of the pixel at (x, y).
8: // At(Bounds().Min.X, Bounds().Min.Y) returns the upper-left pixel of the grid.
9: // At(Bounds().Max.X-1, Bounds().Max.Y-1) returns the lower-right one.
10: At(x, y int) color.Color
11: }
畫一個字體
效果圖,畫一個藍色背景的字體。
相關偽代碼:
1: src := &image.Uniform{color.RGBA{0, 0, 255, 255}}
2: mask := theGlyphImageForAFont()
3: mr := theBoundsFor(glyphIndex)
4: draw.DrawMask(dst, mr.Sub(mr.Min).Add(p), src, image.ZP, mask, mr.Min, draw.Over)
上面例子完整的代碼請看:
http://golang.org/doc/progs/image_draw.go
參考: