Closed mokiat closed 7 months ago
P.S. I am also seeing that the RGBA
methods of the different color types are not per spec as well. They need to return alpha-premultiplied 16bit color components but in most cases they return 8bit non-alpha-premultiplied components.
You can compare this implementation with the official NRGBA color, which is the same as RGBA8888
:
https://cs.opensource.google/go/go/+/refs/tags/go1.21.4:src/image/color/color.go;l=60-76
You can see how they convert a non-alpha-premultiplied color into an alpha-premultiplied 16bit-per-component color.
I might be open to opening a PR for this through I would have a hard time testing it on my own and it might be breaking change for people (though I think it is worth it).
Hm... after further analysis, I see that the Set
function always deals with 8bit RGBA components that it then manually shuffles and reassigns. It might be sufficient to do the following at the start of the method:
nrgbaColor := color.NRGBAModel.Convert(c).(color.NRGBA)
r, g, b, a := nrgbaColor.R, nrgbaColor.G, nrgbaColor.B, nrgbaColor.A
// the r, g, b, a components above are guaranteed to be 8bit non-alpha-premultiplied
// so we can use them in the switch statement, without having to cast anything more
switch surface.Format.Format {
case PIXELFORMAT_ARGB8888:
pix[i+0] = b
pix[i+1] = g
pix[i+2] = r
pix[i+3] = a
case .... // and so on, always using the r, g, b, a values from above
}
I have now implemented a local workaround Wrapper that fixes the problem. It looks as follows.
Not only does it not panic anymore, but it also now fixes an issue I had with transparent colors. Please tell me if I could open a PR for this.
Hi @mokiat, thanks for opening up an issue and looking into it! Of course, please open a pull request and I will review and merge it.
Go version: 1.21.3 Go-SDL2 version: 0.4.35 SDL2 version: irrelevant OS: Linux Architecture: amd64
There is a problem with how Surface handles colors.
I have the following fragment of code and in some situations it panics and in others it does not:
(Side note: I am not sure if this is the most optimal way to set an icon but I did not find another)
All of this depends on the color format of the image but it should not, since
func (surface *Surface) Set(x, y int, c color.Color) {
deals with theColor
abstraction and it should handle any input.The problem is due to how color models are implemented: https://github.com/veandco/go-sdl2/blob/9405dd390eb0a6e9076b629debd80f7f4332b47c/sdl/pixels.go#L809-L815
This returns a
color.RGBA
color sometimes andBGRA8888
other times. From my understanding of the Go's color package, the model should always convert to one single type - the one specific to the model. So in this case it should always returnBGRA8888
.The current implementation results in a panic when trying to convert the color to the respective model type: https://github.com/veandco/go-sdl2/blob/9405dd390eb0a6e9076b629debd80f7f4332b47c/sdl/surface.go#L809-L814
It assumes (normally a correct assumption) that it will get a
BGRA8888
type but this is not the case due to thecolor.RGBA
branch above.