From 4e17c0cfe2d33b9eb430dfaf8bc0944a24c65914 Mon Sep 17 00:00:00 2001 From: Robin Becker Date: Fri, 23 Aug 2019 13:17:00 +0100 Subject: [PATCH 1/3] allow -k --kind svg|image, make svg rendering like image version --- pdf417gen/console.py | 170 ++++++++++++++++++++++------------------- pdf417gen/rendering.py | 66 +++++++++++----- 2 files changed, 136 insertions(+), 100 deletions(-) diff --git a/pdf417gen/console.py b/pdf417gen/console.py index 79abba8..31bb864 100644 --- a/pdf417gen/console.py +++ b/pdf417gen/console.py @@ -1,112 +1,124 @@ +import logging import sys from argparse import ArgumentParser -from pdf417gen import encode, render_image +from pdf417.encoding import encode +from pdf417.rendering import render_image, render_svg -def print_usage(): - print("Usage: pdf417gen [command]") - print("") - print("Commands:") - print(" help show this help message and exit") - print(" encode generate a bar code from given input") - print("") - print("https://github.com/ihabunek/pdf417gen") +def encode_data(args): + if not args.text: + logging.info("Waiting data on stdin.") + args.text = sys.stdin.read() + codes = encode( + args.text, + columns=args.columns, + security_level=args.security_level, + encoding=args.encoding, + numeric_compaction=args.numeric_compaction, + ) -def print_err(msg): - sys.stderr.write('\033[91m' + msg + '\033[0m' + "\n") + if args.kind=='svg': + xml = render_svg( + codes, + scale=args.scale, + ratio=args.ratio, + padding=args.padding, + fg_color=args.fg_color, + bg_color=args.bg_color, + ) + import xml.etree.ElementTree as ET + print(ET.tostring(xml.getroot())) + else: + image = render_image( + codes, + scale=args.scale, + ratio=args.ratio, + padding=args.padding, + fg_color=args.fg_color, + bg_color=args.bg_color, + ) + if args.output: + image.save(args.output) + else: + image.show() -def get_parser(): - parser = ArgumentParser(epilog="https://github.com/ihabunek/pdf417gen", - description="Generate a bar code from given input") - parser.add_argument("text", type=str, nargs="?", - help="Text or data to encode. Alternatively data can be piped in.") +parser = ArgumentParser(epilog="https://github.com/mosquito/pdf417", + description="Generate a bar code from given input") - parser.add_argument("-c", "--columns", dest="columns", type=int, - help="The number of columns (default is 6).", - default=6) +parser.set_defaults(func=lambda *_: parser.print_help()) - parser.add_argument("-l", "--security-level", dest="security_level", type=int, - help="Security level (default is 2).", - default=2) - parser.add_argument("-e", "--encoding", dest="encoding", type=str, - help="Character encoding used to decode input (default is utf-8).", - default='utf-8') +subparsers = parser.add_subparsers(help="Encodes text to barcode") +subparser = subparsers.add_parser("encode") - parser.add_argument("-s", "--scale", dest="scale", type=int, - help="Module width in pixels (default is 3).", - default=3) +subparser.add_argument("text", type=str, nargs="?", + help="Text or data to encode. " + "Alternatively data can be piped in.") - parser.add_argument("-r", "--ratio", dest="ratio", type=int, - help="Module height to width ratio (default is 3).", - default=3) +subparser.add_argument("-c", "--columns", type=int, default=6, + help="The number of columns (default is 6).") - parser.add_argument("-p", "--padding", dest="padding", type=int, - help="Image padding in pixels (default is 20).", - default=20) +subparser.add_argument("-l", "--security-level", default=2, type=int, + help="Security level (default is 2).") - parser.add_argument("-f", "--foreground-color", dest="fg_color", type=str, - help="Foreground color in hex (default is '#000000').", - default="#000000") +subparser.add_argument("-e", "--encoding", type=str, default='utf-8', + help="Character encoding used to decode " + "input (default is utf-8).") - parser.add_argument("-b", "--background-color", dest="bg_color", type=str, - help="Foreground color in hex (default is '#FFFFFF').", - default="#FFFFFF") +subparser.add_argument("-n", "--numeric_compaction", action='store_true', + help="This mode can pack almost 3 digits " + "(2.93) info a symbol character") - parser.add_argument("-o", "--output", dest="output", type=str, - help="Target file (if not given, will just show the barcode).") +subparser.add_argument("-s", "--scale", default=3, type=int, + help="Module width in pixels (default is 3).") - return parser +subparser.add_argument("-r", "--ratio", dest="ratio", type=int, default=3, + help="Module height to width ratio (default is 3).") +subparser.add_argument("-p", "--padding", default=20, type=int, + help="Image padding in pixels (default is 20).") -def do_encode(args): - args = get_parser().parse_args(args) - text = args.text +subparser.add_argument("-f", "--foreground-color", dest="fg_color", type=str, + help="Foreground color in hex (default is '#000000').", + default="#000000") - # If no text is given, check stdin - if not text: - text = sys.stdin.read() +subparser.add_argument("-b", "--background-color", dest="bg_color", type=str, + help="Foreground color in hex (default is '#FFFFFF'.", + default="#FFFFFF") - if not text: - print_err("No input given") - return +subparser.add_argument("-o", "--output", dest="output", type=str, + help="Target file (if not given, " + "will just show the barcode).") +subparser.add_argument("-k", "--kind", type=str, default='image', + help=" what kind of image to produce eg image|svg " + "input (default is image).") +subparser.set_defaults(func=encode_data) - try: - codes = encode( - text, - columns=args.columns, - security_level=args.security_level, - encoding=args.encoding, - ) - image = render_image( - codes, - scale=args.scale, - ratio=args.ratio, - padding=args.padding, - fg_color=args.fg_color, - bg_color=args.bg_color, - ) +def entrypoint(): + logging.basicConfig( + format='\033[91m%(message)s\033[0m', + level=logging.INFO + ) + + arguments = parser.parse_args() + try: + arguments.func(arguments) except Exception as e: - print_err(str(e)) - return + logging.exception("%r", e) + return 10 - if args.output: - image.save(args.output) - else: - image.show() + return 0 def main(): - command = sys.argv[1] if len(sys.argv) > 1 else None - args = sys.argv[2:] + exit(entrypoint()) - if command == 'encode': - do_encode(args) - else: - print_usage() + +if __name__ == '__main__': + main() diff --git a/pdf417gen/rendering.py b/pdf417gen/rendering.py index 72cd8eb..c0ec120 100644 --- a/pdf417gen/rendering.py +++ b/pdf417gen/rendering.py @@ -1,6 +1,12 @@ -from PIL import Image, ImageColor, ImageOps from xml.etree.ElementTree import ElementTree, Element, SubElement +try: + from PIL import Image, ImageColor, ImageOps +except ImportError: + Image = None + ImageColor = None + ImageOps = None + def barcode_size(codes): """Returns the barcode size in modules.""" @@ -29,6 +35,7 @@ def modules(codes): def parse_color(color): + assert ImageColor, "Module PIL is not installed" return ImageColor.getrgb(color) @@ -36,7 +43,11 @@ def rgb_to_hex(color): return '#{0:02x}{1:02x}{2:02x}'.format(*color) -def render_image(codes, scale=3, ratio=3, padding=20, fg_color="#000", bg_color="#FFF"): +def render_image(codes, scale=3, ratio=3, padding=20, fg_color="#000", + bg_color="#FFF"): + + assert Image and ImageOps, "Module PIL is not installed" + width, height = barcode_size(codes) # Translate hex code colors to RGB tuples @@ -58,32 +69,45 @@ def render_image(codes, scale=3, ratio=3, padding=20, fg_color="#000", bg_color= return image -def render_svg(codes, scale=3, ratio=3, color="#000", description=None): +def render_svg(codes, scale=3, ratio=3, padding=20, fg_color="#000", bg_color=None, description=None): # Barcode size in modules width, height = barcode_size(codes) + padding = max(padding,0) #disallow negative padding # Size of each module scale_x = scale scale_y = scale * ratio - color = rgb_to_hex(parse_color(color)) + fg_color = rgb_to_hex(parse_color(fg_color)) - root = Element('svg', { - "version": "1.1", - "xmlns": "http://www.w3.org/2000/svg", - "width": str(width * scale_x), - "height": str(height * scale_y), - }) + w = str(width * scale_x+2*padding) + h = str(height * scale_y+2*padding) + root = Element('svg', dict( + version = "1.1", + xmlns = "http://www.w3.org/2000/svg", + width = w, + height = h, + )) if description: description_element = SubElement(root, 'description') description_element.text = description - group = SubElement(root, 'g', { - "id": "barcode", - "fill": color, - "stroke": "none" - }) + if bg_color is not None: + SubElement(root, 'rect', dict( + x = "0", + y = "0", + width = w, + height = h, + fill = bg_color, + )) + + group = SubElement(root, 'g', dict( + id = "barcode", + fill = fg_color, + stroke = "none", + transform="translate(%s,%s)" % (padding,padding), + )) # Generate the barcode modules for col_id, row_id, visible in modules(codes): @@ -91,11 +115,11 @@ def render_svg(codes, scale=3, ratio=3, color="#000", description=None): y = row_id * scale_y if visible: - SubElement(group, 'rect', { - "x": str(x), - "y": str(y), - "width": str(scale_x), - "height": str(scale_y), - }) + SubElement(group, 'rect', dict( + x = str(x), + y = str(y), + width = str(scale_x), + height = str(scale_y), + )) return ElementTree(element=root) From f355deeaded418cc8dd3842b17d0fdef4c36f6c1 Mon Sep 17 00:00:00 2001 From: Robin Becker Date: Fri, 23 Aug 2019 14:59:32 +0100 Subject: [PATCH 2/3] fix imports and get svg showing (at least in ubuntu) --- pdf417gen/console.py | 208 ++++++++++++++++++++++------------------ tests/test_renderers.py | 7 +- 2 files changed, 118 insertions(+), 97 deletions(-) diff --git a/pdf417gen/console.py b/pdf417gen/console.py index 31bb864..65c3b19 100644 --- a/pdf417gen/console.py +++ b/pdf417gen/console.py @@ -1,124 +1,144 @@ -import logging -import sys +import sys, os from argparse import ArgumentParser -from pdf417.encoding import encode -from pdf417.rendering import render_image, render_svg - - -def encode_data(args): - if not args.text: - logging.info("Waiting data on stdin.") - args.text = sys.stdin.read() - - codes = encode( - args.text, - columns=args.columns, - security_level=args.security_level, - encoding=args.encoding, - numeric_compaction=args.numeric_compaction, - ) - - if args.kind=='svg': - xml = render_svg( - codes, - scale=args.scale, - ratio=args.ratio, - padding=args.padding, - fg_color=args.fg_color, - bg_color=args.bg_color, - ) - import xml.etree.ElementTree as ET - print(ET.tostring(xml.getroot())) - else: - image = render_image( - codes, - scale=args.scale, - ratio=args.ratio, - padding=args.padding, - fg_color=args.fg_color, - bg_color=args.bg_color, - ) +from pdf417gen import encode, render_image, render_svg - if args.output: - image.save(args.output) - else: - image.show() +def print_usage(): + print("Usage: pdf417gen [command]") + print("") + print("Commands:") + print(" help show this help message and exit") + print(" encode generate a bar code from given input") + print("") + print("https://github.com/ihabunek/pdf417gen") -parser = ArgumentParser(epilog="https://github.com/mosquito/pdf417", - description="Generate a bar code from given input") -parser.set_defaults(func=lambda *_: parser.print_help()) +def print_err(msg): + sys.stderr.write('\033[91m' + msg + '\033[0m' + "\n") -subparsers = parser.add_subparsers(help="Encodes text to barcode") -subparser = subparsers.add_parser("encode") +def get_parser(): + parser = ArgumentParser(epilog="https://github.com/ihabunek/pdf417gen", + description="Generate a bar code from given input") -subparser.add_argument("text", type=str, nargs="?", - help="Text or data to encode. " - "Alternatively data can be piped in.") + parser.add_argument("text", type=str, nargs="?", + help="Text or data to encode. Alternatively data can be piped in.") -subparser.add_argument("-c", "--columns", type=int, default=6, - help="The number of columns (default is 6).") + parser.add_argument("-c", "--columns", dest="columns", type=int, + help="The number of columns (default is 6).", + default=6) -subparser.add_argument("-l", "--security-level", default=2, type=int, - help="Security level (default is 2).") + parser.add_argument("-l", "--security-level", dest="security_level", type=int, + help="Security level (default is 2).", + default=2) -subparser.add_argument("-e", "--encoding", type=str, default='utf-8', - help="Character encoding used to decode " - "input (default is utf-8).") + parser.add_argument("-e", "--encoding", dest="encoding", type=str, + help="Character encoding used to decode input (default is utf-8).", + default='utf-8') -subparser.add_argument("-n", "--numeric_compaction", action='store_true', - help="This mode can pack almost 3 digits " - "(2.93) info a symbol character") + parser.add_argument("-s", "--scale", dest="scale", type=int, + help="Module width in pixels (default is 3).", + default=3) -subparser.add_argument("-s", "--scale", default=3, type=int, - help="Module width in pixels (default is 3).") + parser.add_argument("-r", "--ratio", dest="ratio", type=int, + help="Module height to width ratio (default is 3).", + default=3) -subparser.add_argument("-r", "--ratio", dest="ratio", type=int, default=3, - help="Module height to width ratio (default is 3).") + parser.add_argument("-p", "--padding", dest="padding", type=int, + help="Image padding in pixels (default is 20).", + default=20) -subparser.add_argument("-p", "--padding", default=20, type=int, - help="Image padding in pixels (default is 20).") + parser.add_argument("-f", "--foreground-color", dest="fg_color", type=str, + help="Foreground color in hex (default is '#000000').", + default="#000000") -subparser.add_argument("-f", "--foreground-color", dest="fg_color", type=str, - help="Foreground color in hex (default is '#000000').", - default="#000000") + parser.add_argument("-b", "--background-color", dest="bg_color", type=str, + help="Foreground color in hex (default is '#FFFFFF').", + default="#FFFFFF") -subparser.add_argument("-b", "--background-color", dest="bg_color", type=str, - help="Foreground color in hex (default is '#FFFFFF'.", - default="#FFFFFF") + parser.add_argument("-o", "--output", dest="output", type=str, + help="Target file (if not given, will just show the barcode).") -subparser.add_argument("-o", "--output", dest="output", type=str, - help="Target file (if not given, " - "will just show the barcode).") -subparser.add_argument("-k", "--kind", type=str, default='image', + parser.add_argument("-k", "--kind", type=str, default='image', help=" what kind of image to produce eg image|svg " - "input (default is image).") -subparser.set_defaults(func=encode_data) + "(default is image).") + + return parser + + +def do_encode(args): + args = get_parser().parse_args(args) + text = args.text + # If no text is given, check stdin + if not text: + text = sys.stdin.read() -def entrypoint(): - logging.basicConfig( - format='\033[91m%(message)s\033[0m', - level=logging.INFO - ) + if not text: + print_err("No input given") + return - arguments = parser.parse_args() try: - arguments.func(arguments) - except Exception as e: - logging.exception("%r", e) - return 10 + codes = encode( + text, + columns=args.columns, + security_level=args.security_level, + encoding=args.encoding, + ) - return 0 + if args.kind=='svg': + xml = render_svg( + codes, + scale=args.scale, + ratio=args.ratio, + padding=args.padding, + fg_color=args.fg_color, + bg_color=args.bg_color, + ) + import xml.etree.ElementTree as ET + svg = ET.tostring(xml.getroot()) + if args.output: #we need to show it + with open(args.output,'w') as f: + f.write(svg) + else: + import tempfile + try: + from PIL import ImageShow + except ImportError: + print '!!!!! unable to show svg' + f, afn = tempfile.mkstemp(suffix='.svg') + os.write(f,svg) + os.close(f) + for v in ImageShow._viewers: + if v.show_file(afn): break + else: + os.remove(afn) + print '!!!!! cannot find svg viewer' + else: + image = render_image( + codes, + scale=args.scale, + ratio=args.ratio, + padding=args.padding, + fg_color=args.fg_color, + bg_color=args.bg_color, + ) + if args.output: + image.save(args.output) + else: + image.show() + except Exception as e: + print_err(str(e)) + return def main(): - exit(entrypoint()) - + command = sys.argv[1] if len(sys.argv) > 1 else None + args = sys.argv[2:] -if __name__ == '__main__': - main() + if command == 'encode': + do_encode(args) + else: + print_usage() diff --git a/tests/test_renderers.py b/tests/test_renderers.py index 2eaf272..f4fa6b8 100644 --- a/tests/test_renderers.py +++ b/tests/test_renderers.py @@ -22,8 +22,9 @@ def test_render_svg(): scale = 2 ratio = 4 description = "hi there" + padding = 5 - tree = render_svg(codes, scale=scale, ratio=ratio, description=description) + tree = render_svg(codes, scale=scale, ratio=ratio, description=description, padding=padding) assert isinstance(tree, ElementTree) assert tree.findtext("description") == description @@ -32,8 +33,8 @@ def test_render_svg(): root = tree.getroot() - assert root.get("width") == str(width * scale) - assert root.get("height") == str(height * scale * ratio) + assert root.get("width") == str(width * scale+2*padding) + assert root.get("height") == str(height * scale * ratio + 2*padding) assert root.get("version") == "1.1" assert root.get("xmlns") == "http://www.w3.org/2000/svg" From b9ed5cf1ee773b0a2a06753044f7d0eba3b41576 Mon Sep 17 00:00:00 2001 From: Robin Becker Date: Fri, 23 Aug 2019 15:09:28 +0100 Subject: [PATCH 3/3] fixed up python3 errors --- pdf417gen/console.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pdf417gen/console.py b/pdf417gen/console.py index 65c3b19..d09c8d1 100644 --- a/pdf417gen/console.py +++ b/pdf417gen/console.py @@ -107,7 +107,7 @@ def do_encode(args): try: from PIL import ImageShow except ImportError: - print '!!!!! unable to show svg' + print('!!!!! unable to show svg') f, afn = tempfile.mkstemp(suffix='.svg') os.write(f,svg) os.close(f) @@ -115,7 +115,7 @@ def do_encode(args): if v.show_file(afn): break else: os.remove(afn) - print '!!!!! cannot find svg viewer' + print('!!!!! cannot find svg viewer') else: image = render_image( codes,