-
Notifications
You must be signed in to change notification settings - Fork 86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
pygame integration: confusion over rgba byte order #247
Comments
It's certainly possible, though counter-intuitive, looking at the pygame docs Can you verify it by making a test image and loading it on the cairo side before displaying it ? It looks like pygame has some support for pre-multiplied alpha, maybe we should extend the example here to let pygame know the alpha format too. |
You mean like this?
Yes, the saved test.png has the correct colours. Oh, and I forgot to mention: even after solving the invisibility problem, I still have red and blue the wrong way round, so need to use (g,b,r) colours instead of (r,g,b). But that's easy enough to address. |
Cheers, that demos this really well. The implementation of image_frombuffer looks like it does byteswapping Based on SDL_BYTEORDER, and SDL_CreateRGBSurfaceFrom which it calls may be able to do what we need, but there isn't an obvious way to do it. I'm going to open a ticket on the pygame side as it's looks like it there's a missing feature here. |
Thanks, that's some nice detective work! As an end user, I've now got it doing what I need (I can "manually" swap the bytes), and am just looking to get this documented in case others trip over the same issue. But if you can actually get this fixed, that's even better. And it's interesting to see what's happening under the hood. |
When I'm lucky enough to have the time, it's good to grab enough info so the developer on the other end doesn't need to think to much. We'll keep this ticket open until we see what happens on the pygame side. |
This has highlighted a couple of things:
|
I think Cairo always expects B to be in the least significant byte, G in the next byte up from that, and R in the byte up from that. In other words, given (r, g, b) components where each is a real in [0, 1], the Cairo pixel can be computed as
and this calculation is endian-independent. |
At the moment, a fix is to use PIL (or something) to do the conversion BGRA (cairo surface) to RGBA (pygame image), The above code with an example fix,
A direct pycairo <-> pygame format would be ideal. |
It should also be noted that at present, the demo, and the pycairo docs, are incorrect. |
Looking at https://github.com/pygobject/pycairo/blob/master/docs/integration.rst -- this is a clear and helpful page. But following the instructions for pygame, I had issues with green and blue being invisible!
It turns out, at least on my system, that if you create a surface with
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
then the lineimage = pygame.image.frombuffer(buf, (width, height), "ARGB")
will swap the channels, and you have to useimage = pygame.image.frombuffer(data, (WIDTH, HEIGHT),"RGBA",)
instead.My best guess is that this is something to do with endianness, and pygame and cairo handling it differently. i don't know whether it would be consistent across different OSs and architectures, so can't say whether others would see the same results as me. Is it worth adding a comment to the documentation?
For reference: I'm on Ubuntu 18.04 64-bit,
cairo.__version__
not found (how do I check my cairo version?), pygame version 1.9.1, python 2.7.1 and 3.6.9 (same behaviour on both).The text was updated successfully, but these errors were encountered: