From 84af5fd0a330ed3d9ece23c5b596e2b87772393a Mon Sep 17 00:00:00 2001 From: ed Date: Fri, 7 Oct 2022 00:59:44 +0200 Subject: [PATCH] scale qr-code to fit console size --- copyparty/__main__.py | 3 ++- copyparty/stolen/qrcodegen.py | 25 ++++++++++++++++--------- copyparty/tcpsrv.py | 15 +++++++++++++-- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/copyparty/__main__.py b/copyparty/__main__.py index 9479da78..2a626616 100755 --- a/copyparty/__main__.py +++ b/copyparty/__main__.py @@ -587,7 +587,8 @@ def run_argparse(argv: list[str], formatter: Any, retry: bool) -> argparse.Names ap2.add_argument("--qr-ip", metavar="PREFIX", type=u, default="", help="select IP which starts with PREFIX") ap2.add_argument("--qr-fg", metavar="COLOR", type=int, default=16, help="foreground") ap2.add_argument("--qr-bg", metavar="COLOR", type=int, default=229, help="background (white=255)") - ap2.add_argument("--qr-pad", metavar="CELLS", type=int, default=4, help="padding (spec says 4 or more)") + ap2.add_argument("--qr-pad", metavar="CELLS", type=int, default=4, help="padding (spec says 4 or more, but 1 is usually fine)") + ap2.add_argument("--qr-zoom", metavar="N", type=int, default=0, help="[\033[32m1\033[0m]=1x, [\033[32m2\033[0m]=2x, [\033[32m0\033[0m]=auto (try 2 on broken fonts)") ap2 = ap.add_argument_group('upload options') ap2.add_argument("--dotpart", action="store_true", help="dotfile incomplete uploads, hiding them from clients unless -ed") diff --git a/copyparty/stolen/qrcodegen.py b/copyparty/stolen/qrcodegen.py index 4f2e4f47..3edc3171 100644 --- a/copyparty/stolen/qrcodegen.py +++ b/copyparty/stolen/qrcodegen.py @@ -170,23 +170,30 @@ class QrCode(object): self._apply_mask(msk) # Apply the final choice of mask self._draw_format_bits(msk) # Overwrite old format bits - def render(self, pad=4) -> str: + def render(self, zoom=1, pad=4) -> str: tab = self.modules sz = self.size - if sz % 2: + if sz % 2 and zoom == 1: tab.append([False] * sz) tab = [[False] * sz] * pad + tab + [[False] * sz] * pad tab = [[False] * pad + x + [False] * pad for x in tab] rows: list[str] = [] - for y in range(0, len(tab), 2): - row = "" - for x in range(len(tab[y])): - v = 2 if tab[y][x] else 0 - v += 1 if tab[y + 1][x] else 0 - row += " ▄▀█"[v] - rows.append(row) + if zoom == 1: + for y in range(0, len(tab), 2): + row = "" + for x in range(len(tab[y])): + v = 2 if tab[y][x] else 0 + v += 1 if tab[y + 1][x] else 0 + row += " ▄▀█"[v] + rows.append(row) + else: + for tr in tab: + row = "" + for zb in tr: + row += " █"[int(zb)] * 2 + rows.append(row) return "\n".join(rows) diff --git a/copyparty/tcpsrv.py b/copyparty/tcpsrv.py index fa4a4fb5..3c46d0ce 100644 --- a/copyparty/tcpsrv.py +++ b/copyparty/tcpsrv.py @@ -8,7 +8,7 @@ import sys from .__init__ import ANYWIN, MACOS, PY2, TYPE_CHECKING, VT100, unicode from .stolen.qrcodegen import QrCode -from .util import chkcmd, sunpack +from .util import chkcmd, sunpack, termsize if TYPE_CHECKING: from .svchub import SvcHub @@ -391,7 +391,18 @@ class TcpSrv(object): if PY2: btxt = sunpack(b"B" * len(btxt), btxt) - qr = QrCode.encode_binary(btxt).render() + pad = self.args.qr_pad + zoom = self.args.qr_zoom + qrc = QrCode.encode_binary(btxt) + if zoom == 0: + try: + tw, th = termsize() + tsz = min(tw // 2, th) + zoom = 1 if qrc.size + pad * 2 >= tsz else 2 + except: + zoom = 1 + + qr = qrc.render(zoom, pad) if not VT100: return "{}\n{}".format(txt, qr)