sharp-watch
Resize images in folder recursively using sharp.
This project was developed to resize all images in a given folder (recursively) to create optimized assets.
Features
- Super simple to use
- Uses trusted dependencies (chokidar, commander, sharp, etc…)
- Written in TypeScript
Installation
npm install sharp-watch -g
Usage
$ sharp-watch -h
Usage: sharp-watch [options]
Options:
--src <source> path to image folder
--filter <filter> filter used to select which image formats will be resized (choices: "dz", "fits", "gif", "heif", "jp2k", "jpeg", "jpg", "magick", "openslide", "pdf", "png", "ppm", "raw", "svg", "tiff", "vips", "webp", default: "gif,jpeg,jpg,png,webp")
--formats <formats> formats at which images will be transcoded (choices: "dz", "fits", "gif", "heif", "jp2k", "jpeg", "magick", "openslide", "original", "pdf", "png", "ppm", "raw", "svg", "tiff", "vips", "webp", default: "original,webp")
--quality <quality> quality at which images will be transcoded (default: "80")
--sizes <sizes> sizes at which images will be resized (example: 640x360,1280x720,1920x1080)
--without-enlargement do not enlarge images
--fit <fit> fit at which images will be resized (choices: "contain", "cover", "fill", "inside", "outside", default: "outside")
--dest <destination> path to resized image folder (default: source)
--content-hash append content hash to filenames
--manifest generate resized image manifest
--manifest-dest <destination> path to resized image manifest file (default: source/manifest.json)
--blurhash compute image blurhash
--purge purge resized image folder
--watch watch source for changes
--verbose show more debug info
--yes skip confirmation prompt
-h, --help display help for command
For CRA projects, consider using concurrently to run both start
and sharp
scripts concurrently using npm run code
.
{
"scripts": {
"start": "react-scripts start",
"sharp": "sharp-watch --src example --sizes 640x360,1280x720,1920x1080 --without-enlargement --dest example-resized --content-hash --manifest --blurhash --watch",
"code": "concurrently -n start,sharp npm:start npm:sharp"
}
}
Notice the --watch
argument? This runs sharp-watch
in the background, resizing and deleting images as they are created, updated and deleted.
Example
In following example, we resize and transcode images in example to jpeg
format and save processed images to example-resized.
$ pwd
/Users/sunknudsen/Code/sunknudsen/sharp-watch
$ tree example
example
├── eberhard-grossgasteiger-S-2Ukb_VqpA-unsplash.jpg
├── foo
│ ├── bar
│ │ └── courtney-read-EWhLexezAkA-unsplash.jpg
│ └── michael-james-IEbeDBPeIfs-unsplash.jpg
└── jonathan-gallegos-PgHc0Ka1E0A-unsplash.png
$ sharp-watch --src example --sizes 640x360,1280x720,1920x1080 --without-enlargement --dest example-resized --content-hash --manifest --blurhash --purge
Purging /Users/sunknudsen/Code/sunknudsen/sharp-watch/example-resized…
? Do you wish to proceed? Yes
Purged /Users/sunknudsen/Code/sunknudsen/sharp-watch/example-resized successfully!
Resizing images…
Resized images successfully!
$ tree example-resized
example-resized
├── eberhard-grossgasteiger-S-2Ukb_VqpA-unsplash-1280x720.024d5921de3383d0ec63.webp
├── eberhard-grossgasteiger-S-2Ukb_VqpA-unsplash-1280x720.764bf8f7c411200b94a8.jpg
├── eberhard-grossgasteiger-S-2Ukb_VqpA-unsplash-1920x1080.eda37c05a6c8d575f33f.webp
├── eberhard-grossgasteiger-S-2Ukb_VqpA-unsplash-1920x1080.ff4b2c42b4ab8181f846.jpg
├── eberhard-grossgasteiger-S-2Ukb_VqpA-unsplash-640x360.b1a3c4af32658dca13f6.jpg
├── eberhard-grossgasteiger-S-2Ukb_VqpA-unsplash-640x360.d55c37270a6630c31ae3.webp
├── foo
│ ├── bar
│ │ ├── courtney-read-EWhLexezAkA-unsplash-1280x720.0182e03090d84739634d.jpg
│ │ ├── courtney-read-EWhLexezAkA-unsplash-1280x720.185d2c369db4d3051154.webp
│ │ ├── courtney-read-EWhLexezAkA-unsplash-1920x1080.0a896278fb87d46c5060.webp
│ │ ├── courtney-read-EWhLexezAkA-unsplash-1920x1080.1813ea4bbc4a5178f31b.jpg
│ │ ├── courtney-read-EWhLexezAkA-unsplash-640x360.0c44b2bc2e7904721253.jpg
│ │ └── courtney-read-EWhLexezAkA-unsplash-640x360.d8a863bfeb13812ab289.webp
│ ├── michael-james-IEbeDBPeIfs-unsplash-1280x720.01a0a018abc420281e72.webp
│ ├── michael-james-IEbeDBPeIfs-unsplash-1280x720.a67a3f980b2a4bf09556.jpg
│ ├── michael-james-IEbeDBPeIfs-unsplash-1920x1080.446313fac859ec926beb.jpg
│ ├── michael-james-IEbeDBPeIfs-unsplash-1920x1080.4ef88eddbf951403156a.webp
│ ├── michael-james-IEbeDBPeIfs-unsplash-640x360.5d99c373311a70f9b37c.jpg
│ └── michael-james-IEbeDBPeIfs-unsplash-640x360.8fef4b3fab81f7acc5e1.webp
├── jonathan-gallegos-PgHc0Ka1E0A-unsplash-1280x720.30b24c3a9c5b255d1b2d.png
├── jonathan-gallegos-PgHc0Ka1E0A-unsplash-1280x720.75345407c731ec20a987.webp
├── jonathan-gallegos-PgHc0Ka1E0A-unsplash-1920x1080.30b24c3a9c5b255d1b2d.png
├── jonathan-gallegos-PgHc0Ka1E0A-unsplash-1920x1080.75345407c731ec20a987.webp
├── jonathan-gallegos-PgHc0Ka1E0A-unsplash-640x360.098985870db8063a735c.png
└── jonathan-gallegos-PgHc0Ka1E0A-unsplash-640x360.f153b5a506a5b1e8dbd6.webp
$ cat example/manifest.json
{
"eberhard-grossgasteiger-S-2Ukb_VqpA-unsplash.jpg": {
"original": {
"640x360": {
"width": 640,
"height": 960,
"ratio": 0.6666666666666666,
"fileSize": 28096,
"mediaType": "image/jpeg",
"color": "#f8d8d8",
"contentHash": "b1a3c4af32658dca13f6",
"blurhash": "UjQu:9}[RP%2{1J7ayniODW;s:WVxaoLbbkC"
},
"1280x720": {
"width": 1280,
"height": 1920,
"ratio": 0.6666666666666666,
"fileSize": 93277,
"mediaType": "image/jpeg",
"color": "#f8d8d8",
"contentHash": "764bf8f7c411200b94a8",
"blurhash": "UiQu:9}[M{%2{1J7ayniODW;s:WVxaoLbbkC"
},
"1920x1080": {
"width": 1920,
"height": 2880,
"ratio": 0.6666666666666666,
"fileSize": 219572,
"mediaType": "image/jpeg",
"color": "#f8d8d8",
"contentHash": "ff4b2c42b4ab8181f846",
"blurhash": "UiQu:9}[M{%2{1J7ayniODW;s:WVxaoLbbkC"
}
},
"webp": {
"640x360": {
"width": 640,
"height": 960,
"ratio": 0.6666666666666666,
"fileSize": 10648,
"mediaType": "image/webp",
"color": "#f8d8d8",
"contentHash": "d55c37270a6630c31ae3",
"blurhash": "UjQu:9}[RP%2{1J7ayniODW;s:WVxaoLbbkC"
},
"1280x720": {
"width": 1280,
"height": 1920,
"ratio": 0.6666666666666666,
"fileSize": 30936,
"mediaType": "image/webp",
"color": "#f8d8d8",
"contentHash": "024d5921de3383d0ec63",
"blurhash": "UiQu:9}[M{%2{1J7ayniODW;s:WVxaoLbbkC"
},
"1920x1080": {
"width": 1920,
"height": 2880,
"ratio": 0.6666666666666666,
"fileSize": 64654,
"mediaType": "image/webp",
"color": "#f8d8d8",
"contentHash": "eda37c05a6c8d575f33f",
"blurhash": "UiQu:9}[M{%2{1J7ayniODW;s:WVxaoLbbkC"
}
}
},
"jonathan-gallegos-PgHc0Ka1E0A-unsplash.png": {
"original": {
"640x360": {
"width": 640,
"height": 895,
"ratio": 0.7150837988826816,
"fileSize": 771840,
"mediaType": "image/png",
"color": "#080808",
"contentHash": "098985870db8063a735c",
"blurhash": "U^HL_6RPaet8_NjsayofxutRkCWBt7kCfkae"
},
"1280x720": {
"width": 915,
"height": 1280,
"ratio": 0.71484375,
"fileSize": 1522262,
"mediaType": "image/png",
"color": "#080808",
"contentHash": "30b24c3a9c5b255d1b2d",
"blurhash": "U_HL}DRPaet8_NjsayofxutRkCWBt7kCfkae"
},
"1920x1080": {
"width": 915,
"height": 1280,
"ratio": 0.71484375,
"fileSize": 1522262,
"mediaType": "image/png",
"color": "#080808",
"contentHash": "30b24c3a9c5b255d1b2d",
"blurhash": "U_HL}DRPaet8_NjsayofxutRkCWBt7kCfkae"
}
},
"webp": {
"640x360": {
"width": 640,
"height": 895,
"ratio": 0.7150837988826816,
"fileSize": 36066,
"mediaType": "image/webp",
"color": "#080808",
"contentHash": "f153b5a506a5b1e8dbd6",
"blurhash": "U^HL_6RPaet8_NjsayofxutRkCWBt7kCfkae"
},
"1280x720": {
"width": 915,
"height": 1280,
"ratio": 0.71484375,
"fileSize": 72308,
"mediaType": "image/webp",
"color": "#080808",
"contentHash": "75345407c731ec20a987",
"blurhash": "U_HL}DRPaet8_NjsayofxutRkCWBt7kCfkae"
},
"1920x1080": {
"width": 915,
"height": 1280,
"ratio": 0.71484375,
"fileSize": 72308,
"mediaType": "image/webp",
"color": "#080808",
"contentHash": "75345407c731ec20a987",
"blurhash": "U_HL}DRPaet8_NjsayofxutRkCWBt7kCfkae"
}
}
},
"foo/michael-james-IEbeDBPeIfs-unsplash.jpg": {
"original": {
"640x360": {
"width": 640,
"height": 395,
"ratio": 1.620253164556962,
"fileSize": 49290,
"mediaType": "image/jpeg",
"color": "#282828",
"contentHash": "5d99c373311a70f9b37c",
"blurhash": "UhEW2WxuRPof_Nofaxof~qt7jZof_Nt7jZof"
},
"1280x720": {
"width": 1280,
"height": 791,
"ratio": 1.618204804045512,
"fileSize": 187341,
"mediaType": "image/jpeg",
"color": "#282828",
"contentHash": "a67a3f980b2a4bf09556",
"blurhash": "UgEC^1xuM{kB_4ofWBof~qt7aeof_Nt7aeof"
},
"1920x1080": {
"width": 1920,
"height": 1186,
"ratio": 1.6188870151770658,
"fileSize": 430782,
"mediaType": "image/jpeg",
"color": "#282828",
"contentHash": "446313fac859ec926beb",
"blurhash": "UgEC^1xuM{kB_4ofWBof~qt7aeof_Nt7aeof"
}
},
"webp": {
"640x360": {
"width": 640,
"height": 395,
"ratio": 1.620253164556962,
"fileSize": 40602,
"mediaType": "image/webp",
"color": "#282828",
"contentHash": "8fef4b3fab81f7acc5e1",
"blurhash": "UhEW2WxuRPof_Nofaxof~qt7jZof_Nt7jZof"
},
"1280x720": {
"width": 1280,
"height": 791,
"ratio": 1.618204804045512,
"fileSize": 155714,
"mediaType": "image/webp",
"color": "#282828",
"contentHash": "01a0a018abc420281e72",
"blurhash": "UgEC^1xuM{kB_4ofWBof~qt7aeof_Nt7aeof"
},
"1920x1080": {
"width": 1920,
"height": 1186,
"ratio": 1.6188870151770658,
"fileSize": 364550,
"mediaType": "image/webp",
"color": "#282828",
"contentHash": "4ef88eddbf951403156a",
"blurhash": "UgEC^1xuM{kB_4ofWBof~qt7aeof_Nt7aeof"
}
}
},
"foo/bar/courtney-read-EWhLexezAkA-unsplash.jpg": {
"original": {
"640x360": {
"width": 640,
"height": 400,
"ratio": 1.6,
"fileSize": 49464,
"mediaType": "image/jpeg",
"color": "#282828",
"contentHash": "0c44b2bc2e7904721253",
"blurhash": "U:F6e3oza#oz_4ogWVof-;kCWBoft7j[WBj["
},
"1280x720": {
"width": 1280,
"height": 800,
"ratio": 1.6,
"fileSize": 188579,
"mediaType": "image/jpeg",
"color": "#282828",
"contentHash": "0182e03090d84739634d",
"blurhash": "U:E{^Toga#oz_4ofWVof-;j]WBofxtj@WBj["
},
"1920x1080": {
"width": 1920,
"height": 1200,
"ratio": 1.6,
"fileSize": 387692,
"mediaType": "image/jpeg",
"color": "#282828",
"contentHash": "1813ea4bbc4a5178f31b",
"blurhash": "U:E{^Toga#oz_4ofWVof-;j]WBofxtj@WBj["
}
},
"webp": {
"640x360": {
"width": 640,
"height": 400,
"ratio": 1.6,
"fileSize": 40724,
"mediaType": "image/webp",
"color": "#282828",
"contentHash": "d8a863bfeb13812ab289",
"blurhash": "U:F6e3oza#oz_4ogWVof-;kCWBoft7j[WBj["
},
"1280x720": {
"width": 1280,
"height": 800,
"ratio": 1.6,
"fileSize": 154220,
"mediaType": "image/webp",
"color": "#282828",
"contentHash": "185d2c369db4d3051154",
"blurhash": "U:E{^Toga#oz_4ofWVof-;j]WBofxtj@WBj["
},
"1920x1080": {
"width": 1920,
"height": 1200,
"ratio": 1.6,
"fileSize": 305408,
"mediaType": "image/webp",
"color": "#282828",
"contentHash": "0a896278fb87d46c5060",
"blurhash": "U:E{^Toga#oz_4ofWVof-;j]WBofxtj@WBj["
}
}
}
}
Contributors
Licence
MIT