Search code examples
imagegopngtransparency

Golang, transparent background appears black once image is downloaded


At first I thought it was a mac issue because of dark mode, but no.

My software inserts a logo within an image.

Once the insertion is done, the image can be saved either as a png, jpeg or pdf. Even after applying a white background to the whole image, when downloading it as a png the logo has a black background surrounding it. Only from the PDF version, the logo is correctly displayed with a white background.

Here is the transformation:

func moveLogoPosition(mainImage, logo image.Image, poseX, poseY, width, size int, excavate bool) {
    const regularMainImageSize = 300

    m := resize.Resize(uint(75), 0, logo, resize.Bilinear)
    sr := m.Bounds()

    xOrigin := mainImage.Bounds().Size().X/2 - sr.Size().X/2
    yOrigin := mainImage.Bounds().Size().Y/2 - sr.Size().Y/2
    xFinal := xOrigin + sr.Bounds().Size().X
    yFinal := yOrigin + sr.Bounds().Size().Y

    r := image.Rectangle{
        Min: image.Point{X: xOrigin + poseX, Y: yOrigin + poseY},
        Max: image.Point{X: xFinal + poseX, Y: yFinal + poseY},
    }

    draw.Draw(mainImage.(*image.NRGBA), r, m, sr.Min, draw.Src)
}

I'm wondering if I am missing something, should I draw the background white? I'm quite unsure how to do that to be honest.

On the other hand, the main image has no issue with transparency!

I'm joining an example of a current result (as a png)

enter image description here


Solution

  • Alright, so if you try to let transparency behave by itself you'll encounter too many issues depending on the OS, the quality of the PNG etc.

    Thus we force draw transparent pixels to white (in our case) to make sure that: not only the "non excavated transparent" parts are correctly displayed as white, but also to make sure that if the logo / image where to be opened with illustrator or else, the "transparency" now white is correctly supported.

    Here is what I added:

    white := color.RGBA{255, 255, 255, 255}
    draw.Draw(mainImage, r, &image.Uniform{C: white}, image.Point{}, draw.Src)
    draw.Draw(mainImage, r, m, sr.Min, draw.Over)
    

    I don't know if that will ever help anyone, but that's the only alternative I found with Go.