안녕하세요. 개발자 모도리입니다.
The Go Programming Language 라는 책으로 Go를 공부하고 있으며, 해당 책의 내용을 요약 정리해서 올리려고 합니다. 저는 번역본을 구매해서 공부하고 있습니다.
// Lissajous는 임의의 리사주 형태의 애니메이션 GIF를 생성한다.
package main
import (
"image"
"image/color"
"image/gif"
"io"
"math"
"math/rand"
"os"
)
var palette = []color.Color{color.White, color.Black}
const (
whiteIndex = 0 // 팔레트의 첫 번째 색상
blackIndex = 1 // 팔레트의 다음 색상
)
func main() {
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) // NOTE: 인코딩 오류 무시
}
예제코드 [ch1/lissajous.go]
실행결과
$ go run ch1/lissajous.go > out.gif
out.gif 파일을 확인하면 아래와 같습니다.
image/color는 color를 참조하여 color.White 처럼 사용하고, image/gif는 gif를 참조하여 gif.GIF처럼 사용합니다.cycle, frame, delay 등의 수치형 파라미터는 컴파일 시 고정된 값을 갖습니다.[]color.Color{...} : 슬라이스gif.GIF{...} : 구조체anim 변수는 gif.GIF 타입의 구조체입니다.anim.Delay, anim.Image)
- 그 외 코드 설명
- 코드에 이중 루프가 존재합니다.
- 외부 루프는 64회의 반복에 걸쳐 매 반복 마다 애니메이션의 단일 프레임을 생성합니다.
- 이 루프는 흰색과 검은색 두 가지 색상의 팔레트로 새로운 201 x 201 이미지를 만듭니다.
- 모든 픽셀은 최초 흰색으로 지정한 팔레트의 제로 값으로 설정됩니다.
- 일부 픽셀을 검은색으로 설정해 새로운 이미지를 생성하고, 그 결과를 내장 함수
append를 통해서 지정된 80ms 지연과 함께 anim의 프레임 목록에 추가합니다.- 마지막으로 프레임과 지연의 시퀀스들은 GIF 포맷으로 인코딩되고 출력 스트림 out에 기록됩니다.
- out의 타입은 다양한 대상으로 출력할 수 있는
io.Writer입니다.- 내부 루프는 두 개의 진동자를 실행합니다.
- x 진동자는 사인 함수입니다. y 진동자도 사인 함수지만 주파수가 x 진동자의 진동수에 상대적인 0 ~ 3 사이의 임의의 수이고, x 진동자에 상대적인 위상차는 처음에는 0이지만 애니메이션의 각 프레임에 따라 증가합니다.
- 이 루프는 x 진동자가 다섯 번의 전체 주기를 완료할 때까지 실행됩니다.
- 각 단계에서
setColorIndex를 호출해 (x, y) 좌표의 픽셀을 팔레트 1번에 위치한 검은색으로 칠합니다.