mirror of
https://github.com/lovell/sharp.git
synced 2026-02-04 05:36:18 +01:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3511723914 | ||
|
|
6a1c7b7588 | ||
|
|
18fd6ef119 | ||
|
|
0004f5d2ff | ||
|
|
5f29d1ba9c | ||
|
|
791fd35c35 | ||
|
|
e0d622d347 | ||
|
|
6b34e8a804 | ||
|
|
eb8773fe3e | ||
|
|
b40e3fa1f1 | ||
|
|
d25d761b55 |
@@ -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()
|
||||
|
||||
@@ -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'
|
||||
|
||||
38
binding.js
38
binding.js
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
machine:
|
||||
node:
|
||||
version: v4.6.1
|
||||
version: v4.8.4
|
||||
services:
|
||||
- docker
|
||||
test:
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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!
|
||||
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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.
|
||||
|
||||
11
package.json
11
package.json
@@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -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
BIN
test/fixtures/alpha-layer-2-ink.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 36 KiB |
BIN
test/fixtures/expected/alpha-layer-2-trim-resize.jpg
vendored
Normal file
BIN
test/fixtures/expected/alpha-layer-2-trim-resize.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
1
test/fixtures/index.js
vendored
1
test/fixtures/index.js
vendored
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user