pyembroidery/pyembroidery/PecReader.py

158 wiersze
4.6 KiB
Python

from .EmbThreadPec import get_thread_set
from .ReadHelper import read_int_8, read_int_24le, read_string_8
JUMP_CODE = 0x10
TRIM_CODE = 0x20
FLAG_LONG = 0x80
def read(f, out, settings=None):
pec_string = read_string_8(f, 8)
# pec_string must equal #PEC0001
read_pec(f, out)
out.interpolate_duplicate_color_as_stop()
def read_pec(f, out, pes_chart=None):
f.seek(3, 1) # LA:
label = read_string_8(f, 16) # Label
if label is not None:
out.metadata("Name", label.strip())
f.seek(0xF, 1) # Dunno, spaces then 0xFF 0x00
pec_graphic_byte_stride = read_int_8(f)
pec_graphic_icon_height = read_int_8(f)
f.seek(0xC, 1)
color_changes = read_int_8(f)
count_colors = color_changes + 1 # PEC uses cc - 1, 0xFF means 0.
color_bytes = bytearray(f.read(count_colors))
threads = []
map_pec_colors(color_bytes, out, pes_chart, threads)
f.seek(0x1D0 - color_changes, 1)
stitch_block_end = read_int_24le(f) - 5 + f.tell()
# The end of this value is already 5 into the stitchblock.
# 3 bytes, '\x31\xff\xf0', 4 2-byte shorts. 11 total.
f.seek(0x0B, 1)
read_pec_stitches(f, out)
f.seek(stitch_block_end, 0)
byte_size = pec_graphic_byte_stride * pec_graphic_icon_height
read_pec_graphics(
f, out, byte_size, pec_graphic_byte_stride, count_colors + 1, threads
)
def read_pec_graphics(f, out, size, stride, count, values):
v = values[:]
v.insert(0, None)
for i in range(0, count):
graphic = bytearray(f.read(size))
if f is not None:
name = "pec_graphic_" + str(i)
out.metadata(name, (graphic, stride, v[i]))
def process_pec_colors(colorbytes, out, values):
thread_set = get_thread_set()
max_value = len(thread_set)
for byte in colorbytes:
thread_value = thread_set[byte % max_value]
out.add_thread(thread_value)
values.append(thread_value)
def process_pec_table(colorbytes, out, chart, values):
# This is how PEC actually allocates pre-defined threads to blocks.
thread_set = get_thread_set()
max_value = len(thread_set)
thread_map = {}
for i in range(0, len(colorbytes)):
color_index = int(colorbytes[i] % max_value)
thread_value = thread_map.get(color_index, None)
if thread_value is None:
if len(chart) > 0:
thread_value = chart.pop(0)
else:
thread_value = thread_set[color_index]
thread_map[color_index] = thread_value
out.add_thread(thread_value)
values.append(thread_value)
def map_pec_colors(colorbytes, out, chart, values):
if chart is None or len(chart) == 0:
# Reading pec colors.
process_pec_colors(colorbytes, out, values)
elif len(chart) >= len(colorbytes):
# Reading threads in 1 : 1 mode.
for thread in chart:
out.add_thread(thread)
values.append(thread)
else:
# Reading tabled mode threads.
process_pec_table(colorbytes, out, chart, values)
def signed12(b):
b &= 0xFFF
if b > 0x7FF:
return -0x1000 + b
else:
return b
def signed7(b):
if b > 63:
return -128 + b
else:
return b
def read_pec_stitches(f, out):
while True:
val1 = read_int_8(f)
val2 = read_int_8(f)
if (val1 == 0xFF and val2 == 0x00) or val2 is None:
break
if val1 == 0xFE and val2 == 0xB0:
f.seek(1, 1)
out.color_change(0, 0)
continue
jump = False
trim = False
if val1 & FLAG_LONG != 0:
if val1 & TRIM_CODE != 0:
trim = True
if val1 & JUMP_CODE != 0:
jump = True
code = (val1 << 8) | val2
x = signed12(code)
val2 = read_int_8(f)
if val2 is None:
break
else:
x = signed7(val1)
if val2 & FLAG_LONG != 0:
if val2 & TRIM_CODE != 0:
trim = True
if val2 & JUMP_CODE != 0:
jump = True
val3 = read_int_8(f)
if val3 is None:
break
code = val2 << 8 | val3
y = signed12(code)
else:
y = signed7(val2)
if jump:
out.move(x, y)
elif trim:
out.trim()
out.move(x, y)
else:
out.stitch(x, y)
out.end()