Compare commits

...

9 Commits

Author SHA1 Message Date
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
17 changed files with 93 additions and 49 deletions

View File

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

View File

@@ -144,7 +144,7 @@
}], }],
['OS == "linux"', { ['OS == "linux"', {
'variables': { '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': [ 'defines': [
'_GLIBCXX_USE_CXX11_ABI=0' '_GLIBCXX_USE_CXX11_ABI=0'

View File

@@ -5,9 +5,10 @@ const os = require('os');
const path = require('path'); const path = require('path');
const caw = require('caw'); const caw = require('caw');
const got = require('got'); const simpleGet = require('simple-get');
const semver = require('semver'); const semver = require('semver');
const tar = require('tar'); const tar = require('tar');
const detectLibc = require('detect-libc');
const distBaseUrl = process.env.SHARP_DIST_BASE_URL || 'https://dl.bintray.com/lovell/sharp/'; 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)) { if (!isFile(vipsHeaderPath)) {
// Ensure Intel 64-bit or ARM // Ensure Intel 64-bit or ARM
if (arch === 'ia32') { 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 // Ensure glibc Linux
const lddVersion = process.env.LDD_VERSION; if (detectLibc.isNonGlibcLinux) {
if (lddVersion) { error(`Use with ${detectLibc.family} libc requires manual installation of libvips - please see http://sharp.dimens.io/page/install`);
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 >= 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 // Arch/platform-specific .tar.gz
const tarFilename = ['libvips', minimumLibvipsVersion, platformId()].join('-') + '.tar.gz'; const tarFilename = ['libvips', minimumLibvipsVersion, platformId()].join('-') + '.tar.gz';
@@ -98,19 +95,22 @@ module.exports.download_vips = function () {
} catch (err) {} } catch (err) {}
}); });
}); });
const gotOpt = { const url = distBaseUrl + tarFilename;
const simpleGetOpt = {
url: url,
agent: caw(null, { agent: caw(null, {
protocol: 'https' protocol: 'https'
}) })
}; };
const url = distBaseUrl + tarFilename; simpleGet(simpleGetOpt, function (err, response) {
got.stream(url, gotOpt).on('response', function (response) { if (err) {
error('Download of ' + url + ' failed: ' + err.message);
}
if (response.statusCode !== 200) { if (response.statusCode !== 200) {
error(url + ' status code ' + response.statusCode); error(url + ' status code ' + response.statusCode);
} }
}).on('error', function (err) { response.pipe(tmpFile);
error('Download of ' + url + ' failed: ' + err.message); });
}).pipe(tmpFile);
} }
} }
}; };

View File

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

View File

@@ -9,14 +9,14 @@
## cache ## 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. Existing entries in the cache will be trimmed after any change in limits.
This method always returns cache statistics, This method always returns cache statistics,
useful for determining how much working memory is required for a particular task. useful for determining how much working memory is required for a particular task.
**Parameters** **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.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.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`) - `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 ## 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 number of threads _libvips'_ should create to process each image.
The default value is the number of CPU cores. The default value is the number of CPU cores.
A value of `0` will reset to this default. A value of `0` will reset to this default.

View File

