007-绘制三角函数图像(一)
本篇需要带你复习一下三角函数知识。不用太多,只要你知道 是什么样子就行了。什么?忘记长啥样了?看下面。
图1 图像
我们的目标是,使用 go 语言生成一幅 的曲线图像出来, jpeg
或者 png
随便你。下面是使用 go 生成图像的一个例子。
图2 使用 go 生成的
png
图像 虽然有点丑,但是美化的目标就交给你了。
1. 基础知识
1.1 相关的包介绍
主要使用的包有这三类
-
image
,在内存里创建图像会用到这个包的相关函数。 -
image/color
,和颜色相关的函数都在这里。 -
image/png
,将内存里的图像编码png
文件。
类似 png
的包还有 image/jpeg
,image/gif
这些包,它们的功能都是将内存里的像素信息编码成具体某种格式的图片。
1.2 相关的概念
- 彩色图像
彩色图像是一个矩形,由一行一行的像素点组成,每个像素点有自己的颜色。这些颜色的类型可以是 RGBA 类型,也可以是 CMYK 类型。本文只介绍 RGBA 类型。
RGBA 是 Red-Green-Blue-Alpha 的首字母缩写,使用 R, G, B 就可以控制像素的颜色,使用 A 可以控制像素的透明度。
绘制图像的基本原理就是给矩形中每个像素设置一个颜色。
- in-memory image
在内存中的图像,是指还没有被编码成具体格式的图像数据。只要有了 in-memory image,我们就可以将其编码成任意格式的图像。我们可以把 in-memory image 看成是图 3 里的样子,从左到右是 轴,从上到下是 轴,左上角坐标是 。
图3 in-memory image
在 go 语言中,in-memory image 有很多种,但是他们都需要实现 image.Image 接口。接口的概念我们还没有正式学过,这里暂且认为它是某个抽象类,定义了以下几个方法:
type Image interface {
ColorModel() color.Model
Bounds() Rectangle
At(x, y int) color.Color
}
1.3 编码成具体格式的图像
只要有了 in-memory image,我们就可以使用某种编码器,比如 jpeg
来将其编码成 jpeg
的 2 进制图像数据,然后保存到本地。
jpeg.Encode(file, in-memory image)
2. 程序
2.1 原理
绘制部分的主要原理就是给 in-memory image 里的像素填颜色。就好比图像 3 里那样,要想绘制图三角函数图像,就需要在图 3 里找到正确的像素小方格,填充好颜色。
难点在于,要给哪些像素点填充颜色?这里,我们不妨就假设 轴就是图3 里的 x 轴,但是 轴方向和我们在数学课上学到的是反的,其实这无关紧要。
假设图像是个正方形,其边长是 个像素,则需要绘制的坐标点应该像下面这个参数公式(使用参数 来控制 和 )
上面的公式你完全可以改造, 坐标加上 size 的原因是希望图像不要太靠上方了,应该尽量位于中心,当然你可以不加这个值,再尝试输出图像看看。 乘以 100 是为了让三解函数这幅值变化更大一点,这样显的不是那么扁。这些参数你都可以任意更改,这也算是一个作业。
2.2 实现
创建的文件名字叫 sin1.go
. 文件路径是 gopl/tutorial/image/rgba/sin1.go
// sin1.go
package main
import (
"fmt"
"image"
"image/color"
"image/png"
"math"
"os"
)
const (
size = 128 // 常量
)
func main() {
rec := image.Rect(0, 0, 2*size, 2*size) // 创建矩形画布
image := image.NewRGBA(rec) // 返回一个 in-memory image
c := color.RGBA{0xff, 0, 0, 0xff} // 定义一个红色值
// 下面两个 for 循环是把 in-memory 中所有的像素初始化为灰色 #eeeeee
for x := 0; x < 2*size; x++ {
for y := 0; y < 2*size; y++ {
image.Set(x, y, color.RGBA{0xee, 0xee, 0xee, 0xff})
}
}
// 绘制 sin 函数曲线
for t := 0.0; t < 2*math.Pi; t += 0.001 {
x := int(2.0*size*t/(2.0*math.Pi) + 0.5) // 加 0.5 是为了4舍5入
y := int(size + 100*math.Sin(t) + 0.5)
image.Set(x, 2*size-y, c) // 给对应的像素位置设置颜色值
}
// 将 in-memory image 编码成 png 格式数据,并写入标准输出。
err := png.Encode(os.Stdout, image)
if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
}
}
2.3 运行
$ go run sin1.go > a.png
这样就生成了一幅三角函数图像啦。
2.4 分析
- 常量
在 go 里,常量使用 const 关键字声明,且只能是数字、字符串和布尔值。在上面的程序里,我们声明了一个 size 常量,它在需要的时候,可以转换成 int 类型,也可以转换成 float64 类型。具体转换成什么类型,就看它怎么使用了。
关于常量,后面还会详细介绍。
color.RGBA
这种类型有点像我们在 c/c++ 里学习的结构体,在 go 里它被称之为复合类型。在我们程序里,我们使用 color.RGBA{...}
初始化一个颜色值,这是复合类型初始化的一种方法。关于复合类型,后续还会介绍。
3. 总结
- 了解 go 语言更多的语法结构
- 了解 go 语言强大的包支持,知道 go 语言可以非常方便的做很多事情
练习:
1. 通过命令行参数来控制三角函数曲线的『频率,幅值和相位』。
2. 更改曲线的颜色。
3. 编码成 jpeg 图片。
上一篇: 数据库MySQL的常用命令
下一篇: iOS 自定义底部弹出视图