Reputation: 562
I am trying to merge an array of N images (where N will be a dynamic value) with Go, but I always get a black image as result.
Here you are my code:
package main
import (
"image"
"image/draw"
"image/jpeg"
"image/png"
"log"
"os"
)
func openAndDecode(imgPath string) image.Image {
img, err := os.Open(imgPath)
if err != nil {
log.Fatalf("Failed to open %s", err)
}
decoded, err := png.Decode(img)
if err != nil {
log.Fatalf("Failed to decode %s", err)
}
defer img.Close()
return decoded
}
func main () {
var images = [4]string{"background", "shadow", "item1 ", "item2"}
var decodedImages = [4]*image.RGBA{}
for i, img := range images {
decodedImage := openAndDecode("./imgs/" + img + ".png")
bounds := decodedImage.Bounds()
newImg := image.NewRGBA(bounds)
decodedImages[i] = newImg
}
bounds := decodedImages[0].Bounds()
newImage := image.NewRGBA(bounds)
for _, img := range decodedImages {
draw.Draw(newImage, img.Bounds(), img, image.ZP, draw.Src)
}
result, err := os.Create("result.jpg")
if err != nil {
log.Fatalf("Failed to create: %s", err)
}
jpeg.Encode(result, newImage, &jpeg.Options{jpeg.DefaultQuality})
defer result.Close()
}
I am pretty new to Go and I can't find out where I am wrong.
Upvotes: 2
Views: 2521
Reputation: 417612
In your first loop where you load the images, you also create a new, empty image and you store this empty image in decodedImages
. And then you iterate over these empty images and combine them.
Instead you should store the loaded images in decodedImages
:
for i, img := range images {
decodedImages[i] = openAndDecode("./imgs/" + img + ".png")
}
For this to work, declare decodedImages
to be a slice of image.Image
(since openAndDecode()
returns a value of type image.Image
):
var decodedImages = make([]image.Image, len(images))
Also, whenever you open a file and check the error, you should defer close it right after so if subsequent code fails, the file would still get closed.
Also to "combine" images with an alpha channel, you should use draw.Over
operator. Quoting from the blog post: The Go Blog: The Go image/draw package:
The
Over
operator performs the natural layering of a source image over a destination image: the change to the destination image is smaller where the source (after masking) is more transparent (that is, has lower alpha). TheSrc
operator merely copies the source (after masking) with no regard for the destination image's original content. For fully opaque source and mask images, the two operators produce the same output, but theSrc
operator is usually faster.
Upvotes: 5