micropython-micro-gui/gui/widgets/qrcode.py

79 wiersze
2.8 KiB
Python
Czysty Zwykły widok Historia

2022-05-21 17:56:04 +00:00
# qrcode.py Provides the QRMap widget to display the output of uQR library.
# Released under the MIT License (MIT). See LICENSE.
# Copyright (c) 2022 Peter Hinch
import gc
from framebuf import FrameBuffer, MONO_HLSB
from gui.core.ugui import Widget
from gui.core.colors import *
from gui.core.ugui import ssd
class QRMap(Widget):
@staticmethod
def make_buffer(height, width): # Given dimensions in pixels
w = (width >> 3) + int(width & 7 > 0)
return bytearray(height * w)
def __init__(self, writer, row, col, image, scale=1, *, fgcolor=None, bgcolor=None, bdcolor=RED, buf=None):
self._scale = scale
self._image = image
try:
height, width = self.dimensions()
except OSError:
print(f"Failed to access {obj}.")
raise
super().__init__(writer, row, col, height, width, fgcolor, bgcolor, bdcolor, False)
if buf is None:
buf = QRMap.make_buffer(height, width)
else:
if len(buf) != ((width >> 3) + int(width & 7 > 0)) * height:
raise OSError("Buffer size does not match width and height.")
self._fb = FrameBuffer(buf, width, height, MONO_HLSB)
if isinstance(image, list):
self.value(image)
def show(self):
if super().show(True): # Draw or erase border
palette = ssd.palette
palette.bg(self.bgcolor)
palette.fg(self.fgcolor)
ssd.blit(self._fb, self.col, self.row, -1, palette)
def color(self, fgcolor=None, bgcolor=None):
if fgcolor is not None:
self.fgcolor = fgcolor
if bgcolor is not None:
self.bgcolor = bgcolor
self.draw = True
def dimensions(self): # Dimensions of current image in pixels
obj = self._image
if isinstance(obj, list): # 2d list of booleans
return len(obj) * self._scale, len(obj[0] * self._scale)
if isinstance(obj, tuple):
return obj
raise OSError
def value(self, obj):
self._image = obj
self._fb.fill(self.bgcolor) # In case tuple was passed or image smaller than buffer
if isinstance(obj, list): # 2d list of booleans
wd, ht = self.dimensions()
s = self._scale
if wd > self.width or ht > self.height:
print('Object too large for buffer', wd, self.width, ht, self.height)
else:
print(f"Object is {wd} x {ht} pixels")
for row in range(ht//s):
for col in range(wd//s):
v = obj[row][col]
for nc in range(s):
for nr in range(s):
self._fb.pixel(col * s + nc, row * s + nr, v)
else:
print(f"Invalid QR code {obj}.")
self.draw = True
gc.collect()