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.