goanimated-gif

Differences between console output stream and file stream for media


I encountered a problem while trying to render a GIF in Go. The output GIF file cannot be opened when following a certain method, but works fine with another approach. I found Rendering .gif in Go, but it doesn't address my specific issue.

Here is problematic code:

package main

import (
    "bufio"
    "fmt"
    "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() {
    w := bufio.NewWriter(os.Stdout)
    lissajous(w)
}

func lissajous(out io.Writer) {
    const (
        cycles  = 5
        res     = 0.001
        size    = 100
        nframes = 64
        delay   = 8
    )
    rand.Seed(time.Now().UTC().UnixNano())

    freq := rand.Float64() * 3.0
    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)
    }
    err := gif.EncodeAll(out, &anim)
    if err != nil {
        return
    } else {
        fmt.Println(err)
    }
}

Here are commands:

go build main.go
main > out.gif

Then, out.gif cannot be opened. However, this method works fine:

func main() {
    fileName := "out.gif"
    f, err3 := os.Create(fileName)
    if err3 != nil {
        fmt.Println("create file fail")
    }
    w := bufio.NewWriter(f) 
    lissajous(w)
    w.Flush()
    f.Close()

}

I'm puzzled about why the first approach fails to create a functional GIF file, while the second approach works. Does it have to do with the way Go handles file writing or buffering?


Solution

  • According to @CeriseLimón comment:

    Add w.Flush() to the end of main()

    func main() {
        w := bufio.NewWriter(os.Stdout)
        lissajous(w)
        w.Flush()
    }
    

    Explanation for the final question