Golang 绘图基础 -绘制简单图形
前一节讲的是 绘图到不同输出源,请看地址: http://www.cnblogs.com/ghj1976/p/3440856.html
上一节的例子效果是通过设置每一个点的的RGBA属性来实现的,这是最基础的方式,通过这种方式我们可以绘制任意形状的图形。
1、设置点的颜色一个简单例子:
效果如下:

代码如下,跟最初我们的代码唯一不同的是设置点颜色时,多了一个条件判断语句: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: }
2、划线
Golang 官方库没有提供划线的库,不过既然有了画点的方法,我们就可以根据一套算法画出点,下面的效果和代码是按照 Bresenham's line algorithm 算法画的线。
http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
这个算法画的线简单可以用下面图来标示:

下面演示代码画出来的效果图如下:
注意,为了便于看到效果, 图的左右都画了一条竖线,斜线是按照上面算法画出来的。

相关代码如下:
这里的代码借鉴了下面的代码。
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: }
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: }
更复杂的算法
比如下面代码实现了图片简单的上下左右翻转的功能。
图片旋转的算法
https://github.com/mpl/goexif/blob/a588a5577cedfda71e3645f8137c38495f308f6c/exif/rotate_test.go
Golang 绘图基础 -绘制简单图形的更多相关文章
- 学习笔记:HTML5 Canvas绘制简单图形
HTML5 Canvas绘制简单图形 1.添加Canvas标签,添加id供js操作. <canvas id="mycanvas" height="700" ...
- Java入门:绘制简单图形
在上一节,我们学习了如何使用swing和awt工具创建一个空的窗口,本节学习如何绘制简单图形. 基本绘图介绍 Java中绘制基本图形,可以使用Java类库中的Graphics类,此类位于java.aw ...
- CSS绘制简单图形
究竟该用字体图标.图片图标.还是CSS画一个图标?我也不知道.各有千秋吧.本文将介绍如何用css绘制简单的图形,所有测试在chrome58.0完成,如果你不能得到正确结果请到caniuse查一查看看是 ...
- Windows控制台下绘制简单图形
最近接触到一个很有意思的问题,如何在Windows控制台下画图,翻遍了C的头文件也没找到画图的函数,好吧,那就用Windows提供的API函数吧,看来想移植是没戏了.先画一个简单的图,类似心电图那种吧 ...
- 利用 turtle库绘制简单图形
turtle库是python的基础绘图库,这个库被介绍为一个最常用的用来介绍编程知识的方法库,其主要是用于程序设计入门,是标准库之一,利用turtle可以制作很多复杂的绘图. turtle名称含义为“ ...
- iOS:quartz2D绘图(绘制渐变图形)
quartzD可以用来绘制渐变图形,即图形向外或向内发散,会变得越来越模糊. 渐变分为线性渐变和径向渐变,所谓线性渐变,就是图形以线的方式发散,发散后一般呈现出矩形的样子:而径向渐变,就是以半径的大小 ...
- shape-自绘制简单图形
shape 可以绘制简单的图形,颜色等.它主要就是应用于selector 的一些状态. 本文内容参考自http://www.cnblogs.com/cyanfei/archive/2012/07/27 ...
- 在高德地图上用svg.js绘制简单图形
这段时间做的一个项目,需要在地图上绘制简单的图形.在学习高德地图JS API的过程中,发现高德地图提供的点.线等API并不能满足我的需求,还好它开放了自定义图层CustomLayer,官方说自定义图层 ...
- 利用Microsoft VC++6.0 的MFC 的绘图工具实现简单图形的绘制
MFC运算功能强大,拥有完备的绘图功能. 在Windows平台上,应用程序的图形设备接口(graphics device interface,GDI)被抽象为设备上下文(Dev ...
随机推荐
- outlook圆角table
<table cellpadding="0" cellspacing="0" border="0" width="800&q ...
- iOS 动态特性和RunTime
过去的几年中涌现了大量的Objective-C开发者.有些是从动态语言转过来的,比如Ruby或Python,有些是从强类型语言转过来的,如Java或C#,当然也有直接以Objective-C作为入门语 ...
- JVM垃圾回收机制总结(5) :JDK垃圾收集器的配置命令
以下配置主要针对分代垃圾回收算法而言. 堆大小设置 年轻代的设置很关键 JVM中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制:系统的可用虚拟内存限制:系统的可用物理 ...
- 276. Paint Fence
题目: There is a fence with n posts, each post can be painted with one of the k colors. You have to pa ...
- MyBatis学习总结_16_Mybatis使用的几个建议
1.Mapper层参数为Map,由Service层负责重载. Mapper由于机制的问题,不能重载,参数一般设置成Map,但这样会使参数变得模糊,如果想要使代码变得清晰,可以通过service层来实现 ...
- 使用shell查看局域网中主机的IP地址
此脚本只是快速查看所在局域网中其它主机的IP地址,如果对方设置了禁ping,则无法显示出此主机的IP地址: #!/bin/bash ` do ping -c2 .$i &>/dev/nu ...
- URAL 1066 Garland 二分
二分H2的位置,判断条件为是否有Hi < 0 #include <cstdio> #include <cstring> #include <cstdlib> ...
- 【Tech】Ganglia安装配置
基础配置: Hadoop 2.2.0,Hbase 0.96. 四台集群机器,一台master,三台slave. 三台slave上分别装gmond:namenode机器上设置datasource. 客户 ...
- SQLite学习手册(内置函数)
一.聚合函数: SQLite中支持的聚合函数在很多其他的关系型数据库中也同样支持,因此我们这里将只是给出每个聚集函数的简要说明,而不在给出更多的示例了.这里还需要进一步说明的是,对于所有聚合函数而言, ...
- django-based blog- mezzanine
django-based blog- mezzanine zinnia 博客 hydra 暴力破解