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/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 {String} [options.width] - alternative means of specifying `width`. If both are present this take priority.
221
- * @param {String} [options.height] - alternative means of specifying `height`. If both are present this take priority.
222
- * @param {String} [options.fit='cover'] - how the image should be resized to fit both provided dimensions, one of `cover`, `contain`, `fill`, `inside` or `outside`.
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'] - the kernel to use for image reduction.
226
- * @param {Boolean} [options.withoutEnlargement=false] - do not enlarge if the width *or* height are already less than the specified dimensions, equivalent to GraphicsMagick's `>` geometry option.
227
- * @param {Boolean} [options.withoutReduction=false] - do not reduce if the width *or* height are already greater than the specified dimensions, equivalent to GraphicsMagick's `<` geometry option.
228
- * @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 on some images.
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 (width, height, options) {
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(width)) {
237
- if (is.object(width) && !is.defined(options)) {
238
- options = width;
239
- } else if (is.integer(width) && width > 0) {
240
- this.options.width = 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', width);
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
- * Extends/pads the edges of the image with the provided background colour.
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
@@ -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 platformAndArch = require('./platform')();
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.31.2",
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 --slow=1000 --timeout=30000 ./test/unit/*.js",
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
- "docs-build": "documentation lint lib && node docs/build && node docs/search-index/build",
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": "^5.0.0",
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
- "documentation": "^14.0.0",
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.1.0",
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
- "rimraf": "^3.0.2",
154
- "semistandard": "^16.0.1"
157
+ "semistandard": "^16.0.1",
158
+ "tsd": "^0.28.0"
155
159
  },
156
160
  "license": "Apache-2.0",
157
161
  "config": {
158
- "libvips": "8.13.3",
162
+ "libvips": "8.14.2",
159
163
  "integrity": {
160
- "darwin-arm64v8": "sha512-xFgYt7CtQSZcWoyUdzPTDNHbioZIrZSEU+gkMxzH4Cgjhi4/N49UsonnIZhKQoTBGloAqEexHeMx4rYTQ2Kgvw==",
161
- "darwin-x64": "sha512-6SivWKzu15aUMMohe0wg7sNYMPETVnOe40BuWsnKOgzl3o5FpQqNSgs+68Mi8Za3Qti9/DaR+H/fyD0x48Af2w==",
162
- "linux-arm64v8": "sha512-b+iI9V/ehgDabXYRQcvqa5CEysh+1FQsgFmYc358StCrJCDahwNmsQdsiH1GOVd5WaWh5wHUGByPwMmFOO16Aw==",
163
- "linux-armv6": "sha512-zRP2F+EiustLE4bXSH8AHCxwfemh9d+QuvmPjira/HL6uJOUuA7SyQgVV1TPwTQle2ioCNnKPm7FEB/MAiT+ug==",
164
- "linux-armv7": "sha512-6OCChowE5lBXXXAZrnGdA9dVktg7UdODEBpE5qTroiAJYZv4yXRMgyDFYajok7du2NTgoklhxGk8d9+4vGv5hg==",
165
- "linux-x64": "sha512-OTmlmP2r8ozGKdB96X+K5oQE1ojVZanqLqqKlwDpEnfixyIaDGYbVzcjWBNGU3ai/26bvkaCkjynnc2ecYcsuA==",
166
- "linuxmusl-arm64v8": "sha512-Qh5Wi+bkKTohFYHzSPssfjMhIkD6z6EHbVmnwmWSsgY9zsUBStFp6+mKcNTQfP5YM5Mz06vJOkLHX2OzEr5TzA==",
167
- "linuxmusl-x64": "sha512-DwB4Fs3+ISw9etaLCANkueZDdk758iOS+wNp4TKZkHdq0al6B/3Pk7OHLR8a9E3H6wYDD328u++dcJzip5tacA==",
168
- "win32-arm64v8": "sha512-96r3W+O4BtX602B1MtxU5Ru4lKzRRTZqM4OQEBJ//TNL3fiCZdd9agD+RQBjaeR4KFIyBSt3F7IE425ZWmxz+w==",
169
- "win32-ia32": "sha512-qfN1MsfQGek1QQd1UNW7JT+5K5Ne1suFQ2GpgpYm3JLSpIve/tz2vOGEGzvTVssOBADJvAkTDFt+yIi3PgU9pA==",
170
- "win32-x64": "sha512-eb3aAmjbVVBVRbiYgebQwoxkAt69WI8nwmKlilSQ3kWqoc0pXfIe322rF2UR8ebbISCGvYRUfzD2r1k92RXISQ=="
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, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Lovell Fuller and contributors.
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, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Lovell Fuller and contributors.
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 < 13) || \
29
- (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 13 && VIPS_MICRO_VERSION < 3)
30
- #error "libvips version 8.13.3+ is required - please see https://sharp.pixelplumbing.com/install"
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, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Lovell Fuller and contributors.
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.Call({ Napi::String::New(env, warning) });
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", Napi::Buffer<char>::New(env, baton->exif, baton->exifLength, sharp::FreeCallback));
233
+ info.Set("exif", sharp::NewOrCopyBuffer(env, baton->exif, baton->exifLength));
239
234
  }
240
235
  if (baton->iccLength > 0) {
241
- info.Set("icc", Napi::Buffer<char>::New(env, baton->icc, baton->iccLength, sharp::FreeCallback));
236
+ info.Set("icc", sharp::NewOrCopyBuffer(env, baton->icc, baton->iccLength));
242
237
  }
243
238
  if (baton->iptcLength > 0) {
244
- info.Set("iptc", Napi::Buffer<char>::New(env, baton->iptc, baton->iptcLength, sharp::FreeCallback));
239
+ info.Set("iptc", sharp::NewOrCopyBuffer(env, baton->iptc, baton->iptcLength));
245
240
  }
246
241
  if (baton->xmpLength > 0) {
247
- info.Set("xmp", Napi::Buffer<char>::New(env, baton->xmp, baton->xmpLength, sharp::FreeCallback));
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
- Napi::Buffer<char>::New(env, baton->tifftagPhotoshop, baton->tifftagPhotoshopLength, sharp::FreeCallback));
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, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Lovell Fuller and contributors.
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;