Skip to content
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

PicoGraphics: Add support for PNG decoding. #802

Merged
merged 3 commits into from Jul 27, 2023
Merged

PicoGraphics: Add support for PNG decoding. #802

merged 3 commits into from Jul 27, 2023

Conversation

Gadgetoid
Copy link
Member

@Gadgetoid Gadgetoid commented Jul 19, 2023

Should work roughly the same as JPEGDEC except it uses slightly more RAM and handles indexed PNGs. Maybe need an option to simply copy over the indexes rather than try any palette mapping so you can prepare assets with a specific palette and then just load that palette into P4 or P8 mode.

PNG decoding uses about 47K of RAM. Most of this is the zlib inflate_state which is 7K, plus 32K of fixed sliding window buffer in png_image_tag / ucZLIB. There might be a way we can - optionally - sacrifice performance for less RAM usage, but I'm not sure.

@Gadgetoid
Copy link
Member Author

@bitbank2 before I melt my brain looking into this, do you know off the top of your head if you can decode PNG graphics starting from a particular offset? Specific use case would be grabbing portions of a spritesheet. Thank you!

@bitbank2
Copy link

I did that with my TIFF_G4 library to allow for scaling/decoding huge files into a small device, but I hadn't seen a need with PNG images. It's a good idea to add to a future version :)

@Gadgetoid
Copy link
Member Author

Sooo theoretically possible, then? 👀 😆

@bitbank2
Copy link

Certainly possible. It's not hard to selectively use a small area of an image decoded from a larger one. You can already do that with the callback structure I use. You still have to decode the full width of the image, but you can stop decoding when you hit the bottom line of the part you want.

@Gadgetoid
Copy link
Member Author

Ooh, I'd forgotten I can- I think- return a status from the callback function to stop decoding. I was mostly thinking along the lines of scanning ahead in the file to a specific set of coordinates, but I don't know enough about how PNG decompression/decoding works.

I should probably handle bounds checking on the drawing area, and it'll make that easier.

@bitbank2
Copy link

Unfortunately you can't scan ahead in PNG files because each line uses a filter which might be the pixel differences of the line above it. One wrong pixel and the image from that point down is corrupted. There's no concept of "restart markers" like in JPEG.

@Gadgetoid
Copy link
Member Author

Clearly I need to re-read https://ucnv.github.io/pnglitch/ 😆

Thank you!

@bitbank2
Copy link

One last comment - you can get PNGs to decode with less RAM. If the PNG resultant size is very small, then you won't need a 32k sliding window. Also, you can tell the PNG encoder to use a smaller sliding window and then the decoder will use the same.

@Gadgetoid
Copy link
Member Author

Palette cycling demo for Pico Display 2.0:

import time
import pngdec
from picographics import PicoGraphics, DISPLAY_PICO_DISPLAY_2 as DISPLAY, PEN_P8 as PEN

graphics = PicoGraphics(DISPLAY, pen_type=PEN, rotate=0)

png = pngdec.PNG(graphics)
png.open_file("fire.png")
palette = png.get_palette()
graphics.set_pen(0x59)
graphics.clear()
png.decode(0, -10, mode=pngdec.PNG_COPY, scale=(5, 4))

while True:
    for offset in (16, 32, 48):
        gradient = palette[offset:offset + 12]
        gradient.insert(0, gradient.pop())
        palette[offset:offset + 12] = gradient

    graphics.set_palette(palette)
    graphics.update()

    time.sleep(1.0 / 30)

The fire.png is borrowed from here: https://github.com/32blit/32blit-sdk/blob/master/examples/palette-cycle/assets/fire.png

@Gadgetoid Gadgetoid merged commit 51574f8 into main Jul 27, 2023
30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants