Akjava commited on
Commit
6814e59
1 Parent(s): 4c02f08
Files changed (8) hide show
  1. .gitignore +6 -0
  2. anime.gif +0 -0
  3. app.py +292 -0
  4. demo_header.html +18 -0
  5. examples/1024.webp +0 -0
  6. examples/anime.webp +0 -0
  7. links.html +12 -0
  8. requirements.txt +3 -0
.gitignore ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ __pycache__
2
+ *.egg-info
3
+ .ipynb_checkpoints
4
+ dist
5
+ .gradio
6
+ build
anime.gif ADDED
app.py ADDED
@@ -0,0 +1,292 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import spaces
2
+ import gradio as gr
3
+ import re
4
+ from PIL import Image,ImageEnhance
5
+
6
+ import os
7
+
8
+ import numpy as np
9
+ import hashlib
10
+ import io
11
+ import cv2
12
+ import time
13
+
14
+ def clear_old_files(dir,passed_time):
15
+ files = os.listdir(dir)
16
+ current_time = time.time()
17
+ for file in files:
18
+ file_path = os.path.join(dir,file)
19
+
20
+ ctime = os.stat(file_path).st_ctime
21
+ diff = current_time - ctime
22
+ print(f"ctime={ctime},current_time={current_time},passed_time={passed_time},diff={diff}")
23
+ if diff > passed_time:
24
+ os.remove(file_path)
25
+ print(f"file removed {file_path}")#TODO remove later
26
+
27
+
28
+ def get_image_id(image):
29
+ buffer = io.BytesIO()
30
+ image.save(buffer, format='PNG')
31
+ hash_object = hashlib.sha256(buffer.getvalue())
32
+ hex_dig = hash_object.hexdigest()
33
+ unique_id = hex_dig[:32]
34
+ return unique_id
35
+
36
+ dir_name ="images"
37
+ passed_time = 60*3
38
+
39
+
40
+ def process_create_webp(images,duration=100, loop=0,quality=85):
41
+ frames = []
42
+ for image_file in images:
43
+ frames.append(image_file)
44
+
45
+ output_buffer = io.BytesIO()
46
+ frames[0].save(output_buffer,
47
+ save_all=True,
48
+ append_images=frames[1:],
49
+ duration=duration,
50
+ loop=loop,
51
+ format='WebP',
52
+ quality=quality
53
+ )
54
+
55
+ return output_buffer.getvalue()
56
+
57
+ def process_create_apng(images,duration=100, disposal=1,blend=0,loop=0):
58
+ frames = []
59
+ for image_file in images:
60
+ frames.append(image_file)
61
+
62
+ output_buffer = io.BytesIO()
63
+ frames[0].save(output_buffer,
64
+ save_all=True,
65
+ append_images=frames[1:],
66
+ #duration=duration, disposal=0,blend=1,
67
+ duration=duration, disposal=disposal,blend=blend,
68
+ loop=loop,
69
+ format='png')
70
+
71
+ return output_buffer.getvalue()
72
+
73
+ def process_create_gif(images,duration=100, quantize=False,disposal=1,blend=0,loop=0):
74
+ frames = []
75
+ for image_file in images:
76
+ if quantize:
77
+ image_file = image_file.quantize(colors=256, method=2)
78
+ #image_file = image_file.quantize()
79
+
80
+
81
+ frames.append(image_file)
82
+
83
+ output_buffer = io.BytesIO()
84
+ frames[0].save(output_buffer,
85
+ save_all=True,
86
+ append_images=frames[1:],
87
+ #duration=duration, disposal=0,blend=1,
88
+ duration=duration, disposal=disposal,blend=blend,
89
+ loop=loop,
90
+ format='gif',
91
+ optimize=False
92
+ #dither=Image.FLOYDSTEINBERG
93
+ )
94
+
95
+ return output_buffer.getvalue()
96
+
97
+ def convert_webp_to_images(webp_path):
98
+ # 各フレームをリストに保存
99
+ frames = []
100
+ durations = []
101
+ Image.init()
102
+ image = Image.open(webp_path)
103
+ for i in range(image.n_frames):
104
+ image.seek(i)
105
+ frame = image.copy()
106
+ frames.append(frame)
107
+ durations.append(frame.info["duration"])
108
+ return frames,durations
109
+
110
+ def buffer_to_id(buffer_value):
111
+ hash_object = hashlib.sha256(buffer_value)
112
+ hex_dig = hash_object.hexdigest()
113
+ unique_id = hex_dig[:32]
114
+ return unique_id
115
+
116
+ def process_images(input_path,same_size=False,image_width=128,file_format="webp",webp_quality=85):
117
+ if input_path == None:
118
+ raise gr.Error("need image")
119
+
120
+ # cache control
121
+ if not os.path.exists(dir_name):
122
+ os.mkdir(dir_name)
123
+ clear_old_files(dir_name,passed_time)
124
+
125
+
126
+
127
+ images =[]
128
+ frames,durations = convert_webp_to_images(input_path)
129
+ new_frames = []
130
+
131
+
132
+ new_width,new_height = frames[0].size
133
+ if not same_size and image_width!=new_width:
134
+
135
+ ratio = new_width/new_height
136
+ new_height = int(image_width*ratio)
137
+ new_width = image_width
138
+ #print(f"new size {new_width} x {new_height}")
139
+ for frame in frames:
140
+ new_frame = frame.resize((new_width,new_height))# extremly slow Image.LANCZOS
141
+ new_frames.append(new_frame)
142
+ else:
143
+ new_frames = frames
144
+
145
+ if file_format == "webp":
146
+ webp_buffer = process_create_webp(new_frames,durations,webp_quality)
147
+ webp_id = buffer_to_id(webp_buffer)
148
+ webp_path = os.path.join(dir_name,f"{webp_id}.webp")
149
+ with open(webp_path, 'wb') as f:
150
+ f.write(webp_buffer)
151
+
152
+ images.append((webp_path,"webp"))
153
+
154
+ elif file_format == "apng":
155
+ apng_buffer = process_create_apng(new_frames,durations)
156
+ apng_id = buffer_to_id(apng_buffer)
157
+ apng_path = os.path.join(dir_name,f"{apng_id}.apng")
158
+ with open(apng_path, 'wb') as f:
159
+ f.write(apng_buffer)
160
+
161
+ images.append((apng_path,"apng"))
162
+
163
+ elif file_format == "gif":
164
+ gif_buffer = process_create_gif(new_frames,durations,False)
165
+ gif_id = buffer_to_id(gif_buffer)
166
+ gif_path = os.path.join(dir_name,f"{gif_id}.gif")
167
+ with open(gif_path, 'wb') as f:
168
+ f.write(gif_buffer)
169
+
170
+ images.append((gif_path,"gif"))
171
+ else:
172
+ for i ,frame in enumerate(new_frames):
173
+ images.append((frame,f"index {i}"))
174
+
175
+ return images
176
+
177
+
178
+ def read_file(path: str) -> str:
179
+ with open(path, 'r', encoding='utf-8') as f:
180
+ content = f.read()
181
+
182
+ return content
183
+
184
+ def test_echo(param):
185
+ return param
186
+
187
+ def samesize_changed(check,slider):
188
+ return gr.Slider(label="Image Width",
189
+ minimum=8,
190
+ maximum=2048,
191
+ step=1,
192
+ value=slider,
193
+ interactive=not check)
194
+
195
+ css="""
196
+ #col-left {
197
+ margin: 0 auto;
198
+ max-width: 640px;
199
+ }
200
+ #col-right {
201
+ margin: 0 auto;
202
+ max-width: 640px;
203
+ }
204
+ .grid-container {
205
+ display: flex;
206
+ align-items: center;
207
+ justify-content: center;
208
+ gap:10px
209
+ }
210
+
211
+ .image {
212
+ width: 128px;
213
+ height: 128px;
214
+ object-fit: cover;
215
+ }
216
+ }
217
+ }
218
+
219
+ .text {
220
+ font-size: 16px;
221
+ }
222
+ """
223
+ js = """
224
+ function(path){
225
+ console.log(path)
226
+ return path
227
+ }
228
+ """
229
+
230
+ with gr.Blocks(css=css, elem_id="demo-container") as demo:
231
+ with gr.Column():
232
+ gr.HTML(read_file("demo_header.html"))
233
+ gr.HTML(read_file("links.html"))
234
+ with gr.Row():
235
+ with gr.Column():
236
+ image = gr.Image(sources=[],image_mode='RGB', elem_id="Image", type="filepath", label="Preview WebP")
237
+ file = gr.File(label="WebP Upload")
238
+ #file.select(fn=test_echo,inputs=[file])
239
+
240
+ file.upload(fn=test_echo,inputs=[file],outputs=[image])
241
+ file.clear(fn=test_echo,inputs=[file],outputs=[image])
242
+
243
+ btn = gr.Button("Convert", elem_id="run_button",variant="primary")
244
+ # type choice
245
+ # size slider
246
+
247
+ file_format=gr.Dropdown(
248
+ ["webp", "apng", "gif","images"], label="Animation Format", info="Convert to Animattion" )
249
+
250
+ same_size = gr.Checkbox(label="Same Size",value=False)
251
+
252
+ image_width = gr.Slider(
253
+ label="Image Width",info = "new animation size",
254
+ minimum=8,
255
+ maximum=2048,
256
+ step=1,
257
+ value=128,
258
+ interactive=True)
259
+ same_size.change(fn=samesize_changed,inputs=[same_size,image_width],outputs=[image_width])
260
+
261
+ with gr.Accordion(label="Advanced Settings", open=False):
262
+ with gr.Row( equal_height=True):
263
+ webp_quality = gr.Slider(
264
+ label="WebP Quality",info = "this change file size",
265
+ minimum=0,
266
+ maximum=100,
267
+ step=1,
268
+ value=85,
269
+ interactive=True)
270
+
271
+ with gr.Column():
272
+ image_out = gr.Gallery(height=800,label="Output", elem_id="output-img",format="webp", columns=[4],rows=[2])
273
+
274
+
275
+
276
+
277
+ btn.click(fn=process_images, inputs=[file,same_size,image_width,file_format,webp_quality], outputs =[image_out], api_name='infer')
278
+ gr.Examples(
279
+ examples=[
280
+ ["examples/1024.webp","examples/1024.webp"],
281
+ #["images/00346245_00006200.jpg", "images/00346245_00003200.jpg","images/00346245_mask.jpg",10,0,"images/00346245_mixed.jpg"]
282
+
283
+ ]
284
+ ,
285
+ inputs=[image,file]#example not fire event
286
+ )
287
+ gr.HTML(
288
+ """
289
+ <P> Images are generated with <a href="https://huggingface.co/black-forest-labs/FLUX.1-schnell">FLUX.1-schnell</a> and licensed under <a href="http://www.apache.org/licenses/LICENSE-2.0">the Apache 2.0 License</a>
290
+ """)
291
+
292
+ demo.launch(allowed_paths=["examples/anime.webp"])#
demo_header.html ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div style="text-align: center;">
2
+ <h1>
3
+ WebP Resize and Convert
4
+ </h1>
5
+
6
+ <div class="grid-container">
7
+ <img src="/gradio_api/file=examples/anime.webp" alt="Flux.1-schnell-WebP3Frame-TalkingAnimation" class="image">
8
+ <p class="text">
9
+ Hint:Aspect ratio will always keep<br>
10
+ I'm not familiar with apng/gif,maybe quality is low<br>
11
+ </p>
12
+ </div>
13
+
14
+ <p>
15
+
16
+ </p>
17
+
18
+ </div>
examples/1024.webp ADDED
examples/anime.webp ADDED
links.html ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <div style="text-align: center;">
2
+ <p><a href="https://huggingface.co/spaces/Akjava/godot-huggingface-chain">AI Diagram Chat with Voice/Face Character Making Tools</a></p>
3
+ <p><a href="https://huggingface.co/spaces/Akjava/WebPTalkHead">[WebP-3F-TH]</a>
4
+ <a href="https://huggingface.co/spaces/Akjava/flux1-schnell-mask-inpaint">[Flux1-Inpaint(GPU)]</a>
5
+ <a href="https://huggingface.co/spaces/Akjava/OpenCVInpaintCPU">[OpenCV-Inapint]</a>
6
+ <a href="https://huggingface.co/spaces/Akjava/Simple-Whitebalance-Image">[Whitebalance]</a>
7
+ <a href="https://huggingface.co/spaces/Akjava/Simple-Mask-Paste-Image">[Paste Image]</a>
8
+ <a href=" https://huggingface.co/spaces/Akjava/WebP-Resize-Convert">[WebP Resize Convert]</a></p>
9
+
10
+
11
+
12
+ </div>
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ spaces
2
+ numpy
3
+ opencv-contrib-python