Web-based privacy-first image editor with per-layer editing, non-destructive adjustments, layer masks, selections, and multi-format export.
Made with ❤️ in Poland for the European Union.
Offline-first — ReImaage runs entirely in your browser. No data leaves your device. All editing, export, and project storage happens locally.
ReImaage is licensed under the European Union Public Licence v. 1.2 (EUPL-1.2). See LICENSE for the full text, or read it at EUR-Lex.
SPDX identifier: EUPL-1.2
- Per-layer independent pixel editing
- Brush, Eraser, Clone Stamp, Text, and Shape tools
- Rectangular, Elliptical, Lasso, and Magic Wand selections
- Selection Add, Subtract, Intersect operations
- Layer masks with Reveal/Hide painting modes
- Non-destructive adjustments: Brightness, Contrast, Saturation, Exposure, Hue, Levels, Curves, B&W, Invert
- 16 blend modes per layer
- Clip/Copy/Paste workflow
- Transform controls (move, resize, rotate)
- Crop tool with aspect ratio presets
- Undo/Redo with per-layer canvas history
- Export PNG, JPEG (quality), WebP (quality)
- Save/Open native
.reevimgproject format - Project recovery via IndexedDB
- Responsive desktop and mobile layouts
- Touch-friendly mobile editor
- Keyboard shortcuts
- Real layer thumbnails
- Pixel grid at high zoom (2000%+)
- Web Workers for heavy selection operations (Magic Wand, Feather, Expand, Contract)
| Layer | Technology |
|---|---|
| Frontend | Svelte 5 + TypeScript + Vite |
| Rendering | Canvas2D (inline), WebGL2 architecture (future) |
| Workers | Web Workers for selection processing |
| Persistence | IndexedDB (recovery), localStorage (UI state) |
| Icons | Lucide Svelte |
| Build | Vite + Svelte plugin |
| Testing | svelte-check (typecheck) |
pnpm install
pnpm dev # → http://localhost:5173pnpm build # → dist/
pnpm check # → typecheck (0 errors)├── src/
│ ├── components/
│ │ ├── editor/ # CanvasWorkspace, LayerItem, ToolOptions, ColorPicker, ContextMenu
│ │ ├── layout/ # TopBar, LeftToolbar, RightSidebar, DesktopEditor, MobileEditor
│ │ ├── panels/ # LayersPanel, BrushPanel, AdjustmentsPanel, HistoryPanel
│ │ └── modals/ # Export, NewProject, Levels, Curves, About, Input, Recovery
│ ├── stores/ # editor.svelte.ts (central state), ui.svelte.ts, modals.svelte.ts
│ ├── services/ # export, file I/O, keyboard shortcuts, image processing
│ ├── lib/
│ │ ├── rendering/ # Renderer abstraction (Canvas2D, WebGL2, WebGPU placeholders)
│ │ ├── workers/ # Web Worker for selection operations
│ │ ├── layers/ # Layer thumbnail generation
│ │ └── persistence/ # IndexedDB project recovery, autosave
│ ├── data/ # Menu definitions, sample layers, tools
│ ├── types/ # TypeScript interfaces
│ └── app.css # Global dark theme styles
├── PLAN.md # Feature implementation roadmap
├── FINAL_STATUS_REPORT.md # v0.1.0 release status
├── P9_IMPLEMENTATION_REPORT.md
├── LICENSE # EUPL-1.2
└── README.md # This file
Each raster layer owns an independent HTMLCanvasElement stored in editor.layerCanvases (a Map<string, HTMLCanvasElement>). All editing tools — Brush, Eraser, Text, Shape, Clone Stamp — write to the active layer's canvas. Canvas compositing iterates layers front-to-back with per-layer opacity, blend modes, masks, and adjustments.
CanvasWorkspace.renderCanvas()
├── Background (solid color or checkerboard for transparent)
├── For each visible layer (bottom → top):
│ ├── Apply CSS filter adjustments (brightness, contrast, hue, levels, etc.)
│ ├── Draw layer's own canvas pixels
│ ├── Apply layer mask (destination-in compositing)
│ └── Apply blend mode (globalCompositeOperation)
└── Pixel grid overlay (at 2000%+ zoom)
Each pushHistory() call snapshots all layer canvases as PNG data URLs. Undo/Redo restores layer metadata and pixel data. History budget: 256 MB.
JSON-based format containing:
- Canvas dimensions and background
- Layer metadata (names, visibility, opacity, blend modes, positions)
- Per-layer pixel data (PNG data URLs)
- Layer masks and adjustments
| Backend | Status | Capabilities |
|---|---|---|
| Canvas2D | Active (inline) | Full feature set — all blend modes, masks, adjustments, filters |
| WebGL2 | Architecture only | Basic texture compositing — not connected to app rendering |
| WebGPU | Placeholder | Architecture detection — no implementation |
The application renders directly via Canvas2D API in CanvasWorkspace.svelte. The renderer abstraction layer (Canvas2DRenderer, WebGLRenderer, WebGPURenderer) exists as infrastructure for future GPU acceleration but is not currently used by the rendering pipeline.
| Tool | Shortcut | Description |
|---|---|---|
| Move | V | Move layers on canvas |
| Marquee | M | Rectangular selection |
| Lasso | L | Freehand selection |
| Magic Wand | W | Flood-fill color selection |
| Crop | C | Crop canvas area |
| Eyedropper | I | Pick foreground color |
| Brush | B | Paint with foreground color |
| Eraser | E | Erase layer pixels |
| Clone Stamp | S | Clone from source point |
| Text | T | Add text to layer |
| Shape | U | Draw rectangle, ellipse, or line |
| Hand | H | Pan canvas |
| Zoom | Z | Zoom in/out |
| Shortcut | Action |
|---|---|
Ctrl/Cmd + Z |
Undo |
Ctrl/Cmd + Shift + Z |
Redo |
Ctrl/Cmd + C |
Copy |
Ctrl/Cmd + X |
Cut |
Ctrl/Cmd + V |
Paste |
Ctrl/Cmd + O |
Open Image |
Ctrl/Cmd + S |
Save Project |
Ctrl/Cmd + E |
Export |
Ctrl/Cmd + N |
New Project |
Ctrl/Cmd + 0 |
Fit to Screen |
Ctrl/Cmd + 1 |
Zoom 100% |
Ctrl/Cmd + = |
Zoom In |
Ctrl/Cmd + - |
Zoom Out |
[ / ] |
Brush size decrease / increase |
Space |
Temporary Hand tool |
| Format | Quality Control | Transparency |
|---|---|---|
| PNG | Lossless | Supported |
| JPEG | Quality slider (1-100) | Flattened to white |
| WebP | Quality slider (1-100) | Supported |
- Chrome 90+
- Firefox 90+
- Safari 15+
- Edge 90+
- Mobile browsers with pointer event support
ReImaage uses Lucide icons under the ISC License. See package.json for the full dependency list.
All AI-assisted features are intentionally excluded from this editor. No image data is sent to any external server.
Developed in the European Union · Licensed under EUPL-1.2