Jeffgold commited on
Commit
e8cdac5
·
verified ·
1 Parent(s): 093601c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +96 -77
app.py CHANGED
@@ -9,89 +9,108 @@ import time
9
  # Global variable to store generated GIFs
10
  generated_gifs = []
11
 
 
 
 
 
 
 
 
12
  def create_gif(editor1_output, editor2_output, transition_type):
13
- img1 = editor1_output["composite"].convert('RGBA')
14
- img2 = editor2_output["composite"].convert('RGBA')
15
-
16
  frames = []
17
  duration = 100 # Duration for each frame in milliseconds
18
- total_frames = 18 # Total number of frames (increased for smoother animation)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
- size = (256, 256) # Increased size for better quality
21
- img1 = img1.resize(size, Image.LANCZOS)
22
- img2 = img2.resize(size, Image.LANCZOS)
 
 
23
 
24
- if transition_type == "slide":
25
- for i in range(total_frames):
26
- mask = Image.new('L', size, 0)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  draw = ImageDraw.Draw(mask)
28
-
29
- # Calculate position with reversal
30
- progress = (i / (total_frames - 1)) * 2
31
- if progress > 1:
32
- progress = 2 - progress
33
-
34
- x_position = int(size[0] * progress)
35
-
36
- # Ensure x_position is within valid range
37
- x_position = max(0, min(x_position, size[0]))
38
-
39
- # Determine which image should be on the left based on direction
40
- if i < total_frames // 2:
41
- left_img, right_img = img1, img2
42
- else:
43
- left_img, right_img = img2, img1
44
-
45
- draw.rectangle([0, 0, x_position, size[1]], fill=255)
46
- frame = Image.composite(right_img, left_img, mask)
47
-
48
- # Draw green line
49
- draw = ImageDraw.Draw(frame)
50
- draw.line((x_position, 0, x_position, size[1]), fill=(0, 255, 0), width=4)
51
-
52
- frames.append(frame.convert('P', palette=Image.ADAPTIVE))
53
- else: # rotate transition
54
- mask_size = (size[0] * 2, size[1] * 2)
55
- mask = Image.new('L', mask_size, 0)
56
- draw = ImageDraw.Draw(mask)
57
- draw.rectangle([size[0], 0, mask_size[0], mask_size[1]], fill=255)
58
-
59
- center_x, center_y = size[0] // 2, size[1] // 2
60
-
61
- for angle in range(0, 360, 360 // total_frames):
62
- rotated_mask = mask.rotate(angle, center=(mask_size[0] // 2, mask_size[1] // 2), expand=False)
63
- cropped_mask = rotated_mask.crop((size[0] // 2, size[1] // 2, size[0] // 2 + size[0], size[1] // 2 + size[1]))
64
- frame = Image.composite(img1, img2, cropped_mask)
65
-
66
- draw = ImageDraw.Draw(frame)
67
- reverse_angle = -angle + 90
68
- end_x1 = center_x + int(size[0] * 1.5 * cos(radians(reverse_angle)))
69
- end_y1 = center_y + int(size[1] * 1.5 * sin(radians(reverse_angle)))
70
- end_x2 = center_x - int(size[0] * 1.5 * cos(radians(reverse_angle)))
71
- end_y2 = center_y - int(size[1] * 1.5 * sin(radians(reverse_angle)))
72
- draw.line([center_x, center_y, end_x1, end_y1], fill=(0, 255, 0), width=6)
73
- draw.line([center_x, center_y, end_x2, end_y2], fill=(0, 255, 0), width=6)
74
-
75
- frames.append(frame.convert('P', palette=Image.ADAPTIVE))
76
-
77
- # Save as GIF
78
- output = io.BytesIO()
79
- frames[0].save(output, format='GIF', save_all=True, append_images=frames[1:], duration=duration, loop=0, optimize=True)
80
- output.seek(0)
81
-
82
- # Save the GIF to a file with a unique name
83
- os.makedirs("outputs", exist_ok=True)
84
- timestamp = int(time.time())
85
- output_path = f"outputs/output_{timestamp}.gif"
86
- with open(output_path, "wb") as f:
87
- f.write(output.getvalue())
88
-
89
- # Add the new GIF to the list of generated GIFs
90
- global generated_gifs
91
- generated_gifs.append((output_path, f"{transition_type.capitalize()} transition"))
92
-
93
- # Return the updated list of generated GIFs
94
- return generated_gifs
95
 
96
  # Gradio interface
97
  with gr.Blocks() as iface:
 
9
  # Global variable to store generated GIFs
10
  generated_gifs = []
11
 
12
+ def preprocess_image(image):
13
+ # Ensure the image is square by padding it
14
+ size = max(image.size)
15
+ new_image = Image.new("RGBA", (size, size), (255, 255, 255, 0))
16
+ new_image.paste(image, ((size - image.width) // 2, (size - image.height) // 2))
17
+ return new_image
18
+
19
  def create_gif(editor1_output, editor2_output, transition_type):
 
 
 
20
  frames = []
21
  duration = 100 # Duration for each frame in milliseconds
22
+ total_frames = 18 # Total number of frames
23
+
24
+ try:
25
+ # Open images
26
+ img1 = editor1_output["composite"].convert('RGBA')
27
+ img2 = editor2_output["composite"].convert('RGBA')
28
+
29
+ # Preprocess images to make them square and same size
30
+ img1 = preprocess_image(img1)
31
+ img2 = preprocess_image(img2)
32
+
33
+ # Set size for the GIF
34
+ size = (256, 256)
35
+ img1 = img1.resize(size, Image.LANCZOS)
36
+ img2 = img2.resize(size, Image.LANCZOS)
37
+
38
+ if transition_type == "slide":
39
+ # Calculate step size for consistent speed
40
+ full_width = size[0]
41
+ step = full_width // (total_frames // 2) # Divide by 2 as we have 2 parts to the animation
42
 
43
+ # Generate frames from left to right
44
+ for i in range(0, full_width, step):
45
+ frame = Image.new('RGBA', size)
46
+ frame.paste(img1, (0, 0))
47
+ frame.paste(img2.crop((i, 0, full_width, size[1])), (i, 0), mask=img2.crop((i, 0, full_width, size[1])))
48
 
49
+ draw = ImageDraw.Draw(frame)
50
+ draw.line((i, 0, i, size[1]), fill=(0, 255, 0), width=2)
51
+
52
+ # Convert frame to P mode which is a palette-based image
53
+ frame = frame.convert('P', palette=Image.ADAPTIVE)
54
+ frames.append(frame)
55
+
56
+ # Generate frames from right to left
57
+ for i in range(full_width, step, -step):
58
+ frame = Image.new('RGBA', size)
59
+ frame.paste(img1, (0, 0))
60
+ frame.paste(img2.crop((i, 0, full_width, size[1])), (i, 0), mask=img2.crop((i, 0, full_width, size[1])))
61
+
62
+ draw = ImageDraw.Draw(frame)
63
+ draw.line((i, 0, i, size[1]), fill=(0, 255, 0), width=2)
64
+
65
+ # Convert frame to P mode which is a palette-based image
66
+ frame = frame.convert('P', palette=Image.ADAPTIVE)
67
+ frames.append(frame)
68
+ else: # rotate transition
69
+ mask_size = (size[0] * 2, size[1] * 2)
70
+ mask = Image.new('L', mask_size, 0)
71
  draw = ImageDraw.Draw(mask)
72
+ draw.rectangle([size[0], 0, mask_size[0], mask_size[1]], fill=255)
73
+
74
+ center_x, center_y = size[0] // 2, size[1] // 2
75
+
76
+ for angle in range(0, 360, 360 // total_frames):
77
+ rotated_mask = mask.rotate(angle, center=(mask_size[0] // 2, mask_size[1] // 2), expand=False)
78
+ cropped_mask = rotated_mask.crop((size[0] // 2, size[1] // 2, size[0] // 2 + size[0], size[1] // 2 + size[1]))
79
+ frame = Image.composite(img1, img2, cropped_mask)
80
+
81
+ draw = ImageDraw.Draw(frame)
82
+ reverse_angle = -angle + 90
83
+ end_x1 = center_x + int(size[0] * 1.5 * cos(radians(reverse_angle)))
84
+ end_y1 = center_y + int(size[1] * 1.5 * sin(radians(reverse_angle)))
85
+ end_x2 = center_x - int(size[0] * 1.5 * cos(radians(reverse_angle)))
86
+ end_y2 = center_y - int(size[1] * 1.5 * sin(radians(reverse_angle)))
87
+ draw.line([center_x, center_y, end_x1, end_y1], fill=(0, 255, 0), width=3)
88
+ draw.line([center_x, center_y, end_x2, end_y2], fill=(0, 255, 0), width=3)
89
+
90
+ frame = frame.convert('P', palette=Image.ADAPTIVE)
91
+ frames.append(frame)
92
+
93
+ # Save as GIF
94
+ output = io.BytesIO()
95
+ frames[0].save(output, format='GIF', save_all=True, append_images=frames[1:], duration=duration, loop=0, optimize=True)
96
+ output.seek(0)
97
+
98
+ # Save the GIF to a file with a unique name
99
+ os.makedirs("outputs", exist_ok=True)
100
+ timestamp = int(time.time())
101
+ output_path = f"outputs/output_{timestamp}.gif"
102
+ with open(output_path, "wb") as f:
103
+ f.write(output.getvalue())
104
+
105
+ # Add the new GIF to the list of generated GIFs
106
+ global generated_gifs
107
+ generated_gifs.append((output_path, f"{transition_type.capitalize()} transition"))
108
+
109
+ # Return the updated list of generated GIFs
110
+ return generated_gifs
111
+
112
+ except Exception as e:
113
+ raise ValueError(f"Error creating GIF: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
 
115
  # Gradio interface
116
  with gr.Blocks() as iface: