image - 透明像素颜色-Go lang图像

标签 image go transparency

我正在尝试根据眼动仪结果创建热图(显示用户在屏幕上最常注视的位置)。

对于用户经常注视的像素,我想设置不透明的红色,设置不那么频繁的橙色等。 我正在使用红色到绿色的色标。 但是对于频率最低的像素,我希望它们不仅显示绿色,还希望它们是透明的。

imgfile, err := os.Open("unchanged.jpeg")
defer imgfile.Close()
if err != nil {
    fmt.Println(err.Error())
}

decodedImg, err := jpeg.Decode(imgfile)
img := image.NewRGBA(decodedImg.Bounds())

size := img.Bounds().Size()
for x := 0; x < size.X; x++ {
    for y := 0; y < size.Y; y++ {
        img.Set(x, y, decodedImg.At(x, y))
    }
}

// I change some pixels here with img.Set(...)

outFile, _ := os.Create("changed.png")
defer outFile.Close()
png.Encode(outFile, img)

问题是,当我尝试使用 img.Set(x, y, color.RGBA{85, 165, 34, 50}) 更改颜色时,它实际上并没有变色像素作为取决于新旧颜色的平均值,它只是显示一些新的、看起来很奇怪的颜色。

alpha RGBA 值设置为 50 的图像:(透明)

enter image description here

alpha RGBA 值设置为 255 的图像:(不透明)

enter image description here

据我所知,我正在使用支持透明度的 png 图像。 为什么会这样?有什么想法可以解决这个问题并使最不常见的像素看起来透明吗?

感谢您的每一个回答。

最佳答案

这是因为 Set() 方法设置(覆盖)指定位置像素的颜色。这不是您想要的。

您想将像素的原始颜色与您选择的颜色相结合,并且希望这是最终颜色。

为此,首先您可以使用 Image.At() 查询原始颜色,然后将颜色与您想要的任何颜色组合(您可以通过红色、绿色、蓝色和alpha channel ),并使用 Set() 方法设置最终颜色。

合并:

请注意,color.RGBARGBA 字段struct 是 alpha 预乘值,这意味着例如 R 字段包含颜色的红色分量乘以 alpha channel 的值。

您可以使用 RGBA.RGBA()方法将所有字段作为 uint32 值返回,所有字段都在 0..0xffff 范围内,因此您可以对它们进行操作而不必担心溢出( uint8 的最大值为 255,因此即使添加 2 个也很容易溢出)。

因此,当您组合 2 种颜色时,您可以按成分组合。但是请注意,color.RGBA中这些字段的类型是uint8,所以合并后你必须将结果转换为8位,所以你必须右移8.

一个非常简单的组合:计算平均值:

// Query:
x, y := 1, 1
r, g, b, a := img.At(x, y).RGBA()

// Combine:
col := color.RGBA{85, 165, 34, 50}
r2, g2, b2, a2 := col.RGBA()

col.R = uint8((r + r2) >> 9) // div by 2 followed by ">> 8"  is ">> 9"
col.G = uint8((g + g2) >> 9)
col.B = uint8((b + b2) >> 9)
col.A = uint8((a + a2) >> 9)

// Set new pixel:
img.Set(x, y, col)

您可以将其合并到辅助函数中:

func combine(c1, c2 color.Color) color.Color {
    r, g, b, a := c1.RGBA()
    r2, g2, b2, a2 := c2.RGBA()

    return color.RGBA{
        uint8((r + r2) >> 9), // div by 2 followed by ">> 8"  is ">> 9"
        uint8((g + g2) >> 9),
        uint8((b + b2) >> 9),
        uint8((a + a2) >> 9),
    }
}

并使用它:

x, y := 1, 1
img.Set(x, y, combine(img.At(x, y), color.RGBA{85, 165, 34, 50}))

请查看Alpha compositing如果您需要逼真的色彩合成,请查看页面。

关于image - 透明像素颜色-Go lang图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36595687/

相关文章:

java - BufferedImage 的透明区域写出黑色

image - 如何使用 HAML 将图像添加到内容中?

go - 使用反射访问结构中的结构字段

html - 视频作为背景完全覆盖半透明背景颜色

php - 在 Laravel 中提供 PHP 图像资源作为响应

go - 如何在 Gin 中提供静态文件

json - 去测试 map 之间的区别

css - 只使用 CSS,我可以只使用 PNG 的 alpha channel 吗?

css - 应用于文本的透明线性渐变 - Safari 中的错误

html - 需要帮助将图像添加到响应式布局