sharp 0.31.2 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/binding.gyp +1 -1
- package/install/can-compile.js +3 -0
- package/install/dll-copy.js +3 -0
- package/install/libvips.js +6 -6
- package/lib/agent.js +5 -1
- package/lib/channel.js +4 -1
- package/lib/colour.js +3 -0
- package/lib/composite.js +3 -0
- package/lib/constructor.js +23 -9
- package/lib/index.d.ts +1614 -0
- package/lib/index.js +3 -0
- package/lib/input.js +39 -8
- package/lib/is.js +12 -0
- package/lib/libvips.js +4 -0
- package/lib/operation.js +94 -52
- package/lib/output.js +113 -11
- package/lib/platform.js +3 -0
- package/lib/resize.js +54 -19
- package/lib/sharp.js +3 -0
- package/lib/utility.js +5 -1
- package/package.json +30 -23
- package/src/common.cc +43 -14
- package/src/common.h +22 -16
- package/src/libvips/cplusplus/vips-operators.cpp +7 -0
- package/src/metadata.cc +17 -22
- package/src/metadata.h +3 -13
- package/src/operations.cc +13 -23
- package/src/operations.h +4 -15
- package/src/pipeline.cc +129 -69
- package/src/pipeline.h +30 -15
- package/src/sharp.cc +2 -13
- package/src/stats.cc +7 -17
- package/src/stats.h +2 -13
- package/src/utilities.cc +17 -28
- package/src/utilities.h +2 -13
package/lib/resize.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// Copyright 2013 Lovell Fuller and others.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
1
4
|
'use strict';
|
|
2
5
|
|
|
3
6
|
const is = require('./is');
|
|
@@ -36,6 +39,18 @@ const position = {
|
|
|
36
39
|
'left top': 8
|
|
37
40
|
};
|
|
38
41
|
|
|
42
|
+
/**
|
|
43
|
+
* How to extend the image.
|
|
44
|
+
* @member
|
|
45
|
+
* @private
|
|
46
|
+
*/
|
|
47
|
+
const extendWith = {
|
|
48
|
+
background: 'background',
|
|
49
|
+
copy: 'copy',
|
|
50
|
+
repeat: 'repeat',
|
|
51
|
+
mirror: 'mirror'
|
|
52
|
+
};
|
|
53
|
+
|
|
39
54
|
/**
|
|
40
55
|
* Strategies for automagic cover behaviour.
|
|
41
56
|
* @member
|
|
@@ -103,7 +118,7 @@ function isResizeExpected (options) {
|
|
|
103
118
|
* Resize image to `width`, `height` or `width x height`.
|
|
104
119
|
*
|
|
105
120
|
* When both a `width` and `height` are provided, the possible methods by which the image should **fit** these are:
|
|
106
|
-
* - `cover`: (default) Preserving aspect ratio, ensure the image covers both provided dimensions by cropping/clipping to fit.
|
|
121
|
+
* - `cover`: (default) Preserving aspect ratio, attempt to ensure the image covers both provided dimensions by cropping/clipping to fit.
|
|
107
122
|
* - `contain`: Preserving aspect ratio, contain within both provided dimensions using "letterboxing" where necessary.
|
|
108
123
|
* - `fill`: Ignore the aspect ratio of the input and stretch to both provided dimensions.
|
|
109
124
|
* - `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.
|
|
@@ -111,6 +126,8 @@ function isResizeExpected (options) {
|
|
|
111
126
|
*
|
|
112
127
|
* Some of these values are based on the [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) CSS property.
|
|
113
128
|
*
|
|
129
|
+
* <img alt="Examples of various values for the fit property when resizing" width="100%" style="aspect-ratio: 998/243" src="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/image/api-resize-fit.png">
|
|
130
|
+
*
|
|
114
131
|
* When using a **fit** of `cover` or `contain`, the default **position** is `centre`. Other options are:
|
|
115
132
|
* - `sharp.position`: `top`, `right top`, `right`, `right bottom`, `bottom`, `left bottom`, `left`, `left top`.
|
|
116
133
|
* - `sharp.gravity`: `north`, `northeast`, `east`, `southeast`, `south`, `southwest`, `west`, `northwest`, `center` or `centre`.
|
|
@@ -214,32 +231,32 @@ function isResizeExpected (options) {
|
|
|
214
231
|
* .toBuffer()
|
|
215
232
|
* );
|
|
216
233
|
*
|
|
217
|
-
* @param {number} [width] - pixels wide the resultant image should be. Use `null` or `undefined` to auto-scale the width to match the height.
|
|
218
|
-
* @param {number} [height] - pixels high the resultant image should be. Use `null` or `undefined` to auto-scale the height to match the width.
|
|
234
|
+
* @param {number} [width] - How many pixels wide the resultant image should be. Use `null` or `undefined` to auto-scale the width to match the height.
|
|
235
|
+
* @param {number} [height] - How many pixels high the resultant image should be. Use `null` or `undefined` to auto-scale the height to match the width.
|
|
219
236
|
* @param {Object} [options]
|
|
220
|
-
* @param {
|
|
221
|
-
* @param {
|
|
222
|
-
* @param {String} [options.fit='cover'] -
|
|
223
|
-
* @param {String} [options.position='centre'] - position, gravity or strategy to use when `fit` is `cover` or `contain`.
|
|
237
|
+
* @param {number} [options.width] - An alternative means of specifying `width`. If both are present this takes priority.
|
|
238
|
+
* @param {number} [options.height] - An alternative means of specifying `height`. If both are present this takes priority.
|
|
239
|
+
* @param {String} [options.fit='cover'] - How the image should be resized/cropped to fit the target dimension(s), one of `cover`, `contain`, `fill`, `inside` or `outside`.
|
|
240
|
+
* @param {String} [options.position='centre'] - A position, gravity or strategy to use when `fit` is `cover` or `contain`.
|
|
224
241
|
* @param {String|Object} [options.background={r: 0, g: 0, b: 0, alpha: 1}] - background colour when `fit` is `contain`, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black without transparency.
|
|
225
|
-
* @param {String} [options.kernel='lanczos3'] -
|
|
226
|
-
* @param {Boolean} [options.withoutEnlargement=false] -
|
|
227
|
-
* @param {Boolean} [options.withoutReduction=false] -
|
|
228
|
-
* @param {Boolean} [options.fastShrinkOnLoad=true] -
|
|
242
|
+
* @param {String} [options.kernel='lanczos3'] - The kernel to use for image reduction. Use the `fastShrinkOnLoad` option to control kernel vs shrink-on-load.
|
|
243
|
+
* @param {Boolean} [options.withoutEnlargement=false] - Do not scale up if the width *or* height are already less than the target dimensions, equivalent to GraphicsMagick's `>` geometry option. This may result in output dimensions smaller than the target dimensions.
|
|
244
|
+
* @param {Boolean} [options.withoutReduction=false] - Do not scale down if the width *or* height are already greater than the target dimensions, equivalent to GraphicsMagick's `<` geometry option. This may still result in a crop to reach the target dimensions.
|
|
245
|
+
* @param {Boolean} [options.fastShrinkOnLoad=true] - Take greater advantage of the JPEG and WebP shrink-on-load feature, which can lead to a slight moiré pattern or round-down of an auto-scaled dimension.
|
|
229
246
|
* @returns {Sharp}
|
|
230
247
|
* @throws {Error} Invalid parameters
|
|
231
248
|
*/
|
|
232
|
-
function resize (
|
|
249
|
+
function resize (widthOrOptions, height, options) {
|
|
233
250
|
if (isResizeExpected(this.options)) {
|
|
234
251
|
this.options.debuglog('ignoring previous resize options');
|
|
235
252
|
}
|
|
236
|
-
if (is.defined(
|
|
237
|
-
if (is.object(
|
|
238
|
-
options =
|
|
239
|
-
} else if (is.integer(
|
|
240
|
-
this.options.width =
|
|
253
|
+
if (is.defined(widthOrOptions)) {
|
|
254
|
+
if (is.object(widthOrOptions) && !is.defined(options)) {
|
|
255
|
+
options = widthOrOptions;
|
|
256
|
+
} else if (is.integer(widthOrOptions) && widthOrOptions > 0) {
|
|
257
|
+
this.options.width = widthOrOptions;
|
|
241
258
|
} else {
|
|
242
|
-
throw is.invalidParameterError('width', 'positive integer',
|
|
259
|
+
throw is.invalidParameterError('width', 'positive integer', widthOrOptions);
|
|
243
260
|
}
|
|
244
261
|
} else {
|
|
245
262
|
this.options.width = -1;
|
|
@@ -320,7 +337,8 @@ function resize (width, height, options) {
|
|
|
320
337
|
}
|
|
321
338
|
|
|
322
339
|
/**
|
|
323
|
-
*
|
|
340
|
+
* Extend / pad / extrude one or more edges of the image with either
|
|
341
|
+
* the provided background colour or pixels derived from the image.
|
|
324
342
|
* This operation will always occur after resizing and extraction, if any.
|
|
325
343
|
*
|
|
326
344
|
* @example
|
|
@@ -346,11 +364,21 @@ function resize (width, height, options) {
|
|
|
346
364
|
* })
|
|
347
365
|
* ...
|
|
348
366
|
*
|
|
367
|
+
* @example
|
|
368
|
+
* // Extrude image by 8 pixels to the right, mirroring existing right hand edge
|
|
369
|
+
* sharp(input)
|
|
370
|
+
* .extend({
|
|
371
|
+
* right: 8,
|
|
372
|
+
* background: 'mirror'
|
|
373
|
+
* })
|
|
374
|
+
* ...
|
|
375
|
+
*
|
|
349
376
|
* @param {(number|Object)} extend - single pixel count to add to all edges or an Object with per-edge counts
|
|
350
377
|
* @param {number} [extend.top=0]
|
|
351
378
|
* @param {number} [extend.left=0]
|
|
352
379
|
* @param {number} [extend.bottom=0]
|
|
353
380
|
* @param {number} [extend.right=0]
|
|
381
|
+
* @param {String} [extend.extendWith='background'] - populate new pixels using this method, one of: background, copy, repeat, mirror.
|
|
354
382
|
* @param {String|Object} [extend.background={r: 0, g: 0, b: 0, alpha: 1}] - background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to black without transparency.
|
|
355
383
|
* @returns {Sharp}
|
|
356
384
|
* @throws {Error} Invalid parameters
|
|
@@ -391,6 +419,13 @@ function extend (extend) {
|
|
|
391
419
|
}
|
|
392
420
|
}
|
|
393
421
|
this._setBackgroundColourOption('extendBackground', extend.background);
|
|
422
|
+
if (is.defined(extend.extendWith)) {
|
|
423
|
+
if (is.string(extendWith[extend.extendWith])) {
|
|
424
|
+
this.options.extendWith = extendWith[extend.extendWith];
|
|
425
|
+
} else {
|
|
426
|
+
throw is.invalidParameterError('extendWith', 'one of: background, copy, repeat, mirror', extend.extendWith);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
394
429
|
} else {
|
|
395
430
|
throw is.invalidParameterError('extend', 'integer or object', extend);
|
|
396
431
|
}
|
package/lib/sharp.js
CHANGED
package/lib/utility.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// Copyright 2013 Lovell Fuller and others.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
1
4
|
'use strict';
|
|
2
5
|
|
|
3
6
|
const fs = require('fs');
|
|
@@ -43,7 +46,7 @@ const interpolators = {
|
|
|
43
46
|
};
|
|
44
47
|
|
|
45
48
|
/**
|
|
46
|
-
* An Object containing the version numbers of libvips and its dependencies.
|
|
49
|
+
* An Object containing the version numbers of sharp, libvips and its dependencies.
|
|
47
50
|
* @member
|
|
48
51
|
* @example
|
|
49
52
|
* console.log(sharp.versions);
|
|
@@ -54,6 +57,7 @@ let versions = {
|
|
|
54
57
|
try {
|
|
55
58
|
versions = require(`../vendor/${versions.vips}/${platformAndArch}/versions.json`);
|
|
56
59
|
} catch (_err) { /* ignore */ }
|
|
60
|
+
versions.sharp = require('../package.json').version;
|
|
57
61
|
|
|
58
62
|
/**
|
|
59
63
|
* An Object containing the platform and architecture
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sharp",
|
|
3
3
|
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.32.0",
|
|
5
5
|
"author": "Lovell Fuller <npm@lovell.info>",
|
|
6
6
|
"homepage": "https://github.com/lovell/sharp",
|
|
7
7
|
"contributors": [
|
|
@@ -85,21 +85,24 @@
|
|
|
85
85
|
"Brodan <christopher.hranj@gmail.com",
|
|
86
86
|
"Ankur Parihar <ankur.github@gmail.com>",
|
|
87
87
|
"Brahim Ait elhaj <brahima@gmail.com>",
|
|
88
|
-
"Mart Jansink <m.jansink@gmail.com>"
|
|
88
|
+
"Mart Jansink <m.jansink@gmail.com>",
|
|
89
|
+
"Lachlan Newman <lachnewman007@gmail.com>"
|
|
89
90
|
],
|
|
90
91
|
"scripts": {
|
|
91
92
|
"install": "(node install/libvips && node install/dll-copy && prebuild-install) || (node install/can-compile && node-gyp rebuild && node install/dll-copy)",
|
|
92
93
|
"clean": "rm -rf node_modules/ build/ vendor/ .nyc_output/ coverage/ test/fixtures/output.*",
|
|
93
|
-
"test": "npm run test-lint && npm run test-unit && npm run test-licensing",
|
|
94
|
+
"test": "npm run test-lint && npm run test-unit && npm run test-licensing && npm run test-types",
|
|
94
95
|
"test-lint": "semistandard && cpplint",
|
|
95
|
-
"test-unit": "nyc --reporter=lcov --reporter=text --check-coverage --branches=100 mocha
|
|
96
|
+
"test-unit": "nyc --reporter=lcov --reporter=text --check-coverage --branches=100 mocha",
|
|
96
97
|
"test-licensing": "license-checker --production --summary --onlyAllow=\"Apache-2.0;BSD;ISC;MIT\"",
|
|
97
98
|
"test-leak": "./test/leak/leak.sh",
|
|
98
|
-
"
|
|
99
|
+
"test-types": "tsd",
|
|
100
|
+
"docs-build": "node docs/build && node docs/search-index/build",
|
|
99
101
|
"docs-serve": "cd docs && npx serve",
|
|
100
102
|
"docs-publish": "cd docs && npx firebase-tools deploy --project pixelplumbing --only hosting:pixelplumbing-sharp"
|
|
101
103
|
},
|
|
102
104
|
"main": "lib/index.js",
|
|
105
|
+
"types": "lib/index.d.ts",
|
|
103
106
|
"files": [
|
|
104
107
|
"binding.gyp",
|
|
105
108
|
"install/**",
|
|
@@ -131,7 +134,7 @@
|
|
|
131
134
|
"dependencies": {
|
|
132
135
|
"color": "^4.2.3",
|
|
133
136
|
"detect-libc": "^2.0.1",
|
|
134
|
-
"node-addon-api": "^
|
|
137
|
+
"node-addon-api": "^6.0.0",
|
|
135
138
|
"prebuild-install": "^7.1.1",
|
|
136
139
|
"semver": "^7.3.8",
|
|
137
140
|
"simple-get": "^4.0.1",
|
|
@@ -139,35 +142,36 @@
|
|
|
139
142
|
"tunnel-agent": "^0.6.0"
|
|
140
143
|
},
|
|
141
144
|
"devDependencies": {
|
|
145
|
+
"@types/node": "*",
|
|
142
146
|
"async": "^3.2.4",
|
|
143
147
|
"cc": "^3.0.1",
|
|
144
|
-
"
|
|
145
|
-
"exif-reader": "^1.0.3",
|
|
148
|
+
"exif-reader": "^1.2.0",
|
|
146
149
|
"extract-zip": "^2.0.1",
|
|
147
150
|
"icc": "^2.0.0",
|
|
151
|
+
"jsdoc-to-markdown": "^8.0.0",
|
|
148
152
|
"license-checker": "^25.0.1",
|
|
149
|
-
"mocha": "^10.
|
|
153
|
+
"mocha": "^10.2.0",
|
|
150
154
|
"mock-fs": "^5.2.0",
|
|
151
155
|
"nyc": "^15.1.0",
|
|
152
156
|
"prebuild": "^11.0.4",
|
|
153
|
-
"
|
|
154
|
-
"
|
|
157
|
+
"semistandard": "^16.0.1",
|
|
158
|
+
"tsd": "^0.28.0"
|
|
155
159
|
},
|
|
156
160
|
"license": "Apache-2.0",
|
|
157
161
|
"config": {
|
|
158
|
-
"libvips": "8.
|
|
162
|
+
"libvips": "8.14.2",
|
|
159
163
|
"integrity": {
|
|
160
|
-
"darwin-arm64v8": "sha512-
|
|
161
|
-
"darwin-x64": "sha512-
|
|
162
|
-
"linux-arm64v8": "sha512-
|
|
163
|
-
"linux-armv6": "sha512-
|
|
164
|
-
"linux-armv7": "sha512
|
|
165
|
-
"linux-x64": "sha512-
|
|
166
|
-
"linuxmusl-arm64v8": "sha512-
|
|
167
|
-
"linuxmusl-x64": "sha512-
|
|
168
|
-
"win32-arm64v8": "sha512-
|
|
169
|
-
"win32-ia32": "sha512-
|
|
170
|
-
"win32-x64": "sha512-
|
|
164
|
+
"darwin-arm64v8": "sha512-eUuxg6H0tXgX4z2lsaGtZ4cbPAm7yoFgkvPDd4csxoiVt+QUB25pEJwiXw7oB53VlBFIp3O8lbydSFS5zH8MQQ==",
|
|
165
|
+
"darwin-x64": "sha512-cMT4v76IgzSR0VoXqLk/yftRyzMEZ+SBVMLzXCgqP/lmnYisrpmHHNqrWnoZbUUBXbPXLn6KMultYOJHe/c9ZQ==",
|
|
166
|
+
"linux-arm64v8": "sha512-OcDJ/ly80pxwaKnw0W91sSvZczPtWsjmzrY/+6NMiQZT84LkmeaRuwErbHhorKDxnl7iZuNn9Uj5V25Xmj+LDQ==",
|
|
167
|
+
"linux-armv6": "sha512-hk2ohSOYTJEtVQxEQFyQ+tuayKpYqx6NiXa7AE+8MF+yscxt+g+mLJ7TjDqtmb4ttFGH4IVfsEfU2YXIqWqkpg==",
|
|
168
|
+
"linux-armv7": "sha512-/5Ci2Cd+yLZmTaEt9lVJ89elxX3RMJpps0ESjj43X40yrwka51QfXeg1QV38uNzZpCDIZkrbXZK0lyKldjpLuA==",
|
|
169
|
+
"linux-x64": "sha512-wjCKmWfBb0uz1UB7rPDLvO0s+VWuoAY/Vv/YGCRFEQUkdSLQUgHExrOMMbOM3FleuYfQqznDYCXXphkl7X44+w==",
|
|
170
|
+
"linuxmusl-arm64v8": "sha512-QtD2n90yi+rLE65C0gksFUU5uMUFPICI/pS3A0bgthpIcoCejAOYs3ZjVWpZbHQuV/lWahIUYO78MB9CzY860A==",
|
|
171
|
+
"linuxmusl-x64": "sha512-TokQ/ETCJAsPYuxIMOPYDp25rlcwtpmIMtRUR9PB75TmZEJe7abRfCEInIPYeD8F/HxxnJSLiEdlbn1z1Jfzng==",
|
|
172
|
+
"win32-arm64v8": "sha512-IIuj4EAgLqEVAoOuYH79C61a7TcJXlU/RBwk+5JsGWc2mr4J/Ar5J01e6XBvU4Lu3eqcU+3GPaACZEa1511buA==",
|
|
173
|
+
"win32-ia32": "sha512-CsZi7lrReX3B6tmYgOGJ0IiAfcN5APDC6l+3gdosxfTfwpLLO+jXaSmyNwIGeMqrdgckG/gwwc+IrUZmkmjJ/A==",
|
|
174
|
+
"win32-x64": "sha512-J7znmNKUK4ZKo6SnSnEtzT1xRAwvkGXxIx9/QihAadu1TFdS06yNhcENmwC4973+KZBlAdVpWbZ8sLrEoWkdCA=="
|
|
171
175
|
},
|
|
172
176
|
"runtime": "napi",
|
|
173
177
|
"target": 7
|
|
@@ -193,5 +197,8 @@
|
|
|
193
197
|
"filter": [
|
|
194
198
|
"build/include"
|
|
195
199
|
]
|
|
200
|
+
},
|
|
201
|
+
"tsd": {
|
|
202
|
+
"directory": "test/types/"
|
|
196
203
|
}
|
|
197
204
|
}
|
package/src/common.cc
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
|
-
// Copyright 2013
|
|
2
|
-
//
|
|
3
|
-
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
// you may not use this file except in compliance with the License.
|
|
5
|
-
// You may obtain a copy of the License at
|
|
6
|
-
//
|
|
7
|
-
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
//
|
|
9
|
-
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
// See the License for the specific language governing permissions and
|
|
13
|
-
// limitations under the License.
|
|
1
|
+
// Copyright 2013 Lovell Fuller and others.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
14
3
|
|
|
15
4
|
#include <cstdlib>
|
|
16
5
|
#include <string>
|
|
@@ -76,6 +65,16 @@ namespace sharp {
|
|
|
76
65
|
}
|
|
77
66
|
return vector;
|
|
78
67
|
}
|
|
68
|
+
Napi::Buffer<char> NewOrCopyBuffer(Napi::Env env, char* data, size_t len) {
|
|
69
|
+
try {
|
|
70
|
+
return Napi::Buffer<char>::New(env, data, len, FreeCallback);
|
|
71
|
+
} catch (Napi::Error const &err) {
|
|
72
|
+
static_cast<void>(err);
|
|
73
|
+
}
|
|
74
|
+
Napi::Buffer<char> buf = Napi::Buffer<char>::Copy(env, data, len);
|
|
75
|
+
FreeCallback(nullptr, data);
|
|
76
|
+
return buf;
|
|
77
|
+
}
|
|
79
78
|
|
|
80
79
|
// Create an InputDescriptor instance from a Napi::Object describing an input image
|
|
81
80
|
InputDescriptor* CreateInputDescriptor(Napi::Object input) {
|
|
@@ -93,6 +92,10 @@ namespace sharp {
|
|
|
93
92
|
if (HasAttr(input, "density")) {
|
|
94
93
|
descriptor->density = AttrAsDouble(input, "density");
|
|
95
94
|
}
|
|
95
|
+
// Should we ignore any embedded ICC profile
|
|
96
|
+
if (HasAttr(input, "ignoreIcc")) {
|
|
97
|
+
descriptor->ignoreIcc = AttrAsBool(input, "ignoreIcc");
|
|
98
|
+
}
|
|
96
99
|
// Raw pixel input
|
|
97
100
|
if (HasAttr(input, "rawChannels")) {
|
|
98
101
|
descriptor->rawDepth = AttrAsEnum<VipsBandFormat>(input, "rawDepth", VIPS_TYPE_BAND_FORMAT);
|
|
@@ -159,6 +162,9 @@ namespace sharp {
|
|
|
159
162
|
if (HasAttr(input, "textSpacing")) {
|
|
160
163
|
descriptor->textSpacing = AttrAsUint32(input, "textSpacing");
|
|
161
164
|
}
|
|
165
|
+
if (HasAttr(input, "textWrap")) {
|
|
166
|
+
descriptor->textWrap = AttrAsEnum<VipsTextWrap>(input, "textWrap", VIPS_TYPE_TEXT_WRAP);
|
|
167
|
+
}
|
|
162
168
|
}
|
|
163
169
|
// Limit input images to a given number of pixels, where pixels = width * height
|
|
164
170
|
descriptor->limitInputPixels = static_cast<uint64_t>(AttrAsInt64(input, "limitInputPixels"));
|
|
@@ -207,6 +213,9 @@ namespace sharp {
|
|
|
207
213
|
bool IsAvif(std::string const &str) {
|
|
208
214
|
return EndsWith(str, ".avif") || EndsWith(str, ".AVIF");
|
|
209
215
|
}
|
|
216
|
+
bool IsJxl(std::string const &str) {
|
|
217
|
+
return EndsWith(str, ".jxl") || EndsWith(str, ".JXL");
|
|
218
|
+
}
|
|
210
219
|
bool IsDz(std::string const &str) {
|
|
211
220
|
return EndsWith(str, ".dzi") || EndsWith(str, ".DZI");
|
|
212
221
|
}
|
|
@@ -217,6 +226,13 @@ namespace sharp {
|
|
|
217
226
|
return EndsWith(str, ".v") || EndsWith(str, ".V") || EndsWith(str, ".vips") || EndsWith(str, ".VIPS");
|
|
218
227
|
}
|
|
219
228
|
|
|
229
|
+
/*
|
|
230
|
+
Trim space from end of string.
|
|
231
|
+
*/
|
|
232
|
+
std::string TrimEnd(std::string const &str) {
|
|
233
|
+
return str.substr(0, str.find_last_not_of(" \n\r\f") + 1);
|
|
234
|
+
}
|
|
235
|
+
|
|
220
236
|
/*
|
|
221
237
|
Provide a string identifier for the given image type.
|
|
222
238
|
*/
|
|
@@ -237,6 +253,7 @@ namespace sharp {
|
|
|
237
253
|
case ImageType::PPM: id = "ppm"; break;
|
|
238
254
|
case ImageType::FITS: id = "fits"; break;
|
|
239
255
|
case ImageType::EXR: id = "exr"; break;
|
|
256
|
+
case ImageType::JXL: id = "jxl"; break;
|
|
240
257
|
case ImageType::VIPS: id = "vips"; break;
|
|
241
258
|
case ImageType::RAW: id = "raw"; break;
|
|
242
259
|
case ImageType::UNKNOWN: id = "unknown"; break;
|
|
@@ -281,6 +298,8 @@ namespace sharp {
|
|
|
281
298
|
{ "VipsForeignLoadPpmFile", ImageType::PPM },
|
|
282
299
|
{ "VipsForeignLoadFitsFile", ImageType::FITS },
|
|
283
300
|
{ "VipsForeignLoadOpenexr", ImageType::EXR },
|
|
301
|
+
{ "VipsForeignLoadJxlFile", ImageType::JXL },
|
|
302
|
+
{ "VipsForeignLoadJxlBuffer", ImageType::JXL },
|
|
284
303
|
{ "VipsForeignLoadVips", ImageType::VIPS },
|
|
285
304
|
{ "VipsForeignLoadVipsFile", ImageType::VIPS },
|
|
286
305
|
{ "VipsForeignLoadRaw", ImageType::RAW }
|
|
@@ -440,6 +459,7 @@ namespace sharp {
|
|
|
440
459
|
->set("justify", descriptor->textJustify)
|
|
441
460
|
->set("rgba", descriptor->textRgba)
|
|
442
461
|
->set("spacing", descriptor->textSpacing)
|
|
462
|
+
->set("wrap", descriptor->textWrap)
|
|
443
463
|
->set("autofit_dpi", &descriptor->textAutofitDpi);
|
|
444
464
|
if (descriptor->textWidth > 0) {
|
|
445
465
|
textOptions->set("width", descriptor->textWidth);
|
|
@@ -598,6 +618,15 @@ namespace sharp {
|
|
|
598
618
|
return copy;
|
|
599
619
|
}
|
|
600
620
|
|
|
621
|
+
/*
|
|
622
|
+
Remove GIF palette from image.
|
|
623
|
+
*/
|
|
624
|
+
VImage RemoveGifPalette(VImage image) {
|
|
625
|
+
VImage copy = image.copy();
|
|
626
|
+
copy.remove("gif-palette");
|
|
627
|
+
return copy;
|
|
628
|
+
}
|
|
629
|
+
|
|
601
630
|
/*
|
|
602
631
|
Does this image have a non-default density?
|
|
603
632
|
*/
|
|
@@ -913,7 +942,7 @@ namespace sharp {
|
|
|
913
942
|
// Add non-transparent alpha channel, if required
|
|
914
943
|
if (colour[3] < 255.0 && !HasAlpha(image)) {
|
|
915
944
|
image = image.bandjoin(
|
|
916
|
-
VImage::new_matrix(image.width(), image.height()).new_from_image(255 * multiplier));
|
|
945
|
+
VImage::new_matrix(image.width(), image.height()).new_from_image(255 * multiplier).cast(image.format()));
|
|
917
946
|
}
|
|
918
947
|
return std::make_tuple(image, alphaColour);
|
|
919
948
|
}
|
package/src/common.h
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
|
-
// Copyright 2013
|
|
2
|
-
//
|
|
3
|
-
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
// you may not use this file except in compliance with the License.
|
|
5
|
-
// You may obtain a copy of the License at
|
|
6
|
-
//
|
|
7
|
-
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
//
|
|
9
|
-
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
// See the License for the specific language governing permissions and
|
|
13
|
-
// limitations under the License.
|
|
1
|
+
// Copyright 2013 Lovell Fuller and others.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
14
3
|
|
|
15
4
|
#ifndef SRC_COMMON_H_
|
|
16
5
|
#define SRC_COMMON_H_
|
|
@@ -25,9 +14,9 @@
|
|
|
25
14
|
// Verify platform and compiler compatibility
|
|
26
15
|
|
|
27
16
|
#if (VIPS_MAJOR_VERSION < 8) || \
|
|
28
|
-
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION <
|
|
29
|
-
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION ==
|
|
30
|
-
#error "libvips version 8.
|
|
17
|
+
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 14) || \
|
|
18
|
+
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 14 && VIPS_MICRO_VERSION < 2)
|
|
19
|
+
#error "libvips version 8.14.2+ is required - please see https://sharp.pixelplumbing.com/install"
|
|
31
20
|
#endif
|
|
32
21
|
|
|
33
22
|
#if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))
|
|
@@ -55,6 +44,7 @@ namespace sharp {
|
|
|
55
44
|
size_t bufferLength;
|
|
56
45
|
bool isBuffer;
|
|
57
46
|
double density;
|
|
47
|
+
bool ignoreIcc;
|
|
58
48
|
VipsBandFormat rawDepth;
|
|
59
49
|
int rawChannels;
|
|
60
50
|
int rawWidth;
|
|
@@ -81,6 +71,7 @@ namespace sharp {
|
|
|
81
71
|
int textDpi;
|
|
82
72
|
bool textRgba;
|
|
83
73
|
int textSpacing;
|
|
74
|
+
VipsTextWrap textWrap;
|
|
84
75
|
int textAutofitDpi;
|
|
85
76
|
|
|
86
77
|
InputDescriptor():
|
|
@@ -92,6 +83,7 @@ namespace sharp {
|
|
|
92
83
|
bufferLength(0),
|
|
93
84
|
isBuffer(FALSE),
|
|
94
85
|
density(72.0),
|
|
86
|
+
ignoreIcc(FALSE),
|
|
95
87
|
rawDepth(VIPS_FORMAT_UCHAR),
|
|
96
88
|
rawChannels(0),
|
|
97
89
|
rawWidth(0),
|
|
@@ -114,6 +106,7 @@ namespace sharp {
|
|
|
114
106
|
textDpi(72),
|
|
115
107
|
textRgba(FALSE),
|
|
116
108
|
textSpacing(0),
|
|
109
|
+
textWrap(VIPS_TEXT_WRAP_WORD),
|
|
117
110
|
textAutofitDpi(0) {}
|
|
118
111
|
};
|
|
119
112
|
|
|
@@ -133,6 +126,7 @@ namespace sharp {
|
|
|
133
126
|
return static_cast<T>(
|
|
134
127
|
vips_enum_from_nick(nullptr, type, AttrAsStr(obj, attr).data()));
|
|
135
128
|
}
|
|
129
|
+
Napi::Buffer<char> NewOrCopyBuffer(Napi::Env env, char* data, size_t len);
|
|
136
130
|
|
|
137
131
|
// Create an InputDescriptor instance from a Napi::Object describing an input image
|
|
138
132
|
InputDescriptor* CreateInputDescriptor(Napi::Object input);
|
|
@@ -152,6 +146,7 @@ namespace sharp {
|
|
|
152
146
|
PPM,
|
|
153
147
|
FITS,
|
|
154
148
|
EXR,
|
|
149
|
+
JXL,
|
|
155
150
|
VIPS,
|
|
156
151
|
RAW,
|
|
157
152
|
UNKNOWN,
|
|
@@ -182,10 +177,16 @@ namespace sharp {
|
|
|
182
177
|
bool IsHeic(std::string const &str);
|
|
183
178
|
bool IsHeif(std::string const &str);
|
|
184
179
|
bool IsAvif(std::string const &str);
|
|
180
|
+
bool IsJxl(std::string const &str);
|
|
185
181
|
bool IsDz(std::string const &str);
|
|
186
182
|
bool IsDzZip(std::string const &str);
|
|
187
183
|
bool IsV(std::string const &str);
|
|
188
184
|
|
|
185
|
+
/*
|
|
186
|
+
Trim space from end of string.
|
|
187
|
+
*/
|
|
188
|
+
std::string TrimEnd(std::string const &str);
|
|
189
|
+
|
|
189
190
|
/*
|
|
190
191
|
Provide a string identifier for the given image type.
|
|
191
192
|
*/
|
|
@@ -252,6 +253,11 @@ namespace sharp {
|
|
|
252
253
|
*/
|
|
253
254
|
VImage RemoveAnimationProperties(VImage image);
|
|
254
255
|
|
|
256
|
+
/*
|
|
257
|
+
Remove GIF palette from image.
|
|
258
|
+
*/
|
|
259
|
+
VImage RemoveGifPalette(VImage image);
|
|
260
|
+
|
|
255
261
|
/*
|
|
256
262
|
Does this image have a non-default density?
|
|
257
263
|
*/
|
|
@@ -3679,6 +3679,13 @@ VipsBlob *VImage::webpsave_buffer( VOption *options ) const
|
|
|
3679
3679
|
return( buffer );
|
|
3680
3680
|
}
|
|
3681
3681
|
|
|
3682
|
+
void VImage::webpsave_mime( VOption *options ) const
|
|
3683
|
+
{
|
|
3684
|
+
call( "webpsave_mime",
|
|
3685
|
+
(options ? options : VImage::option())->
|
|
3686
|
+
set( "in", *this ) );
|
|
3687
|
+
}
|
|
3688
|
+
|
|
3682
3689
|
void VImage::webpsave_target( VTarget target, VOption *options ) const
|
|
3683
3690
|
{
|
|
3684
3691
|
call( "webpsave_target",
|
package/src/metadata.cc
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
|
-
// Copyright 2013
|
|
2
|
-
//
|
|
3
|
-
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
// you may not use this file except in compliance with the License.
|
|
5
|
-
// You may obtain a copy of the License at
|
|
6
|
-
//
|
|
7
|
-
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
//
|
|
9
|
-
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
// See the License for the specific language governing permissions and
|
|
13
|
-
// limitations under the License.
|
|
1
|
+
// Copyright 2013 Lovell Fuller and others.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
14
3
|
|
|
15
4
|
#include <numeric>
|
|
16
5
|
#include <vector>
|
|
@@ -80,6 +69,9 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|
|
80
69
|
if (image.get_typeof(VIPS_META_RESOLUTION_UNIT) == VIPS_TYPE_REF_STRING) {
|
|
81
70
|
baton->resolutionUnit = image.get_string(VIPS_META_RESOLUTION_UNIT);
|
|
82
71
|
}
|
|
72
|
+
if (image.get_typeof("magick-format") == VIPS_TYPE_REF_STRING) {
|
|
73
|
+
baton->formatMagick = image.get_string("magick-format");
|
|
74
|
+
}
|
|
83
75
|
if (image.get_typeof("openslide.level-count") == VIPS_TYPE_REF_STRING) {
|
|
84
76
|
int const levels = std::stoi(image.get_string("openslide.level-count"));
|
|
85
77
|
for (int l = 0; l < levels; l++) {
|
|
@@ -153,7 +145,7 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|
|
153
145
|
// Handle warnings
|
|
154
146
|
std::string warning = sharp::VipsWarningPop();
|
|
155
147
|
while (!warning.empty()) {
|
|
156
|
-
debuglog.
|
|
148
|
+
debuglog.MakeCallback(Receiver().Value(), { Napi::String::New(env, warning) });
|
|
157
149
|
warning = sharp::VipsWarningPop();
|
|
158
150
|
}
|
|
159
151
|
|
|
@@ -204,6 +196,9 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|
|
204
196
|
if (!baton->resolutionUnit.empty()) {
|
|
205
197
|
info.Set("resolutionUnit", baton->resolutionUnit == "in" ? "inch" : baton->resolutionUnit);
|
|
206
198
|
}
|
|
199
|
+
if (!baton->formatMagick.empty()) {
|
|
200
|
+
info.Set("formatMagick", baton->formatMagick);
|
|
201
|
+
}
|
|
207
202
|
if (!baton->levels.empty()) {
|
|
208
203
|
int i = 0;
|
|
209
204
|
Napi::Array levels = Napi::Array::New(env, static_cast<size_t>(baton->levels.size()));
|
|
@@ -235,24 +230,24 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|
|
235
230
|
info.Set("orientation", baton->orientation);
|
|
236
231
|
}
|
|
237
232
|
if (baton->exifLength > 0) {
|
|
238
|
-
info.Set("exif",
|
|
233
|
+
info.Set("exif", sharp::NewOrCopyBuffer(env, baton->exif, baton->exifLength));
|
|
239
234
|
}
|
|
240
235
|
if (baton->iccLength > 0) {
|
|
241
|
-
info.Set("icc",
|
|
236
|
+
info.Set("icc", sharp::NewOrCopyBuffer(env, baton->icc, baton->iccLength));
|
|
242
237
|
}
|
|
243
238
|
if (baton->iptcLength > 0) {
|
|
244
|
-
info.Set("iptc",
|
|
239
|
+
info.Set("iptc", sharp::NewOrCopyBuffer(env, baton->iptc, baton->iptcLength));
|
|
245
240
|
}
|
|
246
241
|
if (baton->xmpLength > 0) {
|
|
247
|
-
info.Set("xmp",
|
|
242
|
+
info.Set("xmp", sharp::NewOrCopyBuffer(env, baton->xmp, baton->xmpLength));
|
|
248
243
|
}
|
|
249
244
|
if (baton->tifftagPhotoshopLength > 0) {
|
|
250
245
|
info.Set("tifftagPhotoshop",
|
|
251
|
-
|
|
246
|
+
sharp::NewOrCopyBuffer(env, baton->tifftagPhotoshop, baton->tifftagPhotoshopLength));
|
|
252
247
|
}
|
|
253
248
|
Callback().MakeCallback(Receiver().Value(), { env.Null(), info });
|
|
254
249
|
} else {
|
|
255
|
-
Callback().MakeCallback(Receiver().Value(), { Napi::Error::New(env, baton->err).Value() });
|
|
250
|
+
Callback().MakeCallback(Receiver().Value(), { Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
|
|
256
251
|
}
|
|
257
252
|
|
|
258
253
|
delete baton->input;
|
|
@@ -270,7 +265,7 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|
|
270
265
|
Napi::Value metadata(const Napi::CallbackInfo& info) {
|
|
271
266
|
// V8 objects are converted to non-V8 types held in the baton struct
|
|
272
267
|
MetadataBaton *baton = new MetadataBaton;
|
|
273
|
-
Napi::Object options = info[0].As<Napi::Object>();
|
|
268
|
+
Napi::Object options = info[size_t(0)].As<Napi::Object>();
|
|
274
269
|
|
|
275
270
|
// Input
|
|
276
271
|
baton->input = sharp::CreateInputDescriptor(options.Get("input").As<Napi::Object>());
|
|
@@ -279,7 +274,7 @@ Napi::Value metadata(const Napi::CallbackInfo& info) {
|
|
|
279
274
|
Napi::Function debuglog = options.Get("debuglog").As<Napi::Function>();
|
|
280
275
|
|
|
281
276
|
// Join queue for worker thread
|
|
282
|
-
Napi::Function callback = info[1].As<Napi::Function>();
|
|
277
|
+
Napi::Function callback = info[size_t(1)].As<Napi::Function>();
|
|
283
278
|
MetadataWorker *worker = new MetadataWorker(callback, baton, debuglog);
|
|
284
279
|
worker->Receiver().Set("options", options);
|
|
285
280
|
worker->Queue();
|
package/src/metadata.h
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
|
-
// Copyright 2013
|
|
2
|
-
//
|
|
3
|
-
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
// you may not use this file except in compliance with the License.
|
|
5
|
-
// You may obtain a copy of the License at
|
|
6
|
-
//
|
|
7
|
-
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
//
|
|
9
|
-
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
// See the License for the specific language governing permissions and
|
|
13
|
-
// limitations under the License.
|
|
1
|
+
// Copyright 2013 Lovell Fuller and others.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
14
3
|
|
|
15
4
|
#ifndef SRC_METADATA_H_
|
|
16
5
|
#define SRC_METADATA_H_
|
|
@@ -41,6 +30,7 @@ struct MetadataBaton {
|
|
|
41
30
|
int pagePrimary;
|
|
42
31
|
std::string compression;
|
|
43
32
|
std::string resolutionUnit;
|
|
33
|
+
std::string formatMagick;
|
|
44
34
|
std::vector<std::pair<int, int>> levels;
|
|
45
35
|
int subifds;
|
|
46
36
|
std::vector<double> background;
|