0

I need a little hint. I'm creating thumbnails of images in Go and would like to pass them to jpegoptim for crushing.

jpegoptim has the --stdin and --stdout flags, which I would like to use. Now, I don't want to save the generated image to disk first, but convert my *image.RGBA to something that implements io.Reader, so I can pass it to exec.Cmd.Stdin

I'm a little lost on how I could achieve this, would be great if someone can point me in the right direction.

Thanks

tsdtsdtsd
  • 375
  • 4
  • 17
  • 2
    You need to encode the image into some format. If you want a jpeg, then look at the jpeg package: https://golang.org/pkg/image/jpeg/#Encode – JimB Oct 18 '17 at 15:07
  • Thanks @JimB So, for example, I encode to a bytes.Buffer and can use that directly as it also implements the io.Reader, right? – tsdtsdtsd Oct 18 '17 at 15:30

1 Answers1

3

In this case, you don't need to implement your own io.Reader. Use io.Pipe and jpeg.Encode, e.g.

func main() {
    //Prepare image ...
    img := ...

    //Prepare output (file etc.) ...
    outFile := ...

    //Use pipe to connect JPEG encoder output to cmd's STDIN
    pr, pw := io.Pipe()

    //Exec jpegoptim in goroutine
    done := make(chan bool, 1)
    go func() {
        //execute command
        cmdErr := bytes.Buffer{}
        cmd := exec.Command("jpegoptim", "--stdin", "--verbose")
        cmd.Stdin = pr       //image input from PIPE
        cmd.Stderr = &cmdErr //message
        cmd.Stdout = outFile //optimize image output

        if err := cmd.Run(); err != nil {
            // handle error
        }
        fmt.Printf("Result: %s\n", cmdErr.String())
        close(done)
    }()

    //ENCODE image to JPEG then write to PIPE
    o := jpeg.Options{Quality: 90}
    jpeg.Encode(pw, img, &o)

    //When done, close the PIPE
    if err := pw.Close(); err != nil {
        // handle error
    }

    //Wait for jpegoptim
    <-done
}
putu
  • 6,218
  • 1
  • 21
  • 30