Browse Source

add sparkmaker wow conversion script

Thomas Buck 1 year ago
parent
commit
226057263b
2 changed files with 188 additions and 0 deletions
  1. 4
    0
      tools/README.md
  2. 184
    0
      tools/convert_sparkmaker.py

+ 4
- 0
tools/README.md View File

26
 
26
 
27
 Simple G-Code sender using pySerial to access serial port.
27
 Simple G-Code sender using pySerial to access serial port.
28
 For use with Marlin and possibly other RepRap compatible firmwares.
28
 For use with Marlin and possibly other RepRap compatible firmwares.
29
+
30
+## convert_sparkmaker.py
31
+
32
+Convert PrusaSlicer `.sl1` files to Sparkmaker `.wow` files.

+ 184
- 0
tools/convert_sparkmaker.py View File

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()

Loading…
Cancel
Save