Move label creating code from CLI tool brother_ql_create -> module
The code previously found in the function create_label() in brother_ql.brother_ql_create now went into a new function convert() in its own module: convert() in brother_ql.conversion In addition, the new convert() function is now able to put more than one pages (labels) into one instruction file.
This commit is contained in:
@@ -1,27 +1,16 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
from __future__ import division
|
|
||||||
|
|
||||||
import sys, argparse, logging
|
import sys, argparse, logging
|
||||||
|
|
||||||
from PIL import Image
|
|
||||||
import PIL.ImageOps, PIL.ImageChops
|
|
||||||
|
|
||||||
from brother_ql.raster import BrotherQLRaster
|
from brother_ql.raster import BrotherQLRaster
|
||||||
from brother_ql.devicedependent import models, label_type_specs, ENDLESS_LABEL, DIE_CUT_LABEL, ROUND_DIE_CUT_LABEL, right_margin_addition
|
from brother_ql.conversion import convert
|
||||||
from brother_ql import BrotherQLError, BrotherQLUnsupportedCmd, BrotherQLUnknownModel
|
from brother_ql.devicedependent import label_type_specs
|
||||||
from brother_ql.image_trafos import filtered_hsv
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
stdout = sys.stdout.buffer
|
stdout = sys.stdout.buffer
|
||||||
except:
|
except:
|
||||||
stdout = sys.stdout
|
stdout = sys.stdout
|
||||||
|
|
||||||
try:
|
|
||||||
unicode
|
|
||||||
except:
|
|
||||||
unicode = str
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
@@ -42,7 +31,6 @@ def main():
|
|||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
logging.basicConfig(level=args.loglevel)
|
logging.basicConfig(level=args.loglevel)
|
||||||
logging.getLogger("PIL.PngImagePlugin").setLevel(logging.WARNING)
|
|
||||||
|
|
||||||
args.model = args.model.upper()
|
args.model = args.model.upper()
|
||||||
|
|
||||||
@@ -63,145 +51,7 @@ def main():
|
|||||||
args.outfile.write(qlr.data)
|
args.outfile.write(qlr.data)
|
||||||
|
|
||||||
def create_label(qlr, image, label_size, threshold=70, cut=True, dither=False, compress=False, red=False, **kwargs):
|
def create_label(qlr, image, label_size, threshold=70, cut=True, dither=False, compress=False, red=False, **kwargs):
|
||||||
|
convert(qlr, [image], label_size, threshold=threshold, cut=cut, dither=dither, compress=compress, red=red, **kwargs)
|
||||||
label_specs = label_type_specs[label_size]
|
|
||||||
dots_printable = label_specs['dots_printable']
|
|
||||||
right_margin_dots = label_specs['right_margin_dots']
|
|
||||||
right_margin_dots += right_margin_addition.get(qlr.model, 0)
|
|
||||||
device_pixel_width = qlr.get_pixel_width()
|
|
||||||
rotate = kwargs.get('rotate', 'auto')
|
|
||||||
if rotate != 'auto': rotate = int(rotate)
|
|
||||||
dpi_600 = kwargs.get('dpi_600', False)
|
|
||||||
hq = kwargs.get('hq', True)
|
|
||||||
|
|
||||||
threshold = 100.0 - threshold
|
|
||||||
threshold = min(255, max(0, int(threshold/100.0 * 255))) # from percent to pixel val
|
|
||||||
|
|
||||||
if red and not qlr.two_color_support:
|
|
||||||
raise BrotherQLUnsupportedCmd('Printing in red is not supported with the selected model.')
|
|
||||||
|
|
||||||
if isinstance(image, Image.Image):
|
|
||||||
im = image
|
|
||||||
elif isinstance(image, (unicode, str)):
|
|
||||||
im = Image.open(image)
|
|
||||||
else:
|
|
||||||
raise NotImplementedError("The image argument needs to be an Image() instance or the filename to an image.")
|
|
||||||
|
|
||||||
if im.mode.endswith('A'):
|
|
||||||
# place in front of white background and get red of transparency
|
|
||||||
bg = Image.new("RGB", im.size, (255,255,255))
|
|
||||||
bg.paste(im, im.split()[-1])
|
|
||||||
im = bg
|
|
||||||
elif im.mode == "P":
|
|
||||||
# Convert GIF ("P") to RGB
|
|
||||||
im = im.convert("RGB" if red else "L")
|
|
||||||
elif im.mode == "L" and red:
|
|
||||||
# Convert greyscale to RGB if printing on black/red tape
|
|
||||||
im = im.convert("RGB")
|
|
||||||
|
|
||||||
if dpi_600:
|
|
||||||
dots_expected = [el*2 for el in dots_printable]
|
|
||||||
else:
|
|
||||||
dots_expected = dots_printable
|
|
||||||
|
|
||||||
if label_specs['kind'] == ENDLESS_LABEL:
|
|
||||||
if rotate not in ('auto', 0):
|
|
||||||
im = im.rotate(rotate, expand=True)
|
|
||||||
if dpi_600:
|
|
||||||
im = im.resize((im.size[0]//2, im.size[1]))
|
|
||||||
if im.size[0] != dots_printable[0]:
|
|
||||||
hsize = int((dots_printable[0] / im.size[0]) * im.size[1])
|
|
||||||
im = im.resize((dots_printable[0], hsize), Image.ANTIALIAS)
|
|
||||||
logger.warning('Need to resize the image...')
|
|
||||||
if im.size[0] < device_pixel_width:
|
|
||||||
new_im = Image.new(im.mode, (device_pixel_width, im.size[1]), (255,)*len(im.mode))
|
|
||||||
new_im.paste(im, (device_pixel_width-im.size[0]-right_margin_dots, 0))
|
|
||||||
im = new_im
|
|
||||||
elif label_specs['kind'] in (DIE_CUT_LABEL, ROUND_DIE_CUT_LABEL):
|
|
||||||
if rotate == 'auto':
|
|
||||||
if im.size[0] == dots_expected[1] and im.size[1] == dots_expected[0]:
|
|
||||||
im = im.rotate(90, expand=True)
|
|
||||||
elif rotate != 0:
|
|
||||||
im = im.rotate(rotate, expand=True)
|
|
||||||
if im.size[0] != dots_expected[0] or im.size[1] != dots_expected[1]:
|
|
||||||
raise ValueError("Bad image dimensions: %s. Expecting: %s." % (im.size, dots_expected))
|
|
||||||
if dpi_600:
|
|
||||||
im = im.resize((im.size[0]//2, im.size[1]))
|
|
||||||
new_im = Image.new(im.mode, (device_pixel_width, dots_expected[1]), (255,)*len(im.mode))
|
|
||||||
new_im.paste(im, (device_pixel_width-im.size[0]-right_margin_dots, 0))
|
|
||||||
im = new_im
|
|
||||||
|
|
||||||
if red:
|
|
||||||
filter_h = lambda h: 255 if (h < 40 or h > 210) else 0
|
|
||||||
filter_s = lambda s: 255 if s > 100 else 0
|
|
||||||
filter_v = lambda v: 255 if v > 80 else 0
|
|
||||||
red_im = filtered_hsv(im, filter_h, filter_s, filter_v)
|
|
||||||
red_im = red_im.convert("L")
|
|
||||||
red_im = PIL.ImageOps.invert(red_im)
|
|
||||||
red_im = red_im.point(lambda x: 0 if x < threshold else 255, mode="1")
|
|
||||||
|
|
||||||
filter_h = lambda h: 255
|
|
||||||
filter_s = lambda s: 255
|
|
||||||
filter_v = lambda v: 255 if v < 80 else 0
|
|
||||||
black_im = filtered_hsv(im, filter_h, filter_s, filter_v)
|
|
||||||
black_im = black_im.convert("L")
|
|
||||||
black_im = PIL.ImageOps.invert(black_im)
|
|
||||||
black_im = black_im.point(lambda x: 0 if x < threshold else 255, mode="1")
|
|
||||||
black_im = PIL.ImageChops.subtract(black_im, red_im)
|
|
||||||
else:
|
|
||||||
im = im.convert("L")
|
|
||||||
im = PIL.ImageOps.invert(im)
|
|
||||||
|
|
||||||
if dither:
|
|
||||||
im = im.convert("1", dither=Image.FLOYDSTEINBERG)
|
|
||||||
else:
|
|
||||||
im = im.point(lambda x: 0 if x < threshold else 255, mode="1")
|
|
||||||
|
|
||||||
try:
|
|
||||||
qlr.add_switch_mode()
|
|
||||||
except BrotherQLUnsupportedCmd:
|
|
||||||
pass
|
|
||||||
qlr.add_invalidate()
|
|
||||||
qlr.add_initialize()
|
|
||||||
try:
|
|
||||||
qlr.add_switch_mode()
|
|
||||||
except BrotherQLUnsupportedCmd:
|
|
||||||
pass
|
|
||||||
qlr.add_status_information()
|
|
||||||
tape_size = label_specs['tape_size']
|
|
||||||
if label_specs['kind'] in (DIE_CUT_LABEL, ROUND_DIE_CUT_LABEL):
|
|
||||||
qlr.mtype = 0x0B
|
|
||||||
qlr.mwidth = tape_size[0]
|
|
||||||
qlr.mlength = tape_size[1]
|
|
||||||
else:
|
|
||||||
qlr.mtype = 0x0A
|
|
||||||
qlr.mwidth = tape_size[0]
|
|
||||||
qlr.mlength = 0
|
|
||||||
qlr.pquality = int(hq)
|
|
||||||
qlr.add_media_and_quality(im.size[1])
|
|
||||||
try:
|
|
||||||
if cut:
|
|
||||||
qlr.add_autocut(True)
|
|
||||||
qlr.add_cut_every(1)
|
|
||||||
except BrotherQLUnsupportedCmd:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
qlr.dpi_600 = dpi_600
|
|
||||||
qlr.cut_at_end = cut
|
|
||||||
qlr.two_color_printing = True if red else False
|
|
||||||
qlr.add_expanded_mode()
|
|
||||||
except BrotherQLUnsupportedCmd:
|
|
||||||
pass
|
|
||||||
qlr.add_margins(label_specs['feed_margin'])
|
|
||||||
try:
|
|
||||||
if compress: qlr.add_compression(True)
|
|
||||||
except BrotherQLUnsupportedCmd:
|
|
||||||
pass
|
|
||||||
if red:
|
|
||||||
qlr.add_raster_data(black_im, red_im)
|
|
||||||
else:
|
|
||||||
qlr.add_raster_data(im)
|
|
||||||
qlr.add_print()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
Executable
+197
@@ -0,0 +1,197 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
from __future__ import division
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
|
import PIL.ImageOps, PIL.ImageChops
|
||||||
|
|
||||||
|
from brother_ql.raster import BrotherQLRaster
|
||||||
|
from brother_ql.devicedependent import label_type_specs, ENDLESS_LABEL, DIE_CUT_LABEL, ROUND_DIE_CUT_LABEL, right_margin_addition
|
||||||
|
from brother_ql import BrotherQLUnsupportedCmd
|
||||||
|
from brother_ql.image_trafos import filtered_hsv
|
||||||
|
|
||||||
|
try:
|
||||||
|
unicode
|
||||||
|
except:
|
||||||
|
unicode = str
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
logging.getLogger("PIL.PngImagePlugin").setLevel(logging.WARNING)
|
||||||
|
|
||||||
|
def convert(qlr, images, label, **kwargs):
|
||||||
|
r"""Converts one or more images to a raster instruction file.
|
||||||
|
|
||||||
|
:param qlr:
|
||||||
|
An instance of the BrotherQLRaster class
|
||||||
|
:type qlr: :py:class:`brother_ql.raster.BrotherQLRaster`
|
||||||
|
:param images:
|
||||||
|
The images to be converted. They can be filenames or instances of Pillow's Image.
|
||||||
|
:type images: list(PIL.Image.Image) or list(str) images
|
||||||
|
:param str label:
|
||||||
|
Type of label the printout should be on.
|
||||||
|
:param \**kwargs:
|
||||||
|
See below
|
||||||
|
|
||||||
|
:Keyword Arguments:
|
||||||
|
* **cut** (``bool``) --
|
||||||
|
Enable cutting after printing the labels.
|
||||||
|
* **dither** (``bool``) --
|
||||||
|
Instead of applying a threshold to the pixel values, approximate grey tones with dithering.
|
||||||
|
* **compress**
|
||||||
|
* **red**
|
||||||
|
* **rotate**
|
||||||
|
* **dpi_600**
|
||||||
|
* **hq**
|
||||||
|
* **threshold**
|
||||||
|
"""
|
||||||
|
label_specs = label_type_specs[label]
|
||||||
|
|
||||||
|
dots_printable = label_specs['dots_printable']
|
||||||
|
right_margin_dots = label_specs['right_margin_dots']
|
||||||
|
right_margin_dots += right_margin_addition.get(qlr.model, 0)
|
||||||
|
device_pixel_width = qlr.get_pixel_width()
|
||||||
|
|
||||||
|
cut = kwargs.get('cut', True)
|
||||||
|
dither = kwargs.get('dither', False)
|
||||||
|
compress = kwargs.get('compress', False)
|
||||||
|
red = kwargs.get('red', False)
|
||||||
|
rotate = kwargs.get('rotate', 'auto')
|
||||||
|
if rotate != 'auto': rotate = int(rotate)
|
||||||
|
dpi_600 = kwargs.get('dpi_600', False)
|
||||||
|
hq = kwargs.get('hq', True)
|
||||||
|
threshold = kwargs.get('threshold', 70)
|
||||||
|
threshold = 100.0 - threshold
|
||||||
|
threshold = min(255, max(0, int(threshold/100.0 * 255)))
|
||||||
|
|
||||||
|
if red and not qlr.two_color_support:
|
||||||
|
raise BrotherQLUnsupportedCmd('Printing in red is not supported with the selected model.')
|
||||||
|
|
||||||
|
try:
|
||||||
|
qlr.add_switch_mode()
|
||||||
|
except BrotherQLUnsupportedCmd:
|
||||||
|
pass
|
||||||
|
qlr.add_invalidate()
|
||||||
|
qlr.add_initialize()
|
||||||
|
try:
|
||||||
|
qlr.add_switch_mode()
|
||||||
|
except BrotherQLUnsupportedCmd:
|
||||||
|
pass
|
||||||
|
|
||||||
|
for image in images:
|
||||||
|
if isinstance(images, Image.Image):
|
||||||
|
im = image
|
||||||
|
elif isinstance(image, (unicode, str)):
|
||||||
|
im = Image.open(image)
|
||||||
|
else:
|
||||||
|
raise NotImplementedError("The image argument needs to be an Image() instance or the filename to an image.")
|
||||||
|
|
||||||
|
if im.mode.endswith('A'):
|
||||||
|
# place in front of white background and get red of transparency
|
||||||
|
bg = Image.new("RGB", im.size, (255,255,255))
|
||||||
|
bg.paste(im, im.split()[-1])
|
||||||
|
im = bg
|
||||||
|
elif im.mode == "P":
|
||||||
|
# Convert GIF ("P") to RGB
|
||||||
|
im = im.convert("RGB" if red else "L")
|
||||||
|
elif im.mode == "L" and red:
|
||||||
|
# Convert greyscale to RGB if printing on black/red tape
|
||||||
|
im = im.convert("RGB")
|
||||||
|
|
||||||
|
if dpi_600:
|
||||||
|
dots_expected = [el*2 for el in dots_printable]
|
||||||
|
else:
|
||||||
|
dots_expected = dots_printable
|
||||||
|
|
||||||
|
if label_specs['kind'] == ENDLESS_LABEL:
|
||||||
|
if rotate not in ('auto', 0):
|
||||||
|
im = im.rotate(rotate, expand=True)
|
||||||
|
if dpi_600:
|
||||||
|
im = im.resize((im.size[0]//2, im.size[1]))
|
||||||
|
if im.size[0] != dots_printable[0]:
|
||||||
|
hsize = int((dots_printable[0] / im.size[0]) * im.size[1])
|
||||||
|
im = im.resize((dots_printable[0], hsize), Image.ANTIALIAS)
|
||||||
|
logger.warning('Need to resize the image...')
|
||||||
|
if im.size[0] < device_pixel_width:
|
||||||
|
new_im = Image.new(im.mode, (device_pixel_width, im.size[1]), (255,)*len(im.mode))
|
||||||
|
new_im.paste(im, (device_pixel_width-im.size[0]-right_margin_dots, 0))
|
||||||
|
im = new_im
|
||||||
|
elif label_specs['kind'] in (DIE_CUT_LABEL, ROUND_DIE_CUT_LABEL):
|
||||||
|
if rotate == 'auto':
|
||||||
|
if im.size[0] == dots_expected[1] and im.size[1] == dots_expected[0]:
|
||||||
|
im = im.rotate(90, expand=True)
|
||||||
|
elif rotate != 0:
|
||||||
|
im = im.rotate(rotate, expand=True)
|
||||||
|
if im.size[0] != dots_expected[0] or im.size[1] != dots_expected[1]:
|
||||||
|
raise ValueError("Bad image dimensions: %s. Expecting: %s." % (im.size, dots_expected))
|
||||||
|
if dpi_600:
|
||||||
|
im = im.resize((im.size[0]//2, im.size[1]))
|
||||||
|
new_im = Image.new(im.mode, (device_pixel_width, dots_expected[1]), (255,)*len(im.mode))
|
||||||
|
new_im.paste(im, (device_pixel_width-im.size[0]-right_margin_dots, 0))
|
||||||
|
im = new_im
|
||||||
|
|
||||||
|
if red:
|
||||||
|
filter_h = lambda h: 255 if (h < 40 or h > 210) else 0
|
||||||
|
filter_s = lambda s: 255 if s > 100 else 0
|
||||||
|
filter_v = lambda v: 255 if v > 80 else 0
|
||||||
|
red_im = filtered_hsv(im, filter_h, filter_s, filter_v)
|
||||||
|
red_im = red_im.convert("L")
|
||||||
|
red_im = PIL.ImageOps.invert(red_im)
|
||||||
|
red_im = red_im.point(lambda x: 0 if x < threshold else 255, mode="1")
|
||||||
|
|
||||||
|
filter_h = lambda h: 255
|
||||||
|
filter_s = lambda s: 255
|
||||||
|
filter_v = lambda v: 255 if v < 80 else 0
|
||||||
|
black_im = filtered_hsv(im, filter_h, filter_s, filter_v)
|
||||||
|
black_im = black_im.convert("L")
|
||||||
|
black_im = PIL.ImageOps.invert(black_im)
|
||||||
|
black_im = black_im.point(lambda x: 0 if x < threshold else 255, mode="1")
|
||||||
|
black_im = PIL.ImageChops.subtract(black_im, red_im)
|
||||||
|
else:
|
||||||
|
im = im.convert("L")
|
||||||
|
im = PIL.ImageOps.invert(im)
|
||||||
|
|
||||||
|
if dither:
|
||||||
|
im = im.convert("1", dither=Image.FLOYDSTEINBERG)
|
||||||
|
else:
|
||||||
|
im = im.point(lambda x: 0 if x < threshold else 255, mode="1")
|
||||||
|
|
||||||
|
qlr.add_status_information()
|
||||||
|
tape_size = label_specs['tape_size']
|
||||||
|
if label_specs['kind'] in (DIE_CUT_LABEL, ROUND_DIE_CUT_LABEL):
|
||||||
|
qlr.mtype = 0x0B
|
||||||
|
qlr.mwidth = tape_size[0]
|
||||||
|
qlr.mlength = tape_size[1]
|
||||||
|
else:
|
||||||
|
qlr.mtype = 0x0A
|
||||||
|
qlr.mwidth = tape_size[0]
|
||||||
|
qlr.mlength = 0
|
||||||
|
qlr.pquality = int(hq)
|
||||||
|
qlr.add_media_and_quality(im.size[1])
|
||||||
|
try:
|
||||||
|
if cut:
|
||||||
|
qlr.add_autocut(True)
|
||||||
|
qlr.add_cut_every(1)
|
||||||
|
except BrotherQLUnsupportedCmd:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
qlr.dpi_600 = dpi_600
|
||||||
|
qlr.cut_at_end = cut
|
||||||
|
qlr.two_color_printing = True if red else False
|
||||||
|
qlr.add_expanded_mode()
|
||||||
|
except BrotherQLUnsupportedCmd:
|
||||||
|
pass
|
||||||
|
qlr.add_margins(label_specs['feed_margin'])
|
||||||
|
try:
|
||||||
|
if compress: qlr.add_compression(True)
|
||||||
|
except BrotherQLUnsupportedCmd:
|
||||||
|
pass
|
||||||
|
if red:
|
||||||
|
qlr.add_raster_data(black_im, red_im)
|
||||||
|
else:
|
||||||
|
qlr.add_raster_data(im)
|
||||||
|
qlr.add_print()
|
||||||
|
|
||||||
|
return qlr.data
|
||||||
Reference in New Issue
Block a user