Label creation and print
This commit is contained in:
parent
734598a379
commit
8b48741816
|
@ -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 -->
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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,8 +94,10 @@ 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
|
||||||
logo_img = logo_img.resize((128,128))
|
font_size_small = 16
|
||||||
|
owner_name_font_size = 26
|
||||||
|
logo_img = logo_img.resize((128, 128))
|
||||||
logo_img = logo_img.convert('L')
|
logo_img = logo_img.convert('L')
|
||||||
threshold = 20
|
threshold = 20
|
||||||
logo_img = logo_img.point(lambda p: 255 if p < threshold else 0)
|
logo_img = logo_img.point(lambda p: 255 if p < threshold else 0)
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue