1

I am rewriting with golang a script I originally wrote in python. The function I am trying to recreate currently takes one image (a coloured overlay) and pastes it on a background (a map) of the same size, with 50% transparency. The desired output, as produced by my python script, is:

Desired Output with Python

The golang code I have written to try to replicate this in golang, with reference to this stackoverflow thread.

In main.go

// overlayImg is type image.Image, consists of the coloured overlay
overlayImg = lib.AddMap(overlayImg)
// lib.SaveToRecords is a function that saves image.Image overlayImg to path specified by string download.FileName
lib.SaveToRecords(overlayImg, download.FileName)

In package myproject/lib

func AddMap(i image.Image) image.Image{
    // mapFile is the background map image
    mapFile, err := os.Open("./res/map.png")
    if err != nil { panic(err) }
    mapImg, _, err := image.Decode(mapFile)
    if err != nil { panic(err) }
    mask := image.NewUniform(color.Alpha{128})

    canvas := image.NewRGBA(mapImg.Bounds())
    draw.Draw(canvas, canvas.Bounds(), mapImg, image.Point{0, 0}, draw.Src)

    draw.DrawMask(canvas, canvas.Bounds(), i, image.Point{0, 0}, mask, image.Point{0, 0}, draw.Over)

    return canvas
}

However, the resulting image is produced with a sort of 'glitch' in parts of the coloured overlay. This colour glitch is reliably reproduced on each run of the script, even with different overlays (the map stays the same throughout, of course).

Output with Golang

How do I get rid of the 'glitch'?


Things I have tried:

  • Using draw.Draw in place of draw.DrawMask with draw.Over as the 'op' setting. Results in same colour 'glitch', but without transparency.

draw.Draw with draw.Over

  • Using draw.DrawMask, except with draw.Src as the 'op' setting. Result:

draw.DrawMask with draw.Src

  • Using draw.Draw in place of draw.DrawMask, and with draw.Src as the 'op' setting. This was with a slightly different overlay image. Result:

draw.Draw with draw.Src


Update

I've tried assigning mask := image.NewUniform(color.Alpha16{32767}) in place of mask := image.NewUniform(color.Alpha{128}) according to putu's comment. Glitch still appears. Additionally, this glitch is not as consistent as I thought, showing up at only roughly 10% of the time. It seems the glitch shows up depending on the content of the image pasted unto the background.

drawMask with draw.Over and Alpha16


Update 2

Originally, mapImg was of type *image.NRGBA, i and canvas of type *image.RGBA. Once again following the advice in the comments, I converted mapImg to type *image.RGBA to match with the rest. To do this, I used the following few lines of code:

mapImg, _, err := image.Decode(mapFile)
mapImgRGBA := image.NewRGBA(mapImg.Bounds())
draw.Draw(mapImgRGBA, mapImgRGBA.Bounds(), mapImg, image.Point{0, 0}, draw.Src)
// Use mapImgRGBA in place of mapImg from here

Still don't work:

Converting mapImg to RGBA

Community
  • 1
  • 1
ning
  • 1,823
  • 1
  • 19
  • 25
  • 1
    How if you change the `color.Alpha{128}` to `color.Alpha16{32767}`? – putu May 14 '17 at 03:35
  • @putu Hi, thanks for your suggestion! I'll have to confirm with you again if it works, because right now both `color.Alpha{128}` and `color.Alpha16{32767}` is giving me what I want. It seems the glitch here is less reproducible than I thought... I'll update you if I can get it to glitch again. – ning May 14 '17 at 04:03
  • 1
    Maybe glitch occurs when the image you're going to paste to the background has different `bpp` with the mask, e.g. 16-bit vs 8-bit (color.Alpha), 8-bit vs 16-bit (color.Alpha16) etc. Now let use `color.Alpha` as the mask. Print the image type you're going to paste onto the background (`i` in `AddImage`) and observe what was the image type when glitch occurs. In addition, you may also need to print the type of decoded image (i.e. map). – putu May 14 '17 at 04:44
  • @putu Hi, I've converted all images to image.RGBA. Still doesn't work (I've updated my post with the details). – ning May 14 '17 at 11:48
  • 1
    @putu Thanks for your help so far. Turns out it was because I was using the wrong interpolation setting in resizing the overlay. – ning May 15 '17 at 04:18

1 Answers1

2

Thanks to use noethics in the freenode #go-nuts channel for requesting a look at the original overlay, I found the issue while generating the output after each line that manipulates the image.

The issue is not with "image/draw", but with an external library I'm using to resize the overlay to the dimensions of the map, "github.com/nfnt/resize".

The overlay before resizing:

Original image

The overlay after resizing (red & black pixels undesirable):

return resize.Resize(1491, 836, i, resize.Lanczos3)


Update

It's not even an issue with "github.com/nfnt/resize". I was simply using the wrong interpolation algorithm. Turns out bilinear gives me the best output for the image I am working with. I suspect it's also the one used in the library I used to write my original script in.

interpolationComparison

ning
  • 1,823
  • 1
  • 19
  • 25