[The Go Programming Language] 1장 튜토리얼 - 1.4 애니메이션 GIF

in #kr-dev6 years ago

modolee_logo
안녕하세요. 개발자 모도리입니다.
The Go Programming Language 라는 책으로 Go를 공부하고 있으며, 해당 책의 내용을 요약 정리해서 올리려고 합니다. 저는 번역본을 구매해서 공부하고 있습니다.

지난 게시물


1장 튜토리얼

1.4 애니메이션 GIF

// 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 파일을 확인하면 아래와 같습니다.
out.gif

  • 경로에 여러 구성 요소가 포함된 패키지 (line 6, 7)
    • image/colorcolor를 참조하여 color.White 처럼 사용하고, image/gifgif를 참조하여 gif.GIF처럼 사용합니다.
  • const 선언 (line 16, 26)
    • import 와 마찬가지로 단독으로 선언도 가능하고 목록 형태로 선언도 가능합니다.
    • 상수에 이름을 붙이며, cycle, frame, delay 등의 수치형 파라미터는 컴파일 시 고정된 값을 갖습니다.
    • const 선언은 var 선언처럼 패키지 수준(line 16)에서, 또는 함수 내( line 26)에서 사용할 수 있습니다.
    • 상수의 값은 숫자, 문자열, 불리언 이어야 합니다.
  • 복합 리터럴 (line 14, 34)
    • Go의 복합 타입을 원소 값의 나열로 초기화하는 간결한 표기법입니다.
    • []color.Color{...} : 슬라이스
    • gif.GIF{...} : 구조체
  • 구조체 타입 (line 34, line 45)
    • 구조체는 필드라고 불리는 값의 그룹이며, 보통 서로 다른 타입들을 하나의 객체로 묶어 단일 객체로 취급할 수 있습니다.
    • anim 변수는 gif.GIF 타입의 구조체입니다.
    • 이 구조체 리터럴은 LoopCount 필드의 값이 nframes로 설정 된 구조체 값을 생성합니다.
    • 구조체의 개별 필드는 명시적으로 점 표기법으로 사용할 수 있습니다. (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번에 위치한 검은색으로 칠합니다.

Coin Marketplace

STEEM 0.29
TRX 0.11
JST 0.031
BTC 68493.85
ETH 3838.65
USDT 1.00
SBD 3.64