pico-img
v1.1.0
Published
Local-first image & video compressor & TinyPNG alternative — compress JPG, PNG, WebP, AVIF, TIFF & JXL locally. Video compression via ffmpeg.
Maintainers
Readme
Pico
A local-first image & video compressor for JPG, PNG, WebP, AVIF, TIFF, JPEG XL and video formats. Pico runs a small Express server on your machine, compresses everything with Sharp (ffmpeg for video), and shows the results in a terminal style web UI. Nothing is uploaded, there are no accounts, and nothing leaves your computer.
It exists because "free image compressor" usually means sending your photos to someone else's server. Pico does the same work offline.
Built with
GitHub Insights
Features
- Compresses JPG, JPEG, PNG, WebP, AVIF, TIFF, JPEG XL and video (MP4, WebM, MOV, MKV, AVI), up to 200 MB per file and 30 files per batch
- Uses mozjpeg for JPEG, compression level 9 with palette mode for PNG, tuned encoders for WebP/AVIF, LZW for TIFF, libjxl for JPEG XL, and libx264 + AAC for video
- Quality control from 10 to 100, from tiny files to near-lossless
- Shows original size, compressed size and savings for every file
- Keeps the original format, respects EXIF orientation
- Deletes temporary uploads automatically after processing
- REST API if you prefer scripts over clicking
Requirements
- Node.js 18.17 or newer
- A browser, for the web UI
Installation
Run it once without installing:
npx pico-imgOr install it globally:
npm install -g pico-img
picoThe server starts on port 3000 and your browser opens automatically.
To work on the source code instead:
git clone https://github.com/MoHamed-B-M/pico.git
cd pico
npm install
npm run build
npm run devUsage
- Run
picoin a terminal - Drag your images into the upload card, or click to browse
- Pick a quality level. 10 gives the smallest files, 100 keeps the most detail
- Press compress and wait for the results
- Download what you need
Command line options
Usage: pico [options]
Options:
-p, --port <number> Port to serve on (default: 3000)
--no-open Do not auto-open the browser
-v, --version Show version number
-h, --help Show this helpHow it works
flowchart LR
A[Drop files] --> B[Multer temp store]
B --> C{Route}
C -->|image| D[Sharp]
C -->|JXL| E[libjxl]
C -->|video| F[ffmpeg]
D -->|JPG| G[mozjpeg]
D -->|PNG| H[level 9 + palette]
D -->|WebP| I[effort 5]
D -->|AVIF| J[effort 4]
D -->|TIFF| K[lzw compression]
E --> L[compressed folder]
F --> L
G --> L
H --> L
I --> L
J --> L
K --> L
L --> M[JSON stats and downloads]
B -. auto delete .-> N[cleanup]Compression happens in-process through libvips (images) and ffmpeg (video). There are no workers, queues or external services involved.
Results you can expect
Measured on a 1600x1200 test image at quality 60:
| Format | Before | After | Saved | |--------|-------:|------:|------:| | JPG | 1.82 MB | 383 KB | 79% | | PNG | 113 KB | 18 KB | 84% |
API
Compress files with a POST request. The images field is repeatable, quality accepts an integer from 10 to 100.
curl -X POST -F "[email protected]" -F "quality=60" http://localhost:3000/api/compressThe response contains one entry per file:
{
"success": true,
"quality": 60,
"files": [
{
"id": "d38c9894",
"originalName": "photo.jpg",
"downloadUrl": "/compressed/d38c9894__photo.compressed.jpg",
"format": "JPG",
"quality": 60,
"originalSize": 1823679,
"compressedSize": 383140,
"savedPercentage": 79
}
]
}Files that fail are listed under failures and do not stop the rest of the batch. A health probe is available at GET /api/health.
Project structure
pico/
|-- server.js Express server and Sharp pipeline
|-- vite.config.js Vite config, client root
|-- client/
| |-- index.html
| |-- tailwind.config.js
| +-- src/
| |-- components/ Upload card, quality slider, results
| |-- animations/ GSAP hooks
| |-- tokens.css Design tokens
| +-- App.jsx
|-- uploads/ Temporary storage, auto cleaned
+-- compressed/ Output folder, served staticallyContributing
Pull requests are welcome. Fork the repo, make your changes, and open a PR. Some ideas that would be nice: resize presets, a CLI-only batch mode, GIF support, a Docker image.
License
This project is licensed under the GNU General Public License v3.0. See LICENSE for details.
Author
Made by Hamma, IT student.
Disclaimer: TinyPNG is a registered trademark of Tinify B.V. Pico is an independent, open-source project and is not affiliated with or endorsed by Tinify.
