-
Notifications
You must be signed in to change notification settings - Fork 33
Handling rotation and mirroring with MADCTL #20
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
base: main
Are you sure you want to change the base?
Conversation
@@ -98,19 +98,23 @@ | |||
ST7735_YELLOW = 0xFFE0 # 0b 11111 111111 00000 | |||
ST7735_WHITE = 0xFFFF # 0b 11111 111111 11111 | |||
|
|||
|
|||
def color565(r, g, b): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you intend to delete this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, sorry.
I thought that it was legacy code from a prior version of image_to_data
since there was no public method that receives a RGB565 color and the conversion is being handled with bit manipulation in numpy.
Should I restore it?
(Or delete the references in the tests... I didn't see the tests 🤦 .)
Nice work, thank you. I'll have to test this against our board/examples to make sure everything still works as expected- the tests aren't comprehensive in that respect. With rotation happening entirely on device, it might be worth also grabbing the clearer (and faster somehow) version of something like: def image_to_data(self, image, rotation=0):
if not isinstance(image, np.ndarray):
image = np.array(image.convert('RGB'))
# Rotate the image
pb = np.astype('uint16')
# Mask and shift the 888 RGB into 565 RGB
red = (pb[..., [0]] & 0xf8) << 8
green = (pb[..., [1]] & 0xfc) << 3
blue = (pb[..., [2]] & 0xf8) >> 3
# Stick 'em together
result = red | green | blue
# Output the raw bytes
return result.byteswap().tobytes() |
I've ported Is it OK for |
Hmmm tests look like they're breaking because they mock numpy, IIRC. This causes the types (on the mock object) not to be detected as types and break |
Got tests up and running, plus a little bit more test coverage and dropping Python 2.x, with this commit: 826dd48 |
Cool! I'm going to revisit a little more |
Historically the image conversion only worked with a PIL image, so it was pretty cut and dry, but some users wanted to pipe some AI image recognition output into there or something similar. I don't know how you'd reasonably check that raw bytes are any given format but if you're using something that outputs RGB565 directly then - yes - this function would both break it horribly and be wasted effort! Edit: Ah I guess RGB565 = Edit: Also the conversion function expects at least 2D array if one is given, with RGB888 pixels, eg: [[255, 0, 0], [0, 255, 0], [0, 0, 255]] Since >>> numpy.array(Image.new("RGB", (2, 2)))
array([[[0, 0, 0],
[0, 0, 0]],
[[0, 0, 0],
[0, 0, 0]]], dtype=uint8) It's all a bit of a mess! |
Yes, PIL only supports 24bits RGB ( https://pillow.readthedocs.io/en/stable/handbook/concepts.html#concept-modes ). My sugestion is something like:
It will still convert if image is monocrome, gray, et cetera, but it will not be wasting time creating a copy if the image is already RGB. To pass something more low level I think that passing a numpy array is OK. Now, if the data in the numpy matrix is already a raw RGB565 it could not be checked, but it could be passed as a boolean parameter: |
|
Finally I didn't add the raw parameter. If image is a list or a bytes object it will be considered as raw data. If not it must be a PIL Image or a numpy array. I've checked and SpiDev accepts bytes as a parameter to xfer3() method**, so I've deleted the conversion to list. (**: Only one method in the library documents "values must be a list or buffer" and, yes, bytes seems to be a buffer for the SpiDev developers.) |
Updated the tests in 314f973 and they seem to be okay. Will have to try the examples on real hardware, but seems good so far! Thank you. I think spidev was originally written for one specific purpose and ended up getting adopted for wider use. It's a little rough around the edges. I, uh, guess I count as one of the developers 😆 |
Oops ;)
Yes!, and pay special attention on the orientation of the image. The keys in ST7735_MADCTL_ROTATIONS must be reorderer to ensure backward compatibility on the driver. I've no way to test it since my display is different. |
Sorry to come back years later after leaving this to the wayside. I am desperately short on bandwidth for touching stuff that works - this library was pretty much just for our breakout and Grow HAT. I've now conflicted this by merging a smaller, less comprehensive change which I think this functionally replaces or at least works in conjunction with. I don't mind if you have no appetite to come back, but I'm going to leave this PR open for future adventurers. Ideally this library should be more complete than it is and if that involves breaking changes and a bit of shakeup I can version pin our products. |
As commented in #19 , my display is showing a mirror image. Fixing that issue I've ended up rewritten the entire handling of rotations in order to manage it via MADCTL settings.
The parameter values are taken from page 61 in Sytronix datasheet1. I'm using the convention of 0 degrees corresponding with MV,MX,MY=0 and positive angles rotating clockwise. I think that's the driver manufacturer convention.
If it breaks the current library behavior, since the default initialization were MV,MX,MY=011 it could be fixed by switching the 0 and 180 degree definitions on ST7735_MADCTL_ROTATIONS dictionary. I've no preference and I've no problem to update my patch in order to reflect that change.
Please, test it since my display hardware is clearly different that yours.
Footnotes
https://www.displayfuture.com/Display/datasheet/controller/ST7735.pdf ↩