Compare commits

..

21 Commits

Author SHA1 Message Date
Lovell Fuller
c4c43d525b Release v0.26.1 2020-09-20 09:29:50 +01:00
Lovell Fuller
6c5cde363a Ensure animated GIF output is optimised #2376 2020-09-19 20:53:15 +01:00
Lovell Fuller
d46b4d950f Allow spaces in installation directory #2279
Uses new include_dir property of node-addon-api
2020-09-19 14:26:30 +01:00
Lovell Fuller
b369c4bb8a Ensure stats can be calculated for 1x1 input #2372 2020-09-17 11:08:52 +01:00
Lovell Fuller
c3898487c4 CI: name the FreeBSD task 2020-09-17 11:02:16 +01:00
Lovell Fuller
ca3c5b400f CI: install ARM64 nodejs package with dependency on python3-minimal
Node.js 14 will work but 10 and 12 will fail until
https://github.com/nodesource/distributions/issues/1100 is fixed
2020-09-15 19:21:32 +01:00
Lovell Fuller
97772b176c Docs: changelog entry for #2369 2020-09-15 18:05:22 +01:00
AcrylicShrimp
08a2965f1c Ensure animation-related properties work with stream-based input 2020-09-15 15:12:26 +01:00
Lovell Fuller
76dcddfa3d Changelog, credit, doc update for #2348 2020-09-02 09:06:15 +01:00
stefanprobst
79f476ae4d Allow input density range up to 100000 DPI (#2348) 2020-09-02 08:56:12 +01:00
Lovell Fuller
d406cb619c Improve error messaging for unsupported Node.js versions 2020-08-28 21:39:11 +01:00
Lovell Fuller
4f3890f1e4 Issue template: ask about installation architecture and platform 2020-08-28 13:59:44 +01:00
Lovell Fuller
7a9d58cc51 Docs: changelog entry for #2343 2020-08-28 13:56:35 +01:00
Lovell Fuller
eef87da0e1 Docs: CSP allow inline JS 2020-08-28 13:53:19 +01:00
Denis Soldatov
00e65f6f14 Ensure correct pageHeight when verifying image dimensions (#2343) 2020-08-28 13:39:19 +01:00
Lovell Fuller
866e9824d1 Release v0.26.0 2020-08-25 18:42:06 +01:00
Lovell Fuller
482e6078e2 Tests: Update leak suppressions for librsvg static data 2020-08-25 18:40:12 +01:00
Lovell Fuller
bc7ab296ef Tests: Update leak suppressions for static libs 2020-08-24 21:10:20 +01:00
Lovell Fuller
a5f4f53b56 Tests: remove no-longer-used conditional assertions 2020-08-23 20:11:23 +01:00
Lovell Fuller
b1227f526d Verify minimum libvips version at compile time 2020-08-23 20:10:27 +01:00
Lovell Fuller
78b42c8306 Docs: update performance test results 2020-08-23 16:48:46 +01:00
30 changed files with 218 additions and 55 deletions

View File

@@ -2,6 +2,7 @@ freebsd_instance:
image_family: freebsd-13-0-snap
task:
name: FreeBSD 13.0
env:
IGNORE_OSVERSION: yes
prerequisites_script:

View File

@@ -42,10 +42,6 @@ You deserve to add your details to the [list of contributors](https://github.com
Any change that modifies the existing public API should be added to the relevant work-in-progress branch for inclusion in the next major release.
| Release | WIP branch |
| ------: | :--------- |
| v0.26.0 | zoom |
Please squash your changes into a single commit using a command like `git rebase -i upstream/<wip-branch>`.
### Add a new public method

View File

@@ -7,7 +7,7 @@ labels: installation
Did you see the [documentation relating to installation](https://sharp.pixelplumbing.com/install)?
Have you ensured the platform and version of Node.js used for `npm install` is the same as the platform and version of Node.js used at runtime?
Have you ensured the architecture and platform of Node.js used for `npm install` is the same as the architecture and platform of Node.js used at runtime?
Are you using the latest version? Is the version currently in use as reported by `npm ls sharp` the same as the latest version as reported by `npm view sharp dist-tags.latest`?

View File

@@ -72,7 +72,7 @@ jobs:
- sudo docker run -dit --name sharp --env CI --env TRAVIS_TAG --env prebuild_upload --volume "${PWD}:/mnt/sharp" --workdir /mnt/sharp arm64v8/debian:bullseye
- sudo docker exec sharp sh -c "apt-get update && apt-get install -y build-essential git python2 curl"
- sudo docker exec sharp sh -c "curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add -"
- sudo docker exec sharp sh -c "echo 'deb https://deb.nodesource.com/node_10.x buster main' >/etc/apt/sources.list.d/nodesource.list"
- sudo docker exec sharp sh -c "echo 'deb https://deb.nodesource.com/node_10.x sid main' >/etc/apt/sources.list.d/nodesource.list"
- sudo docker exec sharp sh -c "apt-get update && apt-get install -y nodejs=10.*"
install: sudo docker exec sharp sh -c "npm install --unsafe-perm"
script: sudo docker exec sharp sh -c "npm test"
@@ -86,7 +86,7 @@ jobs:
- sudo docker run -dit --name sharp --env CI --volume "${PWD}:/mnt/sharp" --workdir /mnt/sharp arm64v8/debian:bullseye
- sudo docker exec sharp sh -c "apt-get update && apt-get install -y build-essential git python2 curl"
- sudo docker exec sharp sh -c "curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add -"
- sudo docker exec sharp sh -c "echo 'deb https://deb.nodesource.com/node_12.x buster main' >/etc/apt/sources.list.d/nodesource.list"
- sudo docker exec sharp sh -c "echo 'deb https://deb.nodesource.com/node_12.x sid main' >/etc/apt/sources.list.d/nodesource.list"
- sudo docker exec sharp sh -c "apt-get update && apt-get install -y nodejs"
install: sudo docker exec sharp sh -c "npm install --unsafe-perm"
script: sudo docker exec sharp sh -c "npm test"
@@ -100,7 +100,7 @@ jobs:
- sudo docker run -dit --name sharp --env CI --volume "${PWD}:/mnt/sharp" --workdir /mnt/sharp arm64v8/debian:bullseye
- sudo docker exec sharp sh -c "apt-get update && apt-get install -y build-essential git python2 curl"
- sudo docker exec sharp sh -c "curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add -"
- sudo docker exec sharp sh -c "echo 'deb https://deb.nodesource.com/node_14.x buster main' >/etc/apt/sources.list.d/nodesource.list"
- sudo docker exec sharp sh -c "echo 'deb https://deb.nodesource.com/node_14.x sid main' >/etc/apt/sources.list.d/nodesource.list"
- sudo docker exec sharp sh -c "apt-get update && apt-get install -y nodejs"
install: sudo docker exec sharp sh -c "npm install --unsafe-perm"
script: sudo docker exec sharp sh -c "npm test"

View File

@@ -95,7 +95,7 @@
'src/sharp.cc'
],
'include_dirs': [
'<!@(node -p "require(\'node-addon-api\').include")',
'<!(node -p "require(\'node-addon-api\').include_dir")',
],
'conditions': [
['use_global_libvips == "true"', {

View File

@@ -25,7 +25,7 @@ Implements the [stream.Duplex][1] class.
An integral Number of pixels, zero or false to remove limit, true to use default limit of 268402689 (0x3FFF x 0x3FFF). (optional, default `268402689`)
- `options.sequentialRead` **[boolean][5]** Set this to `true` to use sequential rather than random access where possible.
This can reduce memory usage and might improve performance on some systems. (optional, default `false`)
- `options.density` **[number][6]** number representing the DPI for vector images. (optional, default `72`)
- `options.density` **[number][6]** number representing the DPI for vector images in the range 1 to 100000. (optional, default `72`)
- `options.pages` **[number][6]** number of pages to extract for multi-page input (GIF, TIFF, PDF), use -1 for all pages. (optional, default `1`)
- `options.page` **[number][6]** page number to start extracting from for multi-page input (GIF, TIFF, PDF), zero based. (optional, default `0`)
- `options.level` **[number][6]** level to extract from a multi-level input (OpenSlide), zero based. (optional, default `0`)

View File

@@ -4,7 +4,27 @@
Requires libvips v8.10.0
### v0.26.0 - TBD
### v0.26.1 - 20th September 2020
* Ensure correct pageHeight when verifying multi-page image dimensions.
[#2343](https://github.com/lovell/sharp/pull/2343)
[@derom](https://github.com/derom)
* Allow input density range up to 100000 DPI.
[#2348](https://github.com/lovell/sharp/pull/2348)
[@stefanprobst](https://github.com/stefanprobst)
* Ensure animation-related properties can be set for Stream-based input.
[#2369](https://github.com/lovell/sharp/pull/2369)
[@AcrylicShrimp](https://github.com/AcrylicShrimp)
* Ensure `stats` can be calculated for 1x1 input.
[#2372](https://github.com/lovell/sharp/issues/2372)
* Ensure animated GIF output is optimised.
[#2376](https://github.com/lovell/sharp/issues/2376)
### v0.26.0 - 25th August 2020
* Prebuilt libvips binaries are now statically-linked and Brotli-compressed, requiring Node.js 10.16.0+.

View File

@@ -197,3 +197,9 @@ GitHub: https://github.com/deftomat
Name: Robert O'Rourke
GitHub: https://github.com/roborourke
Name: Denis Soldatov
GitHub: https://github.com/derom
Name: Stefan Probst
GitHub: https://github.com/stefanprobst

View File

@@ -8,7 +8,7 @@
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; object-src 'none'; style-src 'unsafe-inline';
img-src 'unsafe-inline' data: https://pixel.plumbing/px/ https://cdn.jsdelivr.net/gh/lovell/ https://www.google-analytics.com;
connect-src 'self' https://cdn.jsdelivr.net/gh/lovell/ https://www.google-analytics.com;
script-src 'sha256-iXDHv+t2aGdJcmEvwHfqmGH4SrOSx+P8rCF6+WLLwXA=' 'unsafe-eval'
script-src 'unsafe-inline' 'unsafe-eval'
https://cdn.jsdelivr.net/npm/docute@4/dist/docute.min.js
https://www.google-analytics.com/analytics.js;">
<link rel="icon" type="image/png" href="https://pixel.plumbing/px/32x32/sharp-logo.svg">
@@ -19,7 +19,7 @@
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="https://pixel.plumbing/px/72x72/sharp-logo.svg">
<link rel="apple-touch-icon-precomposed" href="https://pixel.plumbing/px/57x57/sharp-logo.svg">
<link rel="author" href="/humans.txt" type="text/plain">
<link rel="preload" href="https://cdn.jsdelivr.net/gh/lovell/sharp@v0.25.4/docs/README.md" as="fetch" type="text/markdown" crossorigin>
<link rel="preload" href="https://cdn.jsdelivr.net/gh/lovell/sharp@v0.26.1/docs/README.md" as="fetch" type="text/markdown" crossorigin>
<link rel="preload" href="https://cdn.jsdelivr.net/gh/lovell/sharp@master/docs/image/sharp-logo.svg" as="image" type="image/svg+xml" crossorigin>
<link rel="dns-prefetch" href="https://pixel.plumbing">
<link rel="dns-prefetch" href="https://www.google-analytics.com">
@@ -139,7 +139,7 @@
docuteApiTitlePlugin,
docuteApiSearchPlugin
],
sourcePath: 'https://cdn.jsdelivr.net/gh/lovell/sharp@v0.25.4/docs',
sourcePath: 'https://cdn.jsdelivr.net/gh/lovell/sharp@v0.26.1/docs',
nav: [
{
title: 'Funding',

View File

@@ -4,11 +4,11 @@ A test to benchmark the performance of this module relative to alternatives.
## The contenders
* [jimp](https://www.npmjs.com/package/jimp) v0.9.3 - Image processing in pure JavaScript. Provides bicubic interpolation.
* [mapnik](https://www.npmjs.org/package/mapnik) v4.3.1 - Whilst primarily a map renderer, Mapnik contains bitmap image utilities.
* [jimp](https://www.npmjs.com/package/jimp) v0.16.0 - Image processing in pure JavaScript. Provides bicubic interpolation.
* [mapnik](https://www.npmjs.org/package/mapnik) v4.5.2 - Whilst primarily a map renderer, Mapnik contains bitmap image utilities.
* [imagemagick](https://www.npmjs.com/package/imagemagick) v0.1.3 - Supports filesystem only and "*has been unmaintained for a long time*".
* [gm](https://www.npmjs.com/package/gm) v1.23.1 - Fully featured wrapper around GraphicsMagick's `gm` command line utility.
* sharp v0.24.0 / libvips v8.9.0 - Caching within libvips disabled to ensure a fair comparison.
* sharp v0.26.0 / libvips v8.10.0 - Caching within libvips disabled to ensure a fair comparison.
## The task
@@ -18,25 +18,25 @@ then compress to JPEG at a "quality" setting of 80.
## Test environment
* AWS EC2 eu-west-1 [c5.large](https://aws.amazon.com/ec2/instance-types/c5/) (2x Xeon Platinum 8124M CPU @ 3.00GHz)
* Ubuntu 18.04 (hvm-ssd/ubuntu-bionic-18.04-amd64-server-20180912 ami-00035f41c82244dab)
* Node.js v12.14.1
* AWS EC2 eu-west-1 [c5d.large](https://aws.amazon.com/ec2/instance-types/c5/) (2x Xeon Platinum 8124M CPU @ 3.00GHz)
* Ubuntu 20.04 (ami-0f1d11c92a9467c07)
* Node.js v14.8.0
## Results
| Module | Input | Output | Ops/sec | Speed-up |
| :----------------- | :----- | :----- | ------: | -------: |
| jimp | buffer | buffer | 0.72 | 1.0 |
| mapnik | buffer | buffer | 3.02 | 4.2 |
| gm | buffer | buffer | 3.90 | 5.4 |
| gm | file | file | 3.94 | 5.5 |
| imagemagick | file | file | 4.30 | 6.0 |
| sharp | stream | stream | 23.65 | 32.8 |
| sharp | file | file | 24.66 | 34.3 |
| sharp | buffer | buffer | 25.14 | 34.9 |
| jimp | buffer | buffer | 0.75 | 1.0 |
| mapnik | buffer | buffer | 3.00 | 4.0 |
| gm | buffer | buffer | 4.12 | 5.5 |
| gm | file | file | 4.13 | 5.5 |
| imagemagick | file | file | 4.30 | 5.7 |
| sharp | stream | stream | 22.37 | 29.8 |
| sharp | file | file | 23.40 | 31.2 |
| sharp | buffer | buffer | 24.01 | 32.0 |
Greater libvips performance can be expected with caching enabled (default)
and using 8+ core machines, especially those with larger L1/L2 CPU caches.
and using 4+ core machines, especially those with larger L1/L2 CPU caches.
The I/O limits of the relevant (de)compression library will generally determine maximum throughput.

View File

@@ -80,6 +80,9 @@ try {
throw new Error(`Use with glibc ${detectLibc.version} requires manual installation of libvips >= ${minimumLibvipsVersion}`);
}
}
if (!semver.satisfies(process.versions.node, process.env.npm_package_engines_node)) {
throw new Error(`Expected Node.js version ${process.env.npm_package_engines_node} but found ${process.versions.node}`);
}
// Download to per-process temporary file
const tarFilename = ['libvips', minimumLibvipsVersion, platformAndArch].join('-') + '.tar.br';
const tarPathCache = path.join(libvips.cachePath(), tarFilename);

View File

@@ -102,7 +102,7 @@ const debuglog = util.debuglog('sharp');
* An integral Number of pixels, zero or false to remove limit, true to use default limit of 268402689 (0x3FFF x 0x3FFF).
* @param {boolean} [options.sequentialRead=false] - Set this to `true` to use sequential rather than random access where possible.
* This can reduce memory usage and might improve performance on some systems.
* @param {number} [options.density=72] - number representing the DPI for vector images.
* @param {number} [options.density=72] - number representing the DPI for vector images in the range 1 to 100000.
* @param {number} [options.pages=1] - number of pages to extract for multi-page input (GIF, TIFF, PDF), use -1 for all pages.
* @param {number} [options.page=0] - page number to start extracting from for multi-page input (GIF, TIFF, PDF), zero based.
* @param {number} [options.level=0] - level to extract from a multi-level input (OpenSlide), zero based.

View File

@@ -9,9 +9,9 @@ const sharp = require('../build/Release/sharp.node');
* @private
*/
function _inputOptionsFromObject (obj) {
const { raw, density, limitInputPixels, sequentialRead, failOnError } = obj;
return [raw, density, limitInputPixels, sequentialRead, failOnError].some(is.defined)
? { raw, density, limitInputPixels, sequentialRead, failOnError }
const { raw, density, limitInputPixels, sequentialRead, failOnError, animated, page, pages } = obj;
return [raw, density, limitInputPixels, sequentialRead, failOnError, animated, page, pages].some(is.defined)
? { raw, density, limitInputPixels, sequentialRead, failOnError, animated, page, pages }
: undefined;
}
@@ -57,10 +57,10 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
}
// Density
if (is.defined(inputOptions.density)) {
if (is.inRange(inputOptions.density, 1, 2400)) {
if (is.inRange(inputOptions.density, 1, 100000)) {
inputDescriptor.density = inputOptions.density;
} else {
throw is.invalidParameterError('density', 'number between 1 and 2400', inputOptions.density);
throw is.invalidParameterError('density', 'number between 1 and 100000', inputOptions.density);
}
}
// limitInputPixels

View File

@@ -1,7 +1,7 @@
{
"name": "sharp",
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP and TIFF images",
"version": "0.26.0-beta1",
"version": "0.26.1",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://github.com/lovell/sharp",
"contributors": [
@@ -114,7 +114,7 @@
"dependencies": {
"color": "^3.1.2",
"detect-libc": "^1.0.3",
"node-addon-api": "^3.0.0",
"node-addon-api": "^3.0.2",
"npmlog": "^4.1.2",
"prebuild-install": "^5.3.5",
"semver": "^7.3.2",

View File

@@ -485,8 +485,8 @@ namespace sharp {
Check the proposed format supports the current dimensions.
*/
void AssertImageTypeDimensions(VImage image, ImageType const imageType) {
const int height = image.get_typeof("pageHeight") == G_TYPE_INT
? image.get_int("pageHeight")
const int height = image.get_typeof(VIPS_META_PAGE_HEIGHT) == G_TYPE_INT
? image.get_int(VIPS_META_PAGE_HEIGHT)
: image.height();
if (imageType == ImageType::JPEG) {
if (image.width() > 65535 || height > 65535) {

View File

@@ -24,8 +24,8 @@
// Verify platform and compiler compatibility
#if (VIPS_MAJOR_VERSION < 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 9))
#error "libvips version 8.9.2+ is required - please see https://sharp.pixelplumbing.com/install"
#if (VIPS_MAJOR_VERSION < 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 10))
#error "libvips version 8.10.0+ is required - please see https://sharp.pixelplumbing.com/install"
#endif
#if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))

View File

@@ -782,6 +782,8 @@ class PipelineWorker : public Napi::AsyncWorker {
sharp::AssertImageTypeDimensions(image, sharp::ImageType::GIF);
VipsArea *area = VIPS_AREA(image.magicksave_buffer(VImage::option()
->set("strip", !baton->withMetadata)
->set("optimize_gif_frames", TRUE)
->set("optimize_gif_transparency", TRUE)
->set("format", "gif")));
baton->bufferOut = static_cast<char*>(area->data);
baton->bufferOutLength = area->length;
@@ -925,6 +927,8 @@ class PipelineWorker : public Napi::AsyncWorker {
sharp::AssertImageTypeDimensions(image, sharp::ImageType::GIF);
image.magicksave(const_cast<char*>(baton->fileOut.data()), VImage::option()
->set("strip", !baton->withMetadata)
->set("optimize_gif_frames", TRUE)
->set("optimize_gif_transparency", TRUE)
->set("format", "gif"));
baton->formatOut = "gif";
} else if (baton->formatOut == "tiff" || (mightMatchInput && isTiff) ||

View File

@@ -80,12 +80,14 @@ class StatsWorker : public Napi::AsyncWorker {
// Estimate entropy via histogram of greyscale value frequency
baton->entropy = std::abs(greyscale.hist_find().hist_entropy());
// Estimate sharpness via standard deviation of greyscale laplacian
VImage laplacian = VImage::new_matrixv(3, 3,
0.0, 1.0, 0.0,
1.0, -4.0, 1.0,
0.0, 1.0, 0.0);
laplacian.set("scale", 9.0);
baton->sharpness = greyscale.conv(laplacian).deviate();
if (image.width() > 1 || image.height() > 1) {
VImage laplacian = VImage::new_matrixv(3, 3,
0.0, 1.0, 0.0,
1.0, -4.0, 1.0,
0.0, 1.0, 0.0);
laplacian.set("scale", 9.0);
baton->sharpness = greyscale.conv(laplacian).deviate();
}
// Most dominant sRGB colour via 4096-bin 3D histogram
vips::VImage hist = sharp::RemoveAlpha(image)
.colourspace(VIPS_INTERPRETATION_sRGB)

BIN
test/fixtures/big-height.webp vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

3
test/fixtures/circle.svg vendored Normal file
View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 8 8">
<circle r="3.75" cx="4" cy="4" fill="deeppink" />
</svg>

After

Width:  |  Height:  |  Size: 122 B

BIN
test/fixtures/expected/circle.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -95,6 +95,7 @@ module.exports = {
inputWebPWithTransparency: getPath('5_webp_a.webp'), // http://www.gstatic.com/webp/gallery3/5_webp_a.webp
inputWebPAnimated: getPath('rotating-squares.webp'), // http://www.gstatic.com/webp/gallery3/5_webp_a.webp
inputWebPAnimatedLoop3: getPath('animated-loop-3.webp'), // http://www.gstatic.com/webp/gallery3/5_webp_a.webp
inputWebPAnimatedBigHeight: getPath('big-height.webp'),
inputTiff: getPath('G31D.TIF'), // http://www.fileformat.info/format/tiff/sample/e6c9a6e5253348f4aef6d17b534360ab/index.htm
inputTiffMultipage: getPath('G31D_MULTI.TIF'), // gm convert G31D.TIF -resize 50% G31D_2.TIF ; tiffcp G31D.TIF G31D_2.TIF G31D_MULTI.TIF
inputTiffCielab: getPath('cielab-dagams.tiff'), // https://github.com/lovell/sharp/issues/646
@@ -106,6 +107,7 @@ module.exports = {
inputGifAnimated: getPath('rotating-squares.gif'), // CC0 https://loading.io/spinner/blocks/-rotating-squares-preloader-gif
inputGifAnimatedLoop3: getPath('animated-loop-3.gif'), // CC-BY-SA-4.0 Petrus3743 https://commons.wikimedia.org/wiki/File:01-Goldener_Schnitt_Formel-Animation.gif
inputSvg: getPath('check.svg'), // http://dev.w3.org/SVG/tools/svgweb/samples/svg-files/check.svg
inputSvgSmallViewBox: getPath('circle.svg'),
inputSvgWithEmbeddedImages: getPath('struct-image-04-t.svg'), // https://dev.w3.org/SVG/profiles/1.2T/test/svg/struct-image-04-t.svg
inputJPGBig: getPath('flowers.jpeg'),

View File

@@ -39,6 +39,16 @@
Memcheck:Cond
obj:*/libjpeg.so*
}
{
value_jpeg_obj_static
Memcheck:Value8
obj:*/libvips.so*
}
{
cond_jpeg_obj_static
Memcheck:Cond
obj:*/libvips.so*
}
{
param_jpeg_jpeg_finish_compress
Memcheck:Param
@@ -304,6 +314,16 @@
...
fun:vips__init
}
{
leak_rsvg_static_data
Memcheck:Leak
match-leak-kinds: definite
fun:malloc
...
fun:rsvg_rust_handle_new_from_stream_sync
...
fun:vips_object_build
}
# libuv warnings
{
@@ -418,6 +438,13 @@
...
fun:_ZN4node17CreateEnvironmentEPN2v87IsolateEP9uv_loop_sNS0_5LocalINS0_7ContextEEEiPKPKciSB_
}
{
leak_nodejs_CreateEnvironment_IsolateData
Memcheck:Leak
match-leak-kinds: possible
...
fun:_ZN4node17CreateEnvironmentEPNS_11IsolateDataEN2v85LocalINS2_7ContextEEERKSt6vectorISsSaISsEESA_NS_16EnvironmentFlags5FlagsENS_8ThreadIdESt10unique_ptrINS_21InspectorParentHandleESt14default_deleteISF_EE
}
{
leak_nodejs_Environment_Start
Memcheck:Leak

View File

@@ -98,4 +98,36 @@ describe('GIF input', () => {
sharp().gif({ delay: [65536] });
});
});
it('should work with streams when only animated is set', function (done) {
if (sharp.format.magick.output.buffer) {
fs.createReadStream(fixtures.inputGifAnimated)
.pipe(sharp({ animated: true }))
.gif()
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual(true, data.length > 0);
assert.strictEqual('gif', info.format);
fixtures.assertSimilar(fixtures.inputGifAnimated, data, done);
});
} else {
done();
}
});
it('should work with streams when only pages is set', function (done) {
if (sharp.format.magick.output.buffer) {
fs.createReadStream(fixtures.inputGifAnimated)
.pipe(sharp({ pages: -1 }))
.gif()
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual(true, data.length > 0);
assert.strictEqual('gif', info.format);
fixtures.assertSimilar(fixtures.inputGifAnimated, data, done);
});
} else {
done();
}
});
});

View File

@@ -302,7 +302,7 @@ describe('Input/output', function () {
});
it('Fail when input is empty Buffer', function (done) {
if (sharp.format.magick.input.buffer) return this.skip(); // can be removed with libvips 8.10.0+
if (sharp.format.magick.input.buffer) return this.skip(); // can be removed with libvips 8.10.1+
sharp(Buffer.alloc(0)).toBuffer().then(function () {
assert(false);
done();
@@ -647,7 +647,7 @@ describe('Input/output', function () {
it('Invalid density: string', function () {
assert.throws(function () {
sharp({ density: 'zoinks' });
}, /Expected number between 1 and 2400 for density but received zoinks of type string/);
}, /Expected number between 1 and 100000 for density but received zoinks of type string/);
});
it('Setting animated property updates pages property', function () {
assert.strictEqual(sharp({ animated: false }).options.input.pages, 1);

View File

@@ -462,6 +462,19 @@ describe('Image Stats', function () {
})
);
it('Entropy and sharpness of 1x1 input are zero', async () => {
const { entropy, sharpness } = await sharp({
create: {
width: 1,
height: 1,
channels: 3,
background: 'red'
}
}).stats();
assert.strictEqual(entropy, 0);
assert.strictEqual(sharpness, 0);
});
it('Stream in, Callback out', function (done) {
const readable = fs.createReadStream(fixtures.inputJpg);
const pipeline = sharp().stats(function (err, stats) {

View File

@@ -48,6 +48,31 @@ describe('SVG input', function () {
});
});
it('Convert SVG to PNG at DPI larger than 2400', function (done) {
const size = 1024;
sharp(fixtures.inputSvgSmallViewBox).metadata(function (err, metadata) {
if (err) throw err;
const density = (size / Math.max(metadata.width, metadata.height)) * metadata.density;
sharp(fixtures.inputSvgSmallViewBox, { density })
.resize(size)
.toFormat('png')
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('png', info.format);
assert.strictEqual(size, info.width);
assert.strictEqual(size, info.height);
fixtures.assertSimilar(fixtures.expected('circle.png'), data, function (err) {
if (err) throw err;
sharp(data).metadata(function (err, info) {
if (err) throw err;
assert.strictEqual(9216, info.density);
done();
});
});
});
});
});
it('Convert SVG to PNG at 14.4DPI', function (done) {
sharp(fixtures.inputSvg, { density: 14.4 })
.toFormat('png')

View File

@@ -161,9 +161,7 @@ describe('TIFF', function () {
.then(() => sharp(fixtures.outputTiff)
.metadata()
.then(({ density }) => {
assert.strictEqual(true,
density === 2540 || // libvips <= 8.8.2
density === 25400); // libvips >= 8.8.3
assert.strictEqual(25400, density);
return promisify(rimraf)(fixtures.outputTiff);
})
)
@@ -179,9 +177,7 @@ describe('TIFF', function () {
.then(data => sharp(data)
.metadata()
.then(({ density }) => {
assert.strictEqual(true,
density === 2540 || // libvips <= 8.8.2
density === 25400); // libvips >= 8.8.3
assert.strictEqual(25400, density);
})
)
);

View File

@@ -16,4 +16,12 @@ describe('toBuffer', () => {
});
});
});
it('correctly process animated webp with height > 16383', (done) => {
const image = sharp(fixtures.inputWebPAnimatedBigHeight, { animated: true });
image.toBuffer().then((buff) => {
assert.strictEqual(Buffer.isBuffer(buff), true);
done();
});
});
});

View File

@@ -1,5 +1,6 @@
'use strict';
const fs = require('fs');
const assert = require('assert');
const sharp = require('../../');
@@ -184,4 +185,28 @@ describe('WebP', function () {
assert.deepStrictEqual(updated.delay, expectedDelay);
});
it('should work with streams when only animated is set', function (done) {
fs.createReadStream(fixtures.inputWebPAnimated)
.pipe(sharp({ animated: true }))
.webp({ lossless: true })
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual(true, data.length > 0);
assert.strictEqual('webp', info.format);
fixtures.assertSimilar(fixtures.inputWebPAnimated, data, done);
});
});
it('should work with streams when only pages is set', function (done) {
fs.createReadStream(fixtures.inputWebPAnimated)
.pipe(sharp({ pages: -1 }))
.webp({ lossless: true })
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual(true, data.length > 0);
assert.strictEqual('webp', info.format);
fixtures.assertSimilar(fixtures.inputWebPAnimated, data, done);
});
});
});