Skip to content

Commit

Permalink
Datamatrix can now be up to 174 characters because regions are implem…
Browse files Browse the repository at this point in the history
…ented. See #2
  • Loading branch information
mmulqueen committed Jul 26, 2015
1 parent 6013231 commit 54c6880
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 32 deletions.
7 changes: 4 additions & 3 deletions pystrich/datamatrix/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)]

Expand All @@ -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)
Expand Down
83 changes: 58 additions & 25 deletions pystrich/datamatrix/renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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)

Expand Down
1 change: 1 addition & 0 deletions pystrich/datamatrix/test_datamatrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
12 changes: 9 additions & 3 deletions pystrich/datamatrix/textencoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

__revision__ = "$Rev$"

import sys
from .reedsolomon import get_reed_solomon_code
import logging

Expand All @@ -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
Expand All @@ -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
Expand All @@ -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)

Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name='pyStrich',
version='0.6',
version='0.7',
packages=['pystrich',
'pystrich.ean13',
'pystrich.qrcode',
Expand Down

0 comments on commit 54c6880

Please sign in to comment.