前一節講的是 繪圖到不一樣輸出源,請看地址: http://www.cnblogs.com/ghj1976/p/3440856.htmlhtml
上一節的例子效果是經過設置每個點的的RGBA屬性來實現的,這是最基礎的方式,經過這種方式咱們能夠繪製任意形狀的圖形。git
效果以下:github
代碼以下,跟最初咱們的代碼惟一不一樣的是設置點顏色時,多了一個條件判斷語句: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
下面演示代碼畫出來的效果圖以下:函數
注意,爲了便於看到效果, 圖的左右都畫了一條豎線,斜線是按照上面算法畫出來的。ui
相關代碼以下:
這裏的代碼借鑑了下面的代碼。
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: }
此次繪製出來的圖形效果以下:
相關代碼以下:
這裏的代碼借鑑了下面的代碼:
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