Add blitting function to display
Add a function to draw complete image buffers (encoded in RGB565) to the display. Optionally, an alpha mask can be added.
Merge request reports
Activity
added 3-Module 6 - Needs Review labels
- Resolved by schneider
Sorry for the delay ...
Here at card10workout, we had people play with this MR, and noticed a few things. I'll leave a few more comments when I have more insight into what was going on ...
The one thing that came up, which I can already mention: Because the display expects the data big-endian and our CPU is little-endian, we need to manually swap the bytes in Python code. Maybe it would make more sense to implicitly convert them?
Ok, here's the code with which I've tested the blit-function: https://git.card10.badge.events.ccc.de/snippets/29
There are several demos, let's go through them step by step:
-
3-byte-RGB to 2-byte-RGB: This works well. Although, as I mentioned already above, I was surprised by the order of the two bytes as they appear to be swapped.
-
Drawing a blit inside the screen area This works well and as expected.
-
Drawing a blit (partially) outside the screen area When the blitted area is not displayed entirely on the screen, there will be pixel-noise shown inside the blitted area - but the program does not crash. Which is nice :)
-
Drawing a blit with alpha mask This confused me a bit, but I have to admit that I'm a git-noob and I couldn't find proper documentation of how this parameter is intended to work, so I just experimented wildly. Here's what I found out: The mask seems to be a byte-array with one byte for each pixel of the blitted area. If the value of an alpha byte is set to 255, the according pixel is shown as expected. If it is set to 0, the color which is specified in the bg parameter is shown instead. So this does not really seem to be an alpha channel, as I'd rather expect that a pixel with alpha value zero would not be shown at all. There is a nice side-effect of the alpha channel, though: When all pixels in the alpha byte-array are set to 255, the blitted area can be partially shown on the screen without the pixel noise which would otherwise appear.
-
Drawing many pixels into a fullscreen-sized blit area This works well and as expected. It's not as fast as I hoped, but this might have to do with the way I'v programmed the demo.
To sum it all up:
This is a very useful function and it runs stable. I'd be very glad to have it merged for the next firmware release!
There's room for improvement, though. It would be nice, if the alpha mask would be a real transparency mask. I don't see the use case for the current implementation, where a transparent pixel gets the color which is specified by the bg parameter. One could even consider to skip the alpha and bg parameters in the function and to store an alpha mask directly in the two bytes of each pixel. In that case, the color format could be rgba5551 instead of rgb565. I understand the physiological reasons for reserving 6 bits for the green channel, but I guess a 5-bit-green would be sufficient as well and a properly functioning alpha layer would be definitely very useful to have!
-
Thanks for the feedback.
Maybe I'll split the method up in a plain blitting function and one with alpha channel. I'll also look into the byte-flipping issue.
The alpha attribute is optional, if you pass
None
a (supposedly) much faster blitting algorithm is applied (i.e., the image is copied straigt or line by line if cropping occurs). Otherwise you can pass a byte buffer that contains an alpha channel. Real alpha blending is applied, so you can really use all values from 0x00 to 0xFF.The
bg
argument is currently only a helper since I did not yet figure out how to acctually access the frame buffer (e.g., getpixel or similar).Maybe I'll split the method up in a plain blitting function and one with alpha channel. I'll also look into the byte-flipping issue.
This sounds like a good idea!
I could not really see any difference in speed when I used blit without the alpha and bg argument. So i guess it might make sense to implement the blit without alpha in the same way as blit with alpha and a byte array full of 0xFF currently work. This way, the user could blit just half on the screen without getting the pixel-noise within the blit area.
And for a blit with alpha: IMO true blending over 256 steps is not necessary on that tiny screen. I'd be very happy with a simple binary black and white mask, but where the old screen content remains visible in the 'black' areas of the mask. @rahix can you help @led02 to understand how he can access values from the frame buffer in order to make this happen? This would be super!
The
bg
argument is currently only a helper since I did not yet figure out how to acctually access the frame buffer (e.g., getpixel or similar).It is very well possible that this is just not implemented yet. Ping @msgctl
On the other hand, I agree with @royrobotiks that a binary alpha mask is probably enough. For more advanced use-cases, people should use a direct framebuffer instead (see !211 (closed)) because that is much more flexible and performant.
added 6 - Changes Requested label and removed 6 - Needs Review label
We'd like to get this merged. Proposal is to remove the alpha support for now (but keep the
alpha
parameter in the function signature).We can then later implement proper alpha support.
Edited by schneideradded 522 commits
-
428f4a35...ea3bf8f2 - 520 commits from branch
card10:master
- 26c26f55 - Add blitting function to display
- 2ff38f87 - Add missing entry for blitting
-
428f4a35...ea3bf8f2 - 520 commits from branch
added 1 commit
- 09e5a8cd - change(display): Remove alpha channel from blit function
added 1 commit
- 1b9bb8d5 - change(display): Remove alpha channel from blit function
- Resolved by schneider
added 1 commit
- 3302f222 - fix(display): Explicitly free scratch buffer
- Resolved by schneider
mentioned in commit 9a70773d