kopia lustrzana https://github.com/EmbroidePy/pyembroidery
351 wiersze
11 KiB
Python
351 wiersze
11 KiB
Python
from .PecWriter import write_pec
|
|
from .EmbThreadPec import get_thread_set
|
|
from .WriteHelper import write_string_utf8, write_int_32le, write_int_16le, write_int_8, write_float_32le
|
|
from .EmbConstant import *
|
|
|
|
SEQUIN_CONTINGENCY = CONTINGENCY_SEQUIN_JUMP
|
|
FULL_JUMP = True
|
|
MAX_JUMP_DISTANCE = 2047
|
|
MAX_STITCH_DISTANCE = 2047
|
|
|
|
VERSION_1 = 1
|
|
VERSION_6 = 6
|
|
|
|
PES_VERSION_1_SIGNATURE = "#PES0001"
|
|
PES_VERSION_6_SIGNATURE = "#PES0060"
|
|
|
|
EMB_ONE = "CEmbOne"
|
|
EMB_SEG = "CSewSeg"
|
|
|
|
|
|
def write(pattern, f, settings=None):
|
|
if settings is not None:
|
|
version = settings.get("pes version", VERSION_6)
|
|
truncated = settings.get("truncated", False)
|
|
else:
|
|
version = VERSION_6
|
|
truncated = False
|
|
if truncated:
|
|
if version == VERSION_1:
|
|
write_truncated_version_1(pattern, f)
|
|
elif version == VERSION_6:
|
|
write_truncated_version_6(pattern, f)
|
|
else:
|
|
if version == VERSION_1:
|
|
write_version_1(pattern, f)
|
|
elif version == VERSION_6:
|
|
write_version_6(pattern, f)
|
|
|
|
|
|
def write_truncated_version_1(pattern, f):
|
|
write_string_utf8(f, PES_VERSION_1_SIGNATURE)
|
|
f.write(b'\x16\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
|
write_pec(pattern, f)
|
|
|
|
|
|
def write_truncated_version_6(pattern, f):
|
|
chart = pattern.threadlist
|
|
write_string_utf8(f, PES_VERSION_6_SIGNATURE)
|
|
placeholder_pec_block = f.tell()
|
|
write_int_32le(f, 0) # Placeholder for PEC BLOCK
|
|
write_pes_header_v6(pattern, f, chart, 0)
|
|
write_int_16le(f, 0x0000)
|
|
write_int_16le(f, 0x0000)
|
|
current_position = f.tell()
|
|
f.seek(placeholder_pec_block, 0)
|
|
write_int_32le(f, current_position)
|
|
f.seek(current_position, 0)
|
|
# this might need that node table thing.
|
|
write_pec(pattern, f)
|
|
|
|
|
|
def write_version_1(pattern, f):
|
|
chart = get_thread_set()
|
|
write_string_utf8(f, PES_VERSION_1_SIGNATURE)
|
|
|
|
extends = pattern.extends()
|
|
cx = (extends[2] + extends[0]) / 2.0
|
|
cy = (extends[3] + extends[1]) / 2.0
|
|
|
|
left = extends[0] - cx
|
|
top = extends[1] - cy
|
|
right = extends[2] - cx
|
|
bottom = extends[3] - cy
|
|
|
|
placeholder_pec_block = f.tell()
|
|
write_int_32le(f, 0) # Placeholder for PEC BLOCK
|
|
|
|
if len(pattern.stitches) == 0:
|
|
write_pes_header_v1(f, 0)
|
|
write_int_16le(f, 0x0000)
|
|
write_int_16le(f, 0x0000)
|
|
else:
|
|
write_pes_header_v1(f, 1)
|
|
write_int_16le(f, 0xFFFF)
|
|
write_int_16le(f, 0x0000)
|
|
write_pes_blocks(f, pattern, chart, left, top, right, bottom, cx, cy)
|
|
|
|
current_position = f.tell()
|
|
f.seek(placeholder_pec_block, 0)
|
|
write_int_32le(f, current_position)
|
|
f.seek(current_position, 0)
|
|
|
|
write_pec(pattern, f)
|
|
|
|
|
|
def write_version_6(pattern, f):
|
|
pattern.fix_color_count()
|
|
chart = pattern.threadlist
|
|
write_string_utf8(f, PES_VERSION_6_SIGNATURE)
|
|
|
|
extends = pattern.extends()
|
|
cx = (extends[2] + extends[0]) / 2.0
|
|
cy = (extends[3] + extends[1]) / 2.0
|
|
|
|
left = extends[0] - cx
|
|
top = extends[1] - cy
|
|
right = extends[2] - cx
|
|
bottom = extends[3] - cy
|
|
|
|
placeholder_pec_block = f.tell()
|
|
write_int_32le(f, 0) # Placeholder for PEC BLOCK
|
|
|
|
if len(pattern.stitches) == 0:
|
|
write_pes_header_v6(pattern, f, chart, 0)
|
|
write_int_16le(f, 0x0000)
|
|
write_int_16le(f, 0x0000)
|
|
else:
|
|
write_pes_header_v6(pattern, f, chart, 1)
|
|
write_int_16le(f, 0xFFFF)
|
|
write_int_16le(f, 0x0000)
|
|
log = write_pes_blocks(f, pattern, chart, left, top, right, bottom, cx, cy)
|
|
# In version 6 there is some node, tree, order thing.
|
|
write_int_32le(f, 0)
|
|
write_int_32le(f, 0)
|
|
for i in range(0, len(log)):
|
|
write_int_32le(f, i)
|
|
write_int_32le(f, 0)
|
|
|
|
current_position = f.tell()
|
|
f.seek(placeholder_pec_block, 0)
|
|
write_int_32le(f, current_position)
|
|
f.seek(current_position, 0)
|
|
write_pec(pattern, f)
|
|
|
|
|
|
def write_pes_header_v1(f, distinct_block_objects):
|
|
write_int_16le(f, 0x01) # scale to fit
|
|
write_int_16le(f, 0x01) # 0 = 100x100, 130x180 hoop
|
|
write_int_16le(f, distinct_block_objects)
|
|
|
|
|
|
def write_pes_header_v6(pattern, f, chart, distinct_block_objects):
|
|
write_int_16le(f, 0x01) # 0 = 100x100, 130x180 hoop
|
|
f.write(b'02') # This is an 2-digit ascii number.
|
|
write_pes_string_8(f, pattern.get_metadata("name", None))
|
|
write_pes_string_8(f, pattern.get_metadata("category", None))
|
|
write_pes_string_8(f, pattern.get_metadata("author", None))
|
|
write_pes_string_8(f, pattern.get_metadata("keywords", None))
|
|
write_pes_string_8(f, pattern.get_metadata("comments", None))
|
|
write_int_16le(f, 0) # OptimizeHoopChange = False
|
|
write_int_16le(f, 0) # Design Page Is Custom = False
|
|
write_int_16le(f, 0x64) # Hoop Width
|
|
write_int_16le(f, 0x64) # Hoop Height
|
|
write_int_16le(f, 0) # Use Existing Design Area = False
|
|
write_int_16le(f, 0xC8) # designWidth
|
|
write_int_16le(f, 0xC8) # designHeight
|
|
write_int_16le(f, 0x64) # designPageSectionWidth
|
|
write_int_16le(f, 0x64) # designPageSectionHeight
|
|
write_int_16le(f, 0x64) # p6 # 100
|
|
write_int_16le(f, 0x07) # designPageBackgroundColor
|
|
write_int_16le(f, 0x13) # designPageForegroundColor
|
|
write_int_16le(f, 0x01) # ShowGrid
|
|
write_int_16le(f, 0x01) # WithAxes
|
|
write_int_16le(f, 0x00) # SnapToGrid
|
|
write_int_16le(f, 100) # GridInterval
|
|
write_int_16le(f, 0x01) # p9 curves?
|
|
write_int_16le(f, 0x00) # OptimizeEntryExitPoints
|
|
write_int_8(f, 0) # fromImageStringLength
|
|
# String FromImageFilename
|
|
write_float_32le(f, float(1))
|
|
write_float_32le(f, float(0))
|
|
write_float_32le(f, float(0))
|
|
write_float_32le(f, float(1))
|
|
write_float_32le(f, float(0))
|
|
write_float_32le(f, float(0))
|
|
write_int_16le(f, 0) # numberOfProgrammableFillPatterns
|
|
write_int_16le(f, 0) # numberOfMotifPatterns
|
|
write_int_16le(f, 0) # featherPatternCount
|
|
count_thread = len(chart)
|
|
write_int_16le(f, count_thread) # numberOfColors
|
|
for thread in chart:
|
|
write_pes_thread(f, thread)
|
|
write_int_16le(f, distinct_block_objects) # number ofdistinct blocks
|
|
|
|
|
|
def write_pes_string_8(f, string):
|
|
if string is None:
|
|
write_int_8(f, 0)
|
|
return
|
|
if len(string) > 255:
|
|
string = string[:255]
|
|
write_int_8(f, len(string))
|
|
write_string_utf8(f, string)
|
|
|
|
|
|
def write_pes_string_16(f, string):
|
|
if string is None:
|
|
write_int_16le(f, 0)
|
|
return
|
|
write_int_16le(f, len(string))
|
|
# 16 refers to the size write not the string encoding.
|
|
write_string_utf8(f, string)
|
|
|
|
|
|
def write_pes_thread(f, thread):
|
|
write_pes_string_8(f, thread.catalog_number)
|
|
write_int_8(f, thread.get_red())
|
|
write_int_8(f, thread.get_green())
|
|
write_int_8(f, thread.get_blue())
|
|
write_int_8(f, 0) # unknown
|
|
write_int_32le(f, 0xA) # A is custom color
|
|
write_pes_string_8(f, thread.description)
|
|
write_pes_string_8(f, thread.brand)
|
|
write_pes_string_8(f, thread.chart)
|
|
|
|
|
|
def write_pes_blocks(f, pattern, chart, left, top, right, bottom, cx, cy):
|
|
if len(pattern.stitches) == 0:
|
|
return
|
|
|
|
write_pes_string_16(f, EMB_ONE)
|
|
placeholder = write_pes_sewsegheader(f, left, top, right, bottom)
|
|
write_int_16le(f, 0xFFFF)
|
|
write_int_16le(f, 0x0000) # FFFF0000 means more blocks exist
|
|
|
|
write_pes_string_16(f, EMB_SEG)
|
|
data = write_pes_embsewseg_segments(f, pattern, chart, left, bottom, cx, cy)
|
|
|
|
sections = data[0]
|
|
colorlog = data[1]
|
|
|
|
current_position = f.tell()
|
|
f.seek(placeholder, 0)
|
|
write_int_16le(f, sections)
|
|
f.seek(current_position, 0) # patch final section count.
|
|
|
|
# If there were addition embsewsegheaders or segments they would go here.
|
|
|
|
write_int_16le(f, 0x0000)
|
|
write_int_16le(f, 0x0000) # 00000000 means no more blocks.
|
|
|
|
return colorlog
|
|
|
|
|
|
def write_pes_sewsegheader(f, left, top, right, bottom):
|
|
width = right - left
|
|
height = bottom - top
|
|
hoop_height = 1800
|
|
hoop_width = 1300
|
|
write_int_16le(f, 0) # left
|
|
write_int_16le(f, 0) # top
|
|
write_int_16le(f, 0) # right
|
|
write_int_16le(f, 0) # bottom
|
|
write_int_16le(f, 0) # left
|
|
write_int_16le(f, 0) # top
|
|
write_int_16le(f, 0) # right
|
|
write_int_16le(f, 0) # bottom
|
|
trans_x = 0
|
|
trans_y = 0
|
|
trans_x += float(350)
|
|
trans_y += float(100) + height
|
|
trans_x += hoop_width / 2
|
|
trans_y += hoop_height / 2
|
|
trans_x += -width / 2
|
|
trans_y += -height / 2
|
|
write_float_32le(f, float(1))
|
|
write_float_32le(f, float(0))
|
|
write_float_32le(f, float(0))
|
|
write_float_32le(f, float(1))
|
|
write_float_32le(f, float(trans_x))
|
|
write_float_32le(f, float(trans_y))
|
|
|
|
write_int_16le(f, 1)
|
|
write_int_16le(f, 0)
|
|
write_int_16le(f, 0)
|
|
write_int_16le(f, int(width))
|
|
write_int_16le(f, int(height))
|
|
f.write(b'\x00\x00\x00\x00\x00\x00\x00\x00')
|
|
|
|
placeholder_needs_section_data = f.tell()
|
|
# sections
|
|
write_int_16le(f, 0)
|
|
return placeholder_needs_section_data
|
|
|
|
|
|
def get_as_segments_blocks(pattern, chart, adjust_x, adjust_y):
|
|
color_index = 0
|
|
current_thread = pattern.get_thread_or_filler(color_index)
|
|
color_index += 1
|
|
color_code = current_thread.find_nearest_color_index(chart)
|
|
stitched_x = 0
|
|
stitched_y = 0
|
|
for command_block in pattern.get_as_command_blocks():
|
|
block = []
|
|
command = command_block[0][2]
|
|
if command == JUMP:
|
|
block.append([stitched_x - adjust_x, stitched_y - adjust_y])
|
|
last_pos = command_block[-1]
|
|
block.append([last_pos[0] - adjust_x, last_pos[1] - adjust_y])
|
|
flag = 1
|
|
elif command == COLOR_CHANGE:
|
|
current_thread = pattern.get_thread_or_filler(color_index)
|
|
color_index += 1
|
|
color_code = current_thread.find_nearest_color_index(chart)
|
|
flag = 1
|
|
continue
|
|
elif command == STITCH:
|
|
for stitch in command_block:
|
|
stitched_x = stitch[0]
|
|
stitched_y = stitch[1]
|
|
block.append([stitched_x - adjust_x, stitched_y - adjust_y])
|
|
flag = 0
|
|
else:
|
|
continue
|
|
yield (block, color_code, flag)
|
|
|
|
|
|
def write_pes_embsewseg_segments(f, pattern, chart, left, bottom, cx, cy):
|
|
section = 0
|
|
colorlog = []
|
|
|
|
previous_color_code = -1
|
|
flag = -1
|
|
adjust_x = left + cx
|
|
adjust_y = bottom + cy
|
|
for segs in get_as_segments_blocks(pattern, chart, adjust_x, adjust_y):
|
|
if flag != -1:
|
|
write_int_16le(f, 0x8003) # section end.
|
|
segments = segs[0]
|
|
color_code = segs[1]
|
|
flag = segs[2]
|
|
|
|
if previous_color_code != color_code:
|
|
colorlog.append([section, color_code])
|
|
previous_color_code = color_code
|
|
# This must trigger first segment.
|
|
write_int_16le(f, flag)
|
|
write_int_16le(f, color_code)
|
|
write_int_16le(f, len(segments))
|
|
for segs in segments:
|
|
write_int_16le(f, int(segs[0]))
|
|
write_int_16le(f, int(segs[1]))
|
|
section += 1
|
|
|
|
write_int_16le(f, len(colorlog))
|
|
for log_item in colorlog:
|
|
write_int_16le(f, log_item[0])
|
|
write_int_16le(f, log_item[1])
|
|
|
|
return section, colorlog # how many sections, how color transitions.
|