Essar-HF commited on
Commit
2c6caca
1 Parent(s): 886230e

Added main files

Browse files
Files changed (2) hide show
  1. app.py +49 -0
  2. tiles_to_gif.py +191 -0
app.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from PIL import Image
3
+ from io import BytesIO
4
+ import subprocess
5
+ import tempfile
6
+
7
+ # Assuming your functions are in a module named 'image_utils'
8
+ from tiles_to_gif import tile_and_convert
9
+
10
+ def process_image(image, tile_type, lossy=80, colors=200):
11
+ """Process the image, apply tiling, create GIF, and compress it."""
12
+
13
+ # Tile the image
14
+ gif_buffer = tile_and_convert(image, tile_type)
15
+
16
+ # Compress using Gifsicle
17
+ command = ["gifsicle", "--optimize", f"--lossy={lossy}", f"--colors={colors}", "-"]
18
+ process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
19
+ compressed_data, _ = process.communicate(input=gif_buffer.getvalue())
20
+
21
+ # Create a temporary file
22
+ with tempfile.NamedTemporaryFile(suffix=".gif", delete=False) as temp_file:
23
+ temp_file.write(compressed_data)
24
+ gif_path = temp_file.name # Get the file path
25
+
26
+ # Return the path of the temporary GIF file
27
+ return gif_path
28
+
29
+ docstring = """
30
+ Upload a 1x1, 1x2, 2x1, or 2x2 downloaded tile from ideogram. Choose the same tiling type as what you
31
+ generated with to create a gif. The program is a bit slow, because gifs aren't great. It is optimised to create
32
+ small previews for the ideogram discord (so less than 25MB), however, it might still be that a very detailed and colourful
33
+ image exceeds this file size. Possible sources of error include uploading a file which is too large (e.g. 4x4 tile)
34
+ or forgetting to choose the tiling type parameter from the drop down menu.
35
+ """
36
+ # Create Gradio interface
37
+ iface = gr.Interface(
38
+ fn=process_image,
39
+ allow_flagging="never",
40
+ description=docstring,
41
+ inputs=[
42
+ gr.Image(type="pil"),
43
+ gr.Dropdown(["row", "column", "grid", "vertical_brick", "horizontal_brick"], label="Tiling Type")
44
+ ],
45
+ outputs=gr.File(label="Download Compressed GIF"),
46
+ title="Ideogram Tile GIF creator"
47
+ )
48
+
49
+ iface.launch()
tiles_to_gif.py ADDED
@@ -0,0 +1,191 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from PIL import Image
2
+ from io import BytesIO
3
+
4
+
5
+ def tile_image_row(image):
6
+
7
+ width, height = image.size
8
+ new_width = width * 2
9
+ new_height = height
10
+
11
+ result = Image.new(image.mode, (new_width, new_height))
12
+
13
+ result.paste(image, (0, 0))
14
+ result.paste(image, (width, 0))
15
+
16
+ return result
17
+
18
+ def tile_image_column(image):
19
+
20
+ width, height = image.size
21
+ new_width = width
22
+ new_height = height * 2
23
+
24
+ result = Image.new(image.mode, (new_width, new_height))
25
+
26
+ result.paste(image, (0, 0))
27
+ result.paste(image, (0, height))
28
+
29
+ return result
30
+
31
+ def tile_image_grid(image):
32
+
33
+ temp_image = tile_image_column(image)
34
+ result = tile_image_row(temp_image)
35
+
36
+ return result
37
+
38
+ def tile_image_vert_brick(image):
39
+
40
+ width, height = image.size
41
+
42
+ new_width = width * 2
43
+ new_height = height *2
44
+
45
+ result = Image.new(image.mode, (new_width, new_height))
46
+
47
+ # First column: Doubled image
48
+ result.paste(image, (0, 0))
49
+ result.paste(image, (0, height))
50
+
51
+ # Second column: Shifted doubled image
52
+ top_half = image.crop((0, 0, width, height // 2))
53
+ bottom_half = image.crop((0, height // 2, width, height))
54
+ shifted_image = Image.new(image.mode, (width, height*2))
55
+ shifted_image.paste(bottom_half, (0, 0))
56
+ shifted_image.paste(top_half, (0, height+height // 2))
57
+ shifted_image.paste(image, (0, height // 2))
58
+ result.paste(shifted_image, (width, 0))
59
+
60
+ return result
61
+
62
+ def tile_image_horiz_brick(image):
63
+
64
+ width, height = image.size
65
+
66
+ new_width = width * 2
67
+ new_height = height *2
68
+
69
+ result = Image.new(image.mode, (new_width, new_height))
70
+
71
+ # First column: Doubled image
72
+ result.paste(image, (0, 0))
73
+ result.paste(image, (width, 0))
74
+
75
+ # Second column: Shifted doubled image
76
+ left_half = image.crop((0, 0, width//2, height))
77
+ right_half = image.crop((width//2, 0, width, height))
78
+ shifted_image = Image.new(image.mode, (width*2, height))
79
+ shifted_image.paste(right_half, (0, 0))
80
+ shifted_image.paste(left_half, (width+width // 2, 0))
81
+ shifted_image.paste(image, (width//2, 0))
82
+ result.paste(shifted_image, (0, height))
83
+
84
+ return result
85
+
86
+
87
+ def crop_along_line_to_gif(img, width, height, start_x, start_y, end_x, end_y, num_crops=200, duration=80, loop=0, jpeg_quality=85, scale_factor=0.5):
88
+ # Convert to JPEG in-memory if needed
89
+ if jpeg_quality is not None:
90
+ img = img.convert("RGB") # Ensure RGB mode
91
+ with BytesIO() as buffer:
92
+ img.save(buffer, format="JPEG", quality=jpeg_quality)
93
+ buffer.seek(0)
94
+ img = Image.open(buffer)
95
+ img.load()
96
+
97
+ # Apply scaling factor to image dimensions and coordinates
98
+ if scale_factor != 1.0:
99
+ img = img.resize((int(img.width * scale_factor), int(img.height * scale_factor)), Image.Resampling.LANCZOS)
100
+ width = int(width * scale_factor)
101
+ height = int(height * scale_factor)
102
+ start_x = int(start_x * scale_factor)
103
+ start_y = int(start_y * scale_factor)
104
+ end_x = int(end_x * scale_factor)
105
+ end_y = int(end_y * scale_factor)
106
+
107
+ img_width, img_height = img.size
108
+ x_step = (end_x - start_x) / (num_crops - 1)
109
+ y_step = (end_y - start_y) / (num_crops - 1)
110
+
111
+ cropped_images = []
112
+ for i in range(num_crops):
113
+ x = start_x + i * x_step
114
+ y = start_y + i * y_step
115
+
116
+ if 0 <= x < img_width and 0 <= y < img_height:
117
+ # Calculate crop area coordinates
118
+ left = x
119
+ top = y
120
+ right = x + width
121
+ bottom = y + height
122
+
123
+ cropped_img = img.crop((left, top, right, bottom))
124
+
125
+ # Apply scaling if scale_factor is not 1.0
126
+
127
+
128
+ cropped_images.append(cropped_img)
129
+
130
+ # Create a BytesIO buffer to store the GIF
131
+ gif_buffer = BytesIO()
132
+
133
+ # Save the GIF to the buffer
134
+ first_image = cropped_images[0]
135
+ first_image.info["duration"] = duration
136
+ first_image.save(
137
+ gif_buffer,
138
+ save_all=True,
139
+ append_images=cropped_images[1:],
140
+ loop=loop,
141
+ format="GIF" # Explicitly specify GIF format
142
+ )
143
+
144
+ # Rewind the buffer to the beginning
145
+ gif_buffer.seek(0)
146
+
147
+ # Return the buffer containing the GIF
148
+ return gif_buffer
149
+
150
+ def tile_image(image, tile_type="grid"):
151
+ """Tiles an image based on the specified type using Pillow.
152
+
153
+ Args:
154
+ image: The image to tile (PIL Image object).
155
+ tile_type: The type of tiling ("row", "column", "grid", "vertical_brick").
156
+
157
+ Returns:
158
+ The tiled image (PIL Image object).
159
+ """
160
+ if tile_type == "row":
161
+ return tile_image_row(image)
162
+ elif tile_type == "column":
163
+ return tile_image_column(image)
164
+ elif tile_type == 'grid': # Grid
165
+ return tile_image_grid(image)
166
+ elif tile_type == "vertical_brick":
167
+ return tile_image_vert_brick(image)
168
+ elif tile_type == "horizontal_brick":
169
+ return tile_image_horiz_brick(image)
170
+
171
+ def tile_and_convert(image, tile_type='grid'):
172
+ img_width, img_height = image.size
173
+
174
+ assert img_width < 2600, "Please only upload 1x1, 2x1, 1x2 or 2x2 tiles downloaded from ideogram.ai"
175
+ if img_width > 1280:
176
+ scale_factor = 0.23
177
+ else:
178
+ scale_factor = 0.46
179
+
180
+ tiled_image = tile_image(image, tile_type)
181
+
182
+ start_x, start_y, end_x, end_y = 0,0,0,0 # default values
183
+ if tile_type == 'row':
184
+ end_x = img_width
185
+ elif tile_type == 'column':
186
+ end_y = img_height
187
+ else:
188
+ end_x = img_width
189
+ end_y = img_height
190
+
191
+ return crop_along_line_to_gif(tiled_image, img_width, img_height, start_x, start_y, end_x, end_y, jpeg_quality=80, scale_factor=scale_factor)