Compare commits

...

11 Commits

Author SHA1 Message Date
Lovell Fuller
e40a881ab4 Release v0.30.7 2022-06-22 16:44:16 +01:00
Lovell Fuller
c1b13adac3 Bump deps 2022-06-22 11:53:22 +01:00
Lovell Fuller
29e09898f7 Docs: add examples of custom binary locations 2022-06-22 11:50:30 +01:00
Lovell Fuller
853a20358e Install: add help for possible worker thread problem #3268 2022-06-21 08:22:05 +01:00
Lovell Fuller
8bb30d7801 Docs: changelog and credit #3261 #3267 2022-06-21 07:35:28 +01:00
Blayne Chard
a333b87f5d Prevent upsampling via libwebp (#3267) 2022-06-20 10:49:53 +01:00
AlexanderTheGrey
4662527a17 Allow WebP encoding effort of 0 (#3261) 2022-06-17 08:22:51 +01:00
Lovell Fuller
b10d8f89ca Docs: add example of multi-arch within same install tree 2022-06-10 12:51:44 +01:00
Oleg Andreyev
f903e1465e Docs: clarify wording of resize background option 2022-06-08 12:56:29 +01:00
Lovell Fuller
a75718565c Ensure composite can tile with outside resize #3227 2022-06-08 12:39:00 +01:00
Fonger
4d82331bf6 docs(input): correct getNormalSize with EXIF orientation example (#3241) 2022-05-31 08:59:15 +01:00
14 changed files with 112 additions and 16 deletions

View File

@@ -69,7 +69,7 @@ image
const size = getNormalSize(await sharp(input).metadata());
function getNormalSize({ width, height, orientation }) {
return orientation || 0 >= 5
return (orientation || 0) >= 5
? { width: height, height: width }
: { width, height };
}

View File

@@ -46,7 +46,7 @@ Possible interpolation kernels are:
* `options.height` **[String][10]?** alternative means of specifying `height`. If both are present this take priority.
* `options.fit` **[String][10]** how the image should be resized to fit both provided dimensions, one of `cover`, `contain`, `fill`, `inside` or `outside`. (optional, default `'cover'`)
* `options.position` **[String][10]** position, gravity or strategy to use when `fit` is `cover` or `contain`. (optional, default `'centre'`)
* `options.background` **([String][10] | [Object][9])** background colour when using a `fit` of `contain`, parsed by the [color][11] module, defaults to black without transparency. (optional, default `{r:0,g:0,b:0,alpha:1}`)
* `options.background` **([String][10] | [Object][9])** background colour when `fit` is `contain`, parsed by the [color][11] module, defaults to black without transparency. (optional, default `{r:0,g:0,b:0,alpha:1}`)
* `options.kernel` **[String][10]** the kernel to use for image reduction. (optional, default `'lanczos3'`)
* `options.withoutEnlargement` **[Boolean][12]** do not enlarge if the width *or* height are already less than the specified dimensions, equivalent to GraphicsMagick's `>` geometry option. (optional, default `false`)
* `options.withoutReduction` **[Boolean][12]** do not reduce if the width *or* height are already greater than the specified dimensions, equivalent to GraphicsMagick's `<` geometry option. (optional, default `false`)

View File

@@ -4,6 +4,19 @@
Requires libvips v8.12.2
### v0.30.7 - 22nd June 2022
* Ensure tiled composition always works with outside resizing.
[#3227](https://github.com/lovell/sharp/issues/3227)
* Allow WebP encoding effort of 0.
[#3261](https://github.com/lovell/sharp/pull/3261)
[@AlexanderTheGrey](https://github.com/AlexanderTheGrey)
* Prevent upsampling via libwebp.
[#3267](https://github.com/lovell/sharp/pull/3267)
[@blacha](https://github.com/blacha)
### v0.30.6 - 30th May 2022
* Allow values for `limitInputPixels` larger than 32-bit.

View File

@@ -248,3 +248,9 @@ GitHub: https://github.com/ankurparihar
Name: Joona Heinikoski
GitHub: https://github.com/joonamo
Name: AlexanderTheGrey
GitHub: https://github.com/AlexanderTheGrey
Name: Blayne Chard
GitHub: https://github.com/blacha

View File

@@ -98,6 +98,14 @@ use the following flags:
npm install --arch=x64 --platform=linux --libc=glibc sharp
```
Multiple platforms and architectures can be supported within the same installation tree.
The following example for macOS installs x64 binaries then adds (via a rebuild) arm64 binaries:
```sh
npm install --platform=darwin --arch=x64 sharp
npm rebuild --platform=darwin --arch=arm64 sharp
```
## Custom libvips
To use a custom, globally-installed version of libvips instead of the provided binaries,
@@ -136,6 +144,16 @@ To install the prebuilt sharp binaries from a directory on the local filesystem,
set the `sharp_local_prebuilds` npm config option
or the `npm_config_sharp_local_prebuilds` environment variable.
URL example:
if `sharp_binary_host` is set to `https://hostname/path`
and the sharp version is `1.2.3` then the resultant URL will be
`https://hostname/path/sharp-v1.2.3-napi-v5-platform-arch.tar.gz`.
Filename example:
if `sharp_local_prebuilds` is set to `/path`
and the sharp version is `1.2.3` then the resultant filename will be
`/path/sharp-v1.2.3-napi-v5-platform-arch.tar.gz`.
### Prebuilt libvips binaries
To install the prebuilt libvips binaries from a custom URL,
@@ -146,10 +164,17 @@ To install the prebuilt libvips binaries from a directory on the local filesyste
set the `sharp_libvips_local_prebuilds` npm config option
or the `npm_config_sharp_libvips_local_prebuilds` environment variable.
The version subpath and file name are appended to these.
For example, if `sharp_libvips_binary_host` is set to `https://hostname/path`
and the libvips version is `1.2.3` then the resultant URL will be
`https://hostname/path/v1.2.3/libvips-1.2.3-platform-arch.tar.br`.
The version subpath and filename are appended to these.
URL example:
if `sharp_libvips_binary_host` is set to `https://hostname/path`
and the libvips version is `4.5.6` then the resultant URL will be
`https://hostname/path/v4.5.6/libvips-4.5.6-platform-arch.tar.br`.
Filename example:
if `sharp_libvips_local_prebuilds` is set to `/path`
and the libvips version is `4.5.6` then the resultant filename will be
`/path/v4.5.6/libvips-4.5.6-platform-arch.tar.br`.
See the Chinese mirror below for a further example.

View File

@@ -357,7 +357,7 @@ function _isStreamInput () {
* const size = getNormalSize(await sharp(input).metadata());
*
* function getNormalSize({ width, height, orientation }) {
* return orientation || 0 >= 5
* return (orientation || 0) >= 5
* ? { width: height, height: width }
* : { width, height };
* }

View File

@@ -495,7 +495,7 @@ function webp (options) {
if (is.defined(options.smartSubsample)) {
this._setBooleanOption('webpSmartSubsample', options.smartSubsample);
}
const effort = options.effort || options.reductionEffort;
const effort = is.defined(options.effort) ? options.effort : options.reductionEffort;
if (is.defined(effort)) {
if (is.integer(effort) && is.inRange(effort, 0, 6)) {
this.options.webpEffort = effort;

View File

@@ -211,7 +211,7 @@ function isRotationExpected (options) {
* @param {String} [options.height] - alternative means of specifying `height`. If both are present this take priority.
* @param {String} [options.fit='cover'] - how the image should be resized to fit both provided dimensions, one of `cover`, `contain`, `fill`, `inside` or `outside`.
* @param {String} [options.position='centre'] - position, gravity or strategy to use when `fit` is `cover` or `contain`.
* @param {String|Object} [options.background={r: 0, g: 0, b: 0, alpha: 1}] - background colour when using a `fit` of `contain`, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black without transparency.
* @param {String|Object} [options.background={r: 0, g: 0, b: 0, alpha: 1}] - background colour when `fit` is `contain`, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black without transparency.
* @param {String} [options.kernel='lanczos3'] - the kernel to use for image reduction.
* @param {Boolean} [options.withoutEnlargement=false] - do not enlarge if the width *or* height are already less than the specified dimensions, equivalent to GraphicsMagick's `>` geometry option.
* @param {Boolean} [options.withoutReduction=false] - do not reduce if the width *or* height are already greater than the specified dimensions, equivalent to GraphicsMagick's `<` geometry option.

View File

@@ -12,6 +12,9 @@ try {
help.push('- Update Homebrew: "brew update && brew upgrade vips"');
} else {
const [platform, arch] = platformAndArch.split('-');
if (platform === 'linux' && /Module did not self-register/.test(err.message)) {
help.push('- Using worker threads? See https://sharp.pixelplumbing.com/install#worker-threads');
}
help.push(
'- Install with verbose logging and look for errors: "npm install --ignore-scripts=false --foreground-scripts --verbose sharp"',
`- Install for the current ${platformAndArch} runtime: "npm install --platform=${platform} --arch=${arch} sharp"`

View File

@@ -1,7 +1,7 @@
{
"name": "sharp",
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images",
"version": "0.30.6",
"version": "0.30.7",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://github.com/lovell/sharp",
"contributors": [
@@ -131,14 +131,14 @@
"color": "^4.2.3",
"detect-libc": "^2.0.1",
"node-addon-api": "^5.0.0",
"prebuild-install": "^7.1.0",
"prebuild-install": "^7.1.1",
"semver": "^7.3.7",
"simple-get": "^4.0.1",
"tar-fs": "^2.1.1",
"tunnel-agent": "^0.6.0"
},
"devDependencies": {
"async": "^3.2.3",
"async": "^3.2.4",
"cc": "^3.0.1",
"decompress-zip": "^0.3.3",
"documentation": "^13.2.5",

View File

@@ -188,8 +188,10 @@ class PipelineWorker : public Napi::AsyncWorker {
if (jpegShrinkOnLoad > 1 && static_cast<int>(shrink) == jpegShrinkOnLoad) {
jpegShrinkOnLoad /= 2;
}
} else if (inputImageType == sharp::ImageType::WEBP ||
inputImageType == sharp::ImageType::SVG ||
} else if (inputImageType == sharp::ImageType::WEBP && shrink > 1.0) {
// Avoid upscaling via webp
scale = 1.0 / shrink;
} else if (inputImageType == sharp::ImageType::SVG ||
inputImageType == sharp::ImageType::PDF) {
scale = 1.0 / shrink;
}
@@ -607,14 +609,14 @@ class PipelineWorker : public Napi::AsyncWorker {
int across = 0;
int down = 0;
// Use gravity in overlay
if (compositeImage.width() <= baton->width) {
if (compositeImage.width() <= image.width()) {
across = static_cast<int>(ceil(static_cast<double>(image.width()) / compositeImage.width()));
// Ensure odd number of tiles across when gravity is centre, north or south
if (composite->gravity == 0 || composite->gravity == 1 || composite->gravity == 3) {
across |= 1;
}
}
if (compositeImage.height() <= baton->height) {
if (compositeImage.height() <= image.height()) {
down = static_cast<int>(ceil(static_cast<double>(image.height()) / compositeImage.height()));
// Ensure odd number of tiles down when gravity is centre, east or west
if (composite->gravity == 0 || composite->gravity == 2 || composite->gravity == 4) {

View File

@@ -420,4 +420,31 @@ describe('composite', () => {
assert.deepStrictEqual(red, { r, g, b });
});
it('Ensure tiled composition works with resized fit=outside', async () => {
const { info } = await sharp({
create: {
width: 41, height: 41, channels: 3, background: 'red'
}
})
.resize({
width: 10,
height: 40,
fit: 'outside'
})
.composite([
{
input: {
create: {
width: 16, height: 16, channels: 3, background: 'green'
}
},
tile: true
}
])
.toBuffer({ resolveWithObject: true });
assert.strictEqual(info.width, 40);
assert.strictEqual(info.height, 40);
});
});

View File

@@ -121,6 +121,20 @@ describe('Resize dimensions', function () {
});
});
it('Webp resize then extract large image', function (done) {
sharp(fixtures.inputWebP)
.resize(0x4000, 0x4000)
.extract({ top: 0x2000, left: 0x2000, width: 256, height: 256 })
.webp()
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('webp', info.format);
assert.strictEqual(256, info.width);
assert.strictEqual(256, info.height);
done();
});
});
it('WebP shrink-on-load rounds to zero, ensure recalculation is correct', function (done) {
sharp(fixtures.inputJpg)
.resize(1080, 607)

View File

@@ -133,6 +133,12 @@ describe('WebP', function () {
});
});
it('should set effort to 0', () => {
const effort = sharp().webp({ effort: 0 }).options.webpEffort;
assert.strictEqual(effort, 0);
});
it('invalid loop throws', () => {
assert.throws(() => {
sharp().webp({ loop: -1 });