Skip to content

Branches

Default: main

Tags

No tags yet

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.

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

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.

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