PSNbst commited on
Commit
64b34b6
·
verified ·
1 Parent(s): cfaa580

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +113 -0
app.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from PIL import Image
3
+ import os
4
+ import tempfile
5
+ from typing import List
6
+
7
+ def create_gif(
8
+ image_files: List[str], # 修改为直接接收文件路径列表
9
+ scale: float = 1.0,
10
+ frame_duration: int = 200,
11
+ loop: bool = True
12
+ ) -> tuple:
13
+ """
14
+ 将多张图片合并为GIF动画
15
+
16
+ 参数:
17
+ image_files: 图片文件路径列表
18
+ scale: 缩放比例(0.1-2.0)
19
+ frame_duration: 每帧持续时间(毫秒)
20
+ loop: 是否循环播放
21
+
22
+ 返回:
23
+ (输出路径, 错误信息)
24
+ """
25
+ try:
26
+ # 验证输入
27
+ if not image_files:
28
+ return None, "错误: 请至少选择一张图片"
29
+
30
+ images = []
31
+ for file_info in image_files:
32
+ path = file_info if isinstance(file_info, str) else file_info.name # 处理两种输入方式
33
+ if not os.path.exists(path):
34
+ return None, f"错误: 文件不存在 - {path}"
35
+
36
+ valid_ext = ('.jpg', '.jpeg', '.png', '.webp')
37
+ if not path.lower().endswith(valid_ext):
38
+ return None, f"错误: 不支持的文件格式 - {path}"
39
+
40
+ img = Image.open(path)
41
+ if scale != 1.0:
42
+ new_size = (int(img.width * scale), int(img.height * scale))
43
+ img = img.resize(new_size, Image.LANCZOS)
44
+ images.append(img)
45
+
46
+ # 设置输出路径
47
+ output_dir = tempfile.gettempdir()
48
+ output_path = os.path.join(output_dir, "output.gif")
49
+
50
+ # 保存为GIF
51
+ images[0].save(
52
+ output_path,
53
+ save_all=True,
54
+ append_images=images[1:],
55
+ duration=frame_duration,
56
+ loop=0 if loop else 1,
57
+ optimize=True
58
+ )
59
+
60
+ return output_path, "GIF创建成功!"
61
+
62
+ except Exception as e:
63
+ return None, f"错误: {str(e)}"
64
+
65
+ # Gradio界面
66
+ with gr.Blocks(title="多图转GIF转换器") as demo:
67
+ gr.Markdown("## 🎞️ 多图转GIF转换器")
68
+ gr.Markdown("上传多张图片,设置参数后生成GIF动画")
69
+
70
+ with gr.Row():
71
+ with gr.Column():
72
+ file_input = gr.Files(
73
+ label="选择多张图片",
74
+ file_types=["image"],
75
+ file_count="multiple"
76
+ )
77
+ with gr.Accordion("高级选项", open=False):
78
+ scale_slider = gr.Slider(0.1, 2.0, value=1.0, step=0.1, label="缩放比例")
79
+ duration_slider = gr.Slider(50, 2000, value=200, step=50, label="每帧时长(毫秒)")
80
+ loop_checkbox = gr.Checkbox(value=True, label="循环播放")
81
+ convert_btn = gr.Button("生成GIF", variant="primary")
82
+
83
+ with gr.Column():
84
+ output_gif = gr.Image(label="生成的GIF", interactive=False)
85
+ output_download = gr.File(label="下载GIF", visible=False)
86
+ output_message = gr.Textbox(label="状态信息", interactive=False)
87
+
88
+ # 处理转换
89
+ def process_files(
90
+ files: List, # 修改为普通List类型
91
+ scale: float,
92
+ duration: int,
93
+ loop: bool
94
+ ) -> tuple:
95
+ if not files:
96
+ return None, None, "请先上传图片"
97
+
98
+ output_path, msg = create_gif(files, scale=scale, frame_duration=duration, loop=loop)
99
+
100
+ if output_path:
101
+ return output_path, output_path, msg
102
+ else:
103
+ return None, None, msg
104
+
105
+ convert_btn.click(
106
+ process_files,
107
+ inputs=[file_input, scale_slider, duration_slider, loop_checkbox],
108
+ outputs=[output_gif, output_download, output_message]
109
+ )
110
+
111
+ # 启动应用
112
+ if __name__ == "__main__":
113
+ demo.launch()