Files
brother_ql/brother_ql/raster.py
T
2016-02-12 21:40:06 +01:00

154 lines
4.8 KiB
Python

import struct
import logging
import packbits
import numpy as np
from .devicedependent import models, \
min_max_feed, \
min_max_length_dots, \
paper_dimensions, \
number_bytes_per_row, \
right_margin_addition, \
compressionsupport, \
cuttingsupport, \
modesetting
logger = logging.getLogger(__name__)
class BrotherQLRaster(object):
def __init__(self, model='QL-500'):
if model not in models:
raise BrotherQLRasterUnknownModel()
self.model = model
self.data = b''
self._pquality = 1
self.page_number = 0
self.cut_at_end = True
self.dpi_600 = False
self._compression = False
self.exception_on_warning = False
def warn(self, problem):
if self.exception_on_warning:
raise BrotherQLRasterError(problem)
else:
logger.warning(problem)
def set_initialize(self):
self.page_number = 0
self.data += b'\x1B\x40' # init
def set_mode(self):
""" switch to raster mode """
if self.model not in modesetting:
self.warn("Trying to switch the operating mode on a printer that doesn't support the command.")
return
self.data += b'\x1B\x69\x61\x01'
def set_clear_command_buffer(self):
self.data += b'\x00' * 200
@property
def mtype(self): return self._mtype
@property
def mwidth(self): return self._mwidth
@property
def mlength(self): return self._mlength
@property
def pquality(self): return self._pquality
@mtype.setter
def mtype(self, value):
self._mtype = bytes([value & 0xFF])
@mwidth.setter
def mwidth(self, value):
self._mwidth = bytes([value & 0xFF])
@mlength.setter
def mlength(self, value):
self._mlength = bytes([value & 0xFF])
@pquality.setter
def pquality(self, value):
self._pquality = bytes([value & 0x01])
def set_media_and_quality(self, rnumber):
self.data += b'\x1B\x69\x7A'
valid_flags = 0x80
valid_flags |= (self._mtype is not None) << 1
valid_flags |= (self._mwidth is not None) << 2
valid_flags |= (self._mlength is not None) << 3
valid_flags |= self._pquality << 6
self.data += bytes([valid_flags])
vals = [self._mtype, self._mwidth, self._mlength]
self.data += b''.join(b'\x00' if val is None else val for val in vals)
self.data += struct.pack('<L', rnumber)
self.data += bytes([self.page_number == 0])
self.data += b'\x00'
# INFO: media/quality (1B 69 7A) --> found! (payload: 8E 0A 3E 00 D2 00 00 00 00 00)
def set_autocut(self, autocut = False):
self.data += b'\x1B\x69\x4D'
self.data += bytes([autocut << 6])
def set_cut_every(self, n=1):
self.data += b'\x1B\x69\x41'
self.data += bytes([n & 0xFF])
def set_expanded_mode(self):
if self.model not in cuttingsupport:
self.warn("Trying to set expanded mode on a printer that doesn't support it")
return
self.data += b'\x1B\x69\x4B'
flags = 0x00
flags |= self.cut_at_end << 3
flags |= self.dpi_600 << 6
self.data += bytes([flags])
def set_margins(self, dots=0x23):
self.data += b'\x1B\x69\x64'
self.data += struct.pack('<H', dots)
def set_compression(self, compression=True):
if self.model not in compressionsupport:
self.warn("Trying to set compression on a printer that doesn't support it")
return
self._compression = compression
self.data += b'\x4D'
self.data += bytes([compression << 1])
def set_raster_data(self, np_array):
""" np_array: numpy array of 1-bit values """
np_array = np.fliplr(np_array)
try:
nbpr = number_bytes_per_row[self.model]
except:
nbpr = number_bytes_per_row['default']
for row in np_array:
self.data += b'\x67\x00'
row = bytes(np.packbits(row))
if len(row) != nbpr:
fmt = 'Wrong number of bytes per row: {}, expected {}'
raise BrotherQLRasterError(fmt.format(len(row), nbpr))
if self._compression:
row = packbits.encode(row)
self.data += bytes([len(row)])
self.data += row
def print_cmd(self, last_page=True):
if last_page:
self.data += b'\x1A'
else:
self.data += b'\x0C'
class BrotherQLRasterError(Exception): pass
class BrotherQLRasterUnknownModel(BrotherQLRasterError): pass