pdf2tspl/tspl.py
2021-07-02 20:50:43 +10:00

68 lines
2 KiB
Python
Executable file

#!/usr/bin/env python3
import tempfile
import subprocess
import dataclasses
@dataclasses.dataclass
class Image:
width: int
height: int
data: bytes
def convert_pdf(pdfname, args=[]):
with tempfile.NamedTemporaryFile(suffix='.pbm') as pbmfile:
subprocess.check_call(["pdftoppm", "-mono", "-singlefile"] + args + [pdfname, pbmfile.name.removesuffix('.pbm')])
header = pbmfile.readline()
if header.strip() != b'P4':
raise ValueError("unrecognised image format")
width_height = pbmfile.readline().decode('ascii')
data = bytes(x ^ 0xff for x in pbmfile.read())
width, height = map(int, width_height.strip().split())
return Image(width, height, data)
def convert_pdf_scaled(pdfname, max_width, max_height):
im = convert_pdf(pdfname)
aspect = im.width / im.height
max_aspect = max_width / max_height
if aspect < max_aspect:
max_width = int(max_height * aspect) - 1
else:
# pdftoppm tends to make it 1px too wide
max_width -= 1
max_height = int(max_width / aspect)
args = ['-scale-to-x', str(max_width), '-scale-to-y', str(max_height)]
im = convert_pdf(pdfname, args)
assert im.width <= max_width + 1
assert im.height <= max_height
return im
def pdf2tspl(filename, labelwidth_mm=100, labelheight_mm=150, dpi=203):
labelwidth = int(round(labelwidth_mm / 25.4 * dpi))
labelheight = int(round(labelheight_mm / 25.4 * dpi))
image = convert_pdf_scaled(filename, labelwidth, labelheight)
paste_x = (labelwidth - image.width) // 2
paste_y = (labelheight - image.height) // 2
row_bytes = (image.width + 7) // 8
command = b"\r\n\r\nSIZE %d mm\r\nCLS\r\nBITMAP %d,%d,%d,%d,0," % (labelwidth_mm, paste_x, paste_y, row_bytes, image.height)
command += image.data
command += b"\r\nPRINT 1,1\r\n"
return command
def print_pdf(filename):
cmd = pdf2tspl(filename)
with open("/dev/usb/lp0", "r+b") as prn:
prn.write(cmd)
if __name__ == "__main__":
import sys
print_pdf(sys.argv[1])