|
@@ -0,0 +1,184 @@
|
|
1
|
+#!/usr/bin/env python
|
|
2
|
+
|
|
3
|
+import sys
|
|
4
|
+import os
|
|
5
|
+from zipfile import ZipFile
|
|
6
|
+import re
|
|
7
|
+import pprint
|
|
8
|
+import png
|
|
9
|
+
|
|
10
|
+###############################################################################
|
|
11
|
+
|
|
12
|
+screen_size = (854, 480)
|
|
13
|
+max_height = 120
|
|
14
|
+initial_params = {
|
|
15
|
+ 'layer_height': 0.1,
|
|
16
|
+ 'first_layer_height': 0.1,
|
|
17
|
+ 'exposure_time': 15.0,
|
|
18
|
+ 'first_exposure_time': 120.0,
|
|
19
|
+ 'lift_height': 5.0,
|
|
20
|
+ 'lift_speed': 30.0,
|
|
21
|
+ 'sink_speed': 100.0
|
|
22
|
+}
|
|
23
|
+
|
|
24
|
+###############################################################################
|
|
25
|
+
|
|
26
|
+def read_prusaslicer_ini(f, params):
|
|
27
|
+ lines = f.decode("utf-8").split("\n")
|
|
28
|
+
|
|
29
|
+ for l in lines:
|
|
30
|
+ if l.startswith("exposure_time"):
|
|
31
|
+ params["exposure_time"] = float(l.split(" = ")[1])
|
|
32
|
+ elif l.startswith("initial_exposure_time"):
|
|
33
|
+ params["first_exposure_time"] = float(l.split(" = ")[1])
|
|
34
|
+ elif l.startswith("layer_height"):
|
|
35
|
+ params["layer_height"] = float(l.split(" = ")[1])
|
|
36
|
+ elif l.startswith("initial_layer_height"):
|
|
37
|
+ params["first_layer_height"] = float(l.split(" = ")[1])
|
|
38
|
+
|
|
39
|
+def read_config_ini(f, params):
|
|
40
|
+ lines = f.decode("utf-8").split("\n")
|
|
41
|
+
|
|
42
|
+ for l in lines:
|
|
43
|
+ if l.startswith("expTimeFirst"):
|
|
44
|
+ params["first_exposure_time"] = float(l.split(" = ")[1])
|
|
45
|
+ elif l.startswith("expTime"):
|
|
46
|
+ params["exposure_time"] = float(l.split(" = ")[1])
|
|
47
|
+ elif l.startswith("layerHeight"):
|
|
48
|
+ params["layer_height"] = float(l.split(" = ")[1])
|
|
49
|
+
|
|
50
|
+def read_sl1(f):
|
|
51
|
+ params = initial_params
|
|
52
|
+
|
|
53
|
+ files = f.namelist()
|
|
54
|
+ if "prusaslicer.ini" in files:
|
|
55
|
+ read_prusaslicer_ini(f.read("prusaslicer.ini"), params)
|
|
56
|
+ else:
|
|
57
|
+ print("No prusaslicer.ini found in file")
|
|
58
|
+ if "config.ini" in files:
|
|
59
|
+ read_config_ini(f.read("config.ini"), params)
|
|
60
|
+ else:
|
|
61
|
+ print("No config.ini found in file")
|
|
62
|
+ sys.exit(1)
|
|
63
|
+
|
|
64
|
+ imgs = [x for x in files if x.endswith(".png")]
|
|
65
|
+ imgs = [x for x in imgs if not x.startswith("thumbnail/")]
|
|
66
|
+
|
|
67
|
+ if len(imgs) <= 0:
|
|
68
|
+ print("No slices found in file. Aborting.")
|
|
69
|
+ sys.exit(1)
|
|
70
|
+
|
|
71
|
+ res = re.findall('(\D*)\d*.*', imgs[0])[0]
|
|
72
|
+ print("Internal name: \"" + res + "\"")
|
|
73
|
+ print("Found " + str(len(imgs)) + " slices")
|
|
74
|
+
|
|
75
|
+ images = []
|
|
76
|
+ for img in imgs:
|
|
77
|
+ images.append(f.read(img))
|
|
78
|
+
|
|
79
|
+ return params, images
|
|
80
|
+
|
|
81
|
+###############################################################################
|
|
82
|
+
|
|
83
|
+def write_image(f, img):
|
|
84
|
+ p = png.Reader(bytes = img)
|
|
85
|
+ width, height, rows, info = p.read()
|
|
86
|
+
|
|
87
|
+ if width != screen_size[0]:
|
|
88
|
+ print("Error: layer has wrong width " + str(width) + " != " + str(screen_size[0]))
|
|
89
|
+ sys.exit(1)
|
|
90
|
+
|
|
91
|
+ if height != screen_size[1]:
|
|
92
|
+ print("Error: layer has wrong height " + str(height) + " != " + str(screen_size[1]))
|
|
93
|
+ sys.exit(1)
|
|
94
|
+
|
|
95
|
+ if (not info['greyscale']) or info['alpha']:
|
|
96
|
+ print("Error: invalid image encoding")
|
|
97
|
+ sys.exit(1)
|
|
98
|
+
|
|
99
|
+ data = [0] * int(width * height / 8)
|
|
100
|
+
|
|
101
|
+ y = 0 # width is 854
|
|
102
|
+ x = 0 # height is 480
|
|
103
|
+ for row in rows:
|
|
104
|
+ for v in row:
|
|
105
|
+ if v > 0x7F:
|
|
106
|
+ data[int(height / 8) * y + int(x / 8)] |= (1 << x % 8)
|
|
107
|
+ y += 1
|
|
108
|
+ x += 1
|
|
109
|
+ y = 0
|
|
110
|
+
|
|
111
|
+ for d in data:
|
|
112
|
+ f.write(d.to_bytes(1, 'big'))
|
|
113
|
+
|
|
114
|
+def write_wow(f, params, imgs):
|
|
115
|
+ def write(s):
|
|
116
|
+ #print(s)
|
|
117
|
+ f.write((s + "\n").encode())
|
|
118
|
+
|
|
119
|
+ write("G21;")
|
|
120
|
+ write("G91;")
|
|
121
|
+ write("M17;")
|
|
122
|
+ write("M106 S0;")
|
|
123
|
+ write("G28 Z0;")
|
|
124
|
+
|
|
125
|
+ first_layer = True
|
|
126
|
+
|
|
127
|
+ for i in range(0, len(imgs)):
|
|
128
|
+ write(";L:" + str(int(i)) + ";")
|
|
129
|
+ write("M106 S0;")
|
|
130
|
+
|
|
131
|
+ lift_up = params['lift_height']
|
|
132
|
+ lift_down = -(lift_up - params['layer_height'])
|
|
133
|
+ exposure_time = params['exposure_time']
|
|
134
|
+ if first_layer:
|
|
135
|
+ lift_down = -(lift_up - params['first_layer_height'])
|
|
136
|
+ exposure_time = params['first_exposure_time']
|
|
137
|
+ first_layer = False
|
|
138
|
+
|
|
139
|
+ write("G1 Z" + str(lift_up) + " F" + str(params['lift_speed']) + ";")
|
|
140
|
+ write("G1 Z" + str(lift_down) + " F" + str(params['sink_speed']) + ";")
|
|
141
|
+ write("{{")
|
|
142
|
+ write_image(f, imgs[i])
|
|
143
|
+ write("}}")
|
|
144
|
+ write("M106 S255;")
|
|
145
|
+ write("G4 S" + str(exposure_time) + ";")
|
|
146
|
+ write("G4 S1;")
|
|
147
|
+
|
|
148
|
+ object_height = params['layer_height'] * (len(imgs) - 1) + params['first_layer_height']
|
|
149
|
+ final_move = max_height - object_height
|
|
150
|
+
|
|
151
|
+ write("M106 S0;")
|
|
152
|
+ write("G1 Z" + str(final_move) + " F25;")
|
|
153
|
+ write("M18;")
|
|
154
|
+
|
|
155
|
+###############################################################################
|
|
156
|
+
|
|
157
|
+def main():
|
|
158
|
+ if len(sys.argv) < 2:
|
|
159
|
+ print("Usage:")
|
|
160
|
+ print(" " + sys.argv[0] + " input.sl1 [output.wow]")
|
|
161
|
+ sys.exit(1)
|
|
162
|
+
|
|
163
|
+ in_file_name = sys.argv[1]
|
|
164
|
+
|
|
165
|
+ out_file_name = "print.wow"
|
|
166
|
+ if len(sys.argv) >= 3:
|
|
167
|
+ out_file_name = sys.argv[2]
|
|
168
|
+
|
|
169
|
+ if os.path.exists(out_file_name):
|
|
170
|
+ print("File already exists: \"" + out_file_name + "\". Aborting.")
|
|
171
|
+ sys.exit(1)
|
|
172
|
+
|
|
173
|
+ with ZipFile(in_file_name, 'r') as sl1:
|
|
174
|
+ params, imgs = read_sl1(sl1)
|
|
175
|
+
|
|
176
|
+ print("Using following parameters:")
|
|
177
|
+ pprint.pprint(params)
|
|
178
|
+ print("Writing output to \"" + out_file_name + "\"")
|
|
179
|
+
|
|
180
|
+ with open(out_file_name, 'wb') as wow:
|
|
181
|
+ write_wow(wow, params, imgs)
|
|
182
|
+
|
|
183
|
+if __name__ == '__main__':
|
|
184
|
+ main()
|