File size: 3,671 Bytes
915a172
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import random
import math
import cv2
import numpy as np
from PIL import Image, ImageDraw

class Particle:
    def __init__(self, canvas_w, canvas_h, effect_type):
        self.canvas_w, self.canvas_h = canvas_w, canvas_h
        self.effect_type = effect_type
        self.reset()

    def reset(self):
        self.x = random.uniform(0, self.canvas_w)
        self.y = random.uniform(-50, self.canvas_h + 50)
        self.size = random.uniform(2, 6)
        self.speed = random.uniform(0.5, 2.5)
        self.wind = random.uniform(-0.5, 0.5)
        self.opacity = random.uniform(100, 255)
        self.rotation = random.uniform(0, 360)
        self.rot_speed = random.uniform(-3, 3)
        self.wobble = random.uniform(0, math.pi * 2)

    def update(self):
        self.y += self.speed
        self.x += self.wind + math.sin(self.wobble) * 0.3
        self.wobble += 0.02
        self.rotation += self.rot_speed
        if self.y > self.canvas_h + 50:
            self.reset()
        if self.x < -50:
            self.x = self.canvas_w + 50
        if self.x > self.canvas_w + 50:
            self.x = -50

def draw_snowflake(draw, x, y, size, opacity):
    r = int(size * 3)
    color = (255, 255, 255, int(opacity))
    draw.ellipse([x - r, y - r, x + r, y + r], fill=color)
    for angle in [0, math.pi / 3, math.pi * 2 / 3]:
        ex, ey = x + math.cos(angle) * r * 1.5, y + math.sin(angle) * r * 1.5
        draw.line([x, y, ex, ey], fill=color, width=max(1, int(size)))

def draw_leaf(draw, x, y, size, opacity, rotation):
    leaf_colors = [(180, 60, 30), (200, 120, 20), (220, 160, 40), (160, 80, 20)]
    color = random.choice(leaf_colors) + (int(opacity),)
    r = int(size * 5)
    img = Image.new('RGBA', (r * 2, r * 2), (0, 0, 0, 0))
    leaf_draw = ImageDraw.Draw(img)
    leaf_draw.ellipse([r * 0.2, r * 0.5, r * 1.8, r * 1.5], fill=color)
    img = img.rotate(rotation, expand=False)
    draw._image.paste(img, (int(x - r), int(y - r)), img)

def draw_raindrop(draw, x, y, size, opacity):
    color = (180, 200, 240, int(opacity))
    r = int(size * 1.5)
    draw.ellipse([x - r, y - r * 3, x + r, y + r * 3], fill=color)

def draw_sparkle(draw, x, y, size, opacity):
    gold = (255, 215, 0, int(opacity))
    r = int(size * 2)
    draw.ellipse([x - r, y - r, x + r, y + r], fill=gold)
    for angle in range(0, 360, 45):
        rad = math.radians(angle)
        ex, ey = x + math.cos(rad) * r * 2, y + math.sin(rad) * r * 2
        draw.line([x, y, ex, ey], fill=gold, width=max(1, int(size * 0.8)))

def draw_dust(draw, x, y, size, opacity):
    color = (200, 190, 170, int(opacity))
    r = int(size * 1.2)
    draw.ellipse([x - r, y - r, x + r, y + r], fill=color)

def apply_effect(frame, particles, effect_type):
    img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA))
    overlay = Image.new('RGBA', img.size, (0, 0, 0, 0))
    draw = ImageDraw.Draw(overlay)
    draw._image = overlay
    for p in particles:
        p.update()
        opacity = max(10, min(255, p.opacity * (1 - (p.y / (p.canvas_h + 50)))))
        if effect_type == "snow": draw_snowflake(draw, p.x, p.y, p.size, opacity)
        elif effect_type == "leaves": draw_leaf(draw, p.x, p.y, p.size, opacity, p.rotation)
        elif effect_type == "rain": draw_raindrop(draw, p.x, p.y, p.size, opacity)
        elif effect_type == "sparkle": draw_sparkle(draw, p.x, p.y, p.size, opacity)
        elif effect_type == "dust": draw_dust(draw, p.x, p.y, p.size, opacity)
    img = Image.alpha_composite(img, overlay)
    return cv2.cvtColor(np.array(img), cv2.COLOR_RGBA2BGR)

EFFECTS = ["snow", "leaves", "rain", "sparkle", "dust", "flame", "heat", "oldfilm", "none"]