Golang how to concatenate/append images to one another

Viewed 11725

Go has great image manipulation and data libraries however I'm having trouble creating one big image from smaller ones. Does anyone know how to take two png or jpeg files in Golang and concatenate them to form one big image that encompasses the two (or more) files?

i'm currently reading png files like so:

imgFile, err := os.Open(path)
if err != nil {
    return Image{}, err
}
img, _, err := image.Decode(imgFile)
if err != nil {
    return Image{}, err
}

rgba := image.NewRGBA(img.Bounds())
if rgba.Stride != rgba.Rect.Size().X*4 {
    return Image{}, fmt.Errorf("unsupported stride")
}
draw.Draw(rgba, rgba.Bounds(), img, image.Point{0, 0}, draw.Src)

I'm confused on how to take this png RGBA data and concatenate with other RGBA data and/or combine that into an "empty" image.

4 Answers

I built a library exactly for this purpose.

You can use it as follows;

import gim "github.com/ozankasikci/go-image-merge"

grids := []*gim.Grid{
    {ImageFilePath: "test1.jpg"},
    {ImageFilePath: "test2.png"},
}

// merge the images into a 2x1 grid
rgba, err := gim.New(grids, 2, 1).Merge()

// save the output to jpg or png
file, err := os.Create("file/path.jpg|png")
err = jpeg.Encode(file, rgba, &jpeg.Options{Quality: 80})

https://github.com/ozankasikci/go-image-merge

Resize images and concat them.

import (
    "fmt"
    "github.com/nfnt/resize"
    "image"
    "image/draw"
)

/**
w: resize weight
h: resize height
v: concat dim
images: list
*/
func Concat(w uint, h uint, v bool, images ...image.Image) *image.RGBA {

    var acc uint = 0
    if w == 0 {
        v = false
    } else if h == 0 {
        v = true
    }

    for i, img := range images {
        rimg := resize.Resize(w, h, img, resize.Bilinear)
        if v { // vertical concat, accumulate height
            acc += uint(rimg.Bounds().Dy())
        } else {
            acc += uint(rimg.Bounds().Dx())
        }
        images[i] = rimg
    }

    if v {
        h = acc
    } else {
        w = acc
    }

    r := image.Rectangle{image.Point{0, 0}, image.Point{int(w), int(h)}}
    rgba := image.NewRGBA(r)

    dx := 0
    dy := 0

    for _, img := range images {

        rec := img.Bounds()
        draw.Draw(rgba, image.Rect(dx, dy, dx+rec.Dx(), dy+rec.Dy()), img, image.Point{0, 0}, draw.Src)
        fmt.Println(image.Point{dx, dy})
        if v {
            dy += img.Bounds().Dy()
        } else {
            dx += img.Bounds().Dx()
        }
    }

    return rgba
}
Related