Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
3b6cdad
Initial plan
Copilot Oct 11, 2025
188d6ea
Fix multi-image file opening to support multiple file selection
Copilot Oct 11, 2025
2a295a8
Merge pull request #76 from Pascal-Institute/copilot/fix-image-proces…
volta2030 Oct 11, 2025
28f28fb
feat: add image pannel grab-grabbing effect
volta2030 Oct 11, 2025
d229350
fix: enable drop open multipe files
volta2030 Oct 13, 2025
4dbebd5
feat: add color copied for colorpickerbox #78
volta2030 Oct 13, 2025
a81bd61
fix move message noti to ipcRenderer system...
volta2030 Oct 13, 2025
a9ddfb7
fix: remove imgpanel_template.html
volta2030 Oct 14, 2025
4693982
fix: change name-span to name-input #71
volta2030 Oct 14, 2025
e3b32be
fix: enable change name in name-input #71
volta2030 Oct 14, 2025
f12b9c6
fix: modify name-input css
volta2030 Oct 14, 2025
704cc29
fix: use ipcRenderer showNotificationREQ
volta2030 Oct 15, 2025
891e93f
feat: connect dilate #80
volta2030 Oct 15, 2025
db6915b
fix: replace normalize, median and dilate to image processor
volta2030 Oct 15, 2025
c2b796b
fix: refactor imgkit
volta2030 Oct 15, 2025
c7ad8f7
fix: create sub-directory on imgkit
volta2030 Oct 15, 2025
9c5aacf
fix: replace flip using processImage()
volta2030 Oct 15, 2025
d9ee7b5
fix: replace flop to processImage()
volta2030 Oct 15, 2025
4f9a49b
feat: add prevent global drag
volta2030 Oct 16, 2025
d74c939
feat: add erode function in filter section #81
volta2030 Oct 16, 2025
ae0209e
fix: remove drop effect 'copy' for image swap
volta2030 Oct 16, 2025
7448bd0
npm update
volta2030 Oct 16, 2025
b628cd3
fix: package "files"
volta2030 Oct 16, 2025
304cf86
feat: introduce svg format #82
volta2030 Oct 16, 2025
f588a21
fix: refactor setupDragDrop()
volta2030 Oct 16, 2025
4a11e94
fix: refactor image_processor.js
volta2030 Oct 16, 2025
3bd35db
Initial plan
Copilot Oct 16, 2025
eb7fdd9
Add GIF animation detection and frame extraction support
Copilot Oct 16, 2025
d4aafb7
Add GIF animation pause on image operations and improve stability
Copilot Oct 16, 2025
8359930
Add comprehensive GIF animation documentation
Copilot Oct 16, 2025
b3a446b
fix: add missed image file extension
volta2030 Oct 16, 2025
06ccf58
Merge pull request #84 from Pascal-Institute/copilot/support-gif-file…
volta2030 Oct 16, 2025
fd95015
README.md 업데이트
volta2030 Oct 16, 2025
17e58f8
fix: use processImage for blur
volta2030 Oct 18, 2025
d09055c
fix: use processImage for resize
volta2030 Oct 18, 2025
8d019ed
fix: use processImage() for rotate
volta2030 Oct 19, 2025
d22b41f
fix: move imgkit html into imgkit folder
volta2030 Oct 21, 2025
58c2562
npm update
volta2030 Oct 22, 2025
7896256
fix: replace rotate to processImage()
volta2030 Oct 22, 2025
cc06291
fix: replace nagative to processImage
volta2030 Oct 22, 2025
4afd5c4
fix: disable undo to empty image (#90)
volta2030 Oct 25, 2025
efeb16a
feat: add pad asset
volta2030 Oct 25, 2025
9262f6c
chore: README.md
volta2030 Oct 25, 2025
21d3f7b
feat: introduce pad infrastructure #88
volta2030 Oct 25, 2025
da6323f
feat: implement pad function #88
volta2030 Oct 25, 2025
69675fc
chore: change title
volta2030 Oct 25, 2025
f3ee84f
fix: detatching gif from image_layer.js
volta2030 Oct 25, 2025
f6678da
Merge branch 'develop' of https://github.com/Pascal-Institute/pegasus…
volta2030 Oct 25, 2025
41df4e7
fix: enable image file swaping
volta2030 Oct 25, 2025
63ec2ce
fix: change magnifying shortcut to alt + m
volta2030 Oct 25, 2025
08a9bf8
fix: magnify enabling
volta2030 Oct 25, 2025
a10aaab
fix: enable scrolling
volta2030 Oct 25, 2025
1aeed71
version up: 1.0.8
volta2030 Oct 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
[![DeepWiki](https://img.shields.io/badge/DeepWiki-Pascal--Institute%2Fpegasus-blue.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAyCAYAAAAnWDnqAAAAAXNSR0IArs4c6QAAA05JREFUaEPtmUtyEzEQhtWTQyQLHNak2AB7ZnyXZMEjXMGeK/AIi+QuHrMnbChYY7MIh8g01fJoopFb0uhhEqqcbWTp06/uv1saEDv4O3n3dV60RfP947Mm9/SQc0ICFQgzfc4CYZoTPAswgSJCCUJUnAAoRHOAUOcATwbmVLWdGoH//PB8mnKqScAhsD0kYP3j/Yt5LPQe2KvcXmGvRHcDnpxfL2zOYJ1mFwrryWTz0advv1Ut4CJgf5uhDuDj5eUcAUoahrdY/56ebRWeraTjMt/00Sh3UDtjgHtQNHwcRGOC98BJEAEymycmYcWwOprTgcB6VZ5JK5TAJ+fXGLBm3FDAmn6oPPjR4rKCAoJCal2eAiQp2x0vxTPB3ALO2CRkwmDy5WohzBDwSEFKRwPbknEggCPB/imwrycgxX2NzoMCHhPkDwqYMr9tRcP5qNrMZHkVnOjRMWwLCcr8ohBVb1OMjxLwGCvjTikrsBOiA6fNyCrm8V1rP93iVPpwaE+gO0SsWmPiXB+jikdf6SizrT5qKasx5j8ABbHpFTx+vFXp9EnYQmLx02h1QTTrl6eDqxLnGjporxl3NL3agEvXdT0WmEost648sQOYAeJS9Q7bfUVoMGnjo4AZdUMQku50McDcMWcBPvr0SzbTAFDfvJqwLzgxwATnCgnp4wDl6Aa+Ax283gghmj+vj7feE2KBBRMW3FzOpLOADl0Isb5587h/U4gGvkt5v60Z1VLG8BhYjbzRwyQZemwAd6cCR5/XFWLYZRIMpX39AR0tjaGGiGzLVyhse5C9RKC6ai42ppWPKiBagOvaYk8lO7DajerabOZP46Lby5wKjw1HCRx7p9sVMOWGzb/vA1hwiWc6jm3MvQDTogQkiqIhJV0nBQBTU+3okKCFDy9WwferkHjtxib7t3xIUQtHxnIwtx4mpg26/HfwVNVDb4oI9RHmx5WGelRVlrtiw43zboCLaxv46AZeB3IlTkwouebTr1y2NjSpHz68WNFjHvupy3q8TFn3Hos2IAk4Ju5dCo8B3wP7VPr/FGaKiG+T+v+TQqIrOqMTL1VdWV1DdmcbO8KXBz6esmYWYKPwDL5b5FA1a0hwapHiom0r/cKaoqr+27/XcrS5UwSMbQAAAABJRU5ErkJggg==)](https://deepwiki.com/Pascal-Institute/pegasus)

<!-- DeepWiki badge generated by https://deepwiki.ryoppippi.com/ -->

# pegasus

#### The Image Processing Tool based on Electron framework & sharp npm package

<img width="3071" height="1806" alt="image" src="https://github.com/user-attachments/assets/853e02b8-dffb-44e4-a5f8-d74b81265c3e" />

## 0. Application mission : Give wings to pixels

## 1. Requirements

### For Development

- IDE : Visual Studio Code (Recommemded)
- node.js : v22.18.0 (At least version)

Expand All @@ -21,11 +22,13 @@ npm install -g electron
```bash
npm install --save electron electron-reload electron-rebuild electron-builder sharp sharp-ico sharp-bmp fs imgkit
```

### For Application use

1. Install node.js : https://nodejs.org/

2. Install electron

```bash
npm install -g electron
```
Expand All @@ -43,6 +46,7 @@ npm update
## 3-1. How to execute

### window

```bash
electron .
```
Expand All @@ -54,6 +58,7 @@ npm start
```

### linux line-up

```bash
electron . --ozone-platform=x11
```
Expand All @@ -69,9 +74,11 @@ npm run build
### 4-1. Availiable file extension

```bash
png jpg jpeg webp gif bmp ico tiff tif
png svg jpg jpeg webp gif bmp ico tiff tif
```

**Note:** Animated GIF files are now supported! When you load an animated GIF, playback controls appear automatically. See [GIF Animation Documentation](docs/GIF_ANIMATION.md) for details.

#### 4-2. extension converting

### 4-3. Image Processing
Expand Down
Binary file added assets/dilate.ico
Binary file not shown.
Binary file added assets/erode.ico
Binary file not shown.
Binary file added assets/pad.ico
Binary file not shown.
5 changes: 4 additions & 1 deletion css/filter_panel.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
#medianBtn:hover,
#bitwiseBtn:hover,
#negativeBtn:hover,
#normalizeBtn:hover {
#normalizeBtn:hover,
#dilateBtn:hover,
#erodeBtn:hover {
background-color: #e0e0e0;
cursor: pointer;
}
6 changes: 4 additions & 2 deletions css/paint_panel.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
#grayScaleBtn:hover,
#tintExecuteBtn:hover,
#watermarkBtn:hover,
#colorpickerBtn:hover {
#colorpickerBtn:hover,
#colorpickerBox:hover,
#padBtn:hover {
cursor: pointer;
}

Expand Down Expand Up @@ -71,4 +73,4 @@
align-items: center;
flex-direction: column;
margin-left: 5px;
}
}
15 changes: 1 addition & 14 deletions css/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ select#extensionComboBox {
transform: translateY(1px);
}

#nameSpan {
#nameInput {
position: absolute;
top: 8px;
left: 8px;
Expand Down Expand Up @@ -152,16 +152,3 @@ select#extensionComboBox {
#error_msg {
background-color: #f29999;
}

#scroll-container {
position: relative;
width: auto !important;
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
display: flex;
align-items: center;
box-sizing: border-box;
padding: 48px 48px 48px 48px;
scroll-behavior: smooth;
}
169 changes: 169 additions & 0 deletions docs/GIF_ANIMATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# GIF Animation Support

## Overview

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.

## Features

### Automatic Detection
- When a GIF file is loaded, the application automatically detects if it contains multiple frames (animated)
- Static GIFs (single frame) are displayed normally without playback controls
- Animated GIFs show playback controls below the image

### Playback Controls

The GIF playback controls appear automatically for animated GIFs and include:

1. **Play/Pause Button (▶/⏸)**
- Click to play or pause the animation
- Animation plays automatically when first loaded
- Shows ▶ when paused, ⏸ when playing

2. **Stop Button (■)**
- Stops playback and returns to the first frame
- Useful for resetting the animation

3. **Frame Counter**
- Displays current frame / total frames (e.g., "1/316")
- Updates in real-time as animation plays

### Animation Behavior

- **Auto-play**: Animated GIFs start playing automatically when loaded
- **Frame timing**: Each frame respects its original delay timing from the GIF metadata
- **Looping**: Supports infinite looping (most GIFs) and limited loops
- **Pause on operations**: Animation automatically pauses when you perform operations like:
- Undo/Redo (Ctrl+Z / Ctrl+Y)
- Crop, resize, filter, rotate
- Format conversion

### Technical Details

- Uses Sharp library's native GIF animation support
- Extracts individual frames on-demand for smooth playback
- Respects original frame delays (in milliseconds)
- Memory efficient - doesn't pre-load all frames

## Usage

### Opening Animated GIFs

1. **Via File Menu**:
- Click File → Open
- Select a GIF file
- If animated, controls appear automatically

2. **Via Drag & Drop**:
- Drag a GIF file into the application
- Drop it on the canvas area
- Controls appear if the GIF is animated

3. **Via Paste**:
- Copy a GIF file to clipboard
- Press Ctrl+V in the application
- Controls appear if the GIF is animated

### Controlling Playback

- **Play**: Click the ▶ button or it plays automatically
- **Pause**: Click the ⏸ button to pause
- **Stop**: Click the ■ button to stop and reset to first frame
- **Frame info**: Watch the frame counter to see current position

### Working with Animated GIFs

1. **Editing**: You can apply filters, resize, crop, etc. to the current displayed frame
2. **Converting**: When you convert to another format, animation is removed (uses current frame)
3. **Saving**: Saves the original animated GIF if extension stays as .gif
4. **Format Change**: Changing extension to non-GIF formats will save the current frame only

## Examples

### Loading an Animated GIF
```javascript
// The application automatically detects animation
// You just open the file normally
await layer.openImage('path/to/animated.gif');
// Controls appear automatically if animated
```

### Checking if GIF is Animated
```javascript
if (layer.isAnimatedGif()) {
console.log('This is an animated GIF with', layer.gifMetadata.pages, 'frames');
}
```

### Manual Playback Control
```javascript
// Play
layer.playGifAnimation();

// Pause
layer.pauseGifAnimation();

// Stop (reset to frame 0)
layer.stopGifPlayback();
```

## Supported GIF Features

✅ **Supported**:
- Multiple frames (animated GIFs)
- Per-frame delay timing
- Infinite looping (loop = 0)
- Limited looping (loop = N)
- Variable frame delays
- Transparent backgrounds
- Palette-based GIFs

❌ **Not Supported**:
- Editing individual frames
- Creating new animated GIFs from scratch
- Adding/removing frames
- Modifying frame delays

## Performance Notes

- Frame extraction is on-demand (not pre-loaded)
- Smooth playback for most GIFs
- Large GIFs (many frames or high resolution) may have slight delays during frame extraction
- Memory usage is efficient as frames are not kept in memory

## Troubleshooting

### GIF doesn't animate
- Check if it's a static GIF (only 1 frame)
- Verify the file is not corrupted
- Try re-opening the file

### Playback is choppy
- This is normal for GIFs with very short frame delays (<50ms)
- Try a different GIF to verify
- Check system resources (CPU usage)

### Controls don't appear
- Ensure the GIF has multiple frames
- Check the extension is `.gif`
- Try reloading the file

## Implementation Details

The GIF animation support is implemented in:

1. **ImageLoader** (`imgkit/processing/image_loader.js`)
- Detects animated GIFs via metadata (pages > 1)
- Extracts individual frames using Sharp's page option
- Returns GIF metadata (pages, delay, loop)

2. **ImageLayer** (`imgkit/core/image_layer.js`)
- Manages animation state and playback
- Creates and controls UI elements (buttons, counter)
- Schedules frame display based on delays
- Handles pause/play/stop logic

3. **Sharp Library**
- Provides native GIF reading with animation support
- Extracts frames via `sharp(buffer, { page: N })`
- Returns metadata with pages, delay, loop info
Loading