Skip to content

Commit 0da26fc

Browse files
authored
Merge pull request #116 from EmbroidePy/issue115
Jef ColorCount Bug
2 parents e23708f + a1c34b1 commit 0da26fc

File tree

9 files changed

+172
-16
lines changed

9 files changed

+172
-16
lines changed

pyembroidery/JefReader.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44

55
def read_jef_stitches(f, out, settings=None):
6+
color_index = 1
67
while True:
78
b = bytearray(f.read(2))
89
if len(b) != 2:
@@ -22,7 +23,13 @@ def read_jef_stitches(f, out, settings=None):
2223
out.move(x, y)
2324
continue
2425
if ctrl == 0x01:
25-
out.color_change(0, 0)
26+
# PATCH: None means stop since it was color #0
27+
if out.threadlist[color_index] is None:
28+
out.stop(0, 0)
29+
del out.threadlist[color_index]
30+
else:
31+
out.color_change(0, 0)
32+
color_index += 1
2633
continue
2734
if ctrl == 0x10:
2835
break
@@ -54,7 +61,11 @@ def read(f, out, settings=None):
5461

5562
for i in range(0, count_colors):
5663
index = abs(read_int_32le(f))
57-
out.add_thread(jef_threads[index % len(jef_threads)])
64+
if index == 0:
65+
# Patch: If we have color 0. Go ahead and set that to None.
66+
out.threadlist.append(None)
67+
else:
68+
out.add_thread(jef_threads[index % len(jef_threads)])
5869

5970
f.seek(stitch_offset, 0)
6071
read_jef_stitches(f, out, settings)

pyembroidery/JefWriter.py

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import datetime
22

33
from .EmbConstant import *
4-
from .EmbThread import build_nonrepeat_palette
54
from .EmbThreadJef import get_thread_set
65
from .WriteHelper import write_int_8, write_int_32le, write_string_utf8
76

@@ -30,7 +29,46 @@ def write(pattern, f, settings=None):
3029
date_string = settings.get("date", date_string)
3130

3231
pattern.fix_color_count()
33-
color_count = pattern.count_threads()
32+
# REMOVE BUG: color_count = pattern.count_threads(). #
33+
34+
# PATCH
35+
jef_threads = get_thread_set()
36+
last_index = None
37+
last_thread = None
38+
palette = []
39+
color_toggled = False
40+
color_count = 0 # Color and Stop count.
41+
index_in_threadlist = 0
42+
for stitch in pattern.stitches:
43+
# Iterate all stitches.
44+
flags = stitch[2] & COMMAND_MASK
45+
if flags == COLOR_CHANGE or index_in_threadlist == 0:
46+
# If color change *or* initial color unset.
47+
thread = pattern.threadlist[index_in_threadlist]
48+
index_in_threadlist += 1
49+
color_count += 1
50+
index_of_jefthread = thread.find_nearest_color_index(jef_threads)
51+
if last_index == index_of_jefthread and last_thread != thread:
52+
# Last thread and current thread pigeonhole to same jefcolor.
53+
# We set that thread to None. And get the second closest color.
54+
repeated_thread = jef_threads[index_of_jefthread]
55+
repeated_index = index_of_jefthread
56+
jef_threads[index_of_jefthread] = None
57+
index_of_jefthread = thread.find_nearest_color_index(jef_threads)
58+
jef_threads[repeated_index] = repeated_thread
59+
palette.append(index_of_jefthread)
60+
last_index = index_of_jefthread
61+
last_thread = thread
62+
color_toggled = False
63+
if flags == STOP:
64+
color_count += 1
65+
color_toggled = not color_toggled
66+
if color_toggled:
67+
palette.append(0)
68+
else:
69+
palette.append(last_index)
70+
# END PATCH
71+
3472
offsets = 0x74 + (color_count * 8)
3573
write_int_32le(f, offsets)
3674
write_int_32le(f, 0x14)
@@ -48,7 +86,7 @@ def write(pattern, f, settings=None):
4886
elif data == TRIM:
4987
if trims:
5088
point_count += 2 * command_count_max
51-
elif data == COLOR_CHANGE:
89+
elif data == COLOR_CHANGE or data == STOP: # PATCH: INCLUDE STOP.
5290
point_count += 2
5391
elif data == END:
5492
break
@@ -86,9 +124,12 @@ def write(pattern, f, settings=None):
86124
y_hoop_edge = 1000 - half_height
87125
write_hoop_edge_distance(f, x_hoop_edge, y_hoop_edge)
88126

