-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparse_intarsia_optimized.py
More file actions
154 lines (119 loc) · 3.93 KB
/
Copy pathparse_intarsia_optimized.py
File metadata and controls
154 lines (119 loc) · 3.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import argparse
import math
from PIL import Image
# hex -> name
colors = {}
# hex -> number
max_cakes = {}
# List of segments per row
segments = []
class Segment:
__slots__ = ['color', 'startIndex', 'endIndex']
def __init__(self, color, startIndex):
# hex
self.color = color
self.startIndex = startIndex
self.endIndex = -1
def __repr__(self):
return f"[{self.color}, ({self.startIndex}, {self.endIndex})]"
def toMachineRow(self, imageWidth, ltor=True, offset=None):
if offset is None:
offset = math.ceil(imageWidth / 2.0)
# Calculate left and right coordinates
# Original logic preserved exactly
left = abs(self.startIndex - offset)
if self.startIndex > offset:
left += 1
right = abs(self.endIndex - offset)
if self.endIndex > offset:
right += 1
c_name = getColor(self.color)
if ltor:
return f"Color {c_name}, {int(left)} to {int(right)}"
else:
return f"Color {c_name}, {int(right)} to {int(left)}"
def preprocess(image):
width, height = image.size
pixels = image.load()
next_color = len(colors)
for y in range(height):
row = []
# Process first pixel
curr_pixel = pixels[0, y]
if curr_pixel not in colors:
colors[curr_pixel] = next_color
next_color += 1
start_x = 0
row_cakes = {}
for x in range(1, width):
pixel = pixels[x, y]
if pixel != curr_pixel:
# End current segment
seg = Segment(curr_pixel, start_x)
seg.endIndex = x - 1
row.append(seg)
# Count cakes for this row
row_cakes[curr_pixel] = row_cakes.get(curr_pixel, 0) + 1
# Start new segment
curr_pixel = pixel
start_x = x
if curr_pixel not in colors:
colors[curr_pixel] = next_color
next_color += 1
# Grab the last segment
seg = Segment(curr_pixel, start_x)
seg.endIndex = width - 1
row.append(seg)
row_cakes[curr_pixel] = row_cakes.get(curr_pixel, 0) + 1
# Update max cakes
for color, count in row_cakes.items():
if count > max_cakes.get(color, 0):
max_cakes[color] = count
segments.append(row)
def getColor(color):
index = colors[color]
if named_colors and index < len(named_colors) and named_colors[index]:
return named_colors[index]
return str(index)
def main(fileName):
try:
image = Image.open(fileName)
except Exception as e:
print(f"Error opening image: {e}")
return
preprocess(image)
print("-- File info --")
print(f"File: {fileName} is {image.width} by {image.height} pixels")
print("Expecting work between %d on the left and %d on the right." % (math.ceil(image.width / 2.0), math.floor(image.width / 2.0)))
print("-- Colors --")
print(f"{len(colors)} colors. Indexed from the top left.")
for color, numCakes in max_cakes.items():
print(f"Color {getColor(color)}: {numCakes} cakes")
width = image.width
offset = math.ceil(width / 2.0)
print("\nPress ENTER for each row...")
row_idx = len(segments) - 1
rows_seen = 0
while row_idx >= 0:
input()
print(f"-- Row {len(segments) - row_idx} --")
ltor = (rows_seen % 2) == 0
print("Start on %s" % ("left" if ltor else "right"))
row_segments = segments[row_idx]
orderedSegments = row_segments if ltor else reversed(row_segments)
for segment in orderedSegments:
print(segment.toMachineRow(width, ltor=ltor, offset=offset))
row_idx -= 1
rows_seen += 1
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Print out intarsia machine knitting instructions')
parser.add_argument('--file', type=str,
help='the file to read')
parser.add_argument('--colors', type=str, nargs='+',
help='Optional names of colors')
args = parser.parse_args()
named_colors = args.colors
if args.file:
main(args.file)
else:
parser.print_help()