From 54c6880a9238c3226561e41be885dbd1122c0f0a Mon Sep 17 00:00:00 2001 From: Michael Mulqueen Date: Sun, 26 Jul 2015 17:37:20 +0100 Subject: [PATCH] Datamatrix can now be up to 174 characters because regions are implemented. See https://github.com/mmulqueen/pyStrich/issues/2 --- pystrich/datamatrix/__init__.py | 7 ++- pystrich/datamatrix/renderer.py | 83 ++++++++++++++++++-------- pystrich/datamatrix/test_datamatrix.py | 1 + pystrich/datamatrix/textencoder.py | 12 +++- setup.py | 2 +- 5 files changed, 73 insertions(+), 32 deletions(-) diff --git a/pystrich/datamatrix/__init__.py b/pystrich/datamatrix/__init__.py index b62fde3..496e99f 100644 --- a/pystrich/datamatrix/__init__.py +++ b/pystrich/datamatrix/__init__.py @@ -54,7 +54,8 @@ def __init__(self, text): codewords = enc.encode(text) self.width = 0 self.height = 0 - matrix_size = enc.mtx_size + matrix_size = enc.mtx_size*enc.regions + self.regions = enc.regions self.matrix = [[None] * matrix_size for _ in range(0, matrix_size)] @@ -63,12 +64,12 @@ def __init__(self, text): def save(self, filename, cellsize=5): """Write the matrix out to an image file""" - dmtx = DataMatrixRenderer(self.matrix) + dmtx = DataMatrixRenderer(self.matrix, self.regions) dmtx.write_file(cellsize, filename) def get_imagedata(self, cellsize=5): """Write the matrix out to an PNG bytestream""" - dmtx = DataMatrixRenderer(self.matrix) + dmtx = DataMatrixRenderer(self.matrix, self.regions) self.width = dmtx.width self.height = dmtx.height return dmtx.get_imagedata(cellsize) diff --git a/pystrich/datamatrix/renderer.py b/pystrich/datamatrix/renderer.py index f3ffed7..8298f12 100644 --- a/pystrich/datamatrix/renderer.py +++ b/pystrich/datamatrix/renderer.py @@ -7,14 +7,21 @@ from PIL import Image +def repr_matrix(matrix): + return "\n".join(repr(x) for x in matrix) + + class DataMatrixRenderer: """Rendering class - given a pre-populated datamatrix. it will add edge handles and render to either to an image (including quiet zone) or ascii printout""" - def __init__(self, matrix): + def __init__(self, matrix, regions): self.width = len(matrix) self.height = len(matrix[0]) + self.regions = regions + self.region_size = self.width//regions + self.quiet_zone = 2 self.matrix = matrix @@ -32,41 +39,67 @@ def put_cell(self, position, colour=1): def add_handles(self): """Set up the edge handles""" - # bottom solid border - for posx in range(0, self.width): - self.put_cell((posx, self.height - 1)) - # left solid border - for posy in range(0, self.height): - self.put_cell((0, posy)) + for x_index in range(self.regions): + for y_index in range(self.regions): + x_origin = x_index * (self.region_size + 2) + self.quiet_zone + y_origin = y_index * (self.region_size + 2) + self.quiet_zone + x_max = x_origin + self.region_size + 1 + y_max = y_origin + self.region_size + 1 + + # bottom solid border + for posx in range(x_origin, x_max): + self.put_cell((posx, y_max)) - # top broken border - for i in range(0, self.width - 1, 2): - self.put_cell((i, 0)) + # left solid border + for posy in range(y_origin, y_max): + self.put_cell((x_origin, posy)) - # right broken border - for i in range(self.height - 1, 0, -2): - self.put_cell((self.width - 1, i)) + # top broken border + for i in range(x_origin, x_max, 2): + self.put_cell((i, y_origin)) - def add_border(self, colour=1, width=1): + # right broken border + for i in range(y_max, y_origin, -2): + self.put_cell((x_max, i)) + + def add_border(self, colour=1): """Wrap the matrix in a border of given width and colour""" - self.width += (width * 2) - self.height += (width * 2) - - self.matrix = \ - [[colour] * self.width] * width + \ - [[colour] * width + self.matrix[i] + [colour] * width - for i in range(0, self.height - (width * 2))] + \ - [[colour] * self.width] * width + a_gap = 1 # Gap for alignment/"handles" + self.width += a_gap*2 + self.quiet_zone*2 + (self.regions-1)*a_gap*2 + self.height += a_gap*2 + self.quiet_zone*2 + (self.regions-1)*a_gap*2 + + new_matrix = [] + for i in range(a_gap+self.quiet_zone): + new_matrix += [[colour]*self.width] + + for row_n, row in enumerate(self.matrix): + if row_n > 0 and row_n % self.region_size == 0: + # Vertical gap between regions + for j in range(a_gap*2): + new_matrix += [[colour]*self.width] + # Left gap + new_row = [colour]*(a_gap+self.quiet_zone) + # Split according to regions + for i in range(self.regions): + part = row[i*self.region_size:(i+1)*self.region_size] + if i > 0: + # Add the space for the alignment gap + new_row += [colour]*(a_gap*2) + new_row += part + # Right gap + new_row += [colour]*(a_gap+self.quiet_zone) + new_matrix.append(new_row) + + for i in range(a_gap+self.quiet_zone): + new_matrix += [[colour]*self.width] + self.matrix = new_matrix def get_pilimage(self, cellsize): """Return the matrix as an PIL object""" - # add the quiet zone (2 x cell width) - self.add_border(colour=0, width=2) - # get the matrix into the right buffer format buff = self.get_buffer(cellsize) diff --git a/pystrich/datamatrix/test_datamatrix.py b/pystrich/datamatrix/test_datamatrix.py index fd7ef7b..1b589ec 100644 --- a/pystrich/datamatrix/test_datamatrix.py +++ b/pystrich/datamatrix/test_datamatrix.py @@ -39,6 +39,7 @@ class MatrixTest(unittest.TestCase): "http://www.hudora.de/track/003400", "http://www.hudora.de/track/00340", "http://www.hudora.de/track/0034", + "This sentence will need multiple datamatrix regions. Tests to see whether bug 2 is fixed." ) def test_encode_decode(self): diff --git a/pystrich/datamatrix/textencoder.py b/pystrich/datamatrix/textencoder.py index 3b24f5a..d5abe80 100644 --- a/pystrich/datamatrix/textencoder.py +++ b/pystrich/datamatrix/textencoder.py @@ -2,7 +2,6 @@ __revision__ = "$Rev$" -import sys from .reedsolomon import get_reed_solomon_code import logging @@ -23,6 +22,11 @@ 14, 16, 18, 20, 22, 24, 18, 20, 22) +hv_regions = (1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, + 4, 4, 4, 4, 4, 4, + 6, 6, 6) + class DataTooLongForImplementation(Exception): pass @@ -35,6 +39,7 @@ def __init__(self): self.codewords = '' self.size_index = None self.mtx_size = 0 + self.regions = None def encode(self, text): """Encode the given text and add padding and error codes @@ -53,6 +58,7 @@ def encode(self, text): ' '.join([str(ord(codeword)) for codeword in self.codewords])) self.mtx_size = data_region_size[self.size_index] + self.regions = hv_regions[self.size_index] log.debug("Matrix size will be %d", self.mtx_size) @@ -94,8 +100,8 @@ def pad(self): if length >= unpadded_len: break - if self.size_index > 8: - raise DataTooLongForImplementation("PyStrich does not currently support encoding beyond 44 characters. " + if self.size_index > 13: + raise DataTooLongForImplementation("PyStrich does not currently support encoding beyond 174 characters. " "See https://github.com/mmulqueen/pyStrich/issues/2") # Number of characters with which the data will be padded diff --git a/setup.py b/setup.py index beeaf3c..11b4410 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name='pyStrich', - version='0.6', + version='0.7', packages=['pystrich', 'pystrich.ean13', 'pystrich.qrcode',