micropython-nano-gui/IMAGE_DISPLAY.md

3.5 KiB

1. Displaying photo images

The display drivers in this repo were originally designed for displaying geometric shapes and fonts. With a minor update they may also be used for image display. The method used is ideal for full screen images however with suitable user code smaller images may be rendered. It is also possible to overlay an image with GUI controls, although transparency is not supported.

GUI references:
nanogui
micro-gui
micropython-touch

Images for display should be converted to a netpbm format, namely a .pgm file for a monochrome image or .ppm for color. This may be done using a utility such as Gimp. Netpbm files use 8-bit values. These are then converted to RGB565 for 16-bit drivers, RRRGGGBB for 8-bit color, or 4-bit greyscale to enable a monochrome image to display on a 4-bit driver. This is done using a CPython utility img_cvt.py documented below.

An updated driver has a greyscale method enabling the frame buffer contents to be interpreted at show time as either color or greyscale.

1.2 Supported drivers

Currently gc9a01, ili948x, ili9341 and st7789 drivers are supported.

1.3 Monochrome images

These may be displayed using 8-bit or 16-bit drivers by treating it as if it were color: by exporting the image from the graphics program as a .ppm color image and using img_cvt.py to convert it to the correct color mode.

On 4-bit drivers the image should be exported as a .pgm greyscale; img_cvt.py will convert it to 4-bit format. This utility uses error diffusion (dithering) to avoid banding and produced good results in testing.

1.4 Color images

These cannot be displayed on 4-bit drivers. On 8 or 16 bit drivers these should be exported from the graphics program as a .ppm color image. Then img_cvt.py is used to convert the file to the correct color mode.

1.5 Code samples

Files produced by img_cvt.py are binary files. The first four bytes comprise two 16-bit integers defining the numbers of rows and columns in the image. The following is an example of a full-screen image display in microgui or micropython-touch:

class MoonScreen(Screen):
    def __init__(self):
        super().__init__()

    def after_open(self):
        fn = "test.bin"  # Image created by`img_cvt.py`
        # The following line is required if a 4-bit driver is in use
        # ssd.greyscale(True)
        with open(fn, "rb") as f:
            _ = f.read(4)  # Read and discard rows and cols
            f.readinto(ssd.mvb)  # Read the image into the frame buffer

On nano-gui:

from color_setup import ssd  # Create a display instance
from gui.core.nanogui import refresh

refresh(ssd)  # Initialise display.
fn = "test.bin"  # Image created by`img_cvt.py`
# The following line is required if a 4-bit driver is in use
# ssd.greyscale(True)
with open(fn, "rb") as f:
    _ = f.read(4)  # Read and discard rows and cols
    f.readinto(ssd.mvb)  # Read the image into the frame buffer
refresh(ssd)

These examples rely on the images being configured to precisely match the screen size. In other cases the rows and cols values must be used to populate a subset of the frame buffer pixels or to display a subset of the image pixels. Secondly the built-in flash of some platforms can be slow. If there is a visible pause in displaying the image this is likely to be the cause.

doc to be continued