|
| 1 | +# GIF Animation Support |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +Pegasus now supports displaying and playing animated GIF files. When you load an animated GIF, the application automatically detects the animation and displays playback controls. |
| 6 | + |
| 7 | +## Features |
| 8 | + |
| 9 | +### Automatic Detection |
| 10 | +- When a GIF file is loaded, the application automatically detects if it contains multiple frames (animated) |
| 11 | +- Static GIFs (single frame) are displayed normally without playback controls |
| 12 | +- Animated GIFs show playback controls below the image |
| 13 | + |
| 14 | +### Playback Controls |
| 15 | + |
| 16 | +The GIF playback controls appear automatically for animated GIFs and include: |
| 17 | + |
| 18 | +1. **Play/Pause Button (▶/⏸)** |
| 19 | + - Click to play or pause the animation |
| 20 | + - Animation plays automatically when first loaded |
| 21 | + - Shows ▶ when paused, ⏸ when playing |
| 22 | + |
| 23 | +2. **Stop Button (■)** |
| 24 | + - Stops playback and returns to the first frame |
| 25 | + - Useful for resetting the animation |
| 26 | + |
| 27 | +3. **Frame Counter** |
| 28 | + - Displays current frame / total frames (e.g., "1/316") |
| 29 | + - Updates in real-time as animation plays |
| 30 | + |
| 31 | +### Animation Behavior |
| 32 | + |
| 33 | +- **Auto-play**: Animated GIFs start playing automatically when loaded |
| 34 | +- **Frame timing**: Each frame respects its original delay timing from the GIF metadata |
| 35 | +- **Looping**: Supports infinite looping (most GIFs) and limited loops |
| 36 | +- **Pause on operations**: Animation automatically pauses when you perform operations like: |
| 37 | + - Undo/Redo (Ctrl+Z / Ctrl+Y) |
| 38 | + - Crop, resize, filter, rotate |
| 39 | + - Format conversion |
| 40 | + |
| 41 | +### Technical Details |
| 42 | + |
| 43 | +- Uses Sharp library's native GIF animation support |
| 44 | +- Extracts individual frames on-demand for smooth playback |
| 45 | +- Respects original frame delays (in milliseconds) |
| 46 | +- Memory efficient - doesn't pre-load all frames |
| 47 | + |
| 48 | +## Usage |
| 49 | + |
| 50 | +### Opening Animated GIFs |
| 51 | + |
| 52 | +1. **Via File Menu**: |
| 53 | + - Click File → Open |
| 54 | + - Select a GIF file |
| 55 | + - If animated, controls appear automatically |
| 56 | + |
| 57 | +2. **Via Drag & Drop**: |
| 58 | + - Drag a GIF file into the application |
| 59 | + - Drop it on the canvas area |
| 60 | + - Controls appear if the GIF is animated |
| 61 | + |
| 62 | +3. **Via Paste**: |
| 63 | + - Copy a GIF file to clipboard |
| 64 | + - Press Ctrl+V in the application |
| 65 | + - Controls appear if the GIF is animated |
| 66 | + |
| 67 | +### Controlling Playback |
| 68 | + |
| 69 | +- **Play**: Click the ▶ button or it plays automatically |
| 70 | +- **Pause**: Click the ⏸ button to pause |
| 71 | +- **Stop**: Click the ■ button to stop and reset to first frame |
| 72 | +- **Frame info**: Watch the frame counter to see current position |
| 73 | + |
| 74 | +### Working with Animated GIFs |
| 75 | + |
| 76 | +1. **Editing**: You can apply filters, resize, crop, etc. to the current displayed frame |
| 77 | +2. **Converting**: When you convert to another format, animation is removed (uses current frame) |
| 78 | +3. **Saving**: Saves the original animated GIF if extension stays as .gif |
| 79 | +4. **Format Change**: Changing extension to non-GIF formats will save the current frame only |
| 80 | + |
| 81 | +## Examples |
| 82 | + |
| 83 | +### Loading an Animated GIF |
| 84 | +```javascript |
| 85 | +// The application automatically detects animation |
| 86 | +// You just open the file normally |
| 87 | +await layer.openImage('path/to/animated.gif'); |
| 88 | +// Controls appear automatically if animated |
| 89 | +``` |
| 90 | + |
| 91 | +### Checking if GIF is Animated |
| 92 | +```javascript |
| 93 | +if (layer.isAnimatedGif()) { |
| 94 | + console.log('This is an animated GIF with', layer.gifMetadata.pages, 'frames'); |
| 95 | +} |
| 96 | +``` |
| 97 | + |
| 98 | +### Manual Playback Control |
| 99 | +```javascript |
| 100 | +// Play |
| 101 | +layer.playGifAnimation(); |
| 102 | + |
| 103 | +// Pause |
| 104 | +layer.pauseGifAnimation(); |
| 105 | + |
| 106 | +// Stop (reset to frame 0) |
| 107 | +layer.stopGifPlayback(); |
| 108 | +``` |
| 109 | + |
| 110 | +## Supported GIF Features |
| 111 | + |
| 112 | +✅ **Supported**: |
| 113 | +- Multiple frames (animated GIFs) |
| 114 | +- Per-frame delay timing |
| 115 | +- Infinite looping (loop = 0) |
| 116 | +- Limited looping (loop = N) |
| 117 | +- Variable frame delays |
| 118 | +- Transparent backgrounds |
| 119 | +- Palette-based GIFs |
| 120 | + |
| 121 | +❌ **Not Supported**: |
| 122 | +- Editing individual frames |
| 123 | +- Creating new animated GIFs from scratch |
| 124 | +- Adding/removing frames |
| 125 | +- Modifying frame delays |
| 126 | + |
| 127 | +## Performance Notes |
| 128 | + |
| 129 | +- Frame extraction is on-demand (not pre-loaded) |
| 130 | +- Smooth playback for most GIFs |
| 131 | +- Large GIFs (many frames or high resolution) may have slight delays during frame extraction |
| 132 | +- Memory usage is efficient as frames are not kept in memory |
| 133 | + |
| 134 | +## Troubleshooting |
| 135 | + |
| 136 | +### GIF doesn't animate |
| 137 | +- Check if it's a static GIF (only 1 frame) |
| 138 | +- Verify the file is not corrupted |
| 139 | +- Try re-opening the file |
| 140 | + |
| 141 | +### Playback is choppy |
| 142 | +- This is normal for GIFs with very short frame delays (<50ms) |
| 143 | +- Try a different GIF to verify |
| 144 | +- Check system resources (CPU usage) |
| 145 | + |
| 146 | +### Controls don't appear |
| 147 | +- Ensure the GIF has multiple frames |
| 148 | +- Check the extension is `.gif` |
| 149 | +- Try reloading the file |
| 150 | + |
| 151 | +## Implementation Details |
| 152 | + |
| 153 | +The GIF animation support is implemented in: |
| 154 | + |
| 155 | +1. **ImageLoader** (`imgkit/processing/image_loader.js`) |
| 156 | + - Detects animated GIFs via metadata (pages > 1) |
| 157 | + - Extracts individual frames using Sharp's page option |
| 158 | + - Returns GIF metadata (pages, delay, loop) |
| 159 | + |
| 160 | +2. **ImageLayer** (`imgkit/core/image_layer.js`) |
| 161 | + - Manages animation state and playback |
| 162 | + - Creates and controls UI elements (buttons, counter) |
| 163 | + - Schedules frame display based on delays |
| 164 | + - Handles pause/play/stop logic |
| 165 | + |
| 166 | +3. **Sharp Library** |
| 167 | + - Provides native GIF reading with animation support |
| 168 | + - Extracts frames via `sharp(buffer, { page: N })` |
| 169 | + - Returns metadata with pages, delay, loop info |
0 commit comments