dr9379 2019-04-27 11:47
浏览 129
已采纳

为什么Go的draw.DrawMask似乎忽略了我的黑白蒙版?

I'm attempting to render barcodes in Go with user-input colours for both the data and background, and although the barcodes themselves are produced as expected in black and white, attempting to use them as a mask image in "image/draw"'s draw.DrawMask function results in full pass-through of the source image, ignoring the mask entirely.

This is very much counter to the examples given in the Go blog post on the image/draw package.

I've reduced the problem down to a fairly minimal example, a simple white square on a black background as a mask with uniform colours as source and destination, and the behaviour continues. I'm clearly failing to understand some element of how this function behaves, but attempts at finding similar problems others have encountered all seem to end with a different approach to the problem entirely (eg another library to do the job), rather than understanding the mistake in the usage of draw.DrawMask.

The code I've posted includes a function for writing the three output images to BMP files, but this behaviour is repeated if any other method of saving the image.Image data to a file is used.

package main

import (
    "bytes"
    bmp "golang.org/x/image/bmp"
    "image"
    "image/color"
    "image/draw"
    "io/ioutil"
    "os"
)

func main() {
    //Use one rectange to make all new images
    bounds := image.Rect(0, 0, 100, 100)
    //Generate a 20px wide white square in the centre of a black background
    mask := image.NewNRGBA(bounds)
    draw.Draw(mask, bounds, image.NewUniform(color.Black), image.ZP, draw.Src)
    draw.Draw(mask, image.Rect(40, 40, 60, 60), image.NewUniform(color.White), image.ZP, draw.Src)
    //Generate a blue image of the right size - this is unnecessary, but shouldn't hurt
    blue := image.NewNRGBA(bounds)
    draw.Draw(blue, bounds, image.NewUniform(color.NRGBA{B: 255, A: 255}), image.ZP, draw.Src)
    //Copy the blue image into what is the desired output - also unnecessary, but will help to demonstrate each step is working independently
    result := image.NewNRGBA(bounds)
    draw.Draw(result, bounds, blue, image.ZP, draw.Src)
    //Use mask to draw green onto the blue - but only inside the 20px square (in theory)
    draw.DrawMask(result, bounds, image.NewUniform(color.NRGBA{G: 255, A: 255}), image.ZP, mask, image.ZP, draw.Over)

    writeImageToBMP(blue, "blue.bmp")
    writeImageToBMP(mask, "mask.bmp")
    writeImageToBMP(result, "result.bmp")
}

func writeImageToBMP(img image.Image, filename string) {
    //This part isn't relevant to the problem, I just don't know a better way to show content of an image
    var imgBytes bytes.Buffer
    bmp.Encode(&imgBytes, img)
    ioutil.WriteFile(filename, imgBytes.Bytes(), os.ModeExclusive)
}

I would expect the code above to produce three images:

  1. A blue square, 100px by 100px
  2. A black square, 100px by 100px, with a 20px by 20px white square in its centre
  3. A blue square, 100px by 100px with a 20px by 20px green square in its centre

The first two appear as expected, but the third is entirely green.

  • 写回答

1条回答 默认 最新

  • dtqqq24248 2019-04-27 12:22
    关注

    TLDR: The mask isn't supposed to be black and white, that's just how they rendered it for visual effect. The mask is supposed to be opaque where the Src should be used, and transparent where the Src should not be used.

    Replace the mask generation in my original code with the following and it all suddenly works as expected. (Replace Black with Transparent, replace White with Opaque):

    mask := image.NewNRGBA(bounds)
    draw.Draw(mask, bounds, image.NewUniform(color.Transparent), image.ZP, draw.Src)
    draw.Draw(mask, image.Rect(40, 40, 60, 60), image.NewUniform(color.Opaque), image.ZP, draw.Src)
    

    I spent a full day and a half banging my head against a wall, finally gave in and posted to SO for the first time, then immediately solved my own problem as soon as I stopped thinking about it, like an idiot.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 stm32开发clion时遇到的编译问题
  • ¥15 lna设计 源简并电感型共源放大器
  • ¥15 如何用Labview在myRIO上做LCD显示?(语言-开发语言)
  • ¥15 Vue3地图和异步函数使用
  • ¥15 C++ yoloV5改写遇到的问题
  • ¥20 win11修改中文用户名路径
  • ¥15 win2012磁盘空间不足,c盘正常,d盘无法写入
  • ¥15 用土力学知识进行土坡稳定性分析与挡土墙设计
  • ¥70 PlayWright在Java上连接CDP关联本地Chrome启动失败,貌似是Windows端口转发问题
  • ¥15 帮我写一个c++工程