custodisco-kiosk/tozpl.py

136 lines
4.9 KiB
Python

#this code was converted to python from http://www.jcgonzalez.com/java-image-to-zpl-example by chatgpt and trav. We modified it together a bit to only accept black and white images :)
from PIL import Image
import numpy as np
class ZPLConveter:
def __init__(self):
self.total = 0
self.width_bytes = 0
self.compress_hex = False
self.map_code = {1: 'G', 2: 'H', 3: 'I', 4: 'J', 5: 'K', 6: 'L', 7: 'M', 8: 'N',
9: 'O', 10: 'P', 11: 'Q', 12: 'R', 13: 'S', 14: 'T', 15: 'U', 16: 'V',
17: 'W', 18: 'X', 19: 'Y', 20: 'g', 40: 'h', 60: 'i', 80: 'j', 100: 'k',
120: 'l', 140: 'm', 160: 'n', 180: 'o', 200: 'p', 220: 'q', 240: 'r',
260: 's', 280: 't', 300: 'u', 320: 'v', 340: 'w', 360: 'x', 380: 'y',
400: 'z'}
def convert_from_img(self, img_path):
image = Image.open(img_path)
cuerpo = self.create_body(image)
if self.compress_hex:
cuerpo = self.encode_hex_ascii(cuerpo)
return self.head_doc() + cuerpo + self.foot_doc()
def create_body(self, image):
width, height = image.size
orginal_image = np.array(image)
index = 0
aux_binary_char = ['0', '0', '0', '0', '0', '0', '0', '0']
self.width_bytes = width // 8
if width % 8 > 0:
self.width_bytes = ((width // 8) + 1)
else:
self.width_bytes = width // 8
self.total = self.width_bytes * height
sb = []
for h in range(height):
for w in range(width):
pixel = orginal_image[h, w]
aux_char = '1' if pixel == 0 else '0' # 0 for black, 1 for white
aux_binary_char[index] = aux_char
index += 1
if index == 8 or w == (width - 1):
sb.append(self.four_byte_binary(''.join(aux_binary_char)))
aux_binary_char = ['0', '0', '0', '0', '0', '0', '0', '0']
index = 0
sb.append("\n")
return ''.join(sb)
@staticmethod
def four_byte_binary(binary_str):
decimal = int(binary_str, 2)
if decimal > 15:
return hex(decimal)[2:].upper()
else:
return "0" + hex(decimal)[2:].upper()
def encode_hex_ascii(self, code):
maxlinea = self.width_bytes * 2
sb_code = []
sb_linea = []
previous_line = None
counter = 1
aux = code[0]
first_char = False
for i in range(1, len(code)):
if first_char:
aux = code[i]
first_char = False
continue
if code[i] == '\n':
if counter >= maxlinea and aux == '0':
sb_linea.append(",")
elif counter >= maxlinea and aux == 'F':
sb_linea.append("!")
elif counter > 20:
multi20 = (counter // 20) * 20
resto20 = (counter % 20)
sb_linea.append(self.map_code[multi20])
if resto20 != 0:
sb_linea.append(self.map_code[resto20] + aux)
else:
sb_linea.append(aux)
else:
sb_linea.append(self.map_code[counter] + aux)
counter = 1
first_char = True
if ''.join(sb_linea) == previous_line:
sb_code.append(":")
else:
sb_code.append(''.join(sb_linea))
previous_line = ''.join(sb_linea)
sb_linea = []
continue
if aux == code[i]:
counter += 1
else:
if counter > 20:
multi20 = (counter // 20) * 20
resto20 = (counter % 20)
sb_linea.append(self.map_code[multi20])
if resto20 != 0:
sb_linea.append(self.map_code[resto20] + aux)
else:
sb_linea.append(aux)
else:
sb_linea.append(self.map_code[counter] + aux)
counter = 1
aux = code[i]
return ''.join(sb_code)
def head_doc(self):
return "^XA " + "^FO0,0^GFA," + str(self.total) + "," + str(self.total) + "," + str(self.width_bytes) + ", "
@staticmethod
def foot_doc():
return "^FS" + "^XZ"
def set_compress_hex(self, compress_hex):
self.compress_hex = compress_hex
def set_blackness_limit_percentage(self, percentage):
self.black_limit = (percentage * 768 // 100)
def print_to_zpl(img_path):
converter = ZPLConveter()
converter.set_compress_hex(True)
return converter.convert_from_img(img_path)
if __name__ == "__main__":
zp = ZPLConveter()
zp.set_compress_hex(True)
#print(zp.convert_from_img("drawing.png"))