MalikSahib1 commited on
Commit
84d0fd2
·
verified ·
1 Parent(s): b032d48

Update engine.py

Browse files
Files changed (1) hide show
  1. engine.py +67 -32
engine.py CHANGED
@@ -1,70 +1,105 @@
1
  import numpy as np
2
  from rembg import remove
3
- from PIL import Image, ImageFilter
4
  from moviepy.editor import ImageClip, CompositeVideoClip
5
  import os
6
- import uuid
7
 
8
  class IconAnimator:
9
  def __init__(self, input_path, output_path):
10
  self.input_path = input_path
11
  self.output_path = output_path
12
 
13
- def process_image(self):
 
 
 
14
  # 1. Remove Background
15
  with open(self.input_path, 'rb') as i:
16
  input_data = i.read()
17
  output_data = remove(input_data)
18
 
19
- # Save temp byte stream to PIL Image
20
  from io import BytesIO
21
  img = Image.open(BytesIO(output_data)).convert("RGBA")
22
 
23
- # 2. Make Icon White (Fill Effect)
24
  r, g, b, a = img.split()
25
- white_bg = Image.new("RGB", img.size, (255, 255, 255))
26
- img_white = Image.merge("RGBA", (*white_bg.split(), a))
27
 
28
- return img_white
 
 
 
 
 
 
 
 
 
29
 
30
- def create_glow_layer(self, img, blur_radius):
31
- # Add padding to canvas so glow doesn't get cut off
32
- padding = 50
33
  new_size = (img.width + padding*2, img.height + padding*2)
34
  canvas = Image.new("RGBA", new_size, (0, 0, 0, 0))
35
  canvas.paste(img, (padding, padding), img)
36
 
37
- # Blur
38
- glow = canvas.filter(ImageFilter.GaussianBlur(radius=blur_radius))
 
 
 
 
 
 
 
 
39
  return glow, padding
40
 
41
- def generate_animation(self):
42
- # Prepare Images
43
- base_pil = self.process_image()
44
 
45
- # Create Glows (Layering approach)
46
- glow_small, pad = self.create_glow_layer(base_pil, blur_radius=8)
47
- glow_large, _ = self.create_glow_layer(base_pil, blur_radius=25)
 
 
48
 
49
  w, h = base_pil.size
50
  final_w, final_h = w + (pad*2), h + (pad*2)
51
 
52
- # Duration of animation loop
53
- duration = 2.0
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
- # Create Clips
56
- base_clip = ImageClip(np.array(base_pil)).set_duration(duration).set_position("center")
57
- glow_s_clip = ImageClip(np.array(glow_small)).set_duration(duration)
58
- glow_l_clip = ImageClip(np.array(glow_large)).set_duration(duration)
59
 
60
- # Pulse Logic (Sine Wave)
61
- # Opacity oscillates between 0.6 and 1.0
62
- glow_s_clip = glow_s_clip.set_opacity(lambda t: 0.6 + 0.4 * np.sin(2 * np.pi * t / duration))
63
- glow_l_clip = glow_l_clip.set_opacity(lambda t: 0.4 + 0.2 * np.sin(2 * np.pi * t / duration))
64
 
65
- # Composite
66
- final = CompositeVideoClip([glow_l_clip, glow_s_clip, base_clip], size=(final_w, final_h))
 
 
 
 
67
 
68
- # Export (Optimized for Web)
69
  final.write_gif(self.output_path, fps=15, program='ffmpeg', opt='OptimizeTransparency')
70
  return self.output_path
 
1
  import numpy as np
2
  from rembg import remove
3
+ from PIL import Image, ImageFilter, ImageOps, ImageColor
4
  from moviepy.editor import ImageClip, CompositeVideoClip
5
  import os
6
+ import math # Switched from numpy to math for safer scalar operations
7
 
8
  class IconAnimator:
9
  def __init__(self, input_path, output_path):
10
  self.input_path = input_path
11
  self.output_path = output_path
12
 
13
+ def hex_to_rgb(self, hex_color):
14
+ return ImageColor.getcolor(hex_color, "RGB")
15
+
16
+ def process_image(self, icon_color_hex="#FFFFFF"):
17
  # 1. Remove Background
18
  with open(self.input_path, 'rb') as i:
