Golang 繪圖基礎 -繪製簡單圖形

前一節講的是 繪圖到不一樣輸出源,請看地址: http://www.cnblogs.com/ghj1976/p/3440856.htmlhtml

上一節的例子效果是經過設置每個點的的RGBA屬性來實現的,這是最基礎的方式,經過這種方式咱們能夠繪製任意形狀的圖形。git

一、設置點的顏色一個簡單例子:

效果以下:github

123

代碼以下,跟最初咱們的代碼惟一不一樣的是設置點顏色時,多了一個條件判斷語句:if x%8 == 0 ,代碼以下,這種狀況下,其實咱們經過算法簡單的實現了畫垂直線的效果:算法

   1: package main
   2:  
   3: import (
   4:     "fmt"
   5:     "image"
   6:     "image/color"
   7:     "image/png"
   8:     "log"
   9:     "os"
  10: )
  11:  
  12: func main() {
  13:     const (
  14:         dx = 300
  15:         dy = 500
  16:     )
  17:  
  18:     // 須要保存的文件
  19:     imgcounter := 123
  20:     imgfile, _ := os.Create(fmt.Sprintf("%03d.png", imgcounter))
  21:     defer imgfile.Close()
  22:  
  23:     // 新建一個 指定大小的 RGBA位圖
  24:     img := image.NewNRGBA(image.Rect(0, 0, dx, dy))
  25:  
  26:     for y := 0; y < dy; y++ {
  27:         for x := 0; x < dx; x++ {
  28:  
  29:             if x%8 == 0 {
  30:                 // 設置某個點的顏色,依次是 RGBA
  31:                 img.Set(x, y, color.RGBA{uint8(x % 256), uint8(y % 256), 0, 255})
  32:             }
  33:         }
  34:     }
  35:  
  36:     // 以PNG格式保存文件
  37:     err := png.Encode(imgfile, img)
  38:     if err != nil {
  39:         log.Fatal(err)
  40:     }
  41:  
  42: }

好比下面一個函數就是簡單的畫水平線的代碼函數。數組

   1: // 畫 水平線
   2: func (img *Image) drawHorizLine(color color.Color, fromX, toX, y int) {
   3:     // 遍歷畫每一個點
   4:     for x := fromX; x <= toX; x++ {
   5:         img.Set(x, y, color)
   6:     }
   7: }

 

二、劃線

Golang 官方庫沒有提供劃線的庫,不過既然有了畫點的方法,咱們就能夠根據一套算法畫出點,下面的效果和代碼是按照 Bresenham's line algorithm 算法畫的線。app

http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm ide

這個算法畫的線簡單能夠用下面圖來標示:svg

800px-Bresenham.svg

下面演示代碼畫出來的效果圖以下:函數

注意,爲了便於看到效果, 圖的左右都畫了一條豎線,斜線是按照上面算法畫出來的。ui

250

相關代碼以下:
這裏的代碼借鑑了下面的代碼。
https://github.com/akavel/polyclip-go/blob/9b07bdd6e0a784f7e5d9321bff03425ab3a98beb/polyutil/draw.go

   1: package main
   2:  
   3: import (
   4:     "fmt"
   5:     "image"
   6:     "image/color"
   7:     "image/png"
   8:     "log"
   9:     "os"
  10: )
  11:  
  12: // Putpixel describes a function expected to draw a point on a bitmap at (x, y) coordinates.
  13: type Putpixel func(x, y int)
  14:  
  15: // 求絕對值
  16: func abs(x int) int {
  17:     if x >= 0 {
  18:         return x
  19:     }
  20:     return -x
  21: }
  22:  
  23: // Bresenham's algorithm, http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
  24: // https://github.com/akavel/polyclip-go/blob/9b07bdd6e0a784f7e5d9321bff03425ab3a98beb/polyutil/draw.go
  25: // TODO: handle int overflow etc.
  26: func drawline(x0, y0, x1, y1 int, brush Putpixel) {
  27:     dx := abs(x1 - x0)
  28:     dy := abs(y1 - y0)
  29:     sx, sy := 1, 1
  30:     if x0 >= x1 {
  31:         sx = -1
  32:     }
  33:     if y0 >= y1 {
  34:         sy = -1
  35:     }
  36:     err := dx - dy
  37:  
  38:     for {
  39:         brush(x0, y0)
  40:         if x0 == x1 && y0 == y1 {
  41:             return
  42:         }
  43:         e2 := err * 2
  44:         if e2 > -dy {
  45:             err -= dy
  46:             x0 += sx
  47:         }
  48:         if e2 < dx {
  49:             err += dx
  50:             y0 += sy
  51:         }
  52:     }
  53: }
  54:  
  55: func main() {
  56:  
  57:     const (
  58:         dx = 300
  59:         dy = 500
  60:     )
  61:  
  62:     // 須要保存的文件
  63:  
  64:     // 新建一個 指定大小的 RGBA位圖
  65:     img := image.NewNRGBA(image.Rect(0, 0, dx, dy))
  66:  
  67:     drawline(5, 5, dx-8, dy-10, func(x, y int) {
  68:         img.Set(x, y, color.RGBA{uint8(x), uint8(y), 0, 255})
  69:     })
  70:  
  71:     // 左右都畫一條豎線
  72:     for i := 0; i < dy; i++ {
  73:         img.Set(0, i, color.Black)
  74:         img.Set(dx-1, i, color.Black)
  75:     }
  76:  
  77:     imgcounter := 250
  78:     imgfile, _ := os.Create(fmt.Sprintf("%03d.png", imgcounter))
  79:     defer imgfile.Close()
  80:  
  81:     // 以PNG格式保存文件
  82:     err := png.Encode(imgfile, img)
  83:     if err != nil {
  84:         log.Fatal(err)
  85:     }
  86: }

 

三、特殊圖形

此次繪製出來的圖形效果以下:

1234

 

相關代碼以下:
這裏的代碼借鑑了下面的代碼:
https://github.com/xMachinae/pallinda13/blob/master/uppg2.go

   1: package main
   2:  
   3: import (
   4:     "fmt"
   5:     "image"
   6:     "image/png"
   7:     "log"
   8:     "os"
   9: )
  10:  
  11: func Pic(dx, dy int) [][]uint8 {
  12:     pic := make([][]uint8, dx)
  13:     for i := range pic {
  14:         pic[i] = make([]uint8, dy)
  15:         for j := range pic[i] {
  16:             pic[i][j] = uint8(i * j)
  17:         }
  18:     }
  19:     return pic
  20: }
  21:  
  22: func main() {
  23:     Show(Pic)
  24: }
  25:  
  26: func Show(f func(int, int) [][]uint8) {
  27:     const (
  28:         dx = 256
  29:         dy = 256
  30:     )
  31:     data := f(dx, dy) // 圖片座標點的顏色二維數組。
  32:     m := image.NewNRGBA(image.Rect(0, 0, dx, dy))
  33:     for y := 0; y < dy; y++ {
  34:         for x := 0; x < dx; x++ {
  35:             v := data[y][x]
  36:             i := y*m.Stride + x*4
  37:             m.Pix[i] = v
  38:             m.Pix[i+1] = v
  39:             m.Pix[i+2] = 255
  40:             m.Pix[i+3] = 255
  41:         }
  42:     }
  43:     ShowImage(m)
  44: }
  45:  
  46: func ShowImage(m image.Image) {
  47:  
  48:     // 須要保存的文件
  49:     imgcounter := 1234
  50:     imgfile, _ := os.Create(fmt.Sprintf("%03d.png", imgcounter))
  51:     defer imgfile.Close()
  52:  
  53:     // 以PNG格式保存文件
  54:     err := png.Encode(imgfile, m)
  55:     if err != nil {
  56:         log.Fatal(err)
  57:     }
  58:  
  59: }

 

更復雜的算法

好比下面代碼實現了圖片簡單的上下左右翻轉的功能。

圖片旋轉的算法
https://github.com/mpl/goexif/blob/a588a5577cedfda71e3645f8137c38495f308f6c/exif/rotate_test.go

相關文章
相關標籤/搜索