@@ -4,6 +4,16 @@
Requires libvips v8.5.5. Requires libvips v8.5.5.
#### 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 #### v0.18.2 - 1<sup>st</sup> July 2017
* Expose libvips' xres and yres properties for TIFF output. * 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) * [Alice Monday](https://github.com/alice0meta)
* [Kristo Jorgenson](https://github.com/kristojorg) * [Kristo Jorgenson](https://github.com/kristojorg)
* [Yves Bos](https://github.com/YvesBos) * [Yves Bos](https://github.com/YvesBos)
* [Nicolas Coden](https://github.com/ncoden)
* [Matt Parrish](https://github.com/pbomb)
Thank you! 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, 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: 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 #### Alpine Linux
@@ -55,7 +55,7 @@ libvips is available in the
[testing repository](https://pkgs.alpinelinux.org/packages?name=vips-dev): [testing repository](https://pkgs.alpinelinux.org/packages?name=vips-dev):
```sh ```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 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 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 ### Heroku
libvips and its dependencies are fetched and stored within `node_modules\sharp\vendor` during `npm install`. 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'); 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. * Existing entries in the cache will be trimmed after any change in limits.
* This method always returns cache statistics, * This method always returns cache statistics,
* useful for determining how much working memory is required for a particular task. * 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( { files: 0 } );
* sharp.cache(false); * 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.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.files=20] - is the maximum number of files to hold open
* @param {Number} [options.items=100] - is the maximum number of operations to cache * @param {Number} [options.items=100] - is the maximum number of operations to cache
@@ -39,7 +39,7 @@ function cache (options) {
cache(true); 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 number of threads _libvips'_ should create to process each image.
* The default value is the number of CPU cores. * The default value is the number of CPU cores.
* A value of `0` will reset to this default. * A value of `0` will reset to this default.

View File

@@ -1,7 +1,7 @@
{ {
"name": "sharp", "name": "sharp",
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP and TIFF images", "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.3",
"author": "Lovell Fuller <npm@lovell.info>", "author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://github.com/lovell/sharp", "homepage": "https://github.com/lovell/sharp",
"contributors": [ "contributors": [
@@ -37,7 +37,8 @@
"Kristo Jorgenson <kristo.jorgenson@gmail.com>", "Kristo Jorgenson <kristo.jorgenson@gmail.com>",
"YvesBos <yves_bos@outlook.com>", "YvesBos <yves_bos@outlook.com>",
"Guy Maliar <guy@tailorbrands.com>", "Guy Maliar <guy@tailorbrands.com>",
"Nicolas Coden <nicolas@ncoden.fr>" "Nicolas Coden <nicolas@ncoden.fr>",
"Matt Parrish <matt.r.parrish@gmail.com>"
], ],
"scripts": { "scripts": {
"clean": "rm -rf node_modules/ build/ vendor/ coverage/ test/fixtures/output.*", "clean": "rm -rf node_modules/ build/ vendor/ coverage/ test/fixtures/output.*",
@@ -69,9 +70,10 @@
"dependencies": { "dependencies": {
"caw": "^2.0.0", "caw": "^2.0.0",
"color": "^2.0.0", "color": "^2.0.0",
"got": "^7.1.0", "detect-libc": "^0.2.0",
"nan": "^2.6.2", "nan": "^2.6.2",
"semver": "^5.3.0", "semver": "^5.3.0",
"simple-get": "^2.7.0",
"tar": "^3.1.5" "tar": "^3.1.5"
}, },
"devDependencies": { "devDependencies": {

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, // 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; int shrink_on_load = 1;
if ( if (
xshrink == yshrink && xshrink >= 2 && xshrink == yshrink && xshrink >= 2 &&
(inputImageType == ImageType::JPEG || inputImageType == ImageType::WEBP) && (inputImageType == ImageType::JPEG || inputImageType == ImageType::WEBP) &&
baton->gamma == 0 && baton->topOffsetPre == -1 baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimTolerance == 0
) { ) {
if (xshrink >= 8) { if (xshrink >= 8) {
xfactor = xfactor / 8; xfactor = xfactor / 8;

View File

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

View File

@@ -12,7 +12,12 @@ const gm = require('gm');
const imagemagick = require('imagemagick'); const imagemagick = require('imagemagick');
const mapnik = require('mapnik'); const mapnik = require('mapnik');
const jimp = require('jimp'); const jimp = require('jimp');
const images = require('images'); let images;
try {
images = require('images');
} catch (err) {
console.log('Excluding node-images');
}
let imagemagickNative; let imagemagickNative;
try { try {
imagemagickNative = require('imagemagick-native'); imagemagickNative = require('imagemagick-native');
@@ -268,11 +273,13 @@ async.series({
} }
}); });
// images // images
if (typeof images !== 'undefined') {
jpegSuite.add('images-file-file', function () { jpegSuite.add('images-file-file', function () {
images(fixtures.inputJpg) images(fixtures.inputJpg)
.resize(width, height) .resize(width, height)
.save(fixtures.outputJpg, { quality: 80 }); .save(fixtures.outputJpg, { quality: 80 });
}); });
}
// sharp // sharp
jpegSuite.add('sharp-buffer-file', { jpegSuite.add('sharp-buffer-file', {
defer: true, defer: true,
@@ -827,11 +834,13 @@ async.series({
} }
}); });
// images // images
if (typeof images !== 'undefined') {
pngSuite.add('images-file-file', function () { pngSuite.add('images-file-file', function () {
images(fixtures.inputPng) images(fixtures.inputPng)
.resize(width, height) .resize(width, height)
.save(fixtures.outputPng); .save(fixtures.outputPng);
}); });
}
// sharp // sharp
pngSuite.add('sharp-buffer-file', { pngSuite.add('sharp-buffer-file', {
defer: true, 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/ inputJpgWithLowContrast: getPath('low-contrast.jpg'), // http://www.flickr.com/photos/grizdave/2569067123/
inputJpgLarge: getPath('giant-image.jpg'), inputJpgLarge: getPath('giant-image.jpg'),
inputJpg320x240: getPath('320x240.jpg'), // http://www.andrewault.net/2010/01/26/create-a-test-pattern-video-with-perl/ 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 inputPng: getPath('50020484-00001.png'), // http://c.searspartsdirect.com/lis_png/PLDM/50020484-00001.png
inputPngWithTransparency: getPath('blackbug.png'), // public domain 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) { it('16-bit PNG with alpha channel', function (done) {
sharp(fixtures.inputPngWithTransparency16bit) sharp(fixtures.inputPngWithTransparency16bit)
.resize(32, 32) .resize(32, 32)