Closed
Description
Expected Behavior
Python logo displays correctly.
Python logo in a ZIP archive
Behavior shown
Please feel free to ask me any further questions!
Code
import board
import displayio
import digitalio
import adafruit_imageload # type: ignore
# Device: M5Stack Cardputer
display = board.DISPLAY
bitmap, pallete = adafruit_imageload.load('/untitled_app.png')
image = displayio.TileGrid(bitmap, pixel_shader=pallete, x=5, y=5)
root_group = displayio.Group()
display.root_group = root_group
root_group.append(image)
G0_btn = digitalio.DigitalInOut(board.BUTTON)
G0_btn.direction = digitalio.Direction.INPUT
# Forever loop so we can see what happened :D
while 1:
pass
P.S. Original code in old version of this message.
Metadata
Metadata
Assignees
Labels
No labels
Activity
todbot commentedon Oct 9, 2024
I cannot replicate this. Assuming the github doesn't modify the PNG you included, I used the following code on a Adafruit FunHouse ESP32-S3:
And the output was as expected:

I think the problem is you are re-using
TileGrid
objects with slightly different dimensions. Instead of doing:try doing:
KavyanshKhaitan2 commentedon Oct 9, 2024
@todbot
Hey, thanks! Maybe that is the issue, I'll be back soon and let you know...
KavyanshKhaitan2 commentedon Oct 9, 2024
@todbot, The solution you proposed did not work. Here is the shortest and simplest code I could write to reproduce this error.
The device I am using is the M5Stack Cardputer if that helps.
In this case, I get this output on the screen:

Here is the image (/untitled_app.png) I am trying to use in a zip file (so that no platform can put their hands on it :D):
untitled_app.zip
[-]Incorrect dimensions recorded by load()[/-][+]Incorrect (skewed?) image displayed by image recorded by adafruit_imageload.load()[/+]todbot commentedon Oct 9, 2024
Using the PNG in that zip, I am seeing the same skewing are you are. This reminds me of #74 and it looks like the main way this PNG differs from the one at the top of this issue (recompressed by github) is that it's not palette-based but RGB.
Here's what PNG check shows for your original skewed image and the github one:
So a workaround would be to recompress your images until you find a setting that works with
adafruit_imageload
. (adding to a github issue seems to work :-)I tried re-encoding the PNG using ImageMagick with:
And that provokes a new bug in
adafruit_imageload
:which is the same codeblock that was to fix #74. So I think we're in the right ballpark.
Looks like
adafruit_imageload
still has some issues with PNGs with palettes.RetiredWizard commentedon Oct 9, 2024
#87 might fix this as well
Edit: Well not exactly, I see your image is only 50x50 but I suspect I was seeing the same issue. I'm not sure if applying #74 to all 8 bit images is the correct fix or if we need to track down what's different in the png files for the skewed images.
RetiredWizard commentedon Oct 9, 2024
For more data points here are the working/not working images I've been using:
sbob.zip
and the PNG check results for both files:
RetiredWizard commentedon Oct 9, 2024
Also replacing the < with a <= in the following line of png.py makes the untitled_app.png from the attached zip display properly...

Which of course applies the #74 fix todbot mentioned.
Edit: If like me you're trying to figure the work-around out from this screen shot, I chopped line 120, it should be:
bmp[x + pixel, y] = (byte >> ((pixels_per_byte - pixel - 1) * depth)) & (
RetiredWizard commentedon Oct 9, 2024
Is it possible there's a bug in the Circuitpython memoryview/array copy functions? I haven't stared at the work-around long enough to be sure but it looks to me like at a depth of 8, it's just performing a manual copy of data_bytes directly to bmp, rather than using the memoryview technique.
RetiredWizard commentedon Oct 10, 2024
I don't understand exactly how the memoryview function works but I don't think it's working as expected. I was able to get the untitled_app.png file from the attached zip to display properly by modifying the target memory location from
dst = y * scanline
todst = y * scanline + y*2
(line 111). However this modification doesn't work for the sbob129.png file so the memoryview method of copying the byte data is doing something inconsistent possibly depending on the amount of data being moved.I may try and dig in and figure out exactly how the memoryview function works but until then I think we should just enable the #74 work around for 8 bit images as well. This slows down the image display but moving the data into the bitmap object one byte at a time at least displays the images correctly.
deshipu commentedon Oct 10, 2024
Thew problem is that displayio uses uint32_t arrays internally, but the memoryview exposes that as uint8_t array.
In hindsight, and after reading the docs for https://docs.circuitpython.org/projects/imageload/en/latest/api.html#adafruit_imageload.load I think we should have never used memoryview in imageload in the first place, we should be using
_load_row
only.RetiredWizard commentedon Oct 10, 2024
I think I worked out the adjustment needed to get the memoryview to work. I've tested on 2, 4 & 8 bit mode 8 images and it seems to be working.
https://github.com/adafruit/Adafruit_CircuitPython_ImageLoad/pull/87/files
deshipu commentedon Oct 10, 2024
The original code used
bitmap[x, y]
to fill the pixels, so if that was wrong, then the error is in the displayio bitmap code, not here, and fixing it here is the wrong thing to do.RetiredWizard commentedon Oct 10, 2024
The
bitmap[x, y]
code wasn't wrong and worked fine, it's just much slower to copy a single byte at a time.KavyanshKhaitan2 commentedon Oct 10, 2024
Why dont you create a pull request then?
Also, I had created this image using getpaint.net if anyone is wondering, its a great, lightweight image editor :)
RetiredWizard commentedon Oct 10, 2024
#87 resolves the issue. The <= change was one of the first commits to the PR but after working on it for many hours I was able to get the code to work without the work around which is noticeably faster for larger image files.