89-
jef_threads = get_thread_set()
127+
# REMOVE (We covered this in PATCH).
128+
#jef_threads = get_thread_set()
129+
#
130+
#palette = build_nonrepeat_palette(jef_threads, pattern.threadlist)
131+
# END REMOVE
90132

91-
palette = build_nonrepeat_palette(jef_threads, pattern.threadlist)
92133
for t in palette:
93134
write_int_32le(f, t)
94135

@@ -109,7 +150,7 @@ def write(pattern, f, settings=None):
109150
write_int_8(f, dx)
110151
write_int_8(f, -dy)
111152
continue
112-
elif data == COLOR_CHANGE:
153+
elif data == COLOR_CHANGE or data == STOP: # PATCH INCLUDE STOP.
113154
f.write(b"\x80\x01")
114155
write_int_8(f, dx)
115156
write_int_8(f, -dy)

pyembroidery/PecWriter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def write_pec_header(pattern, f, threadlist):
6060
f.write(b"\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20")
6161
add_value = current_thread_count - 1
6262
color_index_list.insert(0, add_value)
63-
assert color_index_list[0]<255, 'to many color changes, ({0}) out of bounds (0, 255)'.format(len(color_index_list))
63+
assert color_index_list[0] < 255, 'too many color changes, ({0}) out of bounds (0, 255)'.format(len(color_index_list))
6464
f.write(bytes(bytearray(color_index_list)))
6565
else:
6666
f.write(b"\x20\x20\x20\x20\x64\x20\x00\x20\x00\x20\x20\x20\xFF")

pyembroidery/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from .EmbMatrix import EmbMatrix
77
from .EmbPattern import EmbPattern
88
from .EmbThread import EmbThread
9+
from .EmbCompress import compress, expand
910

1011
# items available in a sub-heirarchy (e.g. pyembroidery.PecGraphics.get_graphic_as_string)
1112
from .PecGraphics import get_graphic_as_string

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setuptools.setup(
77
name="pyembroidery",
8-
version="1.4.28",
8+
version="1.4.29",
99
author="Tatarize",
1010
author_email="[email protected]",
1111
description="Embroidery IO library",

test/pattern_for_tests.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ def add_serp(self):
5959
}
6060
evaluate_lsystem(initial, rules, 3) # 6
6161

62+
6263
def get_big_pattern():
6364
pattern = EmbPattern()
6465
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "red")
@@ -131,6 +132,78 @@ def get_shift_pattern():
131132
return pattern
132133

133134

135+
def get_shift_stop_pattern():
136+
pattern = EmbPattern()
137+
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "red")
138+
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
139+
pattern.add_command(MATRIX_ROTATE, 22.5)
140+
pattern.add_command(STOP)
141+
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "red")
142+
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
143+
pattern.add_command(MATRIX_ROTATE, 22.5)
144+
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "green")
145+
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
146+
pattern.add_command(MATRIX_ROTATE, 22.5)
147+
pattern.add_command(STOP)
148+
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "green")
149+
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
150+
pattern.add_command(MATRIX_ROTATE, 22.5)
151+
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "green")
152+
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
153+
pattern.add_command(MATRIX_ROTATE, 22.5)
154+
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "ivory")
155+
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
156+
pattern.add_command(MATRIX_ROTATE, 22.5)
157+
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "ivory")
158+
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
159+
pattern.add_command(MATRIX_ROTATE, 22.5)
160+
pattern.add_command(STOP)
161+
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "ivory")
162+
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
163+
pattern.add_command(MATRIX_ROTATE, 22.5)
164+
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "olive")
165+
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
166+
pattern.add_command(MATRIX_ROTATE, 22.5)
167+
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "olive")
168+
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
169+
pattern.add_command(MATRIX_ROTATE, 22.5)
170+
pattern.add_command(STOP)
171+
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "olive")
172+
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
173+
pattern.add_command(MATRIX_ROTATE, 22.5)
174+
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "olive")
175+
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
176+
pattern.add_command(MATRIX_ROTATE, 22.5)
177+
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "violet")
178+
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
179+
pattern.add_command(MATRIX_ROTATE, 22.5)
180+
pattern.add_command(STOP)
181+
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "white")
182+
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
183+
pattern.add_command(MATRIX_ROTATE, 22.5)
184+
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "salmon")
185+
pattern.add_command(MATRIX_TRANSLATE, 25, 25)
186+
pattern.add_command(MATRIX_ROTATE, 22.5)
187+
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "lime")
188+
return pattern
189+
190+
191+
def get_simple_stop():
192+
pattern = EmbPattern()
193+
pattern += (0,0)
194+
pattern += (0, 100)
195+
pattern += (100, 100)
196+
pattern += (100, 0)
197+
pattern += (0, 0)
198+
pattern.stop()
199+
pattern += (0, 0)
200+
pattern += (0, 100)
201+
pattern += (100, 100)
202+
pattern += (100, 0)
203+
pattern += (0, 0)
204+
return pattern
205+
206+
134207
def get_simple_pattern():
135208
pattern = EmbPattern()
136209
pattern.add_block([(0, 0), (0, 100), (100, 100), (100, 0), (0, 0)], "red")

