Compare commits

...

11 Commits

Author SHA1 Message Date
Lovell Fuller
8bd8709f2b Release v0.25.2 2020-03-20 19:20:34 +00:00
Lovell Fuller
e82a585cec Ensure AsyncWorker options are persisted #2130 2020-03-19 21:21:21 +00:00
Lovell Fuller
c1d4a68558 Add changelog entry, docs and credit for #2098 2020-03-18 13:54:41 +00:00
Edward Silverton
eff36dc09f Add IIIF layout support to tile-based output (#2098) 2020-03-18 13:27:54 +00:00
Lovell Fuller
031a58f817 Docs: AWS Lambda cross-platform no longer requires target flag 2020-03-17 18:33:49 +00:00
Lovell Fuller
cf39fc4fb1 Simplify tiled layout JPEG file extension logic 2020-03-14 22:08:46 +00:00
Lovell Fuller
c9bff94e17 Docs: expand descriptions of resize cover/contain 2020-03-14 21:34:48 +00:00
Lovell Fuller
e78e919925 Clarify diff between install vs bug issue templates 2020-03-10 21:36:48 +00:00
Lovell Fuller
76bb25262e Docs: ARM64/RHEL7 prebuilt binaries changelog entry 2020-03-10 21:22:30 +00:00
Lovell Fuller
d8426b1ed5 CI: Switch Linux x64 to CentOS 7 for glibc 2.17, gcc 4.8.5
Expand Linux ARM64v8 to all supported versions of Node.js
2020-03-10 19:39:26 +00:00
Lovell Fuller
4894c10dd9 Ensure consistent, correct detection of input opts #2118 2020-03-08 14:32:17 +00:00
18 changed files with 176 additions and 59 deletions

View File

@@ -1,6 +1,6 @@
---
name: Installation
about: Something went wrong **installing** sharp
about: Something went wrong during either 'npm install sharp' or 'require("sharp")'
labels: installation
---

View File

@@ -1,6 +1,6 @@
---
name: Possible bug
about: Something unexpected occurred **using** sharp
about: Installation of sharp was successful but then something unexpected occurred using one of its features
labels: triage
---

View File

@@ -1,75 +1,137 @@
matrix:
jobs:
include:
- name: "Linux (glibc 2.17+) - Node.js 10"
os: linux
dist: xenial
language: node_js
node_js: "10"
- name: "Linux (glibc 2.17+) - Node.js 12"
os: linux
dist: xenial
language: node_js
node_js: "12"
- name: "Linux (glibc 2.17+) - Node.js 13"
os: linux
dist: xenial
language: node_js
node_js: "13"
after_success:
- npm install coveralls
- cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
- name: "Linux (musl 1.1.20+) - Node.js 10"
- name: "Linux x64 (CentOS 7, glibc 2.17) - Node.js 10"
os: linux
dist: bionic
language: minimal
language: shell
before_install:
- sudo docker run -dit --name sharp --env CI --env PREBUILD_TOKEN --volume "${PWD}:/mnt/sharp" --workdir /mnt/sharp centos:7
- sudo docker exec sharp bash -c "curl -sL https://rpm.nodesource.com/setup_10.x | bash -"
- sudo docker exec sharp yum install -y gcc-c++ make git nodejs
install: sudo docker exec sharp bash -c "npm install --unsafe-perm"
script: sudo docker exec sharp bash -c "npm test"
- name: "Linux x64 (CentOS 7, glibc 2.17) - Node.js 12"
os: linux
dist: bionic
language: shell
before_install:
- sudo docker run -dit --name sharp --env CI --env PREBUILD_TOKEN --volume "${PWD}:/mnt/sharp" --workdir /mnt/sharp centos:7
- sudo docker exec sharp bash -c "curl -sL https://rpm.nodesource.com/setup_12.x | bash -"
- sudo docker exec sharp yum install -y gcc-c++ make git nodejs
install: sudo docker exec sharp bash -c "npm install --unsafe-perm"
script: sudo docker exec sharp bash -c "npm test"
- name: "Linux x64 (CentOS 7, glibc 2.17) - Node.js 13"
os: linux
dist: bionic
language: shell
before_install:
- sudo docker run -dit --name sharp --env CI --env PREBUILD_TOKEN --volume "${PWD}:/mnt/sharp" --workdir /mnt/sharp centos:7
- sudo docker exec sharp bash -c "curl -sL https://rpm.nodesource.com/setup_13.x | bash -"
- sudo docker exec sharp yum install -y gcc-c++ make git nodejs
install: sudo docker exec sharp bash -c "npm install --unsafe-perm"
script: sudo docker exec sharp bash -c "npm test"
- name: "Linux x64 (Alpine 3.9, musl 1.1.20) - Node.js 10"
os: linux
dist: bionic
language: shell
before_install:
- sudo docker run -dit --name sharp --env CI --env PREBUILD_TOKEN --volume "${PWD}:/mnt/sharp" --workdir /mnt/sharp node:10.17.0-alpine3.9 # https://github.com/nodejs/docker-node/issues/1158
- sudo docker exec sharp apk add build-base git python2 --update-cache
install: sudo docker exec sharp sh -c "npm install --unsafe-perm"
script: sudo docker exec sharp sh -c "npm test"
- name: "Linux (musl 1.1.20+) - Node.js 12"
- name: "Linux x64 (Alpine 3.11, musl 1.1.20) - Node.js 12"
os: linux
dist: bionic
language: minimal
language: shell
before_install:
- sudo docker run -dit --name sharp --env CI --env PREBUILD_TOKEN --volume "${PWD}:/mnt/sharp" --workdir /mnt/sharp node:12.0-alpine
- sudo docker exec sharp apk add build-base git python2 --update-cache
install: sudo docker exec sharp sh -c "npm install --unsafe-perm"
script: sudo docker exec sharp sh -c "npm test"
- name: "Linux (musl 1.1.20+) - Node.js 13"
- name: "Linux x64 (Alpine 3.11, musl 1.1.20) - Node.js 13"
os: linux
dist: bionic
language: minimal
language: shell
before_install:
- sudo docker run -dit --name sharp --env CI --env PREBUILD_TOKEN --volume "${PWD}:/mnt/sharp" --workdir /mnt/sharp node:13.0-alpine
- sudo docker exec sharp apk add build-base git python2 --update-cache
install: sudo docker exec sharp sh -c "npm install --unsafe-perm"
script: sudo docker exec sharp sh -c "npm test"
- name: "Linux ARM64v8 (glibc 2.29+) - Node.js 10"
- name: "Linux ARM64v8 (Debian 11, glibc 2.29) - Node.js 10"
arch: arm64
os: linux
dist: bionic
language: minimal
language: shell
before_install:
- sudo docker run -dit --name sharp --env CI --volume "${PWD}:/mnt/sharp" --workdir /mnt/sharp arm64v8/debian:bullseye
- sudo docker exec sharp apt-get update
- sudo docker exec sharp apt-get install -y build-essential git python2 nodejs npm
- sudo docker run -dit --name sharp --env CI --env PREBUILD_TOKEN --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 "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"
- name: "macOS (10.13+) - Node.js 10"
- name: "Linux ARM64v8 (Debian 11, glibc 2.29) - Node.js 12"
arch: arm64
os: linux
dist: bionic
language: shell
before_install:
- sudo docker run -dit --name sharp --env CI --env PREBUILD_TOKEN --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 "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"
- name: "Linux ARM64v8 (Debian 11, glibc 2.29) - Node.js 13"
arch: arm64
os: linux
dist: bionic
language: shell
before_install:
- sudo docker run -dit --name sharp --env CI --env PREBUILD_TOKEN --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_13.x buster 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"
- name: "macOS (10.13) - Node.js 10"
os: osx
osx_image: xcode10.1
language: node_js
node_js: "10"
- name: "macOS (10.13+) - Node.js 12"
- name: "macOS (10.13) - Node.js 12"
os: osx
osx_image: xcode10.1
language: node_js
node_js: "12"
- name: "macOS (10.13+) - Node.js 13"
- name: "macOS (10.13) - Node.js 13"
os: osx
osx_image: xcode10.1
language: node_js
node_js: "13"
- name: "Unit test coverage report"
os: linux
dist: bionic
language: node_js
node_js: "13"
before_install: unset PREBUILD_TOKEN
after_success:
- npm install coveralls
- cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
cache:
npm: false

View File

@@ -339,7 +339,7 @@ Warning: multiple sharp instances concurrently producing tile output can expose
- `options.depth` **[String][2]?** how deep to make the pyramid, possible values are `onepixel`, `onetile` or `one`, default based on layout.
- `options.skipBlanks` **[Number][9]** threshold to skip tile generation, a value 0 - 255 for 8-bit images or 0 - 65535 for 16-bit images (optional, default `-1`)
- `options.container` **[String][2]** tile container, with value `fs` (filesystem) or `zip` (compressed file). (optional, default `'fs'`)
- `options.layout` **[String][2]** filesystem layout, possible values are `dz`, `zoomify` or `google`. (optional, default `'dz'`)
- `options.layout` **[String][2]** filesystem layout, possible values are `dz`, `iiif`, `zoomify` or `google`. (optional, default `'dz'`)
### Examples

View File

@@ -6,8 +6,8 @@ Resize image to `width`, `height` or `width x height`.
When both a `width` and `height` are provided, the possible methods by which the image should **fit** these are:
- `cover`: Crop to cover both provided dimensions (the default).
- `contain`: Embed within both provided dimensions.
- `cover`: (default) Preserving aspect ratio, ensure the image covers both provided dimensions by cropping/clipping to fit.
- `contain`: Preserving aspect ratio, contain within both provided dimensions using "letterboxing" where necessary.
- `fill`: Ignore the aspect ratio of the input and stretch to both provided dimensions.
- `inside`: Preserving aspect ratio, resize the image to be as large as possible while ensuring its dimensions are less than or equal to both those specified.
- `outside`: Preserving aspect ratio, resize the image to be as small as possible while ensuring its dimensions are greater than or equal to both those specified.

View File

@@ -4,6 +4,23 @@
Requires libvips v8.9.1
### v0.25.2 - 20th March 2020
* Provide prebuilt binaries for Linux ARM64v8.
* Add IIIF layout support to tile-based output.
[#2098](https://github.com/lovell/sharp/pull/2098)
[@edsilv](https://github.com/edsilv)
* Ensure input options are consistently and correctly detected.
[#2118](https://github.com/lovell/sharp/issues/2118)
* Ensure N-API prebuilt binaries work on RHEL7 and its derivatives.
[#2119](https://github.com/lovell/sharp/issues/2119)
* Ensure AsyncWorker options are persisted.
[#2130](https://github.com/lovell/sharp/issues/2130)
### v0.25.1 - 7th March 2020
* Ensure prebuilt binaries are fetched based on N-API version.

View File

@@ -176,3 +176,6 @@ GitHub: https://github.com/rustyguts
Name: Brychan Bennett-Odlum
GitHub: https://github.com/BrychanOdlum
Name: Edward Silverton
GitHub: https://github.com/edsilv

View File

@@ -87,7 +87,7 @@
docuteGoogleAnalytics('UA-13034748-12'),
docuteApiTitlePlugin
],
sourcePath: 'https://cdn.jsdelivr.net/gh/lovell/sharp@v0.25.1/docs',
sourcePath: 'https://cdn.jsdelivr.net/gh/lovell/sharp@v0.25.2/docs',
nav: [
{
title: 'Funding',

View File

@@ -19,6 +19,7 @@ Node.js v10+ on the most common platforms:
* macOS x64 (>= 10.13)
* Linux x64 (glibc >= 2.17, musl >= 1.1.24)
* Linux ARM64 (glibc >= 2.29)
* Windows
A ~10MB tarball containing libvips and its most commonly used dependencies
@@ -31,7 +32,6 @@ The following platforms have prebuilt libvips but not sharp:
* Linux ARMv6
* Linux ARMv7 (glibc >= 2.28)
* Linux ARM64 (glibc >= 2.29)
The following platforms require compilation of both libvips and sharp from source:
@@ -134,7 +134,7 @@ On machines other than Linux x64, such as macOS and Windows, run the following:
```sh
rm -rf node_modules/sharp
npm install --arch=x64 --platform=linux --target=12.0.0 sharp
npm install --arch=x64 --platform=linux sharp
```
Alternatively a Docker container closely matching the Lambda runtime can be used:

View File

@@ -100,10 +100,7 @@ function composite (images) {
if (!is.object(image)) {
throw is.invalidParameterError('image to composite', 'object', image);
}
const { raw, density, limitInputPixels, sequentialRead } = image;
const inputOptions = [raw, density, limitInputPixels, sequentialRead].some(is.defined)
? { raw, density, limitInputPixels, sequentialRead }
: undefined;
const inputOptions = this._inputOptionsFromObject(image);
const composite = {
input: this._createInputDescriptor(image.input, inputOptions, { allowStream: false }),
blend: 'over',

View File

@@ -4,6 +4,17 @@ const color = require('color');
const is = require('./is');
const sharp = require('../build/Release/sharp.node');
/**
* Extract input options, if any, from an object.
* @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 }
: undefined;
}
/**
* Create Object containing input and input-related options.
* @private
@@ -23,12 +34,12 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
} else if (is.plainObject(input) && !is.defined(inputOptions)) {
// Plain Object descriptor, e.g. create
inputOptions = input;
if (is.plainObject(inputOptions.raw) || is.bool(inputOptions.failOnError)) {
// Raw Stream
if (_inputOptionsFromObject(inputOptions)) {
// Stream with options
inputDescriptor.buffer = [];
}
} else if (!is.defined(input) && !is.defined(inputOptions) && is.object(containerOptions) && containerOptions.allowStream) {
// Stream
// Stream without options
inputDescriptor.buffer = [];
} else {
throw new Error(`Unsupported input '${input}' of type ${typeof input}${
@@ -337,6 +348,7 @@ function stats (callback) {
module.exports = function (Sharp) {
Object.assign(Sharp.prototype, {
// Private
_inputOptionsFromObject,
_createInputDescriptor,
_write,
_flattenBufferIn,

View File

@@ -568,7 +568,7 @@ function raw () {
* @param {String} [options.depth] how deep to make the pyramid, possible values are `onepixel`, `onetile` or `one`, default based on layout.
* @param {Number} [options.skipBlanks=-1] threshold to skip tile generation, a value 0 - 255 for 8-bit images or 0 - 65535 for 16-bit images
* @param {String} [options.container='fs'] tile container, with value `fs` (filesystem) or `zip` (compressed file).
* @param {String} [options.layout='dz'] filesystem layout, possible values are `dz`, `zoomify` or `google`.
* @param {String} [options.layout='dz'] filesystem layout, possible values are `dz`, `iiif`, `zoomify` or `google`.
* @returns {Sharp}
* @throws {Error} Invalid parameters
*/
@@ -603,10 +603,10 @@ function tile (options) {
}
// Layout
if (is.defined(options.layout)) {
if (is.string(options.layout) && is.inArray(options.layout, ['dz', 'google', 'zoomify'])) {
if (is.string(options.layout) && is.inArray(options.layout, ['dz', 'google', 'iiif', 'zoomify'])) {
this.options.tileLayout = options.layout;
} else {
throw is.invalidParameterError('layout', 'one of: dz, google, zoomify', options.layout);
throw is.invalidParameterError('layout', 'one of: dz, google, iiif, zoomify', options.layout);
}
}
// Angle of rotation,

View File

@@ -96,8 +96,8 @@ function isRotationExpected (options) {
* Resize image to `width`, `height` or `width x height`.
*
* When both a `width` and `height` are provided, the possible methods by which the image should **fit** these are:
* - `cover`: Crop to cover both provided dimensions (the default).
* - `contain`: Embed within both provided dimensions.
* - `cover`: (default) Preserving aspect ratio, ensure the image covers both provided dimensions by cropping/clipping to fit.
* - `contain`: Preserving aspect ratio, contain within both provided dimensions using "letterboxing" where necessary.
* - `fill`: Ignore the aspect ratio of the input and stretch to both provided dimensions.
* - `inside`: Preserving aspect ratio, resize the image to be as large as possible while ensuring its dimensions are less than or equal to both those specified.
* - `outside`: Preserving aspect ratio, resize the image to be as small as possible while ensuring its dimensions are greater than or equal to both those specified.

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.25.1",
"version": "0.25.2",
"author": "Lovell Fuller <npm@lovell.info>",
"homepage": "https://github.com/lovell/sharp",
"contributors": [
@@ -65,7 +65,8 @@
"Andargor <andargor@yahoo.com>",
"Paul Neave <paul.neave@gmail.com>",
"Brendan Kennedy <brenwken@gmail.com>",
"Brychan Bennett-Odlum <git@brychan.io>"
"Brychan Bennett-Odlum <git@brychan.io>",
"Edward Silverton <e.silverton@gmail.com>"
],
"scripts": {
"install": "(node install/libvips && node install/dll-copy && prebuild-install --runtime=napi) || (node-gyp rebuild && node install/dll-copy)",
@@ -125,7 +126,7 @@
"exif-reader": "^1.0.3",
"icc": "^1.0.0",
"license-checker": "^25.0.1",
"mocha": "^7.1.0",
"mocha": "^7.1.1",
"mock-fs": "^4.11.0",
"nyc": "^15.0.0",
"prebuild": "^10.0.0",

View File

@@ -229,6 +229,7 @@ Napi::Value metadata(const Napi::CallbackInfo& info) {
// Join queue for worker thread
Napi::Function callback = info[1].As<Napi::Function>();
MetadataWorker *worker = new MetadataWorker(callback, baton, debuglog);
worker->Receiver().Set("options", options);
worker->Queue();
// Increment queued task counter

View File

@@ -933,9 +933,6 @@ class PipelineWorker : public Napi::AsyncWorker {
};
suffix = AssembleSuffixString(".webp", options);
} else {
std::string extname = baton->tileLayout == VIPS_FOREIGN_DZ_LAYOUT_GOOGLE
|| baton->tileLayout == VIPS_FOREIGN_DZ_LAYOUT_ZOOMIFY
? ".jpg" : ".jpeg";
std::vector<std::pair<std::string, std::string>> options {
{"Q", std::to_string(baton->jpegQuality)},
{"interlace", baton->jpegProgressive ? "TRUE" : "FALSE"},
@@ -946,6 +943,7 @@ class PipelineWorker : public Napi::AsyncWorker {
{"optimize_scans", baton->jpegOptimiseScans ? "TRUE": "FALSE"},
{"optimize_coding", baton->jpegOptimiseCoding ? "TRUE": "FALSE"}
};
std::string extname = baton->tileLayout == VIPS_FOREIGN_DZ_LAYOUT_DZ ? ".jpeg" : ".jpg";
suffix = AssembleSuffixString(extname, options);
}
// Remove alpha channel from tile background if image does not contain an alpha channel
@@ -1362,6 +1360,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
// Join queue for worker thread
Napi::Function callback = info[1].As<Napi::Function>();
PipelineWorker *worker = new PipelineWorker(callback, baton, debuglog, queueListener);
worker->Receiver().Set("options", options);
worker->Queue();
// Increment queued task counter

View File

@@ -154,6 +154,7 @@ Napi::Value stats(const Napi::CallbackInfo& info) {
// Join queue for worker thread
Napi::Function callback = info[1].As<Napi::Function>();
StatsWorker *worker = new StatsWorker(callback, baton, debuglog);
worker->Receiver().Set("options", options);
worker->Queue();
// Increment queued task counter

View File

@@ -765,6 +765,30 @@ describe('Tile', function () {
});
});
it('IIIF layout', function (done) {
const directory = fixtures.path('output.iiif.info');
rimraf(directory, function () {
sharp(fixtures.inputJpg)
.tile({
layout: 'iiif'
})
.toFile(directory, function (err, info) {
if (err) throw err;
assert.strictEqual('dz', info.format);
assert.strictEqual(2725, info.width);
assert.strictEqual(2225, info.height);
assert.strictEqual(3, info.channels);
assert.strictEqual('number', typeof info.size);
fs.stat(path.join(directory, '0,0,256,256', '256,', '0', 'default.jpg'), function (err, stat) {
if (err) throw err;
assert.strictEqual(true, stat.isFile());
assert.strictEqual(true, stat.size > 0);
done();
});
});
});
});
it('Write to ZIP container using file extension', function (done) {
const container = fixtures.path('output.dz.container.zip');
const extractTo = fixtures.path('output.dz.container');