JacobLinCool commited on
Commit
e572519
·
1 Parent(s): 842c883

feat: web server

Browse files

Former-commit-id: 93ae34305df9f3603529996c9af09b09a611a5b5

Files changed (2) hide show
  1. server.py +73 -0
  2. ui.html +144 -0
server.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+ import tempfile
3
+ import subprocess
4
+ from flask import Flask, request, send_file
5
+
6
+ app = Flask(__name__)
7
+
8
+
9
+ @app.route("/")
10
+ def alive():
11
+ return send_file("ui.html")
12
+
13
+
14
+ @app.route("/create", methods=["POST"])
15
+ def create():
16
+ data = request.get_json()
17
+
18
+ if "svg" not in data:
19
+ return "error"
20
+
21
+ svg = data["svg"]
22
+
23
+ # make a temp dir
24
+ dir = tempfile.mkdtemp()
25
+ filepath = dir + "/temp.svg"
26
+
27
+ with open(filepath, "wb") as f:
28
+ f.write(svg.encode("utf-8"))
29
+ f.flush()
30
+
31
+ rotate_x = data["rotate_x"] if "rotate_x" in data else 0
32
+ rotate_y = data["rotate_y"] if "rotate_y" in data else 0
33
+ rotate_z = data["rotate_z"] if "rotate_z" in data else 0
34
+ thickness = data["thickness"] if "thickness" in data else 1
35
+ distance = data["distance"] if "distance" in data else 1
36
+ light_x = data["light_x"] if "light_x" in data else 0
37
+ light_y = data["light_y"] if "light_y" in data else 0
38
+ light_z = data["light_z"] if "light_z" in data else 0
39
+ light_strength = data["light_strength"] if "light_strength" in data else 1
40
+ color_r = data["color_r"] if "color_r" in data else -1
41
+ color_g = data["color_g"] if "color_g" in data else -1
42
+ color_b = data["color_b"] if "color_b" in data else -1
43
+ size = data["size"] if "size" in data else 2048
44
+ bevel = data["bevel"] if "bevel" in data else 1
45
+
46
+ subprocess.run([
47
+ "blender",
48
+ "--background",
49
+ "--python",
50
+ "create.py",
51
+ "--",
52
+ filepath,
53
+ "--rotate-x", str(rotate_x),
54
+ "--rotate-y", str(rotate_y),
55
+ "--rotate-z", str(rotate_z),
56
+ "--thickness", str(thickness),
57
+ "--distance", str(distance),
58
+ "--light-x", str(light_x),
59
+ "--light-y", str(light_y),
60
+ "--light-z", str(light_z),
61
+ "--light-strength", str(light_strength),
62
+ "--red", str(color_r),
63
+ "--green", str(color_g),
64
+ "--blue", str(color_b),
65
+ "--size", str(size),
66
+ "--bevel", str(bevel)
67
+ ])
68
+
69
+ return send_file(dir + "/temp.png", mimetype="image/png")
70
+
71
+
72
+ if __name__ == "__main__":
73
+ app.run(host="0.0.0.0", port=7860)
ui.html ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Create 3D Icon</title>
7
+ <style>
8
+ * {
9
+ position: relative;
10
+ font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
11
+ }
12
+ html,
13
+ body {
14
+ margin: 0;
15
+ padding: 0;
16
+ height: 100%;
17
+ width: 100%;
18
+ overflow: hidden;
19
+ }
20
+ #app {
21
+ height: 100%;
22
+ width: 100%;
23
+ overflow-y: auto;
24
+ }
25
+ #container {
26
+ display: flex;
27
+ flex-direction: column;
28
+ align-items: center;
29
+ }
30
+ #container > div {
31
+ display: flex;
32
+ flex-direction: row;
33
+ align-items: center;
34
+ justify-content: center;
35
+ width: 100%;
36
+ height: 100%;
37
+ }
38
+ #in {
39
+ flex: 1;
40
+ display: flex;
41
+ flex-direction: column;
42
+ align-items: center;
43
+ justify-content: center;
44
+ padding: 1rem;
45
+ }
46
+ #out {
47
+ flex: 1;
48
+ display: flex;
49
+ flex-direction: column;
50
+ align-items: center;
51
+ justify-content: center;
52
+ padding: 1rem;
53
+ }
54
+ img {
55
+ width: 100%;
56
+ }
57
+ </style>
58
+ </head>
59
+
60
+ <body>
61
+ <div id="app">
62
+ <div id="container">
63
+ <div>
64
+ <h1>Create 3D Icon</h1>
65
+ </div>
66
+
67
+ <div>
68
+ <div id="in">
69
+ <input type="file" id="file" accept="image/svg+xml" />
70
+ <p id="status">Select an SVG file to create a 3D icon</p>
71
+ </div>
72
+ <div id="out">
73
+ <img id="img" />
74
+ </div>
75
+ </div>
76
+ </div>
77
+ </div>
78
+ <script>
79
+ const input = document.querySelector("#file");
80
+ const img = document.querySelector("#img");
81
+ const status = document.querySelector("#status");
82
+
83
+ let running = false;
84
+
85
+ async function run() {
86
+ if (running) {
87
+ alert("Still running");
88
+ return;
89
+ }
90
+ running = true;
91
+ input.disabled = true;
92
+ status.innerText = "Creating icon ...";
93
+
94
+ try {
95
+ const files = input.files;
96
+ if (files.length === 0) {
97
+ throw new Error("No file selected");
98
+ }
99
+
100
+ const file = files[0];
101
+ const reader = new FileReader();
102
+ reader.readAsText(file);
103
+ const svg = await new Promise((resolve, reject) => {
104
+ reader.onload = () => resolve(reader.result);
105
+ reader.onerror = reject;
106
+ });
107
+
108
+ const res = await fetch("/create", {
109
+ method: "POST",
110
+ headers: {
111
+ "Content-Type": "application/json",
112
+ },
113
+ body: JSON.stringify({
114
+ svg,
115
+ size: 1024,
116
+ distance: 0.8,
117
+ light_x: 0.3,
118
+ light_strength: 3,
119
+ rotate_x: 10,
120
+ rotate_z: 10,
121
+ }),
122
+ });
123
+
124
+ if (!res.ok) {
125
+ throw new Error("Failed to create icon");
126
+ }
127
+
128
+ const data = await res.blob();
129
+ const url = URL.createObjectURL(data);
130
+ img.src = url;
131
+ status.innerText = "Done!";
132
+ } catch (err) {
133
+ alert(err.message);
134
+ status.innerText = "Error! " + err.message;
135
+ } finally {
136
+ running = false;
137
+ input.disabled = false;
138
+ }
139
+ }
140
+
141
+ input.addEventListener("change", run);
142
+ </script>
143
+ </body>
144
+ </html>