test/test_convert_jef.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,4 +168,34 @@ def test_convert_jef_to_xxx(self):
168168
self.position_equals(t_pattern.stitches, 0, -1)
169169
print("jef->xxx: ", t_pattern.stitches)
170170
self.addCleanup(os.remove, file1)
171-
self.addCleanup(os.remove, file2)
171+
self.addCleanup(os.remove, file2)
172+
173+
def test_jef_stop_write_simple(self):
174+
file = "stop.jef"
175+
write_jef(get_simple_stop(), file)
176+
s_pattern = read_jef(file)
177+
self.assertEqual(s_pattern.count_stitch_commands(STOP), 1)
178+
self.assertEqual(s_pattern.count_color_changes(), 0)
179+
self.addCleanup(os.remove, file)
180+
181+
def test_jef_stop_write_large(self):
182+
file = "stop2.jef"
183+
pattern = get_shift_stop_pattern()
184+
n_pattern = pattern.get_normalized_pattern()
185+
self.assertEqual(n_pattern.count_stitch_commands(COLOR_CHANGE), 15)
186+
self.assertEqual(n_pattern.count_stitch_commands(STITCH), 16 * 5)
187+
self.assertEqual(n_pattern.count_stitch_commands(STOP), 5)
188+
189+
write_jef(pattern, file)
190+
f_pattern = read_jef(file)
191+
self.assertIsNotNone(f_pattern)
192+
193+
with open(file, "rb") as f:
194+
f.seek(0x18)
195+
colors = f.read(1)
196+
self.assertEqual(ord(colors), f_pattern.count_color_changes() + f_pattern.count_stitch_commands(STOP) + 1)
197+
198+
self.assertEqual(f_pattern.count_stitch_commands(COLOR_CHANGE), 15)
199+
self.assertEqual(f_pattern.count_stitch_commands(STITCH), 16 * 5)
200+
self.assertEqual(f_pattern.count_stitch_commands(STOP), 5)
201+
self.addCleanup(os.remove, file)

test/test_encoder.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,4 @@ def test_transcode_to_self(self):
110110
from pyembroidery.EmbEncoder import Transcoder
111111
encoder = Transcoder()
112112
encoder.transcode(pattern, pattern)
113-
self.assertNotEquals(len(pattern.stitches), 0)
113+
self.assertNotEqual(len(pattern.stitches), 0)

test/test_read_hus.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
import random
44
import unittest
55

6-
from EmbCompress import expand, compress
6+
from pyembroidery import *
77

88

99
class TestReadHus(unittest.TestCase):
1010

1111
def test_fake_compression(self):
1212
for i in range(10):
13-
s = random.randint(10, 1000)
13+
s = random.randint(10, 1000) # May fail if larger.
1414
test_bytes = bytearray(random.getrandbits(8) for _ in range(s))
15-
compressed_bytes = compress(test_bytes)
16-
uncompressed = bytearray(expand(compressed_bytes, len(test_bytes)))
15+
compressed_bytes = EmbCompress.compress(test_bytes)
16+
uncompressed = bytearray(EmbCompress.expand(compressed_bytes, len(test_bytes)))
1717
self.assertEqual(test_bytes, uncompressed)

0 commit comments

Comments
 (0)