Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looking for better way to save an in memory image to file

Tags:

io

image

go

The goal of the code is to download an image, stick it to a larger parent image and save the result.

After quite a few failures I ended up with the following code that does work.

However, is there a better way than using bytes.Buffer and a writer to save the target image to a file / pass it to an httpResponse?

package main

import (
    "image"
    "image/draw"
    "image/jpeg"
    "os"
    // "image/color"
    // "io/ioutil"
    // "fmt"
    "bufio"
    "bytes"
    "log"
    "net/http"
)

func main() {
    // Fetch an image.
    resp, err := http.Get("http://katiebrookekennels.com/wp-content/uploads/2014/10/dog-bone4.jpg")
    if err != nil {
        log.Panic(err)
    }
    defer resp.Body.Close()

    // Keep an in memory copy.
    myImage, err := jpeg.Decode(resp.Body)

    if err != nil {
        log.Panic(err)
    }

    // Prepare parent image where we want to position child image.
    target := image.NewRGBA(image.Rect(0, 0, 800, 800))
    // Draw white layer.
    draw.Draw(target, target.Bounds(), image.White, image.ZP, draw.Src)
    // Draw child image.
    draw.Draw(target, myImage.Bounds(), myImage, image.Point{0, 0}, draw.Src)

    // Encode to jpeg.
    var imageBuf bytes.Buffer
    err = jpeg.Encode(&imageBuf, target, nil)

    if err != nil {
        log.Panic(err)
    }

    // Write to file.
    fo, err := os.Create("img.jpg")
    if err != nil {
        panic(err)
    }
    fw := bufio.NewWriter(fo)

    fw.Write(imageBuf.Bytes())
}
like image 398
coulix Avatar asked Oct 07 '16 23:10

coulix


1 Answers

jpeg.Encode() expects an io.Writer to write the encoded image to (in JPEG format). Both *os.File and http.ResponseWriter implement io.Writer too, so instead of a bytes.Buffer, you can directly pass a file or HTTP response writer too.

To save an image directly to a file:

f, err := os.Create("img.jpg")
if err != nil {
    panic(err)
}
defer f.Close()
if err = jpeg.Encode(f, target, nil); err != nil {
    log.Printf("failed to encode: %v", err)
}

To serve it as an image:

// w is of type http.ResponseWriter:
if err := jpeg.Encode(w, target, nil); err != nil {
    log.Printf("failed to encode: %v", err)
}

You can see some examples in these questions (saving/loading JPEG and PNG images):

Draw a rectangle in Golang?

How to add a simple text label to an image in Go?

Change color of a single pixel - Golang image

like image 80
icza Avatar answered Nov 14 '22 08:11

icza