19
  input_data = i.read()
20
  output_data = remove(input_data)
21
 
22
+ # Load into PIL
23
  from io import BytesIO
24
  img = Image.open(BytesIO(output_data)).convert("RGBA")
25
 
26
+ # 2. Recolor the Icon (Fill non-transparent pixels with chosen color)
27
  r, g, b, a = img.split()
 
 
28
 
29
+ # Get target RGB
30
+ target_r, target_g, target_b = self.hex_to_rgb(icon_color_hex)
31
+
32
+ # Create solid color block
33
+ solid_color = Image.new("RGB", img.size, (target_r, target_g, target_b))
34
+
35
+ # Merge using the original alpha channel as a mask
36
+ img_colored = Image.merge("RGBA", (*solid_color.split(), a))
37
+
38
+ return img_colored
39
 
40
+ def create_glow_layer(self, img, blur_radius, color_hex):
41
+ # Create padding
42
+ padding = 60
43
  new_size = (img.width + padding*2, img.height + padding*2)
44
  canvas = Image.new("RGBA", new_size, (0, 0, 0, 0))
45
  canvas.paste(img, (padding, padding), img)
46
 
47
+ # Extract Alpha to create the glow shape
48
+ r, g, b, a = canvas.split()
49
+
50
+ # Create solid color for glow
51
+ target_r, target_g, target_b = self.hex_to_rgb(color_hex)
52
+ glow_base = Image.new("RGB", new_size, (target_r, target_g, target_b))
53
+ glow_shape = Image.merge("RGBA", (*glow_base.split(), a))
54
+
55
+ # Apply Blur
56
+ glow = glow_shape.filter(ImageFilter.GaussianBlur(radius=blur_radius))
57
  return glow, padding
58
 
59
+ def generate_animation(self, icon_color="#FFFFFF", glow_color="#00ffc8", speed=2.0, intensity=1.0):
60
+ # 1. Prepare Base Image
61
+ base_pil = self.process_image(icon_color)
62
 
63
+ # 2. Create Glow Layers
64
+ # Small intense glow (inner)
65
+ glow_small, pad = self.create_glow_layer(base_pil, blur_radius=10, color_hex=glow_color)
66
+ # Large soft glow (outer)
67
+ glow_large, _ = self.create_glow_layer(base_pil, blur_radius=30, color_hex=glow_color)
68
 
69
  w, h = base_pil.size
70
  final_w, final_h = w + (pad*2), h + (pad*2)
71
 
72
+ # 3. Create Clips
73
+ # Center the base icon
74
+ base_clip = ImageClip(np.array(base_pil)).set_duration(speed).set_position("center")
75
+
76
+ glow_s_clip = ImageClip(np.array(glow_small)).set_duration(speed)
77
+ glow_l_clip = ImageClip(np.array(glow_large)).set_duration(speed)
78
+
79
+ # 4. Apply Animation (Pulse)
80
+ # We use math.sin instead of np.sin to prevent the "function * float" error
81
+ # Intensity scales the opacity (0.0 to 1.0)
82
+
83
+ def pulse_small(t):
84
+ # Oscillates between 0.6 and 1.0 (modified by intensity)
85
+ val = 0.6 + 0.4 * math.sin(2 * math.pi * t / speed)
86
+ return min(max(val * intensity, 0), 1)
87
 
88
+ def pulse_large(t):
89
+ # Oscillates between 0.3 and 0.7 (modified by intensity)
90
+ val = 0.4 + 0.3 * math.sin(2 * math.pi * t / speed)
91
+ return min(max(val * intensity, 0), 1)
92
 
93
+ glow_s_clip = glow_s_clip.set_opacity(pulse_small)
94
+ glow_l_clip = glow_l_clip.set_opacity(pulse_large)
 
 
95
 
96
+ # 5. Composite
97
+ final = CompositeVideoClip([
98
+ glow_l_clip, # Background atmosphere
99
+ glow_s_clip, # Rim light
100
+ base_clip # Sharp Icon
101
+ ], size=(final_w, final_h))
102
 
103
+ # 6. Export
104
  final.write_gif(self.output_path, fps=15, program='ffmpeg', opt='OptimizeTransparency')
105
  return self.output_path