@revizly/sharp 0.33.3-revizly5 → 0.33.4-revizly2
Sign up to get free protection for your applications and to get access to all the features.
- package/install/check.js +2 -2
- package/lib/colour.js +0 -2
- package/lib/index.d.ts +8 -0
- package/lib/input.js +8 -8
- package/lib/libvips.js +10 -4
- package/lib/resize.js +8 -3
- package/lib/utility.js +3 -0
- package/package.json +13 -13
- package/src/common.cc +9 -8
- package/src/common.h +6 -6
- package/src/operations.cc +2 -2
- package/src/pipeline.cc +46 -44
package/install/check.js
CHANGED
@@ -10,8 +10,8 @@ try {
|
|
10
10
|
log(msg);
|
11
11
|
log('Attempting to build from source via node-gyp');
|
12
12
|
try {
|
13
|
-
require('node-addon-api');
|
14
|
-
log(
|
13
|
+
const addonApi = require('node-addon-api');
|
14
|
+
log(`Found node-addon-api ${addonApi.version || ''}`);
|
15
15
|
} catch (err) {
|
16
16
|
log('Please add node-addon-api to your dependencies');
|
17
17
|
return;
|
package/lib/colour.js
CHANGED
@@ -71,8 +71,6 @@ function grayscale (grayscale) {
|
|
71
71
|
* All operations will use this colourspace before converting to the output colourspace,
|
72
72
|
* as defined by {@link #tocolourspace|toColourspace}.
|
73
73
|
*
|
74
|
-
* This feature is experimental and has not yet been fully-tested with all operations.
|
75
|
-
*
|
76
74
|
* @since 0.29.0
|
77
75
|
*
|
78
76
|
* @example
|
package/lib/index.d.ts
CHANGED
@@ -1479,6 +1479,14 @@ declare namespace sharp {
|
|
1479
1479
|
tile?: boolean | undefined;
|
1480
1480
|
/** Set to true to avoid premultipling the image below. Equivalent to the --premultiplied vips option. */
|
1481
1481
|
premultiplied?: boolean | undefined;
|
1482
|
+
/** number representing the DPI for vector overlay image. (optional, default 72)*/
|
1483
|
+
density?: number | undefined;
|
1484
|
+
/** Set to true to read all frames/pages of an animated image. (optional, default false) */
|
1485
|
+
animated?: boolean | undefined;
|
1486
|
+
/** see sharp() constructor, (optional, default 'warning') */
|
1487
|
+
failOn?: FailOnOptions | undefined;
|
1488
|
+
/** see sharp() constructor, (optional, default 268402689) */
|
1489
|
+
limitInputPixels?: number | boolean | undefined;
|
1482
1490
|
}
|
1483
1491
|
|
1484
1492
|
interface TileOptions {
|
package/lib/input.js
CHANGED
@@ -296,17 +296,17 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
296
296
|
}
|
297
297
|
}
|
298
298
|
if (is.defined(inputOptions.text.width)) {
|
299
|
-
if (is.
|
299
|
+
if (is.integer(inputOptions.text.width) && inputOptions.text.width > 0) {
|
300
300
|
inputDescriptor.textWidth = inputOptions.text.width;
|
301
301
|
} else {
|
302
|
-
throw is.invalidParameterError('text.
|
302
|
+
throw is.invalidParameterError('text.width', 'positive integer', inputOptions.text.width);
|
303
303
|
}
|
304
304
|
}
|
305
305
|
if (is.defined(inputOptions.text.height)) {
|
306
|
-
if (is.
|
306
|
+
if (is.integer(inputOptions.text.height) && inputOptions.text.height > 0) {
|
307
307
|
inputDescriptor.textHeight = inputOptions.text.height;
|
308
308
|
} else {
|
309
|
-
throw is.invalidParameterError('text.height', '
|
309
|
+
throw is.invalidParameterError('text.height', 'positive integer', inputOptions.text.height);
|
310
310
|
}
|
311
311
|
}
|
312
312
|
if (is.defined(inputOptions.text.align)) {
|
@@ -324,10 +324,10 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
324
324
|
}
|
325
325
|
}
|
326
326
|
if (is.defined(inputOptions.text.dpi)) {
|
327
|
-
if (is.
|
327
|
+
if (is.integer(inputOptions.text.dpi) && is.inRange(inputOptions.text.dpi, 1, 1000000)) {
|
328
328
|
inputDescriptor.textDpi = inputOptions.text.dpi;
|
329
329
|
} else {
|
330
|
-
throw is.invalidParameterError('text.dpi', '
|
330
|
+
throw is.invalidParameterError('text.dpi', 'integer between 1 and 1000000', inputOptions.text.dpi);
|
331
331
|
}
|
332
332
|
}
|
333
333
|
if (is.defined(inputOptions.text.rgba)) {
|
@@ -338,10 +338,10 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
338
338
|
}
|
339
339
|
}
|
340
340
|
if (is.defined(inputOptions.text.spacing)) {
|
341
|
-
if (is.
|
341
|
+
if (is.integer(inputOptions.text.spacing) && is.inRange(inputOptions.text.spacing, -1000000, 1000000)) {
|
342
342
|
inputDescriptor.textSpacing = inputOptions.text.spacing;
|
343
343
|
} else {
|
344
|
-
throw is.invalidParameterError('text.spacing', '
|
344
|
+
throw is.invalidParameterError('text.spacing', 'integer between -1000000 and 1000000', inputOptions.text.spacing);
|
345
345
|
}
|
346
346
|
}
|
347
347
|
if (is.defined(inputOptions.text.wrap)) {
|
package/lib/libvips.js
CHANGED
@@ -162,15 +162,21 @@ const pkgConfigPath = () => {
|
|
162
162
|
}
|
163
163
|
};
|
164
164
|
|
165
|
+
const skipSearch = (status, reason) => {
|
166
|
+
log(`Detected ${reason}, skipping search for globally-installed libvips`);
|
167
|
+
return status;
|
168
|
+
};
|
169
|
+
|
165
170
|
const useGlobalLibvips = () => {
|
166
171
|
if (Boolean(process.env.SHARP_IGNORE_GLOBAL_LIBVIPS) === true) {
|
167
|
-
|
168
|
-
|
172
|
+
return skipSearch(false, 'SHARP_IGNORE_GLOBAL_LIBVIPS');
|
173
|
+
}
|
174
|
+
if (Boolean(process.env.SHARP_FORCE_GLOBAL_LIBVIPS) === true) {
|
175
|
+
return skipSearch(true, 'SHARP_FORCE_GLOBAL_LIBVIPS');
|
169
176
|
}
|
170
177
|
/* istanbul ignore next */
|
171
178
|
if (isRosetta()) {
|
172
|
-
|
173
|
-
return false;
|
179
|
+
return skipSearch(false, 'Rosetta');
|
174
180
|
}
|
175
181
|
const globalVipsVersion = globalLibvipsVersion();
|
176
182
|
return !!globalVipsVersion && /* istanbul ignore next */
|
package/lib/resize.js
CHANGED
@@ -68,6 +68,7 @@ const strategy = {
|
|
68
68
|
*/
|
69
69
|
const kernel = {
|
70
70
|
nearest: 'nearest',
|
71
|
+
linear: 'linear',
|
71
72
|
cubic: 'cubic',
|
72
73
|
mitchell: 'mitchell',
|
73
74
|
lanczos2: 'lanczos2',
|
@@ -135,18 +136,22 @@ function isResizeExpected (options) {
|
|
135
136
|
*
|
136
137
|
* Some of these values are based on the [object-position](https://developer.mozilla.org/en-US/docs/Web/CSS/object-position) CSS property.
|
137
138
|
*
|
138
|
-
* The
|
139
|
+
* The strategy-based approach initially resizes so one dimension is at its target length
|
139
140
|
* then repeatedly ranks edge regions, discarding the edge with the lowest score based on the selected strategy.
|
140
141
|
* - `entropy`: focus on the region with the highest [Shannon entropy](https://en.wikipedia.org/wiki/Entropy_%28information_theory%29).
|
141
142
|
* - `attention`: focus on the region with the highest luminance frequency, colour saturation and presence of skin tones.
|
142
143
|
*
|
143
|
-
* Possible
|
144
|
+
* Possible downsizing kernels are:
|
144
145
|
* - `nearest`: Use [nearest neighbour interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation).
|
146
|
+
* - `linear`: Use a [triangle filter](https://en.wikipedia.org/wiki/Triangular_function).
|
145
147
|
* - `cubic`: Use a [Catmull-Rom spline](https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline).
|
146
148
|
* - `mitchell`: Use a [Mitchell-Netravali spline](https://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf).
|
147
149
|
* - `lanczos2`: Use a [Lanczos kernel](https://en.wikipedia.org/wiki/Lanczos_resampling#Lanczos_kernel) with `a=2`.
|
148
150
|
* - `lanczos3`: Use a Lanczos kernel with `a=3` (the default).
|
149
151
|
*
|
152
|
+
* When upsampling, these kernels map to `nearest`, `linear` and `cubic` interpolators.
|
153
|
+
* Downsampling kernels without a matching upsampling interpolator map to `cubic`.
|
154
|
+
*
|
150
155
|
* Only one resize can occur per pipeline.
|
151
156
|
* Previous calls to `resize` in the same pipeline will be ignored.
|
152
157
|
*
|
@@ -239,7 +244,7 @@ function isResizeExpected (options) {
|
|
239
244
|
* @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
245
|
* @param {String} [options.position='centre'] - A position, gravity or strategy to use when `fit` is `cover` or `contain`.
|
241
246
|
* @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.
|
242
|
-
* @param {String} [options.kernel='lanczos3'] - The kernel to use for image reduction. Use the `fastShrinkOnLoad` option to control kernel vs shrink-on-load.
|
247
|
+
* @param {String} [options.kernel='lanczos3'] - The kernel to use for image reduction and the inferred interpolator to use for upsampling. Use the `fastShrinkOnLoad` option to control kernel vs shrink-on-load.
|
243
248
|
* @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
249
|
* @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
250
|
* @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.
|
package/lib/utility.js
CHANGED
@@ -153,6 +153,9 @@ function concurrency (concurrency) {
|
|
153
153
|
if (detectLibc.familySync() === detectLibc.GLIBC && !sharp._isUsingJemalloc()) {
|
154
154
|
// Reduce default concurrency to 1 when using glibc memory allocator
|
155
155
|
sharp.concurrency(1);
|
156
|
+
} else if (detectLibc.familySync() === detectLibc.MUSL && sharp.concurrency() === 1024) {
|
157
|
+
// Reduce default concurrency when musl thread over-subscription detected
|
158
|
+
sharp.concurrency(require('node:os').availableParallelism());
|
156
159
|
}
|
157
160
|
|
158
161
|
/**
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "@revizly/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.33.
|
4
|
+
"version": "0.33.4-revizly2",
|
5
5
|
"author": "Lovell Fuller <npm@lovell.info>",
|
6
6
|
"homepage": "https://sharp.pixelplumbing.com",
|
7
7
|
"contributors": [
|
@@ -82,7 +82,7 @@
|
|
82
82
|
"Joris Dugué <zaruike10@gmail.com>",
|
83
83
|
"Chris Banks <christopher.bradley.banks@gmail.com>",
|
84
84
|
"Ompal Singh <ompal.hitm09@gmail.com>",
|
85
|
-
"Brodan <christopher.hranj@gmail.com",
|
85
|
+
"Brodan <christopher.hranj@gmail.com>",
|
86
86
|
"Ankur Parihar <ankur.github@gmail.com>",
|
87
87
|
"Brahim Ait elhaj <brahima@gmail.com>",
|
88
88
|
"Mart Jansink <m.jansink@gmail.com>",
|
@@ -141,30 +141,30 @@
|
|
141
141
|
"semver": "^7.6.0"
|
142
142
|
},
|
143
143
|
"optionalDependencies": {
|
144
|
-
"@revizly/sharp-libvips-linux-arm64": "1.0.
|
145
|
-
"@revizly/sharp-libvips-linux-x64": "1.0.
|
146
|
-
"@revizly/sharp-linux-arm64": "0.33.
|
147
|
-
"@revizly/sharp-linux-x64": "0.33.
|
144
|
+
"@revizly/sharp-libvips-linux-arm64": "1.0.5",
|
145
|
+
"@revizly/sharp-libvips-linux-x64": "1.0.5",
|
146
|
+
"@revizly/sharp-linux-arm64": "0.33.4-revizly1",
|
147
|
+
"@revizly/sharp-linux-x64": "0.33.4-revizly1"
|
148
148
|
},
|
149
149
|
"devDependencies": {
|
150
|
-
"@emnapi/runtime": "^1.1.
|
151
|
-
"@revizly/sharp-libvips-dev": "1.0.
|
150
|
+
"@emnapi/runtime": "^1.1.1",
|
151
|
+
"@revizly/sharp-libvips-dev": "1.0.5",
|
152
152
|
"@types/node": "*",
|
153
153
|
"async": "^3.2.5",
|
154
154
|
"cc": "^3.0.1",
|
155
|
-
"emnapi": "^1.1.
|
155
|
+
"emnapi": "^1.1.1",
|
156
156
|
"exif-reader": "^2.0.1",
|
157
157
|
"extract-zip": "^2.0.1",
|
158
158
|
"icc": "^3.0.0",
|
159
159
|
"jsdoc-to-markdown": "^8.0.1",
|
160
160
|
"license-checker": "^25.0.1",
|
161
|
-
"mocha": "^10.
|
161
|
+
"mocha": "^10.4.0",
|
162
162
|
"node-addon-api": "^8.0.0",
|
163
163
|
"nyc": "^15.1.0",
|
164
|
-
"prebuild": "^13.0.
|
164
|
+
"prebuild": "^13.0.1",
|
165
165
|
"semistandard": "^17.0.0",
|
166
|
-
"tar-fs": "^3.0.
|
167
|
-
"tsd": "^0.
|
166
|
+
"tar-fs": "^3.0.6",
|
167
|
+
"tsd": "^0.31.0"
|
168
168
|
},
|
169
169
|
"license": "Apache-2.0",
|
170
170
|
"engines": {
|
package/src/common.cc
CHANGED
@@ -75,7 +75,7 @@ namespace sharp {
|
|
75
75
|
Napi::Buffer<char> buffer = input.Get("buffer").As<Napi::Buffer<char>>();
|
76
76
|
descriptor->bufferLength = buffer.Length();
|
77
77
|
descriptor->buffer = buffer.Data();
|
78
|
-
descriptor->isBuffer =
|
78
|
+
descriptor->isBuffer = true;
|
79
79
|
}
|
80
80
|
descriptor->failOn = AttrAsEnum<VipsFailOn>(input, "failOn", VIPS_TYPE_FAIL_ON);
|
81
81
|
// Density for vector-based input
|
@@ -384,7 +384,7 @@ namespace sharp {
|
|
384
384
|
->set("access", descriptor->access)
|
385
385
|
->set("fail_on", descriptor->failOn);
|
386
386
|
if (descriptor->unlimited && ImageTypeSupportsUnlimited(imageType)) {
|
387
|
-
option->set("unlimited",
|
387
|
+
option->set("unlimited", true);
|
388
388
|
}
|
389
389
|
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
|
390
390
|
option->set("dpi", descriptor->density);
|
@@ -488,7 +488,7 @@ namespace sharp {
|
|
488
488
|
->set("access", descriptor->access)
|
489
489
|
->set("fail_on", descriptor->failOn);
|
490
490
|
if (descriptor->unlimited && ImageTypeSupportsUnlimited(imageType)) {
|
491
|
-
option->set("unlimited",
|
491
|
+
option->set("unlimited", true);
|
492
492
|
}
|
493
493
|
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
|
494
494
|
option->set("dpi", descriptor->density);
|
@@ -768,7 +768,7 @@ namespace sharp {
|
|
768
768
|
int *timeout = VIPS_NEW(im, int);
|
769
769
|
*timeout = seconds;
|
770
770
|
g_signal_connect(im, "eval", G_CALLBACK(VipsProgressCallBack), timeout);
|
771
|
-
vips_image_set_progress(im,
|
771
|
+
vips_image_set_progress(im, true);
|
772
772
|
}
|
773
773
|
}
|
774
774
|
}
|
@@ -778,7 +778,7 @@ namespace sharp {
|
|
778
778
|
*/
|
779
779
|
void VipsProgressCallBack(VipsImage *im, VipsProgress *progress, int *timeout) {
|
780
780
|
if (*timeout > 0 && progress->run >= *timeout) {
|
781
|
-
vips_image_set_kill(im,
|
781
|
+
vips_image_set_kill(im, true);
|
782
782
|
vips_error("timeout", "%d%% complete", progress->percent);
|
783
783
|
*timeout = 0;
|
784
784
|
}
|
@@ -1081,9 +1081,10 @@ namespace sharp {
|
|
1081
1081
|
/*
|
1082
1082
|
Ensure decoding remains sequential.
|
1083
1083
|
*/
|
1084
|
-
VImage StaySequential(VImage image,
|
1085
|
-
if (
|
1086
|
-
|
1084
|
+
VImage StaySequential(VImage image, bool condition) {
|
1085
|
+
if (vips_image_is_sequential(image.get_image()) && condition) {
|
1086
|
+
image = image.copy_memory().copy();
|
1087
|
+
image.remove(VIPS_META_SEQUENTIAL);
|
1087
1088
|
}
|
1088
1089
|
return image;
|
1089
1090
|
}
|
package/src/common.h
CHANGED
@@ -79,12 +79,12 @@ namespace sharp {
|
|
79
79
|
buffer(nullptr),
|
80
80
|
failOn(VIPS_FAIL_ON_WARNING),
|
81
81
|
limitInputPixels(0x3FFF * 0x3FFF),
|
82
|
-
unlimited(
|
82
|
+
unlimited(false),
|
83
83
|
access(VIPS_ACCESS_RANDOM),
|
84
84
|
bufferLength(0),
|
85
|
-
isBuffer(
|
85
|
+
isBuffer(false),
|
86
86
|
density(72.0),
|
87
|
-
ignoreIcc(
|
87
|
+
ignoreIcc(false),
|
88
88
|
rawDepth(VIPS_FORMAT_UCHAR),
|
89
89
|
rawChannels(0),
|
90
90
|
rawWidth(0),
|
@@ -103,9 +103,9 @@ namespace sharp {
|
|
103
103
|
textWidth(0),
|
104
104
|
textHeight(0),
|
105
105
|
textAlign(VIPS_ALIGN_LOW),
|
106
|
-
textJustify(
|
106
|
+
textJustify(false),
|
107
107
|
textDpi(72),
|
108
|
-
textRgba(
|
108
|
+
textRgba(false),
|
109
109
|
textSpacing(0),
|
110
110
|
textWrap(VIPS_TEXT_WRAP_WORD),
|
111
111
|
textAutofitDpi(0) {}
|
@@ -386,7 +386,7 @@ namespace sharp {
|
|
386
386
|
/*
|
387
387
|
Ensure decoding remains sequential.
|
388
388
|
*/
|
389
|
-
VImage StaySequential(VImage image,
|
389
|
+
VImage StaySequential(VImage image, bool condition = true);
|
390
390
|
|
391
391
|
} // namespace sharp
|
392
392
|
|
package/src/operations.cc
CHANGED
@@ -155,7 +155,7 @@ namespace sharp {
|
|
155
155
|
return image.conv(blur);
|
156
156
|
} else {
|
157
157
|
// Slower, accurate Gaussian blur
|
158
|
-
return StaySequential(image
|
158
|
+
return StaySequential(image).gaussblur(sigma);
|
159
159
|
}
|
160
160
|
}
|
161
161
|
|
@@ -386,7 +386,7 @@ namespace sharp {
|
|
386
386
|
pages.reserve(nPages);
|
387
387
|
|
388
388
|
// Split the image into cropped frames
|
389
|
-
image = StaySequential(image
|
389
|
+
image = StaySequential(image);
|
390
390
|
for (int i = 0; i < nPages; i++) {
|
391
391
|
pages.push_back(
|
392
392
|
image.extract_area(left, *pageHeight * i + top, width, height));
|
package/src/pipeline.cc
CHANGED
@@ -70,8 +70,8 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
70
70
|
// Calculate angle of rotation
|
71
71
|
VipsAngle rotation = VIPS_ANGLE_D0;
|
72
72
|
VipsAngle autoRotation = VIPS_ANGLE_D0;
|
73
|
-
bool autoFlip =
|
74
|
-
bool autoFlop =
|
73
|
+
bool autoFlip = false;
|
74
|
+
bool autoFlop = false;
|
75
75
|
|
76
76
|
if (baton->useExifOrientation) {
|
77
77
|
// Rotate and flip image according to Exif orientation
|
@@ -88,7 +88,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
88
88
|
baton->rotationAngle != 0.0);
|
89
89
|
|
90
90
|
if (shouldRotateBefore) {
|
91
|
-
image = sharp::StaySequential(image,
|
91
|
+
image = sharp::StaySequential(image,
|
92
92
|
rotation != VIPS_ANGLE_D0 ||
|
93
93
|
autoRotation != VIPS_ANGLE_D0 ||
|
94
94
|
autoFlip ||
|
@@ -104,17 +104,17 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
104
104
|
}
|
105
105
|
if (autoFlip) {
|
106
106
|
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
107
|
-
autoFlip =
|
107
|
+
autoFlip = false;
|
108
108
|
} else if (baton->flip) {
|
109
109
|
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
110
|
-
baton->flip =
|
110
|
+
baton->flip = false;
|
111
111
|
}
|
112
112
|
if (autoFlop) {
|
113
113
|
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
114
|
-
autoFlop =
|
114
|
+
autoFlop = false;
|
115
115
|
} else if (baton->flop) {
|
116
116
|
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
117
|
-
baton->flop =
|
117
|
+
baton->flop = false;
|
118
118
|
}
|
119
119
|
if (rotation != VIPS_ANGLE_D0) {
|
120
120
|
if (rotation != VIPS_ANGLE_D180) {
|
@@ -126,7 +126,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
126
126
|
if (baton->rotationAngle != 0.0) {
|
127
127
|
MultiPageUnsupported(nPages, "Rotate");
|
128
128
|
std::vector<double> background;
|
129
|
-
std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground,
|
129
|
+
std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground, false);
|
130
130
|
image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background)).copy_memory();
|
131
131
|
}
|
132
132
|
}
|
@@ -134,7 +134,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
134
134
|
// Trim
|
135
135
|
if (baton->trimThreshold >= 0.0) {
|
136
136
|
MultiPageUnsupported(nPages, "Trim");
|
137
|
-
image = sharp::StaySequential(image
|
137
|
+
image = sharp::StaySequential(image);
|
138
138
|
image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold, baton->trimLineArt);
|
139
139
|
baton->trimOffsetLeft = image.xoffset();
|
140
140
|
baton->trimOffsetTop = image.yoffset();
|
@@ -337,7 +337,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
337
337
|
// Convert to sRGB/P3 using embedded profile
|
338
338
|
try {
|
339
339
|
image = image.icc_transform(processingProfile, VImage::option()
|
340
|
-
->set("embedded",
|
340
|
+
->set("embedded", true)
|
341
341
|
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
342
342
|
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
343
343
|
} catch(...) {
|
@@ -357,11 +357,6 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
357
357
|
image = sharp::Flatten(image, baton->flattenBackground);
|
358
358
|
}
|
359
359
|
|
360
|
-
// Negate the colours in the image
|
361
|
-
if (baton->negate) {
|
362
|
-
image = sharp::Negate(image, baton->negateAlpha);
|
363
|
-
}
|
364
|
-
|
365
360
|
// Gamma encoding (darken)
|
366
361
|
if (baton->gamma >= 1 && baton->gamma <= 3) {
|
367
362
|
image = sharp::Gamma(image, 1.0 / baton->gamma);
|
@@ -397,7 +392,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
397
392
|
->set("kernel", baton->kernel));
|
398
393
|
}
|
399
394
|
|
400
|
-
image = sharp::StaySequential(image,
|
395
|
+
image = sharp::StaySequential(image,
|
401
396
|
autoRotation != VIPS_ANGLE_D0 ||
|
402
397
|
baton->flip ||
|
403
398
|
autoFlip ||
|
@@ -500,7 +495,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
500
495
|
|
501
496
|
// Attention-based or Entropy-based crop
|
502
497
|
MultiPageUnsupported(nPages, "Resize strategy");
|
503
|
-
image = sharp::StaySequential(image
|
498
|
+
image = sharp::StaySequential(image);
|
504
499
|
image = image.smartcrop(baton->width, baton->height, VImage::option()
|
505
500
|
->set("interesting", baton->position == 16 ? VIPS_INTERESTING_ENTROPY : VIPS_INTERESTING_ATTENTION)
|
506
501
|
->set("premultiplied", shouldPremultiplyAlpha)
|
@@ -519,7 +514,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
519
514
|
// Rotate post-extract non-90 angle
|
520
515
|
if (!baton->rotateBeforePreExtract && baton->rotationAngle != 0.0) {
|
521
516
|
MultiPageUnsupported(nPages, "Rotate");
|
522
|
-
image = sharp::StaySequential(image
|
517
|
+
image = sharp::StaySequential(image);
|
523
518
|
std::vector<double> background;
|
524
519
|
std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground, shouldPremultiplyAlpha);
|
525
520
|
image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background));
|
@@ -543,7 +538,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
543
538
|
// Affine transform
|
544
539
|
if (!baton->affineMatrix.empty()) {
|
545
540
|
MultiPageUnsupported(nPages, "Affine");
|
546
|
-
image = sharp::StaySequential(image
|
541
|
+
image = sharp::StaySequential(image);
|
547
542
|
std::vector<double> background;
|
548
543
|
std::tie(image, background) = sharp::ApplyAlpha(image, baton->affineBackground, shouldPremultiplyAlpha);
|
549
544
|
vips::VInterpolate interp = vips::VInterpolate::new_from_name(
|
@@ -566,6 +561,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
566
561
|
std::vector<double> background;
|
567
562
|
std::tie(image, background) = sharp::ApplyAlpha(image, baton->extendBackground, shouldPremultiplyAlpha);
|
568
563
|
|
564
|
+
image = sharp::StaySequential(image, nPages > 1);
|
569
565
|
image = nPages > 1
|
570
566
|
? sharp::EmbedMultiPage(image,
|
571
567
|
baton->extendLeft, baton->extendTop, baton->width, baton->height,
|
@@ -574,7 +570,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
574
570
|
VImage::option()->set("extend", baton->extendWith)->set("background", background));
|
575
571
|
} else {
|
576
572
|
std::vector<double> ignoredBackground(1);
|
577
|
-
image = sharp::StaySequential(image
|
573
|
+
image = sharp::StaySequential(image);
|
578
574
|
image = nPages > 1
|
579
575
|
? sharp::EmbedMultiPage(image,
|
580
576
|
baton->extendLeft, baton->extendTop, baton->width, baton->height,
|
@@ -670,7 +666,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
670
666
|
if (across != 0 || down != 0) {
|
671
667
|
int left;
|
672
668
|
int top;
|
673
|
-
compositeImage = sharp::StaySequential(compositeImage
|
669
|
+
compositeImage = sharp::StaySequential(compositeImage).replicate(across, down);
|
674
670
|
if (composite->hasOffset) {
|
675
671
|
std::tie(left, top) = sharp::CalculateCrop(
|
676
672
|
compositeImage.width(), compositeImage.height(), image.width(), image.height(),
|
@@ -728,13 +724,13 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
728
724
|
|
729
725
|
// Apply normalisation - stretch luminance to cover full dynamic range
|
730
726
|
if (baton->normalise) {
|
731
|
-
image = sharp::StaySequential(image
|
727
|
+
image = sharp::StaySequential(image);
|
732
728
|
image = sharp::Normalise(image, baton->normaliseLower, baton->normaliseUpper);
|
733
729
|
}
|
734
730
|
|
735
731
|
// Apply contrast limiting adaptive histogram equalization (CLAHE)
|
736
732
|
if (baton->claheWidth != 0 && baton->claheHeight != 0) {
|
737
|
-
image = sharp::StaySequential(image
|
733
|
+
image = sharp::StaySequential(image);
|
738
734
|
image = sharp::Clahe(image, baton->claheWidth, baton->claheHeight, baton->claheMaxSlope);
|
739
735
|
}
|
740
736
|
|
@@ -780,7 +776,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
780
776
|
if ((baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) && baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK &&
|
781
777
|
baton->withIccProfile.empty() && sharp::HasProfile(image)) {
|
782
778
|
image = image.icc_transform(processingProfile, VImage::option()
|
783
|
-
->set("embedded",
|
779
|
+
->set("embedded", true)
|
784
780
|
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
785
781
|
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
786
782
|
}
|
@@ -811,7 +807,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
811
807
|
try {
|
812
808
|
image = image.icc_transform(const_cast<char*>(baton->withIccProfile.data()), VImage::option()
|
813
809
|
->set("input_profile", processingProfile)
|
814
|
-
->set("embedded",
|
810
|
+
->set("embedded", true)
|
815
811
|
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
816
812
|
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
817
813
|
} catch(...) {
|
@@ -820,6 +816,12 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
820
816
|
} else if (baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) {
|
821
817
|
image = sharp::SetProfile(image, inputProfile);
|
822
818
|
}
|
819
|
+
|
820
|
+
// Negate the colours in the image
|
821
|
+
if (baton->negate) {
|
822
|
+
image = sharp::Negate(image, baton->negateAlpha);
|
823
|
+
}
|
824
|
+
|
823
825
|
// Override EXIF Orientation tag
|
824
826
|
if (baton->withMetadataOrientation != -1) {
|
825
827
|
image = sharp::SetExifOrientation(image, baton->withMetadataOrientation);
|
@@ -1004,7 +1006,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
1004
1006
|
if (!sharp::HasAlpha(image)) {
|
1005
1007
|
baton->tileBackground.pop_back();
|
1006
1008
|
}
|
1007
|
-
image = sharp::StaySequential(image,
|
1009
|
+
image = sharp::StaySequential(image, baton->tileAngle != 0);
|
1008
1010
|
vips::VOption *options = BuildOptionsDZ(baton);
|
1009
1011
|
VipsArea *area = reinterpret_cast<VipsArea*>(image.dzsave_buffer(options));
|
1010
1012
|
baton->bufferOut = static_cast<char*>(area->data);
|
@@ -1206,7 +1208,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
1206
1208
|
if (!sharp::HasAlpha(image)) {
|
1207
1209
|
baton->tileBackground.pop_back();
|
1208
1210
|
}
|
1209
|
-
image = sharp::StaySequential(image,
|
1211
|
+
image = sharp::StaySequential(image, baton->tileAngle != 0);
|
1210
1212
|
vips::VOption *options = BuildOptionsDZ(baton);
|
1211
1213
|
image.dzsave(const_cast<char*>(baton->fileOut.data()), options);
|
1212
1214
|
baton->formatOut = "dz";
|
@@ -1338,16 +1340,16 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
1338
1340
|
std::tuple<VipsAngle, bool, bool>
|
1339
1341
|
CalculateExifRotationAndFlip(int const exifOrientation) {
|
1340
1342
|
VipsAngle rotate = VIPS_ANGLE_D0;
|
1341
|
-
bool flip =
|
1342
|
-
bool flop =
|
1343
|
+
bool flip = false;
|
1344
|
+
bool flop = false;
|
1343
1345
|
switch (exifOrientation) {
|
1344
1346
|
case 6: rotate = VIPS_ANGLE_D90; break;
|
1345
1347
|
case 3: rotate = VIPS_ANGLE_D180; break;
|
1346
1348
|
case 8: rotate = VIPS_ANGLE_D270; break;
|
1347
|
-
case 2: flop =
|
1348
|
-
case 7: flip =
|
1349
|
-
case 4: flop =
|
1350
|
-
case 5: flip =
|
1349
|
+
case 2: flop = true; break; // flop 1
|
1350
|
+
case 7: flip = true; rotate = VIPS_ANGLE_D90; break; // flip 6
|
1351
|
+
case 4: flop = true; rotate = VIPS_ANGLE_D180; break; // flop 3
|
1352
|
+
case 5: flip = true; rotate = VIPS_ANGLE_D270; break; // flip 8
|
1351
1353
|
}
|
1352
1354
|
return std::make_tuple(rotate, flip, flop);
|
1353
1355
|
}
|
@@ -1395,7 +1397,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
1395
1397
|
std::string suffix;
|
1396
1398
|
if (baton->tileFormat == "png") {
|
1397
1399
|
std::vector<std::pair<std::string, std::string>> options {
|
1398
|
-
{"interlace", baton->pngProgressive ? "
|
1400
|
+
{"interlace", baton->pngProgressive ? "true" : "false"},
|
1399
1401
|
{"compression", std::to_string(baton->pngCompressionLevel)},
|
1400
1402
|
{"filter", baton->pngAdaptiveFiltering ? "all" : "none"}
|
1401
1403
|
};
|
@@ -1404,25 +1406,25 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
1404
1406
|
std::vector<std::pair<std::string, std::string>> options {
|
1405
1407
|
{"Q", std::to_string(baton->webpQuality)},
|
1406
1408
|
{"alpha_q", std::to_string(baton->webpAlphaQuality)},
|
1407
|
-
{"lossless", baton->webpLossless ? "
|
1408
|
-
{"near_lossless", baton->webpNearLossless ? "
|
1409
|
-
{"smart_subsample", baton->webpSmartSubsample ? "
|
1409
|
+
{"lossless", baton->webpLossless ? "true" : "false"},
|
1410
|
+
{"near_lossless", baton->webpNearLossless ? "true" : "false"},
|
1411
|
+
{"smart_subsample", baton->webpSmartSubsample ? "true" : "false"},
|
1410
1412
|
{"preset", vips_enum_nick(VIPS_TYPE_FOREIGN_WEBP_PRESET, baton->webpPreset)},
|
1411
|
-
{"min_size", baton->webpMinSize ? "
|
1412
|
-
{"mixed", baton->webpMixed ? "
|
1413
|
+
{"min_size", baton->webpMinSize ? "true" : "false"},
|
1414
|
+
{"mixed", baton->webpMixed ? "true" : "false"},
|
1413
1415
|
{"effort", std::to_string(baton->webpEffort)}
|
1414
1416
|
};
|
1415
1417
|
suffix = AssembleSuffixString(".webp", options);
|
1416
1418
|
} else {
|
1417
1419
|
std::vector<std::pair<std::string, std::string>> options {
|
1418
1420
|
{"Q", std::to_string(baton->jpegQuality)},
|
1419
|
-
{"interlace", baton->jpegProgressive ? "
|
1421
|
+
{"interlace", baton->jpegProgressive ? "true" : "false"},
|
1420
1422
|
{"subsample_mode", baton->jpegChromaSubsampling == "4:4:4" ? "off" : "on"},
|
1421
|
-
{"trellis_quant", baton->jpegTrellisQuantisation ? "
|
1423
|
+
{"trellis_quant", baton->jpegTrellisQuantisation ? "true" : "false"},
|
1422
1424
|
{"quant_table", std::to_string(baton->jpegQuantisationTable)},
|
1423
|
-
{"overshoot_deringing", baton->jpegOvershootDeringing ? "
|
1424
|
-
{"optimize_scans", baton->jpegOptimiseScans ? "
|
1425
|
-
{"optimize_coding", baton->jpegOptimiseCoding ? "
|
1425
|
+
{"overshoot_deringing", baton->jpegOvershootDeringing ? "true": "false"},
|
1426
|
+
{"optimize_scans", baton->jpegOptimiseScans ? "true": "false"},
|
1427
|
+
{"optimize_coding", baton->jpegOptimiseCoding ? "true": "false"}
|
1426
1428
|
};
|
1427
1429
|
std::string extname = baton->tileLayout == VIPS_FOREIGN_DZ_LAYOUT_DZ ? ".jpeg" : ".jpg";
|
1428
1430
|
suffix = AssembleSuffixString(extname, options);
|