天天看點

010-lissajous(二)

lissajous 曲線随着參數的不同,曲線的形狀也會随之改變。如果每次修改一下參數再生成一張圖檔,未免也太麻煩了。這一次,我們希望生成一個動态圖(GIF,Graphics Interchange Format).

前面我已經學會了将 in-memory 圖像編碼成某種格式(png, jpeg)的方法,如果要将 in-memory 編碼成 gif,那就使用 gif 編碼器就好了。同樣的,gif 也會有相應的 ​

​Encode​

​​ 方法。不過,動态圖的一個特點是它是由很多很多的幀表示,每一幀都是一幀圖像。gif 也提供了一個 ​

​EncodeAll​

​ 圖像,用于将多個 in-memory 編碼成 gif.

1. gif 編碼

gif 包的 ​

​EncodeAll​

​ 定義如下:

func EncodeAll(w io.Writer, g *GIF) error      

其中 GIF 定義是這樣的:

type GIF struct {
    Image     []*image.Paletted // in-memory 的 slice
    Delay     []int // 目前幀延時,機關是 10ms
    LoopCount int // 循環次數
    // ..      

可以看到 GIF 這個『結構體』(暫且這麼稱呼它)裡有一個成員是 Image 『數組』。這就好辦了,隻要我們生成所有不同參數下的 in-memory 圖像再塞到這個『數組』就 ok。(注意,這裡我盡量避免使用 slice 這個類型,說數組你會更容易了解。實際上在 go 裡數組和 slice 是兩種不同的東西)

2. 程式

這個程式的路徑是 ​

​gopl/tutorial/image/lissajous/lissajous2.go​

  • 代碼
// lissajous2.go
package main

import (
    "image"
    "image/color"
    "image/gif"
    "math"
    "os"
)

const (
    size    = 128
    nframes = 100
)

func main() {
    p := 1.0
    q := 2.0
    phi := 0.0

    palett := []color.Color{color.RGBA{0xee, 0xee, 0xee, 0xff}, color.RGBA{0xff, 0, 0, 0xff}}
    rec := image.Rect(0, 0, 2*size, 2*size)

    s := float64(size - 10)

    step := 0.01
    // 生成 100 幀
    anim := gif.GIF{LoopCount: 1}
    for frames := 0; frames < nframes; frames++ {
        img := image.NewPaletted(rec, palett)
        for t := -2 * math.Pi; t <= 2*math.Pi; t += 0.0001 {
            x := math.Sin(p * t)
            y := math.Sin(q*t + phi)
            img.SetColorIndex(size+int(s*x+0.5), size+int(s*y+0.5), 1)
        }
        anim.Image = append(anim.Image, img)
        anim.Delay = append(anim.Delay, 10)
        // 每一幀 q 遞增 0.01,這裡相當于 q/p 以 0.01 步長遞增
        p += step
    }

    gif.EncodeAll(os.Stdout, &anim)
}      
  • 運作
$ go run lissajous2.go      
010-lissajous(二)

圖1

pq=[0.01:0.01:1]

p

q

=

[

0.01

:

0.01

:

1

]

圖 1 所示的動态圖,初始值 p=0.01,q=1

p

=

0.01

,

q

=

1

,每一幀的 p 值增幅是 0.01,也就是說 pq

p

q

  • append 函數

append 函數是 go 的内建函數,用于給 slice 追加元素。定義如下:

func append(slice []Type, elems ...Type) []Type      

3. 總結

  • 掌握動态圖生成方法
  • 掌握 append 函數
  1. 嘗試不同的相位(​

    ​phi​

    ​ 變量)