Cut Picture splits an image into a precise row-by-column grid in the browser. Preview each tile, download individual PNG files, or package the complete grid into one ZIP. Images are processed locally and are never uploaded by the app.
Live app: https://doctorlai-msrc.github.io/cut-picture/
- File picker and drag-and-drop input for browser-supported image formats.
- Configurable 1–20 row and column grid with a one-click swap control.
- Pixel-complete slicing for dimensions that do not divide evenly.
- Individual PNG downloads or one ZIP containing every named tile.
- Automatic grid clamping for images smaller than the selected grid.
- Persistent grid, language, and light/dark theme preferences.
- Responsive keyboard-accessible interface with RTL language support.
- 25 interface languages, including Simplified and Traditional Chinese.
- Release date and commit revision shown in the deployed interface.
- Open the live app.
- Drop an image onto the upload area or choose one with the file picker.
- Set the row and column counts. The preview updates automatically.
- Download one tile or select Download all as ZIP.
Large source images can exceed the browser's available memory because the decoded image, tile canvases, and ZIP data are held locally at the same time. Resize unusually large images before processing them. The grid is capped at 20 × 20.
Animated inputs are exported as static PNG tiles, so animation and source-file metadata are not preserved.
The address bar updates when the language or grid changes, so the current setup can be shared as a link:
https://doctorlai-msrc.github.io/cut-picture/?lang=zh-CN&width=4&height=3
width is the number of columns and height is the number of rows. Each value
is limited to 1–20. URL values take precedence over the corresponding browser
preference; omitted or invalid parameters fall back to local storage. Other
query parameters and URL fragments are preserved.
The interface supports Arabic, Bengali, Chinese (Simplified and Traditional), Dutch, English, Filipino, French, German, Hindi, Indonesian, Italian, Japanese, Korean, Persian, Polish, Portuguese (Brazil), Punjabi, Russian, Spanish, Swahili, Thai, Turkish, Ukrainian, and Vietnamese.
Translations live in public/lang. Every locale is checked
against the English message keys and interpolation placeholders during tests.
Use Node.js 22 LTS (22.13 or newer). Compatible Node.js 24 and 26+ releases are also accepted by the package manifest.
nvm use
npm ci
npm run devThe development server prints its local URL. Production output is written to
dist/, and a dated static-site archive is written to artifacts/.
| Command | Purpose |
|---|---|
npm run dev |
Start the Vite development server |
npm run format |
Format source and documentation |
npm run format:check |
Verify formatting without changing files |
npm run lint |
Run ESLint |
npm run test |
Run the Vitest suite once |
npm run test:watch |
Run Vitest in watch mode |
npm run coverage |
Run tests with the enforced 80% coverage thresholds |
npm run validate:locales |
Validate all locale dictionaries |
npm run build |
Build dist/ and the dated ZIP artifact |
npm run preview |
Preview the production build |
npm run badge |
Generate the JavaScript percentage badge data |
npm run check |
Check formatting, lint, coverage, and production build |
CI runs npm run check for pushes and pull requests targeting main. Pull
requests from this repository receive an updated Vitest coverage comment with
summary and file-level results. The minimum threshold is 80% for lines,
statements, functions, and branches.
GitHub Pages deploys the tested dist/ build from main. A separate workflow
calculates the JavaScript source percentage and commits only its Shields JSON
endpoint to the badges branch, so protected-branch rules remain intact.
Repository administrators must select Settings → Pages → Build and deployment → Source: GitHub Actions once before the first Pages deployment.
Licensed under the MIT License.
Development is supported through Buy Me a Coffee.