sharp 0.30.0 → 0.30.1
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 +3 -3
- package/lib/output.js +1 -0
- package/lib/utility.js +2 -2
- package/package.json +2 -2
- package/src/common.cc +9 -4
- package/src/common.h +1 -1
- package/src/pipeline.cc +23 -35
- package/src/pipeline.h +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# sharp
|
|
2
2
|
|
|
3
|
-
<img src="https://cdn.jsdelivr.net/gh/lovell/sharp@
|
|
3
|
+
<img src="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/image/sharp-logo.svg" width="160" height="160" alt="sharp logo" align="right">
|
|
4
4
|
|
|
5
5
|
The typical use case for this high speed Node.js module
|
|
6
6
|
is to convert large images in common formats to
|
|
@@ -95,10 +95,10 @@ readableStream
|
|
|
95
95
|
|
|
96
96
|
## Contributing
|
|
97
97
|
|
|
98
|
-
A [guide for contributors](https://github.com/lovell/sharp/blob/
|
|
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
102
|
[](https://nodejs.org/dist/latest/docs/api/n-api.html#n_api_n_api_version_matrix)
|
|
103
103
|
|
|
104
104
|
## Licensing
|
package/lib/output.js
CHANGED
package/lib/utility.js
CHANGED
|
@@ -30,11 +30,11 @@ const interpolators = {
|
|
|
30
30
|
bilinear: 'bilinear',
|
|
31
31
|
/** [Bicubic interpolation](http://en.wikipedia.org/wiki/Bicubic_interpolation) (the default). */
|
|
32
32
|
bicubic: 'bicubic',
|
|
33
|
-
/** [LBB interpolation](https://github.com/
|
|
33
|
+
/** [LBB interpolation](https://github.com/libvips/libvips/blob/master/libvips/resample/lbb.cpp#L100). Prevents some "[acutance](http://en.wikipedia.org/wiki/Acutance)" but typically reduces performance by a factor of 2. */
|
|
34
34
|
locallyBoundedBicubic: 'lbb',
|
|
35
35
|
/** [Nohalo interpolation](http://eprints.soton.ac.uk/268086/). Prevents acutance but typically reduces performance by a factor of 3. */
|
|
36
36
|
nohalo: 'nohalo',
|
|
37
|
-
/** [VSQBS interpolation](https://github.com/
|
|
37
|
+
/** [VSQBS interpolation](https://github.com/libvips/libvips/blob/master/libvips/resample/vsqbs.cpp#L48). Prevents "staircasing" when enlarging. */
|
|
38
38
|
vertexSplitQuadraticBasisSpline: 'vsqbs'
|
|
39
39
|
};
|
|
40
40
|
|
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.30.
|
|
4
|
+
"version": "0.30.1",
|
|
5
5
|
"author": "Lovell Fuller <npm@lovell.info>",
|
|
6
6
|
"homepage": "https://github.com/lovell/sharp",
|
|
7
7
|
"contributors": [
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
"mocha": "^9.2.0",
|
|
147
147
|
"mock-fs": "^5.1.2",
|
|
148
148
|
"nyc": "^15.1.0",
|
|
149
|
-
"prebuild": "^11.0.
|
|
149
|
+
"prebuild": "^11.0.3",
|
|
150
150
|
"rimraf": "^3.0.2",
|
|
151
151
|
"semistandard": "^16.0.1"
|
|
152
152
|
},
|
package/src/common.cc
CHANGED
|
@@ -885,7 +885,7 @@ namespace sharp {
|
|
|
885
885
|
}
|
|
886
886
|
|
|
887
887
|
std::pair<double, double> ResolveShrink(int width, int height, int targetWidth, int targetHeight,
|
|
888
|
-
Canvas canvas, bool swap, bool withoutEnlargement) {
|
|
888
|
+
Canvas canvas, bool swap, bool withoutEnlargement, bool withoutReduction) {
|
|
889
889
|
if (swap) {
|
|
890
890
|
// Swap input width and height when requested.
|
|
891
891
|
std::swap(width, height);
|
|
@@ -940,9 +940,14 @@ namespace sharp {
|
|
|
940
940
|
}
|
|
941
941
|
}
|
|
942
942
|
|
|
943
|
-
// We should not enlarge
|
|
944
|
-
//
|
|
945
|
-
if (
|
|
943
|
+
// We should not reduce or enlarge the output image, if
|
|
944
|
+
// withoutReduction or withoutEnlargement is specified.
|
|
945
|
+
if (withoutReduction) {
|
|
946
|
+
// Equivalent of VIPS_SIZE_UP
|
|
947
|
+
hshrink = std::min(1.0, hshrink);
|
|
948
|
+
vshrink = std::min(1.0, vshrink);
|
|
949
|
+
} else if (withoutEnlargement) {
|
|
950
|
+
// Equivalent of VIPS_SIZE_DOWN
|
|
946
951
|
hshrink = std::max(1.0, hshrink);
|
|
947
952
|
vshrink = std::max(1.0, vshrink);
|
|
948
953
|
}
|
package/src/common.h
CHANGED
|
@@ -345,7 +345,7 @@ namespace sharp {
|
|
|
345
345
|
the required thumbnail width/height and canvas mode.
|
|
346
346
|
*/
|
|
347
347
|
std::pair<double, double> ResolveShrink(int width, int height, int targetWidth, int targetHeight,
|
|
348
|
-
Canvas canvas, bool swap, bool withoutEnlargement);
|
|
348
|
+
Canvas canvas, bool swap, bool withoutEnlargement, bool withoutReduction);
|
|
349
349
|
|
|
350
350
|
} // namespace sharp
|
|
351
351
|
|
package/src/pipeline.cc
CHANGED
|
@@ -138,17 +138,6 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
138
138
|
pageHeight = inputHeight;
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
// If withoutReduction is specified,
|
|
142
|
-
// Override target width and height if less than respective value from input file
|
|
143
|
-
if (baton->withoutReduction) {
|
|
144
|
-
if (baton->width < inputWidth) {
|
|
145
|
-
baton->width = inputWidth;
|
|
146
|
-
}
|
|
147
|
-
if (baton->height < inputHeight) {
|
|
148
|
-
baton->height = inputHeight;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
141
|
// Scaling calculations
|
|
153
142
|
double hshrink;
|
|
154
143
|
double vshrink;
|
|
@@ -161,7 +150,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
161
150
|
// Shrink to pageHeight, so we work for multi-page images
|
|
162
151
|
std::tie(hshrink, vshrink) = sharp::ResolveShrink(
|
|
163
152
|
inputWidth, pageHeight, targetResizeWidth, targetResizeHeight,
|
|
164
|
-
baton->canvas, swap, baton->withoutEnlargement);
|
|
153
|
+
baton->canvas, swap, baton->withoutEnlargement, baton->withoutReduction);
|
|
165
154
|
|
|
166
155
|
// The jpeg preload shrink.
|
|
167
156
|
int jpegShrinkOnLoad = 1;
|
|
@@ -184,7 +173,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
184
173
|
|
|
185
174
|
if (inputImageType == sharp::ImageType::JPEG) {
|
|
186
175
|
// Leave at least a factor of two for the final resize step, when fastShrinkOnLoad: false
|
|
187
|
-
// for more consistent results and avoid
|
|
176
|
+
// for more consistent results and to avoid extra sharpness to the image
|
|
188
177
|
int factor = baton->fastShrinkOnLoad ? 1 : 2;
|
|
189
178
|
if (shrink >= 8 * factor) {
|
|
190
179
|
jpegShrinkOnLoad = 8;
|
|
@@ -193,6 +182,10 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
193
182
|
} else if (shrink >= 2 * factor) {
|
|
194
183
|
jpegShrinkOnLoad = 2;
|
|
195
184
|
}
|
|
185
|
+
// Lower shrink-on-load for known libjpeg rounding errors
|
|
186
|
+
if (jpegShrinkOnLoad > 1 && static_cast<int>(shrink) == jpegShrinkOnLoad) {
|
|
187
|
+
jpegShrinkOnLoad /= 2;
|
|
188
|
+
}
|
|
196
189
|
} else if (inputImageType == sharp::ImageType::WEBP ||
|
|
197
190
|
inputImageType == sharp::ImageType::SVG ||
|
|
198
191
|
inputImageType == sharp::ImageType::PDF) {
|
|
@@ -270,35 +263,28 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
270
263
|
}
|
|
271
264
|
|
|
272
265
|
// Any pre-shrinking may already have been done
|
|
273
|
-
|
|
274
|
-
|
|
266
|
+
inputWidth = image.width();
|
|
267
|
+
inputHeight = image.height();
|
|
275
268
|
|
|
276
269
|
// After pre-shrink, but before the main shrink stage
|
|
277
270
|
// Reuse the initial pageHeight if we didn't pre-shrink
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
if (baton->fastShrinkOnLoad && jpegShrinkOnLoad > 1) {
|
|
281
|
-
// JPEG shrink-on-load rounds the output dimensions down, which
|
|
282
|
-
// may cause incorrect dimensions when fastShrinkOnLoad is enabled
|
|
283
|
-
// Just recalculate vshrink / hshrink on the main image instead of
|
|
284
|
-
// the pre-shrunk image when this is the case
|
|
285
|
-
hshrink = static_cast<double>(thumbWidth) / (static_cast<double>(inputWidth) / hshrink);
|
|
286
|
-
vshrink = static_cast<double>(preshrunkPageHeight) / (static_cast<double>(pageHeight) / vshrink);
|
|
287
|
-
} else {
|
|
288
|
-
// Shrink to preshrunkPageHeight, so we work for multi-page images
|
|
289
|
-
std::tie(hshrink, vshrink) = sharp::ResolveShrink(
|
|
290
|
-
thumbWidth, preshrunkPageHeight, targetResizeWidth, targetResizeHeight,
|
|
291
|
-
baton->canvas, swap, baton->withoutEnlargement);
|
|
271
|
+
if (shouldPreShrink) {
|
|
272
|
+
pageHeight = sharp::GetPageHeight(image);
|
|
292
273
|
}
|
|
293
274
|
|
|
294
|
-
|
|
275
|
+
// Shrink to pageHeight, so we work for multi-page images
|
|
276
|
+
std::tie(hshrink, vshrink) = sharp::ResolveShrink(
|
|
277
|
+
inputWidth, pageHeight, targetResizeWidth, targetResizeHeight,
|
|
278
|
+
baton->canvas, swap, baton->withoutEnlargement, baton->withoutReduction);
|
|
279
|
+
|
|
280
|
+
int targetHeight = static_cast<int>(std::rint(static_cast<double>(pageHeight) / vshrink));
|
|
295
281
|
int targetPageHeight = targetHeight;
|
|
296
282
|
|
|
297
283
|
// In toilet-roll mode, we must adjust vshrink so that we exactly hit
|
|
298
|
-
//
|
|
299
|
-
if (
|
|
284
|
+
// pageHeight or we'll have pixels straddling pixel boundaries
|
|
285
|
+
if (inputHeight > pageHeight) {
|
|
300
286
|
targetHeight *= nPages;
|
|
301
|
-
vshrink = static_cast<double>(
|
|
287
|
+
vshrink = static_cast<double>(inputHeight) / targetHeight;
|
|
302
288
|
}
|
|
303
289
|
|
|
304
290
|
// Ensure we're using a device-independent colour space
|
|
@@ -532,12 +518,14 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
532
518
|
MultiPageUnsupported(nPages, "Affine");
|
|
533
519
|
std::vector<double> background;
|
|
534
520
|
std::tie(image, background) = sharp::ApplyAlpha(image, baton->affineBackground, shouldPremultiplyAlpha);
|
|
521
|
+
vips::VInterpolate interp = vips::VInterpolate::new_from_name(
|
|
522
|
+
const_cast<char*>(baton->affineInterpolator.data()));
|
|
535
523
|
image = image.affine(baton->affineMatrix, VImage::option()->set("background", background)
|
|
536
524
|
->set("idx", baton->affineIdx)
|
|
537
525
|
->set("idy", baton->affineIdy)
|
|
538
526
|
->set("odx", baton->affineOdx)
|
|
539
527
|
->set("ody", baton->affineOdy)
|
|
540
|
-
->set("interpolate",
|
|
528
|
+
->set("interpolate", interp));
|
|
541
529
|
}
|
|
542
530
|
|
|
543
531
|
// Extend edges
|
|
@@ -1442,7 +1430,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1442
1430
|
baton->affineIdy = sharp::AttrAsDouble(options, "affineIdy");
|
|
1443
1431
|
baton->affineOdx = sharp::AttrAsDouble(options, "affineOdx");
|
|
1444
1432
|
baton->affineOdy = sharp::AttrAsDouble(options, "affineOdy");
|
|
1445
|
-
baton->affineInterpolator =
|
|
1433
|
+
baton->affineInterpolator = sharp::AttrAsStr(options, "affineInterpolator");
|
|
1446
1434
|
baton->removeAlpha = sharp::AttrAsBool(options, "removeAlpha");
|
|
1447
1435
|
baton->ensureAlpha = sharp::AttrAsDouble(options, "ensureAlpha");
|
|
1448
1436
|
if (options.Has("boolean")) {
|
package/src/pipeline.h
CHANGED
|
@@ -126,7 +126,7 @@ struct PipelineBaton {
|
|
|
126
126
|
double affineIdy;
|
|
127
127
|
double affineOdx;
|
|
128
128
|
double affineOdy;
|
|
129
|
-
|
|
129
|
+
std::string affineInterpolator;
|
|
130
130
|
int jpegQuality;
|
|
131
131
|
bool jpegProgressive;
|
|
132
132
|
std::string jpegChromaSubsampling;
|
|
@@ -268,7 +268,7 @@ struct PipelineBaton {
|
|
|
268
268
|
affineIdy(0),
|
|
269
269
|
affineOdx(0),
|
|
270
270
|
affineOdy(0),
|
|
271
|
-
affineInterpolator(
|
|
271
|
+
affineInterpolator("bicubic"),
|
|
272
272
|
jpegQuality(80),
|
|
273
273
|
jpegProgressive(false),
|
|
274
274
|
jpegChromaSubsampling("4:2:0"),
|