Created
October 19, 2021 12:56
-
-
Save waylan/29f4b7d97c02da4d10336fba8bbe2e43 to your computer and use it in GitHub Desktop.
Print labels directly to Brother QL label printer using brother_ql lib.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from PIL import Image, ImageDraw, ImageFont | |
from brother_ql.devicedependent import label_type_specs | |
from brother_ql import BrotherQLRaster, create_label | |
from brother_ql.backends.helpers import send | |
PRINTER = { | |
'model': 'QL-800', | |
'address': 'usb://0x04f9:0x209b' | |
} | |
def get_font(text, size, margin, fontname, draw, start=100): | |
' Return font after calculating largest size which fits in box of given size.' | |
fontsize = start | |
while True: | |
font = ImageFont.truetype(fontname, fontsize) | |
txtsize = draw.multiline_textsize(text, font=font) | |
if txtsize[0] >= size[0] - (margin * 2) or txtsize[1] >= size[1] - (margin * 2): | |
# reduce font size and try again | |
fontsize -= 2 | |
else: | |
# print(f'Using fontsize {fontsize}') | |
return font | |
def draw_address_label(body, memo, size): | |
img = Image.new('L', size, 'white') | |
draw = ImageDraw.Draw(img) | |
margin = 0 | |
font = get_font(body, size, margin, 'times.ttf', draw, 60) | |
# Center text horizontally and vertically in image. | |
# Set anchor point to the middle (half width and half height of image size) | |
# and anchor alignment to middle/middle (mm) of text. | |
draw.multiline_text((size[0]/2, size[1]/2), body, fill='black', font=font, anchor='mm', align='center') | |
smallfont = ImageFont.truetype('times.ttf', 20) | |
# And memo to bottom left corner | |
draw.text((margin, size[1] - margin), memo, fill='black', font=smallfont, anchor='ld', align='left') | |
# Outline with rounded rect for debuging | |
# draw.rounded_rectangle([(0, 0), (size[0] - 1, size[1] - 1)], radius=10, outline='black', width=1) | |
return img | |
def draw_file_label(body, memo, size): | |
img = Image.new('L', size, 'white') | |
draw = ImageDraw.Draw(img) | |
margin = 0 | |
font = get_font(body, size, margin, 'times.ttf', draw, 50) | |
# Add body to top left | |
draw.multiline_text((margin, margin + 50), body, fill='black', font=font, anchor='la', align='left') | |
# And memo to top right corner | |
draw.text((size[0] - margin, margin), memo, fill='black', font=font, anchor='ra', align='right') | |
# Outline with rounded rect for debuging | |
# draw.rounded_rectangle([(0, 0), (size[0] - 1, size[1] - 1)], radius=10, outline='black', width=1) | |
return img | |
def print_label(style, label_type, body, memo=None, cut=True, printer=PRINTER): | |
''' | |
Print a label directly to printer. | |
style: The style (layout) of the label. One of `address` or `file`. | |
label_type: The type (size) of label in the printer. Valid values include | |
any `name` listed in the output of `brother_ql info labels`. | |
body: The main body of the label. | |
memo: Optional secondary content printed to the label. | |
cut: Instruct the printer to cut after printing the label. Default: `True`. | |
printer: A dict specifying the printer `model` and `address` to send the print job to. | |
''' | |
memo = memo or '' | |
# Width and height are switched so we can draw with horizontal text. Image will then be rotated. | |
size = ( | |
label_type_specs[label_type]['dots_printable'][1], | |
label_type_specs[label_type]['dots_printable'][0] | |
) | |
if style == 'address': | |
img = draw_address_label(body, memo, size) | |
elif style == 'file': | |
img = draw_file_label(body, memo, size) | |
else: | |
raise ValueError(f"'style' must be one of 'address' or 'file'. Got '{style}' instead.") | |
qlr = BrotherQLRaster(printer['model']) | |
create_label(qlr, img, label_type, cut=cut, rotate=90, dpi_600=False) | |
send(qlr.data, printer['address']) | |
if __name__ == '__main__': | |
img1 = draw_address_label('Firstname Somelongname\nSome Building\n123 Any Street Apt C-3\nAnytown PA, 12345', 'No. A.D. 123 of 2021', (991, 306)) | |
img1.save('address_label.png') | |
img2 = draw_file_label('Somelongname, Firstname\nSomelongname, Othername & Another, Name', '123-2021', (991, 306)) | |
img2.save('file_label.png') | |
# To print one of the above generated images, run the following command: | |
# brother_ql -b pyusb -m QL-800 -p usb://0x04f9:0x209b print -l 29x90 address_label.png | |
# To print a label directly from Python, do this: | |
print_label('address', '29x90', 'Firstname Somelongname\nSome Building\n123 Any Street Apt C-3\nAnytown PA, 12345', 'No. A.D. 123 of 2021') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment