# wimp Web image manipulation — in-browser cropping, templates, and high-quality export. Everything runs locally in your browser; your images never leave the page and nothing is uploaded to a server. ## What it does - **Interactive cropping** with zoom, pan, rotation, and horizontal/vertical flip, powered by react-easy-crop. - **Built-in templates** for common targets (OG image, Twitter/X card, Instagram square/portrait, Story/Reel, YouTube thumbnail, LinkedIn cover, avatar, favicon, US passport, and more) — selecting one sets the crop aspect, output size, and sensible encoder defaults. See `src/templates.ts`. - **Color adjustments** (brightness, contrast, saturation, grayscale, sepia, hue rotate) applied live in the preview and baked into the export from a single shared filter definition, so what you see matches what you get. - **High-quality export** to JPEG, WebP, PNG, or AVIF with a quality control, optional long-edge size cap, and a download / copy-to-clipboard result card. All pixel processing and encoding happen off the main thread in a Web Worker, so the UI stays responsive even on large photos. ## Quick start Requires Node 22+ and npm. ```bash npm install npm run dev # start the Vite dev server ``` Open the printed local URL. Load an image by drag-and-drop, clicking the dropzone, or pasting from the clipboard. ### Other scripts ```bash npm run build # type-check then produce a production build npm run preview # serve the production build locally npm run typecheck # tsc, no emit ``` ## Keyboard shortcuts | Key | Action | | -------------- | -------------------------- | | `[` / `]` | Rotate -90° / +90° | | `h` / `v` | Flip horizontal / vertical | | `0` | Reset zoom and pan | | `Cmd/Ctrl`+`S` | Export | ## How it works Three deliberately separated layers: 1. **Interactive UI** (main thread, React 19 + React Compiler) — crop, zoom, rotation, flip, and live CSS-filter color preview. 2. **Pixel processing** (Web Worker) — decode, rotate/flip, crop, and resample to the target size. Uses libvips (lanczos3, via wasm-vips) for meaningful downscales when cross-origin isolation is available, otherwise an OffscreenCanvas high-quality draw. 3. **Encoding** (same worker) — jSquash WASM codecs (MozJPEG / WebP / OxiPNG / AVIF) for real quality control, with `OffscreenCanvas.convertToBlob` as a fallback. For the full design, coordinate model, and file map, see [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md). ## Tech stack - TypeScript, React 19.2 + React Compiler - Vite 8 (Rolldown / Oxc) - Tailwind CSS v4 (design tokens in CSS `@theme`, no config file) - react-easy-crop for the crop UI - wasm-vips (libvips) for resampling; jSquash codecs for encoding The app sets `Cross-Origin-Opener-Policy` and `Cross-Origin-Embedder-Policy` headers so `SharedArrayBuffer` is available for the threaded WASM builds. ## Documentation - [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) — design, data flow, file map. - [`docs/WORKLOG.md`](docs/WORKLOG.md) — what was built and key decisions. - [`docs/VERIFICATION.md`](docs/VERIFICATION.md) — test evidence. - [`docs/deferred/`](docs/deferred/) — intentionally deferred work (background removal, face-aware passport framing, free-form crop, enhancements) and known limitations.