Compare commits

...

11 Commits

Author SHA1 Message Date
Lovell Fuller
3511723914 Release v0.18.4 2017-09-18 18:26:12 +01:00
Lovell Fuller
6a1c7b7588 Ensure input Buffer really is marked as Persistent #950 2017-09-16 20:17:32 +01:00
Lovell Fuller
18fd6ef119 Release v0.18.3 2017-09-13 10:51:08 +01:00
Matt Parrish
0004f5d2ff Migrate from got to simple-get (#945)
The simple-get module provides support for basic auth and
is already used by the future prebuild dependency.
2017-09-12 07:38:17 +01:00
Mario Viens
5f29d1ba9c Clarifying cache documentation (#919) 2017-08-19 10:43:36 +01:00
Jasper Blues
791fd35c35 Update README.md (#913) 2017-08-16 12:09:02 +01:00
Kleis Auke Wolthuizen
e0d622d347 Skip shrink-on-load when trimming (#887) (#888) 2017-07-28 21:02:30 +01:00
Lovell Fuller
6b34e8a804 Docs: FreeBSD gcc v4/v5 needs _GLIBCXX_USE_C99 for C++11 #873 2017-07-25 14:54:44 +01:00
Lovell Fuller
eb8773fe3e Use detect-libc instead of ldd output parsing 2017-07-17 12:11:13 +01:00
Lovell Fuller
b40e3fa1f1 Docs: Alpine vips-dev package requires fftw-dev also 2017-07-15 14:47:25 +01:00
Lovell Fuller
d25d761b55 Update benchmark deps, allow node-images to fail 2017-07-14 13:18:13 +01:00
19 changed files with 103 additions and 52 deletions

View File

@@ -30,8 +30,11 @@ import sharp from 'sharp';
sharp(inputBuffer)
.resize(320, 240)
.toFile('output.webp', (err, info) => ... );
// A Promises/A+ promise is returned when callback is not provided.
```
```javascript
sharp('input.jpg')
.rotate()

View File

@@ -144,7 +144,7 @@
}],
['OS == "linux"', {
'variables': {
'download_vips': '<!(LDD_VERSION="<!(ldd --version 2>&1 || true)" node -e "require(\'./binding\').download_vips()")'
'download_vips': '<!(node -e "require(\'./binding\').download_vips()")'
},
'defines': [
'_GLIBCXX_USE_CXX11_ABI=0'

View File

@@ -5,9 +5,10 @@ const os = require('os');
const path = require('path');
const caw = require('caw');
const got = require('got');
const simpleGet = require('simple-get');
const semver = require('semver');
const tar = require('tar');
const detectLibc = require('detect-libc');
const distBaseUrl = process.env.SHARP_DIST_BASE_URL || 'https://dl.bintray.com/lovell/sharp/';
@@ -68,19 +69,15 @@ module.exports.download_vips = function () {
if (!isFile(vipsHeaderPath)) {
// Ensure Intel 64-bit or ARM
if (arch === 'ia32') {
error('Intel Architecture 32-bit systems require manual installation - please see http://sharp.dimens.io/en/stable/install/');
error('Intel Architecture 32-bit systems require manual installation of libvips - please see http://sharp.dimens.io/page/install');
}
// Ensure glibc >= 2.15
const lddVersion = process.env.LDD_VERSION;
if (lddVersion) {
if (/(glibc|gnu libc|gentoo|solus)/i.test(lddVersion)) {
const glibcVersion = lddVersion ? lddVersion.split(/\n/)[0].split(' ').slice(-1)[0].trim() : '';
if (glibcVersion && semver.lt(glibcVersion + '.0', '2.13.0')) {
error('glibc version ' + glibcVersion + ' requires manual installation - please see http://sharp.dimens.io/en/stable/install/');
}
} else {
error(lddVersion.split(/\n/)[0] + ' requires manual installation - please see http://sharp.dimens.io/en/stable/install/');
}
// Ensure glibc Linux
if (detectLibc.isNonGlibcLinux) {
error(`Use with ${detectLibc.family} libc requires manual installation of libvips - please see http://sharp.dimens.io/page/install`);
}
// Ensure glibc >= 2.13
if (detectLibc.family === detectLibc.GLIBC && detectLibc.version && semver.lt(`${detectLibc.version}.0`, '2.13.0')) {
error(`Use with glibc version ${detectLibc.version} requires manual installation of libvips - please see http://sharp.dimens.io/page/install`);
}
// Arch/platform-specific .tar.gz
const tarFilename = ['libvips', minimumLibvipsVersion, platformId()].join('-') + '.tar.gz';
@@ -98,19 +95,22 @@ module.exports.download_vips = function () {
} catch (err) {}
});
});
const gotOpt = {
const url = distBaseUrl + tarFilename;
const simpleGetOpt = {
url: url,
agent: caw(null, {
protocol: 'https'
})
};
const url = distBaseUrl + tarFilename;
got.stream(url, gotOpt).on('response', function (response) {
simpleGet(simpleGetOpt, function (err, response) {
if (err) {
error('Download of ' + url + ' failed: ' + err.message);
}
if (response.statusCode !== 200) {
error(url + ' status code ' + response.statusCode);
}
}).on('error', function (err) {
error('Download of ' + url + ' failed: ' + err.message);
}).pipe(tmpFile);
response.pipe(tmpFile);
});
}
}
};

View File

@@ -1,6 +1,6 @@
machine:
node:
version: v4.6.1
version: v4.8.4
services:
- docker
test:

View File

@@ -9,14 +9,14 @@
## cache
Gets, or when options are provided sets, the limits of _libvips'_ operation cache.
Gets or, when options are provided, sets the limits of _libvips'_ operation cache.
Existing entries in the cache will be trimmed after any change in limits.
This method always returns cache statistics,
useful for determining how much working memory is required for a particular task.
**Parameters**
- `options` **([Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** Object with the following attributes, or Boolean where true uses default cache settings and false removes all caching.
- `options` **([Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) \| [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean))** Object with the following attributes, or Boolean where true uses default cache settings and false removes all caching (optional, default `true`)
- `options.memory` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** is the maximum memory in MB to use for this cache (optional, default `50`)
- `options.files` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** is the maximum number of files to hold open (optional, default `20`)
- `options.items` **[Number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** is the maximum number of operations to cache (optional, default `100`)
@@ -37,7 +37,7 @@ Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer
## concurrency
Gets, or when a concurrency is provided sets,
Gets or, when a concurrency is provided, sets
the number of threads _libvips'_ should create to process each image.
The default value is the number of CPU cores.
A value of `0` will reset to this default.

View File

@@ -4,6 +4,22 @@
Requires libvips v8.5.5.
#### v0.18.4 - 18<sup>th</sup> September 2017
* Ensure input Buffer really is marked as Persistent, prevents mark-sweep GC.
[#950](https://github.com/lovell/sharp/issues/950)
[@lfdoherty](https://github.com/lfdoherty)
#### v0.18.3 - 13<sup>th</sup> September 2017
* Skip shrink-on-load when trimming.
[#888](https://github.com/lovell/sharp/pull/888)
[@kleisauke](https://github.com/kleisauke)
* Migrate from got to simple-get for basic auth support.
[#945](https://github.com/lovell/sharp/pull/945)
[@pbomb](https://github.com/pbomb)
#### v0.18.2 - 1<sup>st</sup> July 2017
* Expose libvips' xres and yres properties for TIFF output.

View File

@@ -100,6 +100,8 @@ the help and code contributions of the following people:
* [Alice Monday](https://github.com/alice0meta)
* [Kristo Jorgenson](https://github.com/kristojorg)
* [Yves Bos](https://github.com/YvesBos)
* [Nicolas Coden](https://github.com/ncoden)
* [Matt Parrish](https://github.com/pbomb)
Thank you!

View File

@@ -47,7 +47,7 @@ This allows the use of newer versions of libvips with older versions of sharp.
For 32-bit Intel CPUs and older Linux-based operating systems such as Centos 6,
it is recommended to install a system-wide installation of libvips from source:
https://github.com/jcupitt/libvips#building-libvips-from-a-source-tarball
https://jcupitt.github.io/libvips/install.html#building-libvips-from-a-source-tarball
#### Alpine Linux
@@ -55,7 +55,7 @@ libvips is available in the
[testing repository](https://pkgs.alpinelinux.org/packages?name=vips-dev):
```sh
apk add vips-dev --update-cache --repository https://dl-3.alpinelinux.org/alpine/edge/testing/
apk add vips-dev fftw-dev --update-cache --repository https://dl-3.alpinelinux.org/alpine/edge/testing/
```
The smaller stack size of musl libc means
@@ -91,6 +91,9 @@ This can be achieved via [FreshPorts](https://www.freshports.org/graphics/vips/)
cd /usr/ports/graphics/vips/ && make install clean
```
FreeBSD's gcc v4 and v5 need `CXXFLAGS=-D_GLIBCXX_USE_C99` set for C++11 support due to
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=193528
### Heroku
libvips and its dependencies are fetched and stored within `node_modules\sharp\vendor` during `npm install`.

View File

@@ -4,7 +4,7 @@ const is = require('./is');
const sharp = require('../build/Release/sharp.node');
/**
* Gets, or when options are provided sets, the limits of _libvips'_ operation cache.
* Gets or, when options are provided, sets the limits of _libvips'_ operation cache.
* Existing entries in the cache will be trimmed after any change in limits.
* This method always returns cache statistics,
* useful for determining how much working memory is required for a particular task.
@@ -16,7 +16,7 @@ const sharp = require('../build/Release/sharp.node');
* sharp.cache( { files: 0 } );
* sharp.cache(false);
*
* @param {Object|Boolean} options - Object with the following attributes, or Boolean where true uses default cache settings and false removes all caching.
* @param {Object|Boolean} [options=true] - Object with the following attributes, or Boolean where true uses default cache settings and false removes all caching
* @param {Number} [options.memory=50] - is the maximum memory in MB to use for this cache
* @param {Number} [options.files=20] - is the maximum number of files to hold open
* @param {Number} [options.items=100] - is the maximum number of operations to cache
@@ -39,7 +39,7 @@ function cache (options) {
cache(true);
/**
* Gets, or when a concurrency is provided sets,
* Gets or, when a concurrency is provided, sets
* the number of threads _libvips'_ should create to process each image.
* The default value is the number of CPU cores.
* A value of `0` will reset to this default.

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.18.2",
"version": "0.18.4",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://github.com/lovell/sharp",
"contributors": [
@@ -37,7 +37,8 @@
"Kristo Jorgenson <kristo.jorgenson@gmail.com>",
"YvesBos <yves_bos@outlook.com>",
"Guy Maliar <guy@tailorbrands.com>",
"Nicolas Coden <nicolas@ncoden.fr>"
"Nicolas Coden <nicolas@ncoden.fr>",
"Matt Parrish <matt.r.parrish@gmail.com>"
],
"scripts": {
"clean": "rm -rf node_modules/ build/ vendor/ coverage/ test/fixtures/output.*",
@@ -69,9 +70,10 @@
"dependencies": {
"caw": "^2.0.0",
"color": "^2.0.0",
"got": "^7.1.0",
"detect-libc": "^0.2.0",
"nan": "^2.6.2",
"semver": "^5.3.0",
"simple-get": "^2.7.0",
"tar": "^3.1.5"
},
"devDependencies": {
@@ -103,7 +105,8 @@
"filter": [
"build/c++11",
"build/include",
"runtime/indentation_namespace"
"runtime/indentation_namespace",
"runtime/references"
]
}
}

View File

@@ -40,7 +40,7 @@ namespace sharp {
// Create an InputDescriptor instance from a v8::Object describing an input image
InputDescriptor* CreateInputDescriptor(
v8::Handle<v8::Object> input, std::vector<v8::Local<v8::Object>> buffersToPersist
v8::Handle<v8::Object> input, std::vector<v8::Local<v8::Object>> &buffersToPersist
) {
Nan::HandleScope();
InputDescriptor *descriptor = new InputDescriptor;

View File

@@ -89,7 +89,7 @@ namespace sharp {
// Create an InputDescriptor instance from a v8::Object describing an input image
InputDescriptor* CreateInputDescriptor(
v8::Handle<v8::Object> input, std::vector<v8::Local<v8::Object>> buffersToPersist);
v8::Handle<v8::Object> input, std::vector<v8::Local<v8::Object>> &buffersToPersist);
enum class ImageType {
JPEG,

View File

@@ -220,12 +220,12 @@ class PipelineWorker : public Nan::AsyncWorker {
}
// If integral x and y shrink are equal, try to use shrink-on-load for JPEG and WebP,
// but not when applying gamma correction or pre-resize extract
// but not when applying gamma correction, pre-resize extract or trim
int shrink_on_load = 1;
if (
xshrink == yshrink && xshrink >= 2 &&
(inputImageType == ImageType::JPEG || inputImageType == ImageType::WEBP) &&
baton->gamma == 0 && baton->topOffsetPre == -1
baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimTolerance == 0
) {
if (xshrink >= 8) {
xfactor = xfactor / 8;

View File

@@ -8,14 +8,14 @@
"test": "node perf && node random && node parallel"
},
"devDependencies": {
"async": "^2.1.4",
"benchmark": "^2.1.2",
"async": "^2.5.0",
"benchmark": "^2.1.4",
"gm": "^1.23.0",
"imagemagick": "^0.1.3",
"imagemagick-native": "^1.9.3",
"images": "^3.0.0",
"jimp": "^0.2.27",
"mapnik": "^3.6.0",
"jimp": "^0.2.28",
"mapnik": "^3.6.2",
"pajk-lwip": "^0.2.0",
"semver": "^5.3.0"
},

View File

@@ -12,7 +12,12 @@ const gm = require('gm');
const imagemagick = require('imagemagick');
const mapnik = require('mapnik');
const jimp = require('jimp');
const images = require('images');
let images;
try {
images = require('images');
} catch (err) {
console.log('Excluding node-images');
}
let imagemagickNative;
try {
imagemagickNative = require('imagemagick-native');
@@ -268,11 +273,13 @@ async.series({
}
});
// images
jpegSuite.add('images-file-file', function () {
images(fixtures.inputJpg)
.resize(width, height)
.save(fixtures.outputJpg, { quality: 80 });
});
if (typeof images !== 'undefined') {
jpegSuite.add('images-file-file', function () {
images(fixtures.inputJpg)
.resize(width, height)
.save(fixtures.outputJpg, { quality: 80 });
});
}
// sharp
jpegSuite.add('sharp-buffer-file', {
defer: true,
@@ -827,11 +834,13 @@ async.series({
}
});
// images
pngSuite.add('images-file-file', function () {
images(fixtures.inputPng)
.resize(width, height)
.save(fixtures.outputPng);
});
if (typeof images !== 'undefined') {
pngSuite.add('images-file-file', function () {
images(fixtures.inputPng)
.resize(width, height)
.save(fixtures.outputPng);
});
}
// sharp
pngSuite.add('sharp-buffer-file', {
defer: true,

BIN
test/fixtures/alpha-layer-2-ink.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -65,6 +65,7 @@ module.exports = {
inputJpgWithLowContrast: getPath('low-contrast.jpg'), // http://www.flickr.com/photos/grizdave/2569067123/
inputJpgLarge: getPath('giant-image.jpg'),
inputJpg320x240: getPath('320x240.jpg'), // http://www.andrewault.net/2010/01/26/create-a-test-pattern-video-with-perl/
inputJpgOverlayLayer2: getPath('alpha-layer-2-ink.jpg'),
inputPng: getPath('50020484-00001.png'), // http://c.searspartsdirect.com/lis_png/PLDM/50020484-00001.png
inputPngWithTransparency: getPath('blackbug.png'), // public domain

View File

@@ -20,6 +20,20 @@ describe('Trim borders', function () {
});
});
it('Skip shrink-on-load', function (done) {
const expected = fixtures.expected('alpha-layer-2-trim-resize.jpg');
sharp(fixtures.inputJpgOverlayLayer2)
.trim()
.resize(300)
.toBuffer(function (err, data, info) {
if (err) throw err;
assert.strictEqual('jpeg', info.format);
assert.strictEqual(300, info.width);
assert.strictEqual(300, info.height);
fixtures.assertSimilar(expected, data, done);
});
});
it('16-bit PNG with alpha channel', function (done) {
sharp(fixtures.inputPngWithTransparency16bit)
.resize(32, 32)