Image.toarray change rgb to bgr on the Linux
Describe the bug On Linux platform use Image.toarray convert image to array ,then use Image.fromarray convert array to image, R and B chennel of the image will switch
To Reproduce Steps to reproduce the behavior:
import httpx
import skia
url = "https://pic3.zhimg.com/v2-2f57af939aef71f510c35928600d79f2_b.jpg"
response = httpx.get(url)
img1 = skia.Image.MakeFromEncoded(response.content)
img1.save("1.png")
img2 = skia.Image.fromarray(img1.toarray())
img2.save("2.png")
Expected behavior R chennel and B chennel will not switch
Desktop (please complete the following information):
- OS: 22.04.1-Ubuntu
- Python: 3.10.6
- skia-python version: 87.5
Additional context Add any other context about the problem here.
This problem can be solved by passing the "colorType=kia. ColorType. kRGBA_8888_ColorType" parameter when calling toarray
that's interesting. I just encounted a somewhat similar issue - pretty sure internally skia does kN32_8888 by default. FreeType internally does kBGRA actually, so I have to specify kBGRA to render directly from Skia into a freetype bitmap based memory canvas.
You are basically saying that conversion to/from, one of them is not N32.
It is actually documented in one of skin's design document that libjpeg and libpng does RGBA and platform neutral, while skia's internal image format is platform dependent, and on intel/small-endian, it is happens to be BGRA . There are different way of getting at it, and some will invoke auto-swap, some won't. So this behaviour is apparently documented.
I found something similar in my situation. I have a buffer maintained by freetype and I wanted skia to fill it. The default doesn't work, and I have to explicitly tell skia that freetype wants BGRA and so please do it as such.
I was doing a SkBitmap canvas with a freetype buffer backing and just ask Skia use the SkBitmap as a Canvas. I guess in my case, because jpeg/png buffers are RGBA, so SkBitmap probably has a default of being RGBA.
@kyamagu Hmm, looking at this again, why does toarray() and fromarray() have different defaults?
fromarray has a default of py::arg("colorType") = kN32_SkColorType, while toarray has py::arg("colorType") = kUnknown_SkColorType. I think Unknown probably will end up being N32 anyway, but somehow obviously hasn't happened. Assuming the code honours those colortypes correctly.
@HinTak Don't remember why they are different. As kN32_SkColorType seems to exist only for historical reasons, all defaults should be kUnknown_SkColorType.
Hmm, this seems to relate to #250 .