为什么 Golang 的 `png.Encode` 方法会导致颜色数据错误?

huangapple go评论84阅读模式
英文:

Why Golang `png.Encode` method makes color data wrong?

问题

在Golang中,当像素值包含alpha值时,会导致颜色值发生变化。而我在Python中尝试了相同的代码,没有问题!

以下是Golang脚本的翻译:

newRgba := image.NewRGBA(image.Rect(0, 0, 1, 1)) //新建图像
newRgba.SetRGBA(0, 0, color.RGBA{R: 55, G: 23, B: 14, A: 122}) //设置像素值
f, _ := os.Create("./save.png")
defer f.Close()
//保存图像
png.Encode(f, newRgba)

ff, _ := ioutil.ReadFile("./save.png") //读取图像
bbb := bytes.NewBuffer(ff)
m, _, _ := image.Decode(bbb)
R, G, B, A := m.At(0, 0).RGBA()
fmt.Println(R>>8,
    G>>8,
    B>>8,
    A>>8,
) //获取{55 23 13 122},这是错误的!为什么不是{55 23 14 122}?

以下是Python脚本的翻译:

from PIL import Image
img = Image.new('RGBA', (1, 1), (55, 23, 14,122)) #设置像素值
img.save('bg.png')

im = Image.open('bg.png')
pix = im.load()

print(pix[0,0])  #获取(55, 23, 14, 122)

为什么在Golang中得到的结果会改变呢?

英文:

In Golang, when the pixel value carries the alpha value, it will cause the color value to change. And I try same code in python. No problem!

This is Golang script:

newRgba := image.NewRGBA(image.Rect(0, 0, 1, 1)) //new image
newRgba.SetRGBA(0, 0, color.RGBA{R: 55, G: 23, B: 14, A: 122}) // set pixel value
f, _ := os.Create("./save.png")
defer f.Close()
// save image
png.Encode(f, newRgba)


ff, _ := ioutil.ReadFile("./save.png") //read image
bbb := bytes.NewBuffer(ff)
m, _, _ := image.Decode(bbb)
R, G, B, A := m.At(0, 0).RGBA()
fmt.Println(R>>8,
	G>>8,
	B>>8,
	A>>8,
) // get {55 23 13 122} , it is wrong! Why not {55 23 14 122} ?

This is python script:

from PIL import Image
img = Image.new('RGBA', (1, 1), (55, 23, 14,122)) # set pixel value
img.save('bg.png')


im = Image.open('bg.png')
pix = im.load()

print(pix[0,0])  // get (55, 23, 14, 122)

Why does the result obtained in Golang change?

答案1

得分: 4

color.RGBA 表示预乘的带透明度的颜色。对于预乘的颜色,透明度组件表示 R/G/B 组件可以取的最大值。因此,color.RGBA{122,122,122,122} 表示带有透明度 122 的白色。

png.Decode 返回的是未预乘的 image.NRGBA。当显示像素类型时,这一点更加清晰。例如:

fmt.Printf("%#v\n", m.At(0, 0))
// color.NRGBA{R:0xff, G:0xff, B:0xff, A:0x7a}

在使用 NRGBA 类型时,您的示例将起作用。

请参考这个运行示例:https://play.golang.org/p/69bvYQfkCA_P

Before: color.NRGBA: {55 23 14 122}
After:  color.NRGBA: {55 23 14 122}
英文:

color.RGBA represents an alpha-premultiplied colour. For pre-multiplied colours, the alpha component represents the maximum value an R/G/B component can take. Hence color.RGBA{122,122,122,122} represents White with alpha 122.

png.Decode returns an image.NRGBA which is not pre-multiplied. This is clearer when the pixel type is displayed. Eg:

fmt.Printf("%#v\n", m.At(0, 0))
// color.NRGBA{R:0xff, G:0xff, B:0xff, A:0x7a}

Your example will work when using NRGBA types.

See this running example: https://play.golang.org/p/69bvYQfkCA_P

Before: color.NRGBA: {55 23 14 122}
After:  color.NRGBA: {55 23 14 122}

huangapple
  • 本文由 发表于 2021年9月18日 14:39:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/69232239.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定