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

Bitmap demo broken? #17

Open
Pharkie opened this issue Dec 16, 2024 · 7 comments
Open

Bitmap demo broken? #17

Pharkie opened this issue Dec 16, 2024 · 7 comments

Comments

@Pharkie
Copy link

Pharkie commented Dec 16, 2024

Thank you for a great project. In

gui/demos/bitmap.py

The path to the demo bitmap files seems wrong. The current code looks for e.g. "m00" in the filesystem root, but the files are in

/optional/bitmaps/

Changing this function in bitmap.py works for me:

    def cb(self, _):
        file_path = f"/optional/bitmaps/m{self.image:02d}"
        if file_path.split("/")[-1] in os.listdir("/optional/bitmaps"):
            self.graphic.value(file_path)
            self.image += 1
            self.image %= 4
            if self.image == 3:
                self.graphic.color(BLUE)
            else:
                self.graphic.color(WHITE)
        else:
            print(f"File not found: {file_path}")

(I'm afraid I don't know how to contribute the fix directly via pull request)

I will also note that I'm using a Waveshare RP2350 1.28" round display and it works perfectly with the existing setup offered in

setup_examples/gc9a01_ws_rp2040_touch.py

This new device seems to use:

Display: GC9A01
Touch: CST816T

Just with the Pico2 MCU, the RP2350.

Best wishes,

@Pharkie
Copy link
Author

Pharkie commented Dec 16, 2024

I see now a comment in

https://github.com/peterhinch/micropython-touch/blob/master/README.md#618-bitmap-widget

Which says

For this demo four files must be copied from gui/fonts/bitmaps/ to the root directory of the device.

So, this is not a bug. Maybe a comment at the top of bitmap.py may be helpful?

On my setup (as above), I couldn't get a bitmap to display using the 16-bit driver (drivers.gc9a01.gc9a01). The image array was always 2x or 4x the display / SSD array, and I was getting out of range errors. I managed to get my image to display with the 8-bit driver (drivers.gc9a01.gc9a01_8_bit), with an 8-bit .BIN created by img_cvt.py from a .PPM file saved from Gimp.

peterhinch added a commit that referenced this issue Dec 16, 2024
@peterhinch
Copy link
Owner

Thanks for the reports. The docs were wrong too. The directory you quoted was for micro-gui.

I have pushed corrections. These days I try to ensure demos will run without installation, using mpremote mount . so copying files is not ideal. I've changed docs and code on the assumption that the images will be in optional/bitmaps/. The docs now advocate either copying that tree or running via mpremote mount ..

I have implemented error trapping in a slightly simpler way.

The 16-bit driver is intended for image display - it confers no advantage when using the GUI alone. I'll review its behaviour with the bitmap widget and either document or fix it.

@Pharkie
Copy link
Author

Pharkie commented Dec 16, 2024

That's great, Peter, that will certainly help.

Yes, I was hoping to get the 16 bit GC9A01 driver working to display my image, but couldn't get it working.

This works:

  1. Use 8-bit GC9A01 driver
  2. Save image from Gimp and convert with
    python3 img_cvt.py Riccy\'s\ Casino-black-240.ppm mylogo8bit.bin -r 240 -c 240
  3. Show with
class LogoScreen(Screen):
    def __init__(self):
        super().__init__()

    def after_open(self):
        print(f"SSD dimensions: {ssd.width} x {ssd.height}")
        fn = "mylogo8bit.bin"  # Image created by `img_cvt.py`

        try:
            with open(fn, "rb") as f:
                rows = int.from_bytes(f.read(2), "big")
                cols = int.from_bytes(f.read(2), "big")

            print(f"Image size: {rows} rows x {cols} cols")

            with open(fn, "rb") as f:
                _ = f.read(4)  # Discard first 4 bytes (rows and cols)
                f.readinto(ssd.mvb)  # Read the image into the frame buffer

            ssd.show()  # Refresh the display to show the new image

        except OSError as e:
            print(f"Failed to open file {fn}: {e}")
        except Exception as e:
            print(f"An error occurred: {e}")

        print("Logo displayed")

This does not work:

  1. Use 16-bit GC9A01 driver
  2. Save image from Gimp and convert with
    python3 img_cvt.py Riccy\'s\ Casino-black-240.ppm mylogo16bit.bin -r 240 -c 240 --rgb565
  3. Show with function above.

@peterhinch
Copy link
Owner

I can't replicate these problems. I used a RP2040-Touch-LCD-1.28 as the nearest thing to your hardware, with gc9a01_ws_rp2040_touch.py as hardware_setup.py adapted to import the 16-bit driver. Firstly I ran the bitmap demo, which ran correctly. Then I tested image display as follows.

I took a JPEG image and used Gimp to scale it to 240x240 and export it to file me.ppm. I then did

$ ./img_cvt.py me.ppm me.bin -r 240 -c 240 --rgb565
Writing file, dimensions rows = 240, cols = 240
Binary file me.bin written in 16-bit color RGB565.

and ran the following script

import hardware_setup
from gui.core.tgui import Screen, ssd

from gui.widgets import Label, Button, CloseButton
from gui.core.writer import CWriter
import gui.fonts.freesans20 as font
from gui.core.colors import *

class BaseScreen(Screen):
    def __init__(self):

        super().__init__()
        wri = CWriter(ssd, font, GREEN, BLACK)  # Verbose
        col = 2
        row = 2
        Label(wri, row, col, "Simple Demo")
        CloseButton(wri, 30)  # Quit the application

    def after_open(self):
        with open("me.bin", "rb") as f:
            f.read(4)
            f.readinto(ssd.mvb)

def test():
    Screen.change(BaseScreen)

test()

Result was a fine portrait of yours truly.

Note that ssd.show() is not required. On the touch gui (and micro-gui) refresh is automatic. Aside from that it's not obvious what is going wrong with your setup.

@Pharkie
Copy link
Author

Pharkie commented Dec 16, 2024

Ah, great! Thanks for the full code example. I'd like to try that here.

Are me.ppm and me.bin available somewhere? That way I can check if it's my image generation or the code that's the problem.

Re:ssd.show() thanks for confirming: it keeps getting added by Github Copilot, presumably because its a common code pattern with these kind of small displays.

@Pharkie
Copy link
Author

Pharkie commented Dec 17, 2024

(No worries if you don't have time to help a n00b here, Peter, but..)

With the 16 bit driver loaded in hardware_setup.py, then this file

https://github.com/Pharkie/PokerBlindsMPTouch/blob/master/load_logo.py (with "fn = "mylogo16bit.bin")

shows this:

16bit_mylogo

With the 16 bit driver loaded in hardware_setup.py, then this file, based on your code above in this thread

https://github.com/Pharkie/PokerBlindsMPTouch/blob/master/peter_image.py

shows this:

16bit_petercode

And with the 8 bit driver loaded in hardware_setup.py, then this file

https://github.com/Pharkie/PokerBlindsMPTouch/blob/master/load_logo.py (with fn = "mylogo8bit.bin")

shows this, the only correct version:

8bit_mylogo

@peterhinch
Copy link
Owner

peterhinch commented Dec 17, 2024

I have put me.ppm here. Generate me.bin using the above command.

I would caution against relying on AI for coding, particularly when writing to a specialised API. The show() command is required by nano-gui which is synchronous; micropython-touch is asynchronous, with refresh handled by a background task.
[EDIT]
I just remembered that the command required by nano-gui is refresh. The ssd.show method is for internal use by the GUI. Its use in an application context is an AI hallucination.

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

No branches or pull requests

2 participants