sharp 0.31.0 → 0.31.2
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 +0 -1
- package/lib/libvips.js +1 -0
- package/lib/output.js +2 -2
- package/lib/resize.js +6 -9
- package/package.json +17 -18
- package/src/common.cc +3 -1
- package/src/common.h +2 -2
- package/src/operations.cc +10 -7
- package/src/pipeline.cc +43 -33
package/README.md
CHANGED
|
@@ -98,7 +98,6 @@ readableStream
|
|
|
98
98
|
A [guide for contributors](https://github.com/lovell/sharp/blob/main/.github/CONTRIBUTING.md)
|
|
99
99
|
covers reporting bugs, requesting features and submitting code changes.
|
|
100
100
|
|
|
101
|
-
[](https://coveralls.io/r/lovell/sharp?branch=main)
|
|
102
101
|
[](https://nodejs.org/dist/latest/docs/api/n-api.html#n_api_n_api_version_matrix)
|
|
103
102
|
|
|
104
103
|
## Licensing
|
package/lib/libvips.js
CHANGED
|
@@ -89,6 +89,7 @@ const removeVendoredLibvips = function () {
|
|
|
89
89
|
rm(vendorPath, { recursive: true, maxRetries: 3, force: true });
|
|
90
90
|
};
|
|
91
91
|
|
|
92
|
+
/* istanbul ignore next */
|
|
92
93
|
const pkgConfigPath = function () {
|
|
93
94
|
if (process.platform !== 'win32') {
|
|
94
95
|
const brewPkgConfigPath = spawnSync(
|
package/lib/output.js
CHANGED
|
@@ -1205,7 +1205,7 @@ function _pipeline (callback) {
|
|
|
1205
1205
|
this.push(data);
|
|
1206
1206
|
}
|
|
1207
1207
|
this.push(null);
|
|
1208
|
-
this.emit('close');
|
|
1208
|
+
this.on('end', () => this.emit('close'));
|
|
1209
1209
|
});
|
|
1210
1210
|
});
|
|
1211
1211
|
if (this.streamInFinished) {
|
|
@@ -1221,7 +1221,7 @@ function _pipeline (callback) {
|
|
|
1221
1221
|
this.push(data);
|
|
1222
1222
|
}
|
|
1223
1223
|
this.push(null);
|
|
1224
|
-
this.emit('close');
|
|
1224
|
+
this.on('end', () => this.emit('close'));
|
|
1225
1225
|
});
|
|
1226
1226
|
}
|
|
1227
1227
|
return this;
|
package/lib/resize.js
CHANGED
|
@@ -111,7 +111,7 @@ function isResizeExpected (options) {
|
|
|
111
111
|
*
|
|
112
112
|
* Some of these values are based on the [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) CSS property.
|
|
113
113
|
*
|
|
114
|
-
* When using a
|
|
114
|
+
* When using a **fit** of `cover` or `contain`, the default **position** is `centre`. Other options are:
|
|
115
115
|
* - `sharp.position`: `top`, `right top`, `right`, `right bottom`, `bottom`, `left bottom`, `left`, `left top`.
|
|
116
116
|
* - `sharp.gravity`: `north`, `northeast`, `east`, `southeast`, `south`, `southwest`, `west`, `northwest`, `center` or `centre`.
|
|
117
117
|
* - `sharp.strategy`: `cover` only, dynamically crop using either the `entropy` or `attention` strategy.
|
|
@@ -428,7 +428,7 @@ function extend (extend) {
|
|
|
428
428
|
* @throws {Error} Invalid parameters
|
|
429
429
|
*/
|
|
430
430
|
function extract (options) {
|
|
431
|
-
const suffix = isResizeExpected(this.options) ||
|
|
431
|
+
const suffix = isResizeExpected(this.options) || this.options.widthPre !== -1 ? 'Post' : 'Pre';
|
|
432
432
|
if (this.options[`width${suffix}`] !== -1) {
|
|
433
433
|
this.options.debuglog('ignoring previous extract options');
|
|
434
434
|
}
|
|
@@ -511,15 +511,12 @@ function trim (trim) {
|
|
|
511
511
|
}
|
|
512
512
|
} else if (is.object(trim)) {
|
|
513
513
|
this._setBackgroundColourOption('trimBackground', trim.background);
|
|
514
|
-
|
|
515
514
|
if (!is.defined(trim.threshold)) {
|
|
516
515
|
this.options.trimThreshold = 10;
|
|
517
|
-
} else if (is.number(trim.threshold)) {
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
throw is.invalidParameterError('threshold', 'positive number', trim);
|
|
522
|
-
}
|
|
516
|
+
} else if (is.number(trim.threshold) && trim.threshold >= 0) {
|
|
517
|
+
this.options.trimThreshold = trim.threshold;
|
|
518
|
+
} else {
|
|
519
|
+
throw is.invalidParameterError('threshold', 'positive number', trim);
|
|
523
520
|
}
|
|
524
521
|
} else {
|
|
525
522
|
throw is.invalidParameterError('trim', 'string, number or object', trim);
|
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.
|
|
4
|
+
"version": "0.31.2",
|
|
5
5
|
"author": "Lovell Fuller <npm@lovell.info>",
|
|
6
6
|
"homepage": "https://github.com/lovell/sharp",
|
|
7
7
|
"contributors": [
|
|
@@ -92,9 +92,8 @@
|
|
|
92
92
|
"clean": "rm -rf node_modules/ build/ vendor/ .nyc_output/ coverage/ test/fixtures/output.*",
|
|
93
93
|
"test": "npm run test-lint && npm run test-unit && npm run test-licensing",
|
|
94
94
|
"test-lint": "semistandard && cpplint",
|
|
95
|
-
"test-unit": "nyc --reporter=lcov --branches=
|
|
95
|
+
"test-unit": "nyc --reporter=lcov --reporter=text --check-coverage --branches=100 mocha --slow=1000 --timeout=30000 ./test/unit/*.js",
|
|
96
96
|
"test-licensing": "license-checker --production --summary --onlyAllow=\"Apache-2.0;BSD;ISC;MIT\"",
|
|
97
|
-
"test-coverage": "./test/coverage/report.sh",
|
|
98
97
|
"test-leak": "./test/leak/leak.sh",
|
|
99
98
|
"docs-build": "documentation lint lib && node docs/build && node docs/search-index/build",
|
|
100
99
|
"docs-serve": "cd docs && npx serve",
|
|
@@ -134,7 +133,7 @@
|
|
|
134
133
|
"detect-libc": "^2.0.1",
|
|
135
134
|
"node-addon-api": "^5.0.0",
|
|
136
135
|
"prebuild-install": "^7.1.1",
|
|
137
|
-
"semver": "^7.3.
|
|
136
|
+
"semver": "^7.3.8",
|
|
138
137
|
"simple-get": "^4.0.1",
|
|
139
138
|
"tar-fs": "^2.1.1",
|
|
140
139
|
"tunnel-agent": "^0.6.0"
|
|
@@ -147,8 +146,8 @@
|
|
|
147
146
|
"extract-zip": "^2.0.1",
|
|
148
147
|
"icc": "^2.0.0",
|
|
149
148
|
"license-checker": "^25.0.1",
|
|
150
|
-
"mocha": "^10.
|
|
151
|
-
"mock-fs": "^5.
|
|
149
|
+
"mocha": "^10.1.0",
|
|
150
|
+
"mock-fs": "^5.2.0",
|
|
152
151
|
"nyc": "^15.1.0",
|
|
153
152
|
"prebuild": "^11.0.4",
|
|
154
153
|
"rimraf": "^3.0.2",
|
|
@@ -156,19 +155,19 @@
|
|
|
156
155
|
},
|
|
157
156
|
"license": "Apache-2.0",
|
|
158
157
|
"config": {
|
|
159
|
-
"libvips": "8.13.
|
|
158
|
+
"libvips": "8.13.3",
|
|
160
159
|
"integrity": {
|
|
161
|
-
"darwin-arm64v8": "sha512-
|
|
162
|
-
"darwin-x64": "sha512-
|
|
163
|
-
"linux-arm64v8": "sha512-
|
|
164
|
-
"linux-armv6": "sha512-
|
|
165
|
-
"linux-armv7": "sha512-
|
|
166
|
-
"linux-x64": "sha512-
|
|
167
|
-
"linuxmusl-arm64v8": "sha512-
|
|
168
|
-
"linuxmusl-x64": "sha512-
|
|
169
|
-
"win32-arm64v8": "sha512-
|
|
170
|
-
"win32-ia32": "sha512-
|
|
171
|
-
"win32-x64": "sha512-
|
|
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=="
|
|
172
171
|
},
|
|
173
172
|
"runtime": "napi",
|
|
174
173
|
"target": 7
|
package/src/common.cc
CHANGED
|
@@ -507,9 +507,10 @@ namespace sharp {
|
|
|
507
507
|
}
|
|
508
508
|
}
|
|
509
509
|
}
|
|
510
|
+
|
|
510
511
|
// Limit input images to a given number of pixels, where pixels = width * height
|
|
511
512
|
if (descriptor->limitInputPixels > 0 &&
|
|
512
|
-
static_cast<uint64_t>(image.width() * image.height()
|
|
513
|
+
static_cast<uint64_t>(image.width()) * image.height() > descriptor->limitInputPixels) {
|
|
513
514
|
throw vips::VError("Input image exceeds pixel limit");
|
|
514
515
|
}
|
|
515
516
|
return std::make_tuple(image, imageType);
|
|
@@ -556,6 +557,7 @@ namespace sharp {
|
|
|
556
557
|
VImage RemoveExifOrientation(VImage image) {
|
|
557
558
|
VImage copy = image.copy();
|
|
558
559
|
copy.remove(VIPS_META_ORIENTATION);
|
|
560
|
+
copy.remove("exif-ifd0-Orientation");
|
|
559
561
|
return copy;
|
|
560
562
|
}
|
|
561
563
|
|
package/src/common.h
CHANGED
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
|
|
27
27
|
#if (VIPS_MAJOR_VERSION < 8) || \
|
|
28
28
|
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 13) || \
|
|
29
|
-
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 13 && VIPS_MICRO_VERSION <
|
|
30
|
-
#error "libvips version 8.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"
|
|
31
31
|
#endif
|
|
32
32
|
|
|
33
33
|
#if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))
|
package/src/operations.cc
CHANGED
|
@@ -289,17 +289,20 @@ namespace sharp {
|
|
|
289
289
|
background = image.extract_area(0, 0, 1, 1)(0, 0);
|
|
290
290
|
multiplier = 1.0;
|
|
291
291
|
}
|
|
292
|
-
if (background.size() == 4) {
|
|
292
|
+
if (HasAlpha(image) && background.size() == 4) {
|
|
293
293
|
// Just discard the alpha because flattening the background colour with
|
|
294
294
|
// itself (effectively what find_trim() does) gives the same result
|
|
295
295
|
backgroundAlpha[0] = background[3] * multiplier;
|
|
296
296
|
}
|
|
297
|
-
|
|
298
|
-
background
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
297
|
+
if (image.bands() > 2) {
|
|
298
|
+
background = {
|
|
299
|
+
background[0] * multiplier,
|
|
300
|
+
background[1] * multiplier,
|
|
301
|
+
background[2] * multiplier
|
|
302
|
+
};
|
|
303
|
+
} else {
|
|
304
|
+
background[0] = background[0] * multiplier;
|
|
305
|
+
}
|
|
303
306
|
int left, top, width, height;
|
|
304
307
|
left = image.find_trim(&top, &width, &height, VImage::option()
|
|
305
308
|
->set("background", background)
|
package/src/pipeline.cc
CHANGED
|
@@ -81,32 +81,47 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
81
81
|
int pageHeight = sharp::GetPageHeight(image);
|
|
82
82
|
|
|
83
83
|
// Calculate angle of rotation
|
|
84
|
-
VipsAngle rotation;
|
|
85
|
-
|
|
86
|
-
bool
|
|
84
|
+
VipsAngle rotation = VIPS_ANGLE_D0;
|
|
85
|
+
VipsAngle autoRotation = VIPS_ANGLE_D0;
|
|
86
|
+
bool autoFlip = FALSE;
|
|
87
|
+
bool autoFlop = FALSE;
|
|
87
88
|
if (baton->useExifOrientation) {
|
|
88
89
|
// Rotate and flip image according to Exif orientation
|
|
89
|
-
std::tie(
|
|
90
|
+
std::tie(autoRotation, autoFlip, autoFlop) = CalculateExifRotationAndFlip(sharp::ExifOrientation(image));
|
|
91
|
+
image = sharp::RemoveExifOrientation(image);
|
|
90
92
|
} else {
|
|
91
93
|
rotation = CalculateAngleRotation(baton->angle);
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
// Rotate pre-extract
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
bool const shouldRotateBefore = baton->rotateBeforePreExtract &&
|
|
98
|
+
(rotation != VIPS_ANGLE_D0 || autoRotation != VIPS_ANGLE_D0 ||
|
|
99
|
+
autoFlip || baton->flip || autoFlop || baton->flop ||
|
|
100
|
+
baton->rotationAngle != 0.0);
|
|
101
|
+
|
|
102
|
+
if (shouldRotateBefore) {
|
|
103
|
+
if (autoRotation != VIPS_ANGLE_D0) {
|
|
104
|
+
image = image.rot(autoRotation);
|
|
105
|
+
autoRotation = VIPS_ANGLE_D0;
|
|
98
106
|
}
|
|
99
|
-
if (
|
|
107
|
+
if (autoFlip) {
|
|
100
108
|
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
|
109
|
+
autoFlip = FALSE;
|
|
110
|
+
} else if (baton->flip) {
|
|
111
|
+
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
|
112
|
+
baton->flip = FALSE;
|
|
101
113
|
}
|
|
102
|
-
if (
|
|
114
|
+
if (autoFlop) {
|
|
115
|
+
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
|
116
|
+
autoFlop = FALSE;
|
|
117
|
+
} else if (baton->flop) {
|
|
103
118
|
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
|
119
|
+
baton->flop = FALSE;
|
|
104
120
|
}
|
|
105
|
-
if (rotation != VIPS_ANGLE_D0
|
|
106
|
-
image =
|
|
121
|
+
if (rotation != VIPS_ANGLE_D0) {
|
|
122
|
+
image = image.rot(rotation);
|
|
123
|
+
rotation = VIPS_ANGLE_D0;
|
|
107
124
|
}
|
|
108
|
-
flop = FALSE;
|
|
109
|
-
flip = FALSE;
|
|
110
125
|
if (baton->rotationAngle != 0.0) {
|
|
111
126
|
MultiPageUnsupported(nPages, "Rotate");
|
|
112
127
|
std::vector<double> background;
|
|
@@ -147,7 +162,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
147
162
|
int targetResizeHeight = baton->height;
|
|
148
163
|
|
|
149
164
|
// Swap input output width and height when rotating by 90 or 270 degrees
|
|
150
|
-
bool swap = !baton->rotateBeforePreExtract &&
|
|
165
|
+
bool swap = !baton->rotateBeforePreExtract &&
|
|
166
|
+
(rotation == VIPS_ANGLE_D90 || rotation == VIPS_ANGLE_D270 ||
|
|
167
|
+
autoRotation == VIPS_ANGLE_D90 || autoRotation == VIPS_ANGLE_D270);
|
|
151
168
|
|
|
152
169
|
// Shrink to pageHeight, so we work for multi-page images
|
|
153
170
|
std::tie(hshrink, vshrink) = sharp::ResolveShrink(
|
|
@@ -167,7 +184,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
167
184
|
// - input colourspace is not specified;
|
|
168
185
|
bool const shouldPreShrink = (targetResizeWidth > 0 || targetResizeHeight > 0) &&
|
|
169
186
|
baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold == 0.0 &&
|
|
170
|
-
baton->colourspaceInput == VIPS_INTERPRETATION_LAST;
|
|
187
|
+
baton->colourspaceInput == VIPS_INTERPRETATION_LAST && !shouldRotateBefore;
|
|
171
188
|
|
|
172
189
|
if (shouldPreShrink) {
|
|
173
190
|
// The common part of the shrink: the bit by which both axes must be shrunk
|
|
@@ -364,30 +381,21 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
364
381
|
->set("kernel", baton->kernel));
|
|
365
382
|
}
|
|
366
383
|
|
|
384
|
+
// Auto-rotate post-extract
|
|
385
|
+
if (autoRotation != VIPS_ANGLE_D0) {
|
|
386
|
+
image = image.rot(autoRotation);
|
|
387
|
+
}
|
|
367
388
|
// Flip (mirror about Y axis)
|
|
368
|
-
if (baton->flip ||
|
|
389
|
+
if (baton->flip || autoFlip) {
|
|
369
390
|
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
|
370
|
-
image = sharp::RemoveExifOrientation(image);
|
|
371
391
|
}
|
|
372
|
-
|
|
373
392
|
// Flop (mirror about X axis)
|
|
374
|
-
if (baton->flop ||
|
|
393
|
+
if (baton->flop || autoFlop) {
|
|
375
394
|
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
|
376
|
-
image = sharp::RemoveExifOrientation(image);
|
|
377
395
|
}
|
|
378
|
-
|
|
379
396
|
// Rotate post-extract 90-angle
|
|
380
|
-
if (
|
|
397
|
+
if (rotation != VIPS_ANGLE_D0) {
|
|
381
398
|
image = image.rot(rotation);
|
|
382
|
-
if (flip) {
|
|
383
|
-
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
|
384
|
-
flip = FALSE;
|
|
385
|
-
}
|
|
386
|
-
if (flop) {
|
|
387
|
-
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
|
388
|
-
flop = FALSE;
|
|
389
|
-
}
|
|
390
|
-
image = sharp::RemoveExifOrientation(image);
|
|
391
399
|
}
|
|
392
400
|
|
|
393
401
|
// Join additional color channels to the image
|
|
@@ -899,12 +907,13 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
899
907
|
} else if (baton->formatOut == "heif" ||
|
|
900
908
|
(baton->formatOut == "input" && inputImageType == sharp::ImageType::HEIF)) {
|
|
901
909
|
// Write HEIF to buffer
|
|
902
|
-
image = sharp::RemoveAnimationProperties(image);
|
|
910
|
+
image = sharp::RemoveAnimationProperties(image).cast(VIPS_FORMAT_UCHAR);
|
|
903
911
|
VipsArea *area = reinterpret_cast<VipsArea*>(image.heifsave_buffer(VImage::option()
|
|
904
912
|
->set("strip", !baton->withMetadata)
|
|
905
913
|
->set("Q", baton->heifQuality)
|
|
906
914
|
->set("compression", baton->heifCompression)
|
|
907
915
|
->set("effort", baton->heifEffort)
|
|
916
|
+
->set("bitdepth", 8)
|
|
908
917
|
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
|
909
918
|
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
|
910
919
|
->set("lossless", baton->heifLossless)));
|
|
@@ -1070,12 +1079,13 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1070
1079
|
} else if (baton->formatOut == "heif" || (mightMatchInput && isHeif) ||
|
|
1071
1080
|
(willMatchInput && inputImageType == sharp::ImageType::HEIF)) {
|
|
1072
1081
|
// Write HEIF to file
|
|
1073
|
-
image = sharp::RemoveAnimationProperties(image);
|
|
1082
|
+
image = sharp::RemoveAnimationProperties(image).cast(VIPS_FORMAT_UCHAR);
|
|
1074
1083
|
image.heifsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
|
1075
1084
|
->set("strip", !baton->withMetadata)
|
|
1076
1085
|
->set("Q", baton->heifQuality)
|
|
1077
1086
|
->set("compression", baton->heifCompression)
|
|
1078
1087
|
->set("effort", baton->heifEffort)
|
|
1088
|
+
->set("bitdepth", 8)
|
|
1079
1089
|
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
|
1080
1090
|
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
|
1081
1091
|
->set("lossless", baton->heifLossless));
|