本节将通过示例来介绍一下Go语言标准库中图像包的使用,并使用这些图像包来创建一系列的位图图像,然后将位图序列编码为 GIF 动画。
下面的图像叫作利萨茹图形,它类似于 20 世纪 60 年代科幻片中出现的一种纤维状视觉效果,利萨茹图形是由在互相垂直的方向上的两个频率成简单整数比的简谐振动所合成的规则的、稳定的曲线。
上图中所示的图像看似复杂,利用Go语言标准库中的图像包可以很轻松的实现,代码如下所示:
package main
import (
"image"
"image/color"
"image/gif"
"io"
"math"
"math/rand"
"os"
"time"
)
var palette = []color.Color{color.White, color.Black} //调色板
const (
whiteIndex = 0
blackIndex = 1
)
func main() {
rand.Seed(time.Now().UTC().UnixNano())
lissajous(os.Stdout)
}
func lissajous(out io.Writer) {
const (
cycles = 5 //完整的x振荡器变化的个数
res = 0.001 //角度分辨率
size = 100 //图像画布包含[-size. .+size]
nframes = 64 //动画中的帧数
delay = 8 //以10ms为单位的帧间延迟
)
freq := rand.Float64() * 3.0 //y 振荡器的相对频率
anim := gif.GIF{LoopCount: nframes}
phase := 0.0
for i := 0; i < nframes; i++ {
rect := image.Rect(0, 0, 2*size+1, 2*size+1)
img := image.NewPaletted(rect, palette)
for t := 0.0; t < cycles*2*math.Pi; t += res {
x := math.Sin(t)
y := math.Sin(t*freq + phase)
img.SetColorIndex(size+int(x*size+0.5), size+int(y*size+0.5), blackIndex)
}
phase += 0.1
anim.Delay = append(anim.Delay, delay)
anim.Image = append(anim.Image, img)
}
gif.EncodeAll(out, &anim)
}
其中,lissajous 函数内部包含两层嵌套的 for 循环,外层循环会循环 64 次,每一次都会生成一个单独的动画帧,即生成一个只有黑色和白色,且大小为 201*201 的图片。
而 lissajous 函数的内层循环则设置了两个偏振值 x 和 y,x 轴偏振使用 sin 函数,y 轴偏振也是正弦波,但其相对 x 轴的偏振是一个 0~3 的随机值。初始偏振值是一个零值,随着动画的每一帧逐渐增加,循环会一直跑到 x 轴完成五次完整的循环,每一步它都会调用 SetColorIndex 来把 (x, y) 点来染成黑色。
想要成功的生成 gif 图像需要我们先使用go build 命令将代码编译为可执行文件,然后在 CMD(命令行工具)中运行所生成的可执行文件,如下所示:
其中,>在这里用来指定生成图像的文件名,1.gif 为文件名。
执行成功后就可以在当前目录下找到生成的 gif 文件了,如下图所示: