from PIL import Image, ImageEnhance
import numpy as np
import os

def create_3d_flip(front_path, back_path, output_path, frames=72, fps=30):
    """
    Creates a 3D flipping animation that switches between front and back images
    during rotation for a realistic 3D effect, preserving transparency in the GIF.

    Parameters:
    - front_path (str): File path to the front image (PNG with transparency).
    - back_path (str): File path to the back image (PNG with transparency).
    - output_path (str): File path where the output GIF will be saved.
    - frames (int): Total number of frames in the GIF.
    - fps (int): Frames per second for the GIF animation.
    """
    # Load both front and back images with RGBA channels to preserve transparency
    front_logo = Image.open(front_path).convert('RGBA')
    back_logo = Image.open(back_path).convert('RGBA')
    
    # Ensure both images are the same size
    if front_logo.size != back_logo.size:
        raise ValueError("Front and back images must have the same dimensions.")
    
    width, height = front_logo.size
    
    # Define canvas size with padding for rotation
    canvas_size = (int(width * 1.3), int(height * 1.3))
    frames_list = []
    
    for i in range(frames):
        # Calculate rotation angle for this frame (0 to 360 degrees)
        angle = (i / frames) * 360
        
        # Create a new transparent canvas
        canvas = Image.new('RGBA', canvas_size, (0, 0, 0, 0))
        
        # Determine which logo to use based on rotation angle
        if 90 <= angle < 270:
            current_logo = back_logo
            # Adjust angle for back side to maintain correct rotation direction
            display_angle = angle - 180
        else:
            current_logo = front_logo
            display_angle = angle
        
        # Calculate scaling factor for perspective effect (simulating 3D rotation)
        scale_factor = 0.7 + 0.3 * abs(np.cos(np.radians(angle)))
        
        # Calculate new dimensions with perspective scaling
        new_width = int(width * scale_factor)
        new_height = int(height * scale_factor)
        
        # Resize the current logo with high-quality resampling
        frame_logo = current_logo.resize((new_width, new_height), Image.LANCZOS)
        
        # Rotate the logo around its center
        frame_logo = frame_logo.rotate(display_angle, expand=True, resample=Image.BICUBIC)
        
        # Calculate position to center the rotated logo on the canvas
        paste_x = (canvas_size[0] - frame_logo.width) // 2
        paste_y = (canvas_size[1] - frame_logo.height) // 2
        
        # Add subtle brightness variation based on rotation to simulate lighting
        enhancer = ImageEnhance.Brightness(frame_logo)
        brightness_factor = 0.8 + 0.2 * abs(np.cos(np.radians(angle)))
        frame_logo = enhancer.enhance(brightness_factor)
        
        # Paste the logo onto the canvas using its alpha channel as mask for transparency
        canvas.paste(frame_logo, (paste_x, paste_y), frame_logo)
        
        # Append the frame (PIL Image) to the frames list
        frames_list.append(canvas)
    
    # Create output directory if it doesn't exist
    os.makedirs(os.path.dirname(output_path), exist_ok=True)
    
    # Convert duration from frames per second to milliseconds per frame
    duration_ms = int(1000 / fps)
    
    # Save the frames as a GIF using Pillow's native save functionality
    # The first frame is saved with additional frames appended
    # disposal=2 ensures each frame is cleared before the next one is drawn
    frames_list[0].save(
        output_path,
        save_all=True,
        append_images=frames_list[1:],
        duration=duration_ms,
        loop=0,
        disposal=2,
        transparency=0  # Assumes the first palette index (0) is transparent
    )
    
    print(f"3D flipping animation saved to {output_path}")

if __name__ == "__main__":
    # Define file paths
    front_path = "/root/auto/img/transparent.png"    # Path to the front image (PNG with transparency)
    back_path = "/root/auto/img/rev_logo.png"        # Path to the back image (PNG with transparency)
    output_path = "/root/auto/output/spin_effect.gif" # Desired output path for the GIF
    
    # Create the 3D flipping animation GIF
    create_3d_flip(front_path, back_path, output_path) (final) {24-10-29 19:01}localhost:~/auto root# python3 spin_effect.py
Traceback (most recent call last):
  File "/root/auto/spin_effect.py", line 103, in <module>
    create_3d_flip(front_path, back_path, output_path)
  File "/root/auto/spin_effect.py", line 84, in create_3d_flip
    frames_list[0].save(
  File "/root/auto/final/lib/python3.12/site-packages/PIL/Image.py", line 2605, in save
    save_handler(self, fp, filename)
  File "/root/auto/final/lib/python3.12/site-packages/PIL/GifImagePlugin.py", line 774, in _save_all
    _save(im, fp, filename, save_all=True)
  File "/root/auto/final/lib/python3.12/site-packages/PIL/GifImagePlugin.py", line 787, in _save
    if not save_all or not _write_multiple_frames(im, fp, palette):
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/root/auto/final/lib/python3.12/site-packages/PIL/GifImagePlugin.py", line 700, in _write_multiple_frames
    background_im.putpalette(im_frames[0].im.palette)
  File "/root/auto/final/lib/python3.12/site-packages/PIL/Image.py", line 2103, in putpalette
    self.load()  # install new palette
    ^^^^^^^^^^^
  File "/root/auto/final/lib/python3.12/site-packages/PIL/Image.py", line 909, in load
    self.im.putpalette(self.palette.mode, mode, arr)
ValueError: invalid palette size