@srijanpokhrel/image-shrink
v1.0.3
Published
Compress AVIF, WebP, JPEG, and PNG images from the CLI or Node.js API — powered by [sharp](https://sharp.pixelplumbing.com/) (libvips).
Maintainers
Readme
image-shrink
Compress AVIF, WebP, JPEG, and PNG images from the CLI or Node.js API — powered by sharp (libvips).
Features
- Compress JPEG, PNG, WebP, and AVIF
- Convert between formats (e.g. JPEG → WebP)
- Resize to a max width or height while preserving aspect ratio
- Strip EXIF/GPS metadata
- Batch compress via glob patterns
- Use as a CLI tool or Node.js API
Install
# CLI (global install)
npm install -g @srijanpokhrel/image-shrink
# Node.js API (project dependency)
npm install @srijanpokhrel/image-shrinkNote: Remove the
-gflag when installing as a project dependency.
CLI Usage
# Compress a single file (in-place)
image-shrink "photo.jpg"
# Batch compress all JPEGs in a folder
image-shrink "images/**/*.jpg"
# Convert to WebP with custom quality
image-shrink "images/**/*.jpg" --format webp --quality 80
# Resize to max 800px width and output to a folder
image-shrink "images/**/*.jpg" --width 800 --out dist/images
# Convert to AVIF
image-shrink "images/**/*.{jpg,png}" --format avif --quality 60Options
| Flag | Default | Description |
|------|---------|-------------|
| --quality, -q | 80 | Compression quality, 1–100 |
| --format, -f | auto | Output format: jpeg, png, webp, avif |
| --out, -o | in-place | Output directory |
| --width, -w | — | Max width in px, preserves aspect ratio |
| --strip | true | Strip EXIF/GPS metadata |
Node.js API
import { compress } from 'image-shrink';
import fs from 'fs/promises';
const input = await fs.readFile('photo.jpg');
const result = await compress(input, {
quality: 80,
format: 'webp',
stripMetadata: true,
});
await fs.writeFile('photo.webp', result.outputBuffer);
console.log(`Saved ${result.savedPercent}%`);
// → Saved 63%compress(input, options)
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| quality | number | 80 | Compression quality, 1–100 |
| format | 'jpeg' \| 'png' \| 'webp' \| 'avif' | auto-detect | Output format |
| width | number | — | Max width in px, preserves aspect ratio |
| height | number | — | Max height in px, preserves aspect ratio |
| stripMetadata | boolean | true | Strip EXIF/GPS metadata |
| lossless | boolean | false | Lossless compression (WebP/AVIF only) |
| effort | number | 4 | Compression effort, 0–9 (AVIF only) |
CompressResult
{
inputSize: number; // original size in bytes
outputSize: number; // compressed size in bytes
savedBytes: number; // bytes saved
savedPercent: number; // % reduction
outputBuffer: Buffer; // compressed image data
}Real-World Results
Tested on a high-resolution JPEG (743 KB, 4500×3000 px):
| Command | Output | Saved |
|---------|--------|-------|
| --quality 75 | 104 KB | 86% |
| --format webp --quality 80 | 78 KB | 89% |
| --width 800 --quality 75 | 41 KB | 94% |
Results vary by image content. High-detail photos compress differently than flat graphics.
Local Development
git clone https://github.com/crizanp/image-shrink
cd image-shrink
npm install
npm run buildRun Manually
# Test the CLI directly (no global install needed)
node dist/cli.js "tests/fixtures/sample.jpg" --quality 80
# Watch mode — rebuilds on every save
npm run devRun Tests
npm test
# With coverage report
npm test -- --coverageTest Results
PASS tests/compress.test.ts
compress()
✓ compresses JPEG and returns smaller output (310ms)
✓ converts to WebP (280ms)
✓ converts to AVIF (890ms)
✓ resizes to max width (200ms)
✓ strips EXIF metadata (195ms)
✓ savings stats are mathematically correct (190ms)
✓ throws on invalid input (12ms)
Tests: 7 passed | Time: ~2.5sScripts
| Command | Description |
|---------|-------------|
| npm run build | Compile TypeScript → dist/ |
| npm run dev | Watch mode, rebuild on save |
| npm test | Run Jest test suite |
| npm test -- --coverage | Tests + coverage report |
License
MIT
