peterhinch / micropython-nano-gui

A lightweight MicroPython GUI library for display drivers based on framebuf class
MIT License
507 stars 88 forks source link

How to display a picture? #16

Closed kekemuyu closed 2 months ago

peterhinch commented 3 years ago

This is not supported by nano-gui. However the drivers are subclassed from FrameBuffer.framebuf, so you can use methods documented here to draw anything you like. Note that some of the drivers (especially the 4-bit ones) support only limited color spaces to conserve RAM, so the rendition of pictures will be poor.

kekemuyu commented 3 years ago

My lcd is st7789. I made a try to display a picture with framebuf as your said. The effect is too bad to see it clearly.

color_setup.py:

import machine

import gc

# *** Choose your color display driver here ***

# Driver supporting non-STM platforms

# from drivers.ssd1351.ssd1351_generic import SSD1351 as SSD

# STM specific driver

from drivers.st7789.st7789_4bit import *
SSD=ST7789

#height = 96  # 1.27 inch 96*128 (rows*cols) display

machine.Pin(4, machine.Pin.OUT, value=1)

pdc = machine.Pin(22, machine.Pin.OUT, value=0)

pcs = machine.Pin(21, machine.Pin.OUT, value=1)

prst = machine.Pin(5, machine.Pin.OUT, value=1)

spi = machine.SPI(2)

gc.collect()  # Precaution before instantiating framebuf
spi = machine.SPI(1, 30_000_000, sck=machine.Pin(18), mosi=machine.Pin(23))

ssd = SSD(spi, height=132, width=240, dc=pdc, cs=pcs, rst=prst, disp_mode=USD|REFLECT , display=TDISPLAY)

dis_bmp.py:


from color_setup import ssd
from gui.core.nanogui import refresh,fillcircle,circle
from gui.core.writer import Writer, CWriter
import gui.fonts.arial10 as arial10
from gui.core.colors import *
import framebuf

f=open('test.bmp', 'rb')

if f.read(2) == b'BM':  #header
    dummy = f.read(8) #file size(4), creator bytes(4)
    offset = int.from_bytes(f.read(4), 'little')
    hdrsize = int.from_bytes(f.read(4), 'little')
    width = int.from_bytes(f.read(4), 'little')
    height = int.from_bytes(f.read(4), 'little')

    if int.from_bytes(f.read(2), 'little') == 1: #planes must be 1
        depth = int.from_bytes(f.read(2), 'little')
        print(depth)
        #if depth == 24 and int.from_bytes(f.read(4), 'little') == 0:#compress method == uncompressed

        if int.from_bytes(f.read(4), 'little') == 3:#compress method == uncompressed
            print("Image size:", width, "x", height)
            rowsize = (width * 3 + 3) & ~3
            if height < 0:
                height = -height
                flip = False
            else:
                flip = True
            w, h = width, height
            if w > 240: w = 240
            if h > 135: h = 135

            fbuf = framebuf.FrameBuffer(bytearray(f.read()), 198, 120, framebuf.RGB565)

            ssd.blit(fbuf, 0, 0)
            ssd.show()```
peterhinch commented 3 years ago

Displaying a picture with a maximum of 16 colors was never going to produce great results. However the framebuf.blit method has a documented limitation: blitting between buffers created in different modes produces unexpected results. In my view this is a major shortcoming, but discussions on fixing it petered out with no resolution. Until this is fixed you'll have to render pixel by pixel. You'll also need to create a set of 16 colors suitable for the purpose and decide how to map the image's RGB values onto the set of colors you've chosen.

Arguably you're trying to use a screwdriver to install a nail: drawing pictures has nothing to do with nano-gui and your test script uses none of the GUI's features apart from the driver. This is a driver designed for rendering nano-gui widgets and to save RAM by limiting the range of colors to 16. If you don't intend to use features of nano-gui you may find a driver which uses rgb565. Such a driver would be better suited to rendering pictures and would overcome the problems of blitting between incompatible color modes. You might find some help by posting a query in the forum.

peterhinch commented 2 months ago

Closing as it is out of date. For image display see this doc.