英文:
Image glitch using golang's drawmask with draw.Over
问题
我正在使用golang重写一个最初用Python编写的脚本。我正在尝试重新创建的函数目前接受一张图片(一个彩色叠加层),并将其粘贴到一个相同大小的背景图(一张地图)上,透明度为50%。期望的输出如下所示,这是由我的Python脚本生成的:
我已经编写了以下的golang代码,试图用golang复制这个功能,参考了这个stackoverflow线程。
在main.go中:
// overlayImg是image.Image类型,包含彩色叠加层
overlayImg = lib.AddMap(overlayImg)
// lib.SaveToRecords是一个将image.Image overlayImg保存到指定路径(由字符串download.FileName指定)的函数
lib.SaveToRecords(overlayImg, download.FileName)
在myproject/lib包中:
func AddMap(i image.Image) image.Image{
// mapFile是背景地图图像
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
}
然而,生成的图像在彩色叠加层的某些部分出现了一种“glitch”。这种颜色故障在每次运行脚本时都能可靠地重现,即使使用不同的叠加层(地图当然保持不变)。
我该如何消除这个“glitch”?
我尝试过的方法:
- 在
draw.DrawMask
中使用draw.Draw
,并将draw.Over
作为“op”设置。结果是相同的颜色“glitch”,但没有透明度。
- 使用
draw.DrawMask
,但将“op”设置为draw.Src
。结果如下:
- 在
draw.Draw
中使用draw.DrawMask
,并将draw.Src
作为“op”设置。这是使用稍微不同的叠加层图像进行的尝试。结果如下:
更新
根据putu的评论,我尝试将mask := image.NewUniform(color.Alpha{128})
替换为mask := image.NewUniform(color.Alpha16{32767})
。故障仍然存在。此外,这个故障并不像我想象的那样一致,只有大约10%的时间会出现。似乎这个故障出现取决于粘贴到背景上的图像的内容。
更新2
最初,mapImg
的类型是image.NRGBA,i
和canvas
的类型是image.RGBA。再次根据评论中的建议,我将mapImg
转换为*image.RGBA以与其他部分匹配。为此,我使用了以下几行代码:
mapImg, _, err := image.Decode(mapFile)
mapImgRGBA := image.NewRGBA(mapImg.Bounds())
draw.Draw(mapImgRGBA, mapImgRGBA.Bounds(), mapImg, image.Point{0, 0}, draw.Src)
// 从这里开始使用mapImgRGBA替代mapImg
仍然无效:
英文:
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:
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).
How do I get rid of the 'glitch'?
Things I have tried:
- Using
draw.Draw
in place ofdraw.DrawMask
withdraw.Over
as the 'op' setting. Results in same colour 'glitch', but without transparency.
- Using
draw.DrawMask
, except withdraw.Src
as the 'op' setting. Result:
- Using
draw.Draw
in place ofdraw.DrawMask
, and withdraw.Src
as the 'op' setting. This was with a slightly different overlay image. Result:
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.
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:
答案1
得分: 2
感谢您在freenode的#go-nuts频道中使用noethics
请求查看原始叠加图层,我在处理每一行操作图像后生成输出时发现了问题。
问题不在于“image/draw”,而是在于我使用的一个外部库来调整叠加图层的尺寸,即“github.com/nfnt/resize”。
调整大小之前的叠加图层:
调整大小后的叠加图层(红色和黑色像素不理想):
更新
问题甚至不是由于“github.com/nfnt/resize”。我只是使用了错误的插值算法。事实证明,双线性插值对我正在处理的图像给出了最佳输出。我怀疑这也是我用来编写原始脚本的库中使用的插值算法。
英文:
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:
The overlay after resizing (red & black pixels undesirable):
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论