latterworks commited on
Commit
1f93618
·
verified ·
1 Parent(s): 66c6199

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +243 -0
app.py ADDED
@@ -0,0 +1,243 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ from PIL import Image
4
+ from typing import List, Optional, Tuple
5
+ import logging
6
+ import random
7
+
8
+ # Configure logging
9
+ logging.basicConfig(
10
+ level=logging.INFO,
11
+ format='%(asctime)s - %(levelname)s - %(message)s'
12
+ )
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ def create_gif_from_folder(
17
+ input_folder: str,
18
+ output_path: str,
19
+ duration: int = 100,
20
+ loop: int = 0,
21
+ resize: Optional[tuple] = None,
22
+ quality: int = 90,
23
+ shuffle: bool = False
24
+ ) -> None:
25
+ """
26
+ Convert a folder of images into a GIF.
27
+
28
+ Args:
29
+ input_folder (str): Path to the folder containing images
30
+ output_path (str): Path where the GIF will be saved
31
+ duration (int): Duration of each frame in milliseconds
32
+ loop (int): Number of times to loop the GIF (0 for infinite)
33
+ resize (Optional[tuple]): Tuple of (width, height) to resize images
34
+ quality (int): Quality of the output GIF (1-100)
35
+ shuffle (bool): Whether to randomize the order of images
36
+ """
37
+ try:
38
+ # Get all image files from the folder
39
+ image_files = [
40
+ f for f in os.listdir(input_folder)
41
+ if f.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.gif'))
42
+ ]
43
+
44
+ if not image_files:
45
+ raise ValueError(f"No image files found in {input_folder}")
46
+
47
+ # Sort or shuffle files
48
+ if shuffle:
49
+ random.shuffle(image_files)
50
+ logger.info("Images will be shown in random order")
51
+ else:
52
+ image_files.sort()
53
+ logger.info("Images will be shown in alphabetical order")
54
+
55
+ # Load images
56
+ images: List[Image.Image] = []
57
+ for file in image_files:
58
+ try:
59
+ img_path = os.path.join(input_folder, file)
60
+ img = Image.open(img_path)
61
+
62
+ # Convert to RGB if necessary
63
+ if img.mode != 'RGB':
64
+ img = img.convert('RGB')
65
+
66
+ # Resize if specified
67
+ if resize:
68
+ img = img.resize(resize, Image.Resampling.LANCZOS)
69
+
70
+ images.append(img)
71
+ logger.info(f"Processed image: {file}")
72
+ except Exception as e:
73
+ logger.warning(f"Failed to process {file}: {str(e)}")
74
+ continue
75
+
76
+ if not images:
77
+ raise ValueError("No valid images were processed")
78
+
79
+ # Save as GIF with optimized settings
80
+ images[0].save(
81
+ output_path,
82
+ save_all=True,
83
+ append_images=images[1:],
84
+ duration=duration,
85
+ loop=loop,
86
+ optimize=True,
87
+ quality=quality,
88
+ disposal=2 # Clear background between frames
89
+ )
90
+
91
+ logger.info(f"Successfully created GIF at {output_path}")
92
+ logger.info(f"Processed {len(images)} images")
93
+ logger.info(f"Settings: {duration}ms/frame, quality={quality}")
94
+ logger.info(f"Shuffle: {'enabled' if shuffle else 'disabled'}")
95
+
96
+ except Exception as e:
97
+ logger.error(f"Error creating GIF: {str(e)}")
98
+ raise
99
+
100
+
101
+ def create_gif_interface(
102
+ input_folder: str,
103
+ output_name: str,
104
+ duration: int,
105
+ quality: int,
106
+ width: int,
107
+ height: int,
108
+ shuffle: bool
109
+ ) -> Tuple[str, str]:
110
+ """
111
+ Web interface wrapper for GIF creation.
112
+
113
+ Returns:
114
+ Tuple of (output path, status message)
115
+ """
116
+ try:
117
+ # Validate inputs
118
+ if not os.path.exists(input_folder):
119
+ return "", f"Error: Input folder '{input_folder}' does not exist"
120
+
121
+ if not output_name.endswith('.gif'):
122
+ output_name += '.gif'
123
+
124
+ # Save to current working directory (Hugging Face Spaces best practice)
125
+ output_path = os.path.join(os.getcwd(), output_name)
126
+
127
+ # Create the GIF
128
+ create_gif_from_folder(
129
+ input_folder=input_folder,
130
+ output_path=output_path,
131
+ duration=duration,
132
+ quality=quality,
133
+ resize=(width, height),
134
+ shuffle=shuffle
135
+ )
136
+
137
+ return output_path, "GIF created successfully!"
138
+
139
+ except Exception as e:
140
+ error_msg = f"Error creating GIF: {str(e)}"
141
+ return "", error_msg
142
+
143
+
144
+ # Create the Gradio interface
145
+ with gr.Blocks(
146
+ title="🎞️ Image to GIF Converter",
147
+ theme=gr.themes.Soft()
148
+ ) as interface:
149
+ gr.Markdown("# 🎞️ Image to GIF Converter")
150
+ gr.Markdown("Convert a folder of images into an animated GIF")
151
+
152
+ with gr.Row():
153
+ with gr.Column(scale=2):
154
+ input_folder = gr.Textbox(
155
+ label="Input Folder Path",
156
+ placeholder="Enter the path to your images folder"
157
+ )
158
+ output_name = gr.Textbox(
159
+ label="Output GIF Name",
160
+ value="animation.gif",
161
+ placeholder="Enter the name for your GIF"
162
+ )
163
+
164
+ with gr.Row():
165
+ duration = gr.Slider(
166
+ minimum=50,
167
+ maximum=1000,
168
+ value=100,
169
+ step=50,
170
+ label="Frame Duration (ms)"
171
+ )
172
+ quality = gr.Slider(
173
+ minimum=1,
174
+ maximum=100,
175
+ value=90,
176
+ step=1,
177
+ label="Quality"
178
+ )
179
+
180
+ with gr.Row():
181
+ width = gr.Number(
182
+ value=800,
183
+ label="Width (px)",
184
+ precision=0
185
+ )
186
+ height = gr.Number(
187
+ value=600,
188
+ label="Height (px)",
189
+ precision=0
190
+ )
191
+
192
+ shuffle = gr.Checkbox(
193
+ label="Shuffle Images",
194
+ value=True
195
+ )
196
+
197
+ create_btn = gr.Button(
198
+ "Create GIF",
199
+ variant="primary"
200
+ )
201
+
202
+ with gr.Column(scale=3):
203
+ output = gr.Textbox(
204
+ label="Output Path",
205
+ interactive=False
206
+ )
207
+ error_msg = gr.Textbox(
208
+ label="Status",
209
+ interactive=False
210
+ )
211
+ preview = gr.Image(
212
+ label="GIF Preview",
213
+ type="filepath",
214
+ interactive=False
215
+ )
216
+
217
+ # Set up the event handler
218
+ create_btn.click(
219
+ fn=create_gif_interface,
220
+ inputs=[
221
+ input_folder,
222
+ output_name,
223
+ duration,
224
+ quality,
225
+ width,
226
+ height,
227
+ shuffle
228
+ ],
229
+ outputs=[output, error_msg]
230
+ ).then(
231
+ fn=lambda x: x if x else None,
232
+ inputs=[output],
233
+ outputs=[preview]
234
+ )
235
+
236
+
237
+ if __name__ == "__main__":
238
+ interface.launch(
239
+ server_name="0.0.0.0",
240
+ server_port=7860,
241
+ share=True,
242
+ show_error=True
243
+ )