Skip to content

Version 1.20.4

Compare
Choose a tag to compare
@Gadgetoid Gadgetoid released this 04 Aug 15:56
· 202 commits to main since this release
d93839d

Spin Me Right 'Round

Text bugs & rotation

In our continued quest to make doin'-text-stuff better, this version fixes a couple of text rendering bugs. The code wasn't taking into account letter spacing when calculating the width of words, resulting in auto word-wrap failing to wrap words that didn't fit. Additionally it was ignoring line breaks (\n) so that manually wrapped text was rendered as one line. Both of these bugs should now bug fixed, and -

You can now rotate Bitmap text in 90 degree intervals. Just provide an angle argument when drawing text. Text is always drawn with the origin at the top-left, so a 180 degree rotation for text shown at 0, 0 will disappear the text off the left-edge of the screen. You'll need to offset your text accordingly to avoid this.

text rgb

PNG support

Hands up, JPEG was an odd choice of format to start with for embedded graphics. It was grabbing JPEG files over the network and display them on e-ink displays that drove us towards it. Using it for icons in Badger/Badger 2040 was not a great fit- we had to be very careful to avoid JPEG artefacts resulting in spurious pixels. If only there was a better way-

There is! Microcontroller optimisation wizard @bitbank2 - the very same wizard who created the JPEG decoded we use - has a PNG decoder. This release adds that PNG decoder to our codebase and glues it into MicroPython for all your crisp, icon-drawing needs.

Like JPEG decoding, PNG decoding supports loading files from microSD, flash and RAM, but unlike JPEG decoding there are some new options for cropping, scaling and rotating you PNG images. (Note: the order is always crop, scale and rotate.)

A basic example looks something like this:

from pngdec import PNG
png = PNG(display)
png.open_file("fire.png")
png.decode(0, 0)

But say you have a spritesheet with 8x8 sprites and you want to display a 3x2 character from it at 4x scale, you might do something like this:

from pngdec import PNG
png = PNG(display)
png.open_file("/s4m_ur4i-pirate-characters.png")

png.decode(0, 0, source=(32, 48, 24, 16), scale=(4, 4), rotate=0)

rotate rgb

The source argument is the region, in pixels, you want to show from the PNG- offset left and top, plus width and height. The whole PNG is loaded and decoded no matter what you put here, but this makes it easier to manage multiple images for things like icons.

rotate rgb

The scale argument lets you scale images up by a fixed multiplier along the X and Y axis. If you want to make an image 4x wider and 2x taller you'd use scale=(4, 2).

rotate rgb

Finally, rotate lets you rotate your PNG graphic in 90 degree intervals.

rotate rgb

Both full-colour RGB PNGs and indexed ones are supported. For indexed PNGs - ie: one that has a palette - you can supply a mode argument with one of PNG_COPY, PNG_DITHER and PNG_POSTERISE.

PNG_COPY will copy the palette indexes into a P4 or P8 graphics buffer rather than dithering or posterising (snapping to the nearest available colour).

PNG_DITHER will use a simple ordered dither matrix to dither the image colours to the available display colours.

PNG_POSTERISE will snap the colours in the PNG to their nearest display counterpart.

rotate rgb

Posterise is the default in all cases.

What's Changed

New Contributors

Full Changelog: v1.20.3...v1.20.4