Label creation and print

This commit is contained in:
Dirk Jahnke 2022-04-01 10:19:41 +02:00
parent 734598a379
commit 8b48741816
3 changed files with 138 additions and 30 deletions

View File

@ -4,17 +4,33 @@
{% block title %}Container: {{ container.named_id }}{% endblock %} {% block title %}Container: {{ container.named_id }}{% endblock %}
{% block content %} {% block content %}
===== Print Label Content ===== <h1>Print Container Label</h1>
<!-- Action buttons --> <!-- Action buttons -->
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-12">
Label created for container {{ container.named_id }} of type {{ container.container_type.named_id }} Label created for container {{ container.named_id }} of type {{ container.container_type.named_id }}:
<br /> <br />
<img class="img-fluid shadow p-3 mb-5 bg-body rounded" src="{{ barcode_img }}"> <img class="img-fluid shadow p-3 mb-5 bg-body rounded" src="{{ barcode_img }}">
</div> </div>
<div class="col-sm-12">
<form method="gest">
{% csrf_token %}
<label for="num_copies">Number of copies:</label><input type="number" id="num_copies" size="2" min="1" max="8" name="num_copies" value="1">
<input type="submit" class="btn btn-primary" value="Print">
</form>
</div>
<div class="col-sm-12">
<!--
{% if logs %}
{% for msg in logs %}
{{ msg }}<br />
{% endfor %}
{% else %}
no messages
{% endif %}
-->
</div>
</div> </div>
<!-- End Action buttons --> <!-- End Action buttons -->

View File

@ -1,6 +1,8 @@
from django.views import generic from django.views import generic
from .models import Container, ContainerType from .models import Container, ContainerType
from labelprinter.labels import container_label import logging, json
logger = logging.getLogger(__name__)
class ContainerListView(generic.ListView): class ContainerListView(generic.ListView):
@ -62,22 +64,81 @@ class ContainerPrintLabelView(generic.DetailView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
from labelprinter.labels import container_label num_copies = int(self.request.GET['num_copies']) if 'num_copies' in self.request.GET else 0
context['num_copies'] = num_copies
context['logs'] = ['creating label for container ' + self.object.named_id]
from labelprinter.labels import container_label, pil_to_html_imgdata
container_description = self.object.container_type.named_id container_description = self.object.container_type.named_id
if len(self.object.container_type.description) > 0: if len(self.object.container_type.description) > 0:
container_description += ': ' + self.object.container_type.description container_description += ': ' + self.object.container_type.description
if len(self.object.description) > 0: if len(self.object.description) > 0:
container_description += ' / ' + self.object.description container_description_line2 = self.object.description
context['barcode_img'] = container_label(self.object.named_id, description=container_description, writer_options={'background': 'white', label_image = container_label(
'font_size': 10, self.object.named_id,
'foreground': 'black', fmt='image',
description=container_description,
description_line2=container_description_line2,
writer_options={'font_size': 14,
'module_height': 10.0, 'module_height': 10.0,
'module_width': 0.2, 'quiet_zone': 4.5,
'quiet_zone': 2.5,
'text': 'This is the text', 'text': 'This is the text',
'text_distance': 3.0, 'text_distance': 1.0
'write_text': True
}) })
context['barcode_img'] = pil_to_html_imgdata(label_image, fmt='PNG')
context['logs'].append('Image created')
if num_copies > 0:
#from brother_ql.devicedependent import models, label_type_specs, label_sizes
#from brother_ql.devicedependent import ENDLESS_LABEL, DIE_CUT_LABEL, ROUND_DIE_CUT_LABEL
from brother_ql import BrotherQLRaster, create_label
from brother_ql.backends import backend_factory, guess_backend
try:
with open('config.json', encoding='utf-8') as fh:
config = json.load(fh)
except FileNotFoundError as e:
with open('config.example.json', encoding='utf-8') as fh:
config = json.load(fh)
# LABEL_SIZES = [(name, label_type_specs[name]['name']) for name in label_sizes]
'''
if context['kind'] == ENDLESS_LABEL:
rotate = 0 if context['orientation'] == 'standard' else 90
elif context['kind'] in (ROUND_DIE_CUT_LABEL, DIE_CUT_LABEL):
rotate = 'auto'
red = False
if 'red' in context['label_size']:
red = True
'''
qlr = BrotherQLRaster(config['PRINTER']['MODEL'])
context['logs'].append('Connected to printer')
create_label(qlr, image=label_image, label_size='62', red=False, threshold=1,
cut=True, rotate='auto')
context['logs'].append('Created raster information')
try:
selected_backend = guess_backend(config['PRINTER']['PRINTER'])
except ValueError:
context['messages'].append(
"Could't guess the backend to use from the printer string descriptor (config PRINTER.PRINTER)")
context['logs'].append('Backend found: ' + selected_backend)
try:
be_class = backend_factory(selected_backend)['backend_class']
be = be_class(config['PRINTER']['PRINTER'])
context['logs'].append('Got backend driver')
for i in range(1,num_copies):
be.write(qlr.data)
context['logs'].append('Data sent to printer')
be.dispose()
del be
except Exception as e:
context['logs'].append('Exception: ' + str(e))
logger.warning('Exception happened: %s', e)
context['logs'].append('Finished printing label')
return context return context

View File

@ -6,8 +6,11 @@ from io import BytesIO
import datetime import datetime
import textwrap import textwrap
from math import floor from math import floor
import PIL.Image
import barcode as python_barcode import barcode as python_barcode
from PIL import Image, ImageDraw, ImageFont from PIL import Image, ImageDraw, ImageFont
import labelprinter
def now(fmt="%Y-%m-%d %H:%M"): def now(fmt="%Y-%m-%d %H:%M"):
@ -43,7 +46,8 @@ def wrap(text, col_width):
return "\n".join(textwrap.wrap(text, col_width)) return "\n".join(textwrap.wrap(text, col_width))
def container_label(data, barcode_class='code128', fmt='png', logo_file='./static/images/djlogo256.png',owner_name='Dirk Jahnke', description='', **writer_options): def container_label(data, barcode_class='code128', fmt='png', logo_file='./static/images/djlogo256.png',
owner_name='Dirk Jahnke', description='', description_line2='', **options):
"""Return a barcode's image data. """Return a barcode's image data.
Powered by the Python library ``python-barcode``. See this library's Powered by the Python library ``python-barcode``. See this library's
documentation for more details. documentation for more details.
@ -60,6 +64,10 @@ def container_label(data, barcode_class='code128', fmt='png', logo_file='./stati
svg -> embeddable code for html img tag svg -> embeddable code for html img tag
logo_file logo_file
File path to logo file to be included File path to logo file to be included
owner_name
Name of owner printed underneath the logo
description
Text to be printed on bottom of the label
writer_options writer_options
Various options for the writer to tune the appearance of the barcode Various options for the writer to tune the appearance of the barcode
(see python-barcode documentation). (see python-barcode documentation).
@ -86,7 +94,9 @@ def container_label(data, barcode_class='code128', fmt='png', logo_file='./stati
""" """
with Image.open(logo_file) as logo_img: with Image.open(logo_file) as logo_img:
font_size = 16 font_size = 22
font_size_small = 16
owner_name_font_size = 26
logo_img = logo_img.resize((128, 128)) logo_img = logo_img.resize((128, 128))
logo_img = logo_img.convert('L') logo_img = logo_img.convert('L')
threshold = 20 threshold = 20
@ -96,26 +106,47 @@ def container_label(data, barcode_class='code128', fmt='png', logo_file='./stati
data = str(data).zfill(constructor.digits) data = str(data).zfill(constructor.digits)
writer = { writer = {
'svg': python_barcode.writer.ImageWriter, 'svg': python_barcode.writer.ImageWriter,
'png': python_barcode.writer.ImageWriter 'png': python_barcode.writer.ImageWriter,
'image': python_barcode.writer.ImageWriter
}[fmt] }[fmt]
barcode_img = constructor(data, writer=writer()) barcode_img = constructor(data, writer=writer())
img = barcode_img.render(writer_options=writer_options) img = barcode_img.render(writer_options=options['writer_options'])
barcode_xsize, barcode_ysize = img.size barcode_xsize, barcode_ysize = img.size
logo_xsize, logo_ysize = logo_img.size logo_xsize, logo_ysize = logo_img.size
result_img = Image.new('1', (696, barcode_ysize+20), 1) label_xsize = 696
result_img.paste(logo_img, (0, floor(barcode_ysize/3)-floor(logo_ysize/2))) label_ysize = barcode_ysize + font_size if description_line2 == '' else barcode_ysize + 2 * font_size
result_img = Image.new('1', (label_xsize, label_ysize), 1)
result_img.paste(logo_img, (owner_name_font_size + 10, floor(barcode_ysize / 2) - 20 - floor(logo_ysize / 2)))
start_x_for_barcode = logo_xsize + 10 start_x_for_barcode = logo_xsize + 10
max_x_for_barcode = 696 - start_x_for_barcode max_x_for_barcode = 696 - start_x_for_barcode
result_img.paste(img, (start_x_for_barcode + floor((max_x_for_barcode - barcode_xsize) / 2), 5)) result_img.paste(img, (start_x_for_barcode + floor((max_x_for_barcode - barcode_xsize) / 2), 5))
# fnt = ImageFont.truetype("Pillow/Tests/fonts/FreeMono.ttf", 40)
fnt = ImageFont.truetype("./static/fonts/DejaVuSerif.ttf", font_size) fnt = ImageFont.truetype("./static/fonts/DejaVuSerif.ttf", font_size)
d = ImageDraw.Draw(result_img) owner_name_fnt = ImageFont.truetype("./static/fonts/DejaVuSerif.ttf", owner_name_font_size)
d.text((20,logo_ysize+40), owner_name, font=fnt) owner_text_img = Image.new('1', (floor(owner_name_fnt.getlength(owner_name)+1), owner_name_font_size+5), 1)
d.text((30+floor((660-fnt.getlength(description))/2),barcode_ysize), description, font=fnt) d = ImageDraw.Draw(owner_text_img)
d.text((0,0), owner_name, font=owner_name_fnt)
owner_text_img = owner_text_img.transpose(PIL.Image.ROTATE_90)
result_img.paste(owner_text_img, (0, 10))
if fmt == 'png': d = ImageDraw.Draw(result_img)
#d.text((20, logo_ysize), owner_name, font=fnt)
if fnt.getlength(description) > 660:
fnt_small = ImageFont.truetype("./static/fonts/DejaVuSerif.ttf", font_size_small)
d.text((0, barcode_ysize), description, font=fnt_small)
if description_line2 != '':
d.text((0, barcode_ysize + font_size), description_line2, font=fnt_small)
else:
#d.text((30 + floor((660 - fnt.getlength(description)) / 2), barcode_ysize), description, font=fnt)
d.text((0, barcode_ysize), description, font=fnt)
if description_line2 != '':
d.text((0, barcode_ysize + font_size), description_line2, font=fnt)
if fmt == 'image':
return result_img
elif fmt == 'png':
return pil_to_html_imgdata(result_img, fmt='PNG') return pil_to_html_imgdata(result_img, fmt='PNG')
else: else:
prefix = "data:image/svg+xml;charset=utf-8;base64," prefix = "data:image/svg+xml;charset=utf-8;base64,"
return prefix + base64.b64encode(result_img).decode() return prefix + base64.b64encode(result_img).decode()