Reworking brother_ql/reader.py
The code used in BrotherQLReader.analyse() is now is now split into a chunker() function which separates (=chunks) a data stream of bytes into individual printer instructions and into the main functionality of the analyse() method: Stating debug information about each instruction and generating images of the expected printer output.
This commit is contained in:
+56
-37
@@ -12,21 +12,21 @@ from matplotlib import pyplot as plt
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
cmds = {
|
cmds = {
|
||||||
# signature name following bytes description
|
# signature name following bytes description
|
||||||
b'\x00': ("preamble", 0, "Preamble, 200-300x 0x00 to clear comamnd buffer"),
|
b'\x00': ("preamble", -1, "Preamble, 200-300x 0x00 to clear comamnd buffer"),
|
||||||
b'\x4D': ("compression", 1, ""),
|
b'\x4D': ("compression", 1, ""),
|
||||||
b'\x67': ("raster", -1, ""),
|
b'\x67': ("raster", -1, ""),
|
||||||
b'\x0C': ("print", 0, "print intermediate page"),
|
b'\x0C': ("print", 0, "print intermediate page"),
|
||||||
b'\x1A': ("print", 0, "print final page"),
|
b'\x1A': ("print", 0, "print final page"),
|
||||||
b'\x1b\x40': ("init", 0, "initialization"),
|
b'\x1b\x40': ("init", 0, "initialization"),
|
||||||
b'\x1b\x69\x61': ("mode setting", 1, ""),
|
b'\x1b\x69\x61': ("mode setting", 1, ""),
|
||||||
b'\x1b\x69\x7A': ("media/quality", 10, "print-media and print-quality"),
|
b'\x1b\x69\x7A': ("media/quality", 10, "print-media and print-quality"),
|
||||||
b'\x1b\x69\x4D': ("various", 1, "Auto cut flag in bit 7"),
|
b'\x1b\x69\x4D': ("various", 1, "Auto cut flag in bit 7"),
|
||||||
b'\x1b\x69\x41': ("cut-every", 1, "cut every n-th page"),
|
b'\x1b\x69\x41': ("cut-every", 1, "cut every n-th page"),
|
||||||
b'\x1b\x69\x4B': ("expanded", 1, ""),
|
b'\x1b\x69\x4B': ("expanded", 1, ""),
|
||||||
b'\x1b\x69\x64': ("margins", 2, ""),
|
b'\x1b\x69\x64': ("margins", 2, ""),
|
||||||
b'\x1b\x69\x55\x77\x01': ('amedia',127, "Additional media information command"),
|
b'\x1b\x69\x55\x77\x01': ('amedia', 127, "Additional media information command"),
|
||||||
b'\x1b\x69\x55\x4A': ('jobid', 14, "Job ID setting command"),
|
b'\x1b\x69\x55\x4A': ('jobid', 14, "Job ID setting command"),
|
||||||
}
|
}
|
||||||
|
|
||||||
dot_widths = {
|
dot_widths = {
|
||||||
@@ -39,6 +39,41 @@ def hex_format(data):
|
|||||||
except ValueError: # Py2
|
except ValueError: # Py2
|
||||||
return ' '.join('{:02X}'.format(ord(byte)) for byte in data)
|
return ' '.join('{:02X}'.format(ord(byte)) for byte in data)
|
||||||
|
|
||||||
|
def chunker(data, raise_exception=False):
|
||||||
|
"""
|
||||||
|
Breaks data stream (bytes) into a list of bytes containing single instructions each.
|
||||||
|
|
||||||
|
Logs warnings for unknown commands.
|
||||||
|
If raise_exception is set to True it raise exceptions instead.
|
||||||
|
|
||||||
|
returns: list of bytes
|
||||||
|
"""
|
||||||
|
instructions = []
|
||||||
|
while True:
|
||||||
|
if len(data) == 0: break
|
||||||
|
cmd_found = False
|
||||||
|
for command in cmds.keys():
|
||||||
|
if data.startswith(command):
|
||||||
|
cmd = cmds[command]
|
||||||
|
num_bytes = len(command)
|
||||||
|
if cmd[1] > 0: num_bytes += cmd[1]
|
||||||
|
if cmd[0] == 'raster':
|
||||||
|
num_bytes += data[2] + 2
|
||||||
|
#payload = data[len(command):num_bytes]
|
||||||
|
instructions.append(data[:num_bytes])
|
||||||
|
data = data[num_bytes:]
|
||||||
|
cmd_found = True
|
||||||
|
if cmd_found:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
msg = 'unknown instruction starting with {}...)'.format(hex_format(data[0:4]))
|
||||||
|
if raise_exception:
|
||||||
|
raise ValueError(msg)
|
||||||
|
else:
|
||||||
|
logger.warning(msg)
|
||||||
|
data = data[1:]
|
||||||
|
return instructions
|
||||||
|
|
||||||
class BrotherQLReader(object):
|
class BrotherQLReader(object):
|
||||||
|
|
||||||
def __init__(self, brother_file):
|
def __init__(self, brother_file):
|
||||||
@@ -52,23 +87,16 @@ class BrotherQLReader(object):
|
|||||||
self.page = 1
|
self.page = 1
|
||||||
|
|
||||||
def analyse(self):
|
def analyse(self):
|
||||||
rem_script = self.brother_file.read()
|
instructions = self.brother_file.read()
|
||||||
while True:
|
for instruction in chunker(instructions):
|
||||||
if len(rem_script) == 0: break
|
|
||||||
cmd_found = False
|
|
||||||
for command in cmds.keys():
|
for command in cmds.keys():
|
||||||
if rem_script.startswith(command):
|
if instruction.startswith(command):
|
||||||
cmd = cmds[command]
|
cmd = cmds[command]
|
||||||
num_bytes = len(command)
|
|
||||||
if cmd[1] > 0: num_bytes += cmd[1]
|
|
||||||
if cmd[0] == 'init':
|
if cmd[0] == 'init':
|
||||||
self.mwidth, self.mheight = None, None
|
self.mwidth, self.mheight = None, None
|
||||||
self.raster_no = None
|
self.raster_no = None
|
||||||
self.rows = []
|
self.rows = []
|
||||||
if cmd[0] == 'raster':
|
payload = instruction[len(command):]
|
||||||
num_bytes += rem_script[2] + 2
|
|
||||||
payload = rem_script[len(command):num_bytes]
|
|
||||||
# now num_bytes and payload are accessable
|
|
||||||
logger.info(" {} ({}) --> found! (payload: {})".format(cmd[0], hex_format(command), hex_format(payload)))
|
logger.info(" {} ({}) --> found! (payload: {})".format(cmd[0], hex_format(command), hex_format(payload)))
|
||||||
if cmd[0] == 'compression':
|
if cmd[0] == 'compression':
|
||||||
self.compression = payload[0] == 0x02
|
self.compression = payload[0] == 0x02
|
||||||
@@ -95,8 +123,8 @@ class BrotherQLReader(object):
|
|||||||
self.rows.append(row)
|
self.rows.append(row)
|
||||||
if cmd[0] == 'media/quality':
|
if cmd[0] == 'media/quality':
|
||||||
self.raster_no = struct.unpack('<L', payload[4:8])[0]
|
self.raster_no = struct.unpack('<L', payload[4:8])[0]
|
||||||
self.mwidth = rem_script[len(command) + 2]
|
self.mwidth = instruction[len(command) + 2]
|
||||||
self.mlength = rem_script[len(command) + 3]*256
|
self.mlength = instruction[len(command) + 3]*256
|
||||||
fmt = " media width: {}mm, media length: {}mm, raster no: {}dots"
|
fmt = " media width: {}mm, media length: {}mm, raster no: {}dots"
|
||||||
logger.info(fmt.format(self.mwidth, self.mlength, self.raster_no))
|
logger.info(fmt.format(self.mwidth, self.mlength, self.raster_no))
|
||||||
if cmd[0] == 'print':
|
if cmd[0] == 'print':
|
||||||
@@ -111,12 +139,3 @@ class BrotherQLReader(object):
|
|||||||
im.save(img_name)
|
im.save(img_name)
|
||||||
print('Page saved as {}'.format(img_name))
|
print('Page saved as {}'.format(img_name))
|
||||||
self.page += 1
|
self.page += 1
|
||||||
|
|
||||||
rem_script = rem_script[num_bytes:]
|
|
||||||
cmd_found = True
|
|
||||||
if cmd_found:
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
logger.error('cmd not found: {0}... ({1}...)'.format(hex_format(rem_script[0:4]), rem_script[0:4]))
|
|
||||||
rem_script = rem_script[1:]
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user