rm-hull / luma.lcd

Python module to drive PCD8544, HT1621, ST7735, ST7567 and UC1701X-based LCDs
https://luma-lcd.readthedocs.io
MIT License
156 stars 56 forks source link

luma screen layout #66

Closed svenyonson closed 2 years ago

svenyonson commented 6 years ago

Hi Richard, I have a question about best practices with the luma library, not sure where else to post it. I need to layout the screen real estate into regions that I can update, e.g. A status bar with a Wifi icon, a title bar, and an area in the middle for dynamic text. I looked at the savepoint example and I was thinking of that approach for redrawing on the same canvas for each of the regions. While I think that might work, I can't see how to update the canvas with an image (wifi icon). I only see pasting the icon onto a background image and then displaying the background image as a whole. Just wondering if there is a best practice here so I don't spend a lot of time down a rabbit hole.

Also, assuming the above is possible, is there a way to have a virtual terminal (scrolling text) as one of my regions?

Thx

rm-hull commented 6 years ago

You should have a look at the hotspot and viewport classes: https://luma-core.readthedocs.io/en/latest/api-documentation.html#luma.core.virtual.hotspot. There is a specific example - carousel; that makes use of the hotspot functionality.

The canvas is a convenience wrapper around drawing text and simple line graphics (with whatever methods Pillows ImageDraw supports). You don't have to use it, as you can create am image directly, paste whatever bitmaps onto it, create an ImageDraw layer from that, updating text, etc. and then flush the image to the display with device.display(img)

svenyonson commented 6 years ago

Thanks, just what I needed.

thijstriemstra commented 6 years ago

A really slick phone-ish interface example would be nice, eg.

x761_17my_ngi_connectivity_tcm76-312913_desktop_1024x576

heat_gauge

svenyonson commented 6 years ago

Snapshots seem to be the way to go, I have several regions set up and working. One outstanding question though - from within the render function for a snapshot, how can I access paste_into() method of the snapshot so that I can paint an image in the snapshot?

svenyonson commented 6 years ago

Update: got it working: draw.bitmap((0,0),wifiIcon) It looks like the draw parameter of the render function is of type PIL.DrawImage.DrawImage. This is the legacy API, yes?

rm-hull commented 6 years ago

Yes, the render canvas is indeed a PIL.DrawImage.DrawImage. The "legacy API" is provided by https://luma-core.readthedocs.io/en/latest/api-documentation.html#module-luma.core.legacy - the docs should explain why they are named legacy.

Also: just be aware that Pillow's draw.bitmap does not do exactly what you might think it does - it is a actually mask operation, but if it probably works for your use case, then fair enough.


screen shot 2018-03-30 at 23 40 33

Would be interested to see a screenshot of your app !

svenyonson commented 6 years ago

Ah, yes it does work for this use case - the icon is all one color with a transparent background, so the mask does pretty much the same thing. But I would very much like to know how to paint an actual bitmap - all colors preserved - from within the render method of a snapshot. Is this possible? Our app is not all that sexy but I will send a screen shot when it is fleshed out.

rm-hull commented 6 years ago

In short, you can't: the render canvas method encapsulates and manages the image and drawing surface entirely. Either something like (untested):

device = ...
bkgnd = Image.new(device.mode, device.size)
bkgnd.paste(wifiIcon, (0, 0))
with canvas(device, bkgnd) as draw:
    draw.line((0, 0) + device.size, fill=128)
    draw.line((0, device.size[1], device.size[0], 0), fill=128)

or dont use the canvas at all, and initiate an unmanaged draw object:

device = ...
im = Image.new(device.mode, device.size)
im.paste(wifiIcon, (0, 0))
draw = ImageDraw.Draw(im)
draw.line((0, 0) + device.size, fill=128)
draw.line((0, device.size[1], device.size[0], 0), fill=128)
del draw
device.display(im)

[All the canvas context really does is manage creating the draw object and deleting it afterwards]

svenyonson commented 6 years ago

Thanks Richard, things are working nicely now. Two questions: 1) Is there a way to specify custom RGB colors when using draw(), text(), etc? All I can find are strings like "yellow", "white", etc. 2) Are there any settings I can try to minimize the horizontal bleed from white text into the darker background colors? (eg. contrast, brightness)

2018-04-11 09 44 53

rm-hull commented 6 years ago

it supports whatever color gamut that Pillow supports, for example, see http://pillow.readthedocs.io/en/5.1.x/reference/ImageColor.html?highlight=color#color-names and https://pillow.readthedocs.io/en/5.1.x/reference/ImageDraw.html#example-draw-partial-opacity-text

You can supply a hex number (in a string, so "#ff0000" is red), or if you supply a 3-tuple (255, 0, 0), then it is a solid color representing the RGB components, else a 4-tuple is RGBA, where the last value is the alpha transparency, eg, (255, 0, 0, 127)

thijstriemstra commented 2 years ago

Update: got it working

Closing.