diff --git a/pyembroidery/DstReader.py b/pyembroidery/DstReader.py index d62b924..8e02f79 100644 --- a/pyembroidery/DstReader.py +++ b/pyembroidery/DstReader.py @@ -59,18 +59,7 @@ def dst_read_header(f, out): def dst_read_stitches(f, out, settings=None): - jump_count_max = 3 - clipping = True - if settings is not None: - jump_count_max = settings.get('trim_at', jump_count_max) - clipping = settings.get('clipping', clipping) sequin_mode = False - jump_count = 0 - jump_start = 0 - jump_dx = 0 - jump_dy = 0 - jumping = False - trimmed = True while True: byte = bytearray(f.read(3)) if len(byte) != 3: @@ -81,38 +70,29 @@ def dst_read_stitches(f, out, settings=None): break elif byte[2] & 0b11000011 == 0b11000011: out.color_change(dx, dy) - trimmed = True - jumping = False elif byte[2] & 0b01000011 == 0b01000011: out.sequin_mode(dx, dy) sequin_mode = not sequin_mode - jumping = False elif byte[2] & 0b10000011 == 0b10000011: if sequin_mode: out.sequin_eject(dx, dy) else: out.move(dx, dy) - if not jumping: - jump_dx = 0 - jump_dy = 0 - jump_count = 0 - jump_start = len(out.stitches) - 1 - jumping = True - jump_count += 1 - jump_dx += dx - jump_dy += dy - if not trimmed and jump_count == jump_count_max: - out.trim(position=jump_start) - jump_start += 1 # We inserted a position, start jump has moved. - trimmed = True - if clipping and jump_dx == 0 and jump_dy == 0: # jump displacement is 0, clip trim command. - out.stitches = out.stitches[:jump_start] else: out.stitch(dx, dy) - trimmed = False - jumping = False out.end() + count_max = 3 + clipping = True + trim_distance = None + if settings is not None: + count_max = settings.get('trim_at', count_max) + trim_distance = settings.get("trim_distance", trim_distance) + clipping = settings.get('clipping', clipping) + if trim_distance is not None: + trim_distance *= 10 # Pixels per mm. Native units are 1/10 mm. + out.interpolate_trims(count_max, trim_distance, clipping) + def read(f, out, settings=None): dst_read_header(f, out) diff --git a/pyembroidery/EmbPattern.py b/pyembroidery/EmbPattern.py index dbc9c53..1b8f13e 100644 --- a/pyembroidery/EmbPattern.py +++ b/pyembroidery/EmbPattern.py @@ -501,6 +501,60 @@ def add_pattern(self, pattern): self.stitches[i][2] = NO_COMMAND self.extras.update(pattern.extras) + def interpolate_trims(self, jumps_to_require_trim=None, distance_to_require_trim=None, clipping=True): + """Processes a pattern adding trims according to the given criteria.""" + i = -1 + ie = len(self.stitches) - 1 + + x = 0 + y = 0 + jump_count = 0 + jump_start = 0 + jump_dx = 0 + jump_dy = 0 + jumping = False + trimmed = True + while i < ie: + i += 1 + stitch = self.stitches[i] + dx = stitch[0] - x + dy = stitch[1] - y + x = stitch[0] + y = stitch[1] + command = stitch[2] & COMMAND_MASK + if command == STITCH or command == SEQUIN_EJECT: + trimmed = False + jumping = False + elif command == COLOR_CHANGE or command == NEEDLE_SET or command == TRIM: + trimmed = True + jumping = False + if command == JUMP: + if not jumping: + jump_dx = 0 + jump_dy = 0 + jump_count = 0 + jump_start = i + jumping = True + jump_count += 1 + jump_dx += dx + jump_dy += dy + if not trimmed: + if jump_count == jumps_to_require_trim or\ + distance_to_require_trim is not None and\ + ( + abs(jump_dy) > distance_to_require_trim or\ + abs(jump_dx) > distance_to_require_trim + ): + self.trim(position=jump_start) + jump_start += 1 # We inserted a position, start jump has moved. + i += 1 + ie += 1 + trimmed = True + if clipping and jump_dx == 0 and jump_dy == 0: # jump displacement is 0, clip trim command. + del self.stitches[jump_start:i+1] + i = jump_start - 1 + ie = len(self.stitches) - 1 + def get_pattern_interpolate_trim(self, jumps_to_require_trim): """Gets a processed pattern with untrimmed jumps merged and trims added if merged jumps are beyond the given value. diff --git a/pyembroidery/JefReader.py b/pyembroidery/JefReader.py index 74b663d..96b0790 100644 --- a/pyembroidery/JefReader.py +++ b/pyembroidery/JefReader.py @@ -3,23 +3,6 @@ def read_jef_stitches(f, out, settings=None): - clipping = True - trims = False - command_count_max = 3 - trim_distance = 3.0 - if settings is not None: - command_count_max = settings.get('trim_at', command_count_max) - trims = settings.get("trims", trims) - trim_distance = settings.get("trim_distance", trim_distance) - clipping = settings.get('clipping', clipping) - if trim_distance is not None: - trim_distance *= 10 # Pixels per mm. Native units are 1/10 mm. - jump_count = 0 - jump_start = 0 - jump_dx = 0 - jump_dy = 0 - jumping = False - trimmed = True while True: b = bytearray(f.read(2)) if len(b) != 2: @@ -28,8 +11,6 @@ def read_jef_stitches(f, out, settings=None): x = signed8(b[0]) y = -signed8(b[1]) out.stitch(x, y) - trimmed = False - jumping = False continue ctrl = b[1] b = bytearray(f.read(2)) @@ -39,47 +20,30 @@ def read_jef_stitches(f, out, settings=None): y = -signed8(b[1]) if ctrl == 0x02: out.move(x, y) - if not jumping: - jump_dx = 0 - jump_dy = 0 - jump_count = 0 - jump_start = len(out.stitches) - 1 - jumping = True - jump_count += 1 - jump_dx += x - jump_dy += y - if not trimmed and\ - ( - ( - trims - and - jump_count == command_count_max - ) - or - ( - trim_distance is not None - and - ( - abs(jump_dy) > trim_distance or abs(jump_dx) > trim_distance - ) - ) - ): - out.trim(position=jump_start) - jump_start += 1 # We inserted a position, start jump has moved. - trimmed = True - if clipping and jump_dx == 0 and jump_dy == 0: # jump displacement is 0, clip trim command. - out.stitches = out.stitches[:jump_start] continue if ctrl == 0x01: out.color_change(0, 0) - trimmed = True - jumping = False continue if ctrl == 0x10: break break # Uncaught Control out.end(0, 0) + clipping = True + trims = False + count_max = None + trim_distance = 3.0 + if settings is not None: + count_max = settings.get('trim_at', count_max) + trims = settings.get("trims", trims) + trim_distance = settings.get("trim_distance", trim_distance) + clipping = settings.get('clipping', clipping) + if trims and count_max is None: + count_max = 3 + if trim_distance is not None: + trim_distance *= 10 # Pixels per mm. Native units are 1/10 mm. + out.interpolate_trims(count_max, trim_distance, clipping) + def read(f, out, settings=None): jef_threads = get_thread_set() diff --git a/pyembroidery/PyEmbroidery.py b/pyembroidery/PyEmbroidery.py index 5c996e8..e27b077 100644 --- a/pyembroidery/PyEmbroidery.py +++ b/pyembroidery/PyEmbroidery.py @@ -107,6 +107,7 @@ def supported_formats(): "reader": DstReader, "writer": DstWriter, "read_options": { + "trim_distance": (None, 3.0, 50.0), "trim_at": (2, 3, 4, 5, 6, 7, 8), "clipping": (True, False) },