diff --git a/src/rmqrcode/qr_image.py b/src/rmqrcode/qr_image.py index f17d7b9..a2ee637 100644 --- a/src/rmqrcode/qr_image.py +++ b/src/rmqrcode/qr_image.py @@ -1,15 +1,12 @@ from PIL import Image, ImageDraw -from .enums.color import Color - class QRImage: def __init__(self, qr, module_size=10): self._module_size = module_size - self._img = Image.new( - "RGB", ((qr.width() + 4) * module_size, (qr.height() + 4) * module_size), (255, 255, 255) - ) - self._make_image(qr) + qr_list = qr.to_list() + self._img = Image.new("RGB", (len(qr_list[0]) * module_size, len(qr_list) * module_size), (255, 255, 255)) + self._make_image(qr_list) def show(self): self._img.show() @@ -26,25 +23,17 @@ def get_ndarray(self): def save(self, name): self._img.save(name) - def _make_image(self, qr): + def _make_image(self, qr_list): draw = ImageDraw.Draw(self._img) - for y in range(qr.height()): - for x in range(qr.width()): - r, g, b = 125, 125, 125 - if qr.value_at(x, y) == Color.BLACK: - r, g, b = 0, 0, 0 - elif qr.value_at(x, y) == Color.WHITE: - r, g, b, = ( - 255, - 255, - 255, - ) + for y in range(len(qr_list)): + for x in range(len(qr_list[0])): + r, g, b = (0, 0, 0) if qr_list[y][x] else (255, 255, 255) draw.rectangle( xy=( - (x + 2) * self._module_size, - (y + 2) * self._module_size, - (x + 1 + 2) * self._module_size, - (y + 1 + 2) * self._module_size, + x * self._module_size, + y * self._module_size, + (x + 1) * self._module_size, + (y + 1) * self._module_size, ), fill=(r, g, b), ) diff --git a/src/rmqrcode/rmqrcode.py b/src/rmqrcode/rmqrcode.py index 0aa599f..41851d5 100644 --- a/src/rmqrcode/rmqrcode.py +++ b/src/rmqrcode/rmqrcode.py @@ -14,6 +14,8 @@ class rMQR: + QUIET_ZONE_MODULES = 2 + @staticmethod def _init_logger(): logger = logging.getLogger(__name__) @@ -72,7 +74,7 @@ def sort_key(x): qr.make(data) return qr - def __init__(self, version, ecc, logger=None): + def __init__(self, version, ecc, with_quiet_zone=True, logger=None): self._logger = logger or rMQR._init_logger() if not rMQR.validate_version(version): @@ -109,10 +111,23 @@ def width(self): def value_at(self, x, y): return self._qr[y][x] - def to_list(self): + def to_list(self, with_quiet_zone=True): + res = [] + if with_quiet_zone: + for y in range(self.QUIET_ZONE_MODULES): + res.append([0] * (self.width() + self.QUIET_ZONE_MODULES * 2)) + for row in self._to_binary_list(): + res.append([0] * self.QUIET_ZONE_MODULES + row + [0] * self.QUIET_ZONE_MODULES) + for y in range(self.QUIET_ZONE_MODULES): + res.append([0] * (self.width() + self.QUIET_ZONE_MODULES * 2)) + else: + res = self._to_binary_list() + return res + + def _to_binary_list(self): return [list(map(lambda x: 1 if x == Color.BLACK else 0, column)) for column in self._qr] - def __str__(self): + def __str__(self, with_quiet_zone=True): res = "" show = {} @@ -123,13 +138,25 @@ def __str__(self): show[False] = "_" res += f"rMQR Version R{self._height}x{self._width}:\n" - for i in range(self._height): - for j in range(self._width): + if with_quiet_zone: + res += (show[False] * (self.width() + self.QUIET_ZONE_MODULES * 2) + "\n") * self.QUIET_ZONE_MODULES + + for i in range(self.height()): + if with_quiet_zone: + res += show[False] * self.QUIET_ZONE_MODULES + + for j in range(self.width()): if self._qr[i][j] in show: res += show[self._qr[i][j]] else: res += self._qr[i][j] + + if with_quiet_zone: + res += show[False] * self.QUIET_ZONE_MODULES res += "\n" + + if with_quiet_zone: + res += (show[False] * (self.width() + self.QUIET_ZONE_MODULES * 2) + "\n") * self.QUIET_ZONE_MODULES return res def _put_finder_pattern(self): diff --git a/tests/rmqrcode_test.py b/tests/rmqrcode_test.py index b857821..c075f77 100644 --- a/tests/rmqrcode_test.py +++ b/tests/rmqrcode_test.py @@ -14,6 +14,12 @@ def test_make(self): qr = rMQR('R13x99', ErrorCorrectionLevel.M) qr.make("abc") + assert len(qr.to_list(with_quiet_zone=True)) is 17 + assert len(qr.to_list(with_quiet_zone=True)[0]) is 103 + + assert len(qr.to_list(with_quiet_zone=False)) is 13 + assert len(qr.to_list(with_quiet_zone=False)[0]) is 99 + def test_raise_too_long_error(self): with pytest.raises(DataTooLongError) as e: s = "a".ljust(200, "a")