我有一个测试jpeg,我正在使用一些图像处理代码&我试图获得与python中的opencv和C以及python中的Pillow(通过scipy)相同的uint8值数组,这些值都与我使用gimp打开jpeg时获得的值相匹配。
我尝试将颜色值移动8位,但这并不能准确地转换值-看起来好像有一些我不太理解的舍入。我知道gimp和opencv和Pillow/scipy都使用libjpeg,所以我尝试使用https://github.com/pixiv/go-libjpeg并使用
将图像转换为8位func Convert(img image.Image) *image.RGBA {
b := img.Bounds()
rgba := image.NewRGBA(b)
for y := b.Min.Y; y < b.Max.Y; y++ {
for x := b.Min.X; x < b.Max.X; x++ {
r32, g32, b32, _ := img.At(x, y).RGBA()
c := color.RGBA{uint8(r32>>8), uint8(g32>>8), uint8(b32>>8), 255}
rgba.SetRGBA(x, y, c)
}
}
return rgba
}
,但这仍然不匹配。我怎样才能得到同样的结果?
JPEG规范没有对解码器的像素精确定义,因此不同的实现将有略微不同的输出。甚至libjpeg本身也有4种不同的离散余弦变换实现,使用整数或浮点数学。
至于你的代码,如果img
已经是image.RGBA
,那么这些值都存储为uint8
,你只是来回移动比特,什么都不做。如果图像是image.YCbCr
,那么还依赖于颜色转换算法,并且YCbCr.RGBA()
方法与color.YCbCrToRGB
函数略有不同。前者试图保持更高的精度,您需要正确地四舍五入值,而不是通过简单的右移截断它们。后者更接近规范建议,但不使用浮点常量,这可能与其他实现有所不同。
最后,图像本身可能有一个嵌入的ICC配置文件,并且根据用于解码图像的软件,在查看原始像素数据时可能已经或可能没有应用该配置文件。