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

64 wiersze
2.3 KiB
Python

# 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
from framebuf import FrameBuffer, MONO_HLSB
from gui.core.ugui import Widget
from gui.core.colors import *
from gui.core.ugui import ssd
from uQR import QRCode
from utime import ticks_diff, ticks_ms
class QRMap(Widget):
@staticmethod
def len_side(version):
return 4 * version + 17
@staticmethod
def make_buffer(version, scale):
side = QRMap.len_side(version) * scale
width = (side >> 3) + int(side & 7 > 0) # Width in bytes
return bytearray(side * width)
def __init__(self, writer, row, col, version=4, scale=1, *, bdcolor=RED, buf=None):
self._version = version
self._scale = scale
self._iside = self.len_side(version) # Dimension of unscaled QR image less border
side = self._iside * scale
# Widget allows 4 * scale border around each edge
border = 4 * scale
wside = side + 2 * border # Widget dimension
super().__init__(writer, row, col, wside, wside, BLACK, WHITE, bdcolor, False)
super()._set_callbacks(self._update, ())
if buf is None:
buf = QRMap.make_buffer(version, scale)
self._fb = FrameBuffer(buf, side, side, MONO_HLSB)
self._irow = row + border
self._icol = col + border
self._qr = QRCode(version, border=0)
def show(self):
if super().show(False): # Show white border
palette = ssd.palette
palette.bg(self.bgcolor)
palette.fg(self.fgcolor)
ssd.blit(self._fb, self._icol, self._irow, -1, palette)
def _update(self, _): # Runs when value changes
t = ticks_ms()
qr = self._qr
qr.clear()
qr.add_data(self._value)
matrix = qr.get_matrix() # 750ms. Rest of the routine adds 50ms
if qr.version != self._version:
raise ValueError("Text too long for QR version.")
wd = self._iside
s = self._scale
for row in range(wd):
for col in range(wd):
v = matrix[row][col]
for nc in range(s):
for nr in range(s):
self._fb.pixel(col * s + nc, row * s + nr, v)