Hey everyone!
I got two gif’s that I played around with displaying. In one the transparent background is displayed as black, in the next the transparent background is displayed in white.
Before posting I’ve already excluded some sources for the error: PIL recognizes the background and transparency colors properly (via PIL.Image.open().info
). Transparency is at the right location (via np.array(PIL.Image.open())
). All other viewers I attempted recognize the transparency properly or at least handles it uniformly, except when displaying it on the LED matrix via rgbmatrix.
Since I’ve not been unable to recreate the issue with any other viewing software / device than the LED matrix,here I am to ask the questions:
- What might cause PIL transparency to be displayed as either white or black?
- Why is transparency not preserved when displaying using
rgbmatrix.RGBMatrix.SetImage(frame)
?
Attached the GIFs in question. Both created with GIMP by adjusting free stationary stock image icons.
(appearing with white background for me)
Second image appearing with black background for me:
(Apologies, apparently new users are only allowed 1 image in a post)
My experience with doing this on arduino is that finding a lib that does everything right for GIF decoding, is not trivial. Many have bugs on corner cases.
You may have to check other decoding libraries.
Thank you very much Marc! After your comment went deeper into the details, and got it fixed - turns out it was a GIF specific problem.
I leave the detailed explanation of this issue here for the next one to find:
It turns out that the color defined to be transparent was different in the GIFs (see: python - Why PIL convert('RGB') makes some transparent into black but some into white? - Stack Overflow)
A fix in GIMP was as simple as changing the selected background color in the tool activated before saving the GIF again.
Maybe there is a way to explicitly set the transparent color in PIL, but I have not found that yet.
Allowing RGBA filling for SetImage, however, requries a GetPixel function to mash RGB values, which is currently not possible as all previous SetPixel functions already converted “to the low level data that is needed” (see: Copying Small Canvas to Large Canvas? · Issue #1213 · hzeller/rpi-rgb-led-matrix · GitHub). This requries a window canvas to set canvas, a feature that might be pretty useful for some people to allow transparency, but doesn’t seem to have been finished yet.
For other people coming across this issue in Python wanting to display images with transparency:
- A threshold implementation in the bindings, however, is viable where only pixels are set with Alpha channel values larger than a certain value.
- Another possibility is using Alpha values to change the RGB values to a darker tone using an rgba2rgb conversion.
One more caveat to be noted, properties of GIF frames can be different, for example the PIL.Image.info description may vary if the GIF image itself is selected or any frame in it when using PIL.Image.seek() including the transparent and background color. Be careful to have the identical values designated in each frame.