lnyan commited on
Commit
c00251a
1 Parent(s): 5704551
Files changed (1) hide show
  1. index.html +192 -0
index.html ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <html>
2
+ <head>
3
+ <title>Stablediffusion Infinity</title>
4
+ <meta charset="utf-8">
5
+ <link rel="icon" type="image/x-icon" href="./favicon.png">
6
+ <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
7
+ <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
8
+ <style>
9
+ #container {
10
+ position: relative;
11
+ margin:auto;
12
+ }
13
+ #container > canvas {
14
+ position: absolute;
15
+ top: 0;
16
+ left: 0;
17
+ }
18
+ .control {
19
+ display: none;
20
+ }
21
+ </style>
22
+
23
+ </head>
24
+ <body>
25
+ <div>
26
+ <button type="button" class="control" id="export">Export</button>
27
+ <button type="button" class="control" id="outpaint">Outpaint</button>
28
+ <button type="button" class="control" id="undo">Undo</button>
29
+ <button type="button" class="control" id="commit">Commit</button>
30
+ <button type="button" class="control" id="transfer">Transfer</button>
31
+ <button type="button" class="control" id="upload">Upload</button>
32
+ <button type="button" class="control" id="draw">Draw</button>
33
+ <input type="text" id="mode" value="✥" class="control">
34
+ <input type="text" id="setup" value="0" class="control">
35
+ <textarea rows="1" id="selbuffer" name="selbuffer" class="control"></textarea>
36
+ <fieldset class="control">
37
+ <div>
38
+ <input type="radio" id="mode0" name="mode" value="0" checked>
39
+ <label for="mode0">SelBox</label>
40
+ </div>
41
+ <div>
42
+ <input type="radio" id="mode1" name="mode" value="1">
43
+ <label for="mode1">Image</label>
44
+ </div>
45
+ <div>
46
+ <input type="radio" id="mode2" name="mode" value="2">
47
+ <label for="mode2">Brush</label>
48
+ </div>
49
+ </fieldset>
50
+ </div>
51
+ <div>
52
+ <div id = "container">
53
+ <canvas id = "canvas0"></canvas>
54
+ <canvas id = "canvas1"></canvas>
55
+ <canvas id = "canvas2"></canvas>
56
+ <canvas id = "canvas3"></canvas>
57
+ <canvas id = "canvas4"></canvas>
58
+ </div>
59
+ </div>
60
+ <py-env>
61
+ - numpy
62
+ - Pillow
63
+ - paths:
64
+ - ./canvas.py
65
+ </py-env>
66
+
67
+ <py-script>
68
+ from pyodide import to_js, create_proxy
69
+ from PIL import Image
70
+ import io
71
+ import time
72
+ import base64
73
+ import numpy as np
74
+ from js import (
75
+ console,
76
+ document,
77
+ parent,
78
+ devicePixelRatio,
79
+ ImageData,
80
+ Uint8ClampedArray,
81
+ CanvasRenderingContext2D as Context2d,
82
+ requestAnimationFrame,
83
+ )
84
+
85
+
86
+ from canvas import InfCanvas
87
+
88
+
89
+
90
+ base_lst = [None]
91
+ async def draw_canvas() -> None:
92
+ width=1500
93
+ height=600
94
+ canvas=InfCanvas(1500,600)
95
+ document.querySelector("#container").style.width = f"{width}px"
96
+ canvas.setup_mouse()
97
+ canvas.clear_background()
98
+ canvas.draw_buffer()
99
+ canvas.draw_selection_box()
100
+ base_lst[0]=canvas
101
+
102
+ async def draw_canvas_func(event):
103
+ try:
104
+ width=parent.document.querySelector("gradio-app").shadowRoot.querySelector("#canvas_width input").value
105
+ height=parent.document.querySelector("gradio-app").shadowRoot.querySelector("#canvas_height input").value
106
+ selection_size=parent.document.querySelector("gradio-app").shadowRoot.querySelector("#selection_size input").value
107
+ except:
108
+ width=1024
109
+ height=768
110
+ selection_size=384
111
+ document.querySelector("#container").style.width = f"{width}px"
112
+ canvas=InfCanvas(int(width),int(height),selection_size=int(selection_size))
113
+ canvas.setup_mouse()
114
+ canvas.clear_background()
115
+ canvas.draw_buffer()
116
+ canvas.draw_selection_box()
117
+ base_lst[0]=canvas
118
+
119
+ async def export_func(event):
120
+ base=base_lst[0]
121
+ arr=base.export()
122
+ base64_str = base.numpy_to_base64(arr)
123
+ time_str = time.strftime("%Y%m%d_%H%M%S")
124
+ console.log(f"Canvas saved to outpaint_{time_str}.png")
125
+ link = document.createElement("a")
126
+ link.download = f"outpaint_{time_str}.png"
127
+ link.href = "data:image/png;base64,"+base64_str
128
+ link.click()
129
+
130
+ async def outpaint_func(event):
131
+ base=base_lst[0]
132
+ base64_str=parent.document.querySelector("gradio-app").shadowRoot.querySelector("#output textarea").value
133
+ arr=base.base64_to_numpy(base64_str)
134
+ base.fill_selection(arr)
135
+ base.draw_selection_box()
136
+
137
+ async def undo_func(event):
138
+ base=base_lst[0]
139
+ if base.sel_dirty:
140
+ base.canvas[2].clear()
141
+ base.sel_buffer = base.sel_buffer_bak.copy()
142
+ base.sel_dirty = False
143
+
144
+ async def commit_func(event):
145
+ base=base_lst[0]
146
+ if base.sel_dirty:
147
+ base.write_selection_to_buffer()
148
+
149
+ async def transfer_func(event):
150
+ base=base_lst[0]
151
+ base.read_selection_from_buffer()
152
+ sel_buffer=base.sel_buffer
153
+ sel_buffer_str=base.numpy_to_base64(sel_buffer)
154
+ parent.document.querySelector("gradio-app").shadowRoot.querySelector("#input textarea").value=sel_buffer_str
155
+ parent.document.querySelector("gradio-app").shadowRoot.querySelector("#proceed").click()
156
+
157
+ async def upload_func(event):
158
+ base=base_lst[0]
159
+ base64_str=parent.document.querySelector("gradio-app").shadowRoot.querySelector("#upload textarea").value
160
+ arr=base.base64_to_numpy(base64_str)
161
+ h,w,_=arr.shape
162
+ yo=(base.height-h)//2
163
+ xo=(base.width-w)//2
164
+ base.buffer_dirty=True
165
+ base.buffer*=0
166
+ base.buffer[yo:yo+h,xo:xo+w,0:3]=arr[:,:,0:3]
167
+ base.buffer[yo:yo+h,xo:xo+w,-1]=arr[:,:,-1]
168
+ base.draw_buffer()
169
+
170
+
171
+
172
+ document.querySelector("#export").addEventListener("click",create_proxy(export_func))
173
+ document.querySelector("#undo").addEventListener("click",create_proxy(undo_func))
174
+ document.querySelector("#commit").addEventListener("click",create_proxy(commit_func))
175
+ document.querySelector("#outpaint").addEventListener("click",create_proxy(outpaint_func))
176
+ document.querySelector("#upload").addEventListener("click",create_proxy(upload_func))
177
+
178
+ document.querySelector("#transfer").addEventListener("click",create_proxy(transfer_func))
179
+ document.querySelector("#draw").addEventListener("click",create_proxy(draw_canvas_func))
180
+
181
+ async def setup_func():
182
+ document.querySelector("#setup").value="1"
183
+
184
+ import asyncio
185
+
186
+ _ = await asyncio.gather(
187
+ setup_func(),draw_canvas()
188
+ )
189
+ </py-script>
190
+
191
+ </body>
192
+ </html>