# 蝈蝈俊的技术心得

posts - 507, comments - 196, trackbacks - 0, articles - 0

# 1、设置点的颜色一个简单例子：

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

# 2、划线

Golang 官方库没有提供划线的库，不过既然有了画点的方法，我们就可以根据一套算法画出点，下面的效果和代码是按照 Bresenham's line algorithm 算法画的线。

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

# 3、特殊图形

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