@revizly/sharp 0.34.5-revizly3 → 0.35.0-revizly10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/install/build.js +2 -2
- package/lib/channel.js +2 -2
- package/lib/colour.js +4 -4
- package/lib/composite.js +4 -4
- package/lib/constructor.js +11 -4
- package/lib/index.d.ts +47 -46
- package/lib/input.js +8 -14
- package/lib/is.js +15 -41
- package/lib/operation.js +9 -40
- package/lib/output.js +102 -17
- package/lib/resize.js +17 -1
- package/lib/sharp.js +4 -2
- package/lib/utility.js +3 -3
- package/package.json +16 -23
- package/src/binding.gyp +7 -4
- package/src/common.cc +62 -14
- package/src/common.h +15 -4
- package/src/metadata.cc +68 -11
- package/src/metadata.h +6 -1
- package/src/operations.cc +25 -8
- package/src/operations.h +1 -1
- package/src/pipeline.cc +59 -47
- package/src/pipeline.h +11 -1
- package/src/stats.cc +2 -3
- package/src/utilities.cc +4 -3
- package/install/check.js +0 -14
package/src/pipeline.cc
CHANGED
|
@@ -84,7 +84,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
84
84
|
if (nPages == -1) {
|
|
85
85
|
// Resolve the number of pages if we need to render until the end of the document
|
|
86
86
|
nPages = image.get_typeof(VIPS_META_N_PAGES) != 0
|
|
87
|
-
? image.get_int(VIPS_META_N_PAGES) - baton->input->page
|
|
87
|
+
? image.get_int(VIPS_META_N_PAGES) - std::max(0, baton->input->page)
|
|
88
88
|
: 1;
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -153,7 +153,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
153
153
|
if (baton->trimThreshold >= 0.0) {
|
|
154
154
|
MultiPageUnsupported(nPages, "Trim");
|
|
155
155
|
image = sharp::StaySequential(image);
|
|
156
|
-
image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold, baton->trimLineArt);
|
|
156
|
+
image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold, baton->trimLineArt, baton->trimMargin);
|
|
157
157
|
baton->trimOffsetLeft = image.xoffset();
|
|
158
158
|
baton->trimOffsetTop = image.yoffset();
|
|
159
159
|
}
|
|
@@ -274,7 +274,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
274
274
|
}
|
|
275
275
|
sharp::SetDensity(image, baton->input->density);
|
|
276
276
|
if (image.width() > 32767 || image.height() > 32767) {
|
|
277
|
-
throw
|
|
277
|
+
throw std::runtime_error("Input SVG image will exceed 32767x32767 pixel limit when scaled");
|
|
278
278
|
}
|
|
279
279
|
} else if (inputImageType == sharp::ImageType::PDF) {
|
|
280
280
|
if (baton->input->buffer != nullptr) {
|
|
@@ -290,12 +290,20 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
290
290
|
}
|
|
291
291
|
} else {
|
|
292
292
|
if (inputImageType == sharp::ImageType::SVG && (image.width() > 32767 || image.height() > 32767)) {
|
|
293
|
-
throw
|
|
293
|
+
throw std::runtime_error("Input SVG image exceeds 32767x32767 pixel limit");
|
|
294
294
|
}
|
|
295
295
|
}
|
|
296
296
|
if (baton->input->autoOrient) {
|
|
297
297
|
image = sharp::RemoveExifOrientation(image);
|
|
298
298
|
}
|
|
299
|
+
if (sharp::HasGainMap(image)) {
|
|
300
|
+
if (baton->withGainMap) {
|
|
301
|
+
image = image.uhdr2scRGB();
|
|
302
|
+
}
|
|
303
|
+
image = sharp::RemoveGainMap(image);
|
|
304
|
+
} else {
|
|
305
|
+
baton->withGainMap = false;
|
|
306
|
+
}
|
|
299
307
|
|
|
300
308
|
// Any pre-shrinking may already have been done
|
|
301
309
|
inputWidth = image.width();
|
|
@@ -335,7 +343,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
335
343
|
image.interpretation() != VIPS_INTERPRETATION_LABS &&
|
|
336
344
|
image.interpretation() != VIPS_INTERPRETATION_GREY16 &&
|
|
337
345
|
baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK &&
|
|
338
|
-
!baton->input->ignoreIcc
|
|
346
|
+
!baton->input->ignoreIcc && !baton->withGainMap
|
|
339
347
|
) {
|
|
340
348
|
// Convert to sRGB/P3 using embedded profile
|
|
341
349
|
try {
|
|
@@ -455,12 +463,10 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
455
463
|
std::tie(image, background) = sharp::ApplyAlpha(image, baton->resizeBackground, shouldPremultiplyAlpha);
|
|
456
464
|
|
|
457
465
|
// Embed
|
|
458
|
-
|
|
459
|
-
int top;
|
|
460
|
-
std::tie(left, top) = sharp::CalculateEmbedPosition(
|
|
466
|
+
const auto& [left, top] = sharp::CalculateEmbedPosition(
|
|
461
467
|
inputWidth, inputHeight, baton->width, baton->height, baton->position);
|
|
462
|
-
int width = std::max(inputWidth, baton->width);
|
|
463
|
-
int height = std::max(inputHeight, baton->height);
|
|
468
|
+
const int width = std::max(inputWidth, baton->width);
|
|
469
|
+
const int height = std::max(inputHeight, baton->height);
|
|
464
470
|
|
|
465
471
|
image = nPages > 1
|
|
466
472
|
? sharp::EmbedMultiPage(image,
|
|
@@ -479,13 +485,10 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
479
485
|
// Crop
|
|
480
486
|
if (baton->position < 9) {
|
|
481
487
|
// Gravity-based crop
|
|
482
|
-
|
|
483
|
-
int top;
|
|
484
|
-
|
|
485
|
-
std::tie(left, top) = sharp::CalculateCrop(
|
|
488
|
+
const auto& [left, top] = sharp::CalculateCrop(
|
|
486
489
|
inputWidth, inputHeight, baton->width, baton->height, baton->position);
|
|
487
|
-
int width = std::min(inputWidth, baton->width);
|
|
488
|
-
int height = std::min(inputHeight, baton->height);
|
|
490
|
+
const int width = std::min(inputWidth, baton->width);
|
|
491
|
+
const int height = std::min(inputHeight, baton->height);
|
|
489
492
|
|
|
490
493
|
image = nPages > 1
|
|
491
494
|
? sharp::CropMultiPage(image,
|
|
@@ -672,7 +675,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
672
675
|
|
|
673
676
|
// Verify within current dimensions
|
|
674
677
|
if (compositeImage.width() > image.width() || compositeImage.height() > image.height()) {
|
|
675
|
-
throw
|
|
678
|
+
throw std::runtime_error("Image to composite must have same dimensions or smaller");
|
|
676
679
|
}
|
|
677
680
|
// Check if overlay is tiled
|
|
678
681
|
if (composite->tile) {
|
|
@@ -797,20 +800,14 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
797
800
|
image = sharp::EnsureAlpha(image, baton->ensureAlpha);
|
|
798
801
|
}
|
|
799
802
|
|
|
800
|
-
//
|
|
803
|
+
// Ensure output colour space
|
|
801
804
|
if (sharp::Is16Bit(image.interpretation())) {
|
|
802
805
|
image = image.cast(VIPS_FORMAT_USHORT);
|
|
803
806
|
}
|
|
804
807
|
if (image.interpretation() != baton->colourspace) {
|
|
805
|
-
// Convert colourspace, pass the current known interpretation so libvips doesn't have to guess
|
|
806
808
|
image = image.colourspace(baton->colourspace, VImage::option()->set("source_space", image.interpretation()));
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
baton->withIccProfile.empty() && sharp::HasProfile(image)) {
|
|
810
|
-
image = image.icc_transform(processingProfile, VImage::option()
|
|
811
|
-
->set("embedded", true)
|
|
812
|
-
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
|
813
|
-
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
|
809
|
+
if (inputProfile.first != nullptr && baton->withIccProfile.empty()) {
|
|
810
|
+
image = sharp::SetProfile(image, inputProfile);
|
|
814
811
|
}
|
|
815
812
|
}
|
|
816
813
|
|
|
@@ -845,8 +842,6 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
845
842
|
} catch(...) {
|
|
846
843
|
sharp::VipsWarningCallback(nullptr, G_LOG_LEVEL_WARNING, "Invalid profile", nullptr);
|
|
847
844
|
}
|
|
848
|
-
} else if (baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) {
|
|
849
|
-
image = sharp::SetProfile(image, inputProfile);
|
|
850
845
|
}
|
|
851
846
|
|
|
852
847
|
// Negate the colours in the image
|
|
@@ -868,8 +863,8 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
868
863
|
if (!baton->withExifMerge) {
|
|
869
864
|
image = sharp::RemoveExif(image);
|
|
870
865
|
}
|
|
871
|
-
for (const auto&
|
|
872
|
-
image.set(
|
|
866
|
+
for (const auto& [key, value] : baton->withExif) {
|
|
867
|
+
image.set(key.c_str(), value.c_str());
|
|
873
868
|
}
|
|
874
869
|
}
|
|
875
870
|
// XMP buffer
|
|
@@ -970,6 +965,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
970
965
|
->set("effort", baton->webpEffort)
|
|
971
966
|
->set("min_size", baton->webpMinSize)
|
|
972
967
|
->set("mixed", baton->webpMixed)
|
|
968
|
+
->set("exact", baton->webpExact)
|
|
973
969
|
->set("alpha_q", baton->webpAlphaQuality)));
|
|
974
970
|
baton->bufferOut = static_cast<char*>(area->data);
|
|
975
971
|
baton->bufferOutLength = area->length;
|
|
@@ -1037,6 +1033,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1037
1033
|
->set("compression", baton->heifCompression)
|
|
1038
1034
|
->set("effort", baton->heifEffort)
|
|
1039
1035
|
->set("bitdepth", baton->heifBitdepth)
|
|
1036
|
+
->set("tune", baton->heifTune.c_str())
|
|
1040
1037
|
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
|
1041
1038
|
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
|
1042
1039
|
->set("lossless", baton->heifLossless)));
|
|
@@ -1089,20 +1086,19 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1089
1086
|
// Get raw image data
|
|
1090
1087
|
baton->bufferOut = static_cast<char*>(image.write_to_memory(&baton->bufferOutLength));
|
|
1091
1088
|
if (baton->bufferOut == nullptr) {
|
|
1092
|
-
(
|
|
1093
|
-
return Error();
|
|
1089
|
+
throw std::runtime_error("Could not allocate enough memory for raw output");
|
|
1094
1090
|
}
|
|
1095
1091
|
baton->formatOut = "raw";
|
|
1096
1092
|
} else {
|
|
1097
1093
|
// Unsupported output format
|
|
1098
|
-
(
|
|
1094
|
+
auto unsupported = std::string("Unsupported output format ");
|
|
1099
1095
|
if (baton->formatOut == "input") {
|
|
1100
|
-
|
|
1101
|
-
|
|
1096
|
+
unsupported.append("when trying to match input format of ");
|
|
1097
|
+
unsupported.append(ImageTypeId(inputImageType));
|
|
1102
1098
|
} else {
|
|
1103
|
-
|
|
1099
|
+
unsupported.append(baton->formatOut);
|
|
1104
1100
|
}
|
|
1105
|
-
|
|
1101
|
+
throw std::runtime_error(unsupported);
|
|
1106
1102
|
}
|
|
1107
1103
|
} else {
|
|
1108
1104
|
// File output
|
|
@@ -1181,6 +1177,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1181
1177
|
->set("effort", baton->webpEffort)
|
|
1182
1178
|
->set("min_size", baton->webpMinSize)
|
|
1183
1179
|
->set("mixed", baton->webpMixed)
|
|
1180
|
+
->set("exact", baton->webpExact)
|
|
1184
1181
|
->set("alpha_q", baton->webpAlphaQuality));
|
|
1185
1182
|
baton->formatOut = "webp";
|
|
1186
1183
|
} else if (baton->formatOut == "gif" || (mightMatchInput && isGif) ||
|
|
@@ -1236,6 +1233,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1236
1233
|
->set("compression", baton->heifCompression)
|
|
1237
1234
|
->set("effort", baton->heifEffort)
|
|
1238
1235
|
->set("bitdepth", baton->heifBitdepth)
|
|
1236
|
+
->set("tune", baton->heifTune.c_str())
|
|
1239
1237
|
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
|
1240
1238
|
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
|
1241
1239
|
->set("lossless", baton->heifLossless));
|
|
@@ -1275,7 +1273,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1275
1273
|
return Error();
|
|
1276
1274
|
}
|
|
1277
1275
|
}
|
|
1278
|
-
} catch (
|
|
1276
|
+
} catch (std::runtime_error const &err) {
|
|
1279
1277
|
char const *what = err.what();
|
|
1280
1278
|
if (what && what[0]) {
|
|
1281
1279
|
(baton->err).append(what);
|
|
@@ -1307,7 +1305,6 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1307
1305
|
}
|
|
1308
1306
|
warning = sharp::VipsWarningPop();
|
|
1309
1307
|
}
|
|
1310
|
-
|
|
1311
1308
|
if (baton->err.empty()) {
|
|
1312
1309
|
int width = baton->width;
|
|
1313
1310
|
int height = baton->height;
|
|
@@ -1350,12 +1347,21 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1350
1347
|
}
|
|
1351
1348
|
|
|
1352
1349
|
if (baton->bufferOutLength > 0) {
|
|
1353
|
-
// Add buffer size to info
|
|
1354
1350
|
info.Set("size", static_cast<uint32_t>(baton->bufferOutLength));
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
baton->bufferOutLength
|
|
1358
|
-
|
|
1351
|
+
if (baton->typedArrayOut) {
|
|
1352
|
+
// ECMAScript ArrayBuffer with Uint8Array view
|
|
1353
|
+
Napi::ArrayBuffer ab = Napi::ArrayBuffer::New(env, baton->bufferOutLength);
|
|
1354
|
+
memcpy(ab.Data(), baton->bufferOut, baton->bufferOutLength);
|
|
1355
|
+
sharp::FreeCallback(static_cast<char*>(baton->bufferOut), nullptr);
|
|
1356
|
+
Napi::TypedArrayOf<uint8_t> data = Napi::TypedArrayOf<uint8_t>::New(env,
|
|
1357
|
+
baton->bufferOutLength, ab, 0, napi_uint8_array);
|
|
1358
|
+
Callback().Call(Receiver().Value(), { env.Null(), data, info });
|
|
1359
|
+
} else {
|
|
1360
|
+
// Node.js Buffer
|
|
1361
|
+
Napi::Buffer<char> data = Napi::Buffer<char>::NewOrCopy(env, static_cast<char*>(baton->bufferOut),
|
|
1362
|
+
baton->bufferOutLength, sharp::FreeCallback);
|
|
1363
|
+
Callback().Call(Receiver().Value(), { env.Null(), data, info });
|
|
1364
|
+
}
|
|
1359
1365
|
} else {
|
|
1360
1366
|
// Add file size to info
|
|
1361
1367
|
if (baton->formatOut != "dz" || sharp::IsDzZip(baton->fileOut)) {
|
|
@@ -1399,7 +1405,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1399
1405
|
|
|
1400
1406
|
void MultiPageUnsupported(int const pages, std::string op) {
|
|
1401
1407
|
if (pages > 1) {
|
|
1402
|
-
throw
|
|
1408
|
+
throw std::runtime_error(op + " is not supported for multi-page images");
|
|
1403
1409
|
}
|
|
1404
1410
|
}
|
|
1405
1411
|
|
|
@@ -1448,11 +1454,11 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1448
1454
|
std::string
|
|
1449
1455
|
AssembleSuffixString(std::string extname, std::vector<std::pair<std::string, std::string>> options) {
|
|
1450
1456
|
std::string argument;
|
|
1451
|
-
for (
|
|
1457
|
+
for (const auto& [key, value] : options) {
|
|
1452
1458
|
if (!argument.empty()) {
|
|
1453
1459
|
argument += ",";
|
|
1454
1460
|
}
|
|
1455
|
-
argument +=
|
|
1461
|
+
argument += key + "=" + value;
|
|
1456
1462
|
}
|
|
1457
1463
|
return extname + "[" + argument + "]";
|
|
1458
1464
|
}
|
|
@@ -1482,6 +1488,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1482
1488
|
{"preset", vips_enum_nick(VIPS_TYPE_FOREIGN_WEBP_PRESET, baton->webpPreset)},
|
|
1483
1489
|
{"min_size", baton->webpMinSize ? "true" : "false"},
|
|
1484
1490
|
{"mixed", baton->webpMixed ? "true" : "false"},
|
|
1491
|
+
{"exact", baton->webpExact ? "true" : "false"},
|
|
1485
1492
|
{"effort", std::to_string(baton->webpEffort)}
|
|
1486
1493
|
};
|
|
1487
1494
|
suffix = AssembleSuffixString(".webp", options);
|
|
@@ -1628,6 +1635,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1628
1635
|
baton->trimBackground = sharp::AttrAsVectorOfDouble(options, "trimBackground");
|
|
1629
1636
|
baton->trimThreshold = sharp::AttrAsDouble(options, "trimThreshold");
|
|
1630
1637
|
baton->trimLineArt = sharp::AttrAsBool(options, "trimLineArt");
|
|
1638
|
+
baton->trimMargin = sharp::AttrAsUint32(options, "trimMargin");
|
|
1631
1639
|
baton->gamma = sharp::AttrAsDouble(options, "gamma");
|
|
1632
1640
|
baton->gammaOut = sharp::AttrAsDouble(options, "gammaOut");
|
|
1633
1641
|
baton->linearA = sharp::AttrAsVectorOfDouble(options, "linearA");
|
|
@@ -1705,6 +1713,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1705
1713
|
// Output
|
|
1706
1714
|
baton->formatOut = sharp::AttrAsStr(options, "formatOut");
|
|
1707
1715
|
baton->fileOut = sharp::AttrAsStr(options, "fileOut");
|
|
1716
|
+
baton->typedArrayOut = sharp::AttrAsBool(options, "typedArrayOut");
|
|
1708
1717
|
baton->keepMetadata = sharp::AttrAsUint32(options, "keepMetadata");
|
|
1709
1718
|
baton->withMetadataOrientation = sharp::AttrAsUint32(options, "withMetadataOrientation");
|
|
1710
1719
|
baton->withMetadataDensity = sharp::AttrAsDouble(options, "withMetadataDensity");
|
|
@@ -1719,6 +1728,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1719
1728
|
}
|
|
1720
1729
|
baton->withExifMerge = sharp::AttrAsBool(options, "withExifMerge");
|
|
1721
1730
|
baton->withXmp = sharp::AttrAsStr(options, "withXmp");
|
|
1731
|
+
baton->withGainMap = sharp::AttrAsBool(options, "withGainMap");
|
|
1722
1732
|
baton->timeoutSeconds = sharp::AttrAsUint32(options, "timeoutSeconds");
|
|
1723
1733
|
baton->loop = sharp::AttrAsUint32(options, "loop");
|
|
1724
1734
|
baton->delay = sharp::AttrAsInt32Vector(options, "delay");
|
|
@@ -1754,6 +1764,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1754
1764
|
baton->webpEffort = sharp::AttrAsUint32(options, "webpEffort");
|
|
1755
1765
|
baton->webpMinSize = sharp::AttrAsBool(options, "webpMinSize");
|
|
1756
1766
|
baton->webpMixed = sharp::AttrAsBool(options, "webpMixed");
|
|
1767
|
+
baton->webpExact = sharp::AttrAsBool(options, "webpExact");
|
|
1757
1768
|
baton->gifBitdepth = sharp::AttrAsUint32(options, "gifBitdepth");
|
|
1758
1769
|
baton->gifEffort = sharp::AttrAsUint32(options, "gifEffort");
|
|
1759
1770
|
baton->gifDither = sharp::AttrAsDouble(options, "gifDither");
|
|
@@ -1788,6 +1799,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1788
1799
|
baton->heifEffort = sharp::AttrAsUint32(options, "heifEffort");
|
|
1789
1800
|
baton->heifChromaSubsampling = sharp::AttrAsStr(options, "heifChromaSubsampling");
|
|
1790
1801
|
baton->heifBitdepth = sharp::AttrAsUint32(options, "heifBitdepth");
|
|
1802
|
+
baton->heifTune = sharp::AttrAsStr(options, "heifTune");
|
|
1791
1803
|
baton->jxlDistance = sharp::AttrAsDouble(options, "jxlDistance");
|
|
1792
1804
|
baton->jxlDecodingTier = sharp::AttrAsUint32(options, "jxlDecodingTier");
|
|
1793
1805
|
baton->jxlEffort = sharp::AttrAsUint32(options, "jxlEffort");
|
package/src/pipeline.h
CHANGED
|
@@ -48,6 +48,7 @@ struct PipelineBaton {
|
|
|
48
48
|
size_t bufferOutLength;
|
|
49
49
|
int pageHeightOut;
|
|
50
50
|
int pagesOut;
|
|
51
|
+
bool typedArrayOut;
|
|
51
52
|
std::vector<Composite *> composite;
|
|
52
53
|
std::vector<sharp::InputDescriptor *> joinChannelIn;
|
|
53
54
|
int topOffsetPre;
|
|
@@ -101,6 +102,7 @@ struct PipelineBaton {
|
|
|
101
102
|
bool trimLineArt;
|
|
102
103
|
int trimOffsetLeft;
|
|
103
104
|
int trimOffsetTop;
|
|
105
|
+
int trimMargin;
|
|
104
106
|
std::vector<double> linearA;
|
|
105
107
|
std::vector<double> linearB;
|
|
106
108
|
int dilateWidth;
|
|
@@ -167,6 +169,7 @@ struct PipelineBaton {
|
|
|
167
169
|
int webpEffort;
|
|
168
170
|
bool webpMinSize;
|
|
169
171
|
bool webpMixed;
|
|
172
|
+
bool webpExact;
|
|
170
173
|
int gifBitdepth;
|
|
171
174
|
int gifEffort;
|
|
172
175
|
double gifDither;
|
|
@@ -194,6 +197,7 @@ struct PipelineBaton {
|
|
|
194
197
|
std::string heifChromaSubsampling;
|
|
195
198
|
bool heifLossless;
|
|
196
199
|
int heifBitdepth;
|
|
200
|
+
std::string heifTune;
|
|
197
201
|
double jxlDistance;
|
|
198
202
|
int jxlDecodingTier;
|
|
199
203
|
int jxlEffort;
|
|
@@ -208,6 +212,7 @@ struct PipelineBaton {
|
|
|
208
212
|
std::unordered_map<std::string, std::string> withExif;
|
|
209
213
|
bool withExifMerge;
|
|
210
214
|
std::string withXmp;
|
|
215
|
+
bool withGainMap;
|
|
211
216
|
int timeoutSeconds;
|
|
212
217
|
std::vector<double> convKernel;
|
|
213
218
|
int convKernelWidth;
|
|
@@ -242,6 +247,7 @@ struct PipelineBaton {
|
|
|
242
247
|
bufferOutLength(0),
|
|
243
248
|
pageHeightOut(0),
|
|
244
249
|
pagesOut(0),
|
|
250
|
+
typedArrayOut(false),
|
|
245
251
|
topOffsetPre(-1),
|
|
246
252
|
topOffsetPost(-1),
|
|
247
253
|
channels(0),
|
|
@@ -281,6 +287,7 @@ struct PipelineBaton {
|
|
|
281
287
|
trimLineArt(false),
|
|
282
288
|
trimOffsetLeft(0),
|
|
283
289
|
trimOffsetTop(0),
|
|
290
|
+
trimMargin(0),
|
|
284
291
|
linearA{},
|
|
285
292
|
linearB{},
|
|
286
293
|
dilateWidth(0),
|
|
@@ -344,6 +351,7 @@ struct PipelineBaton {
|
|
|
344
351
|
webpEffort(4),
|
|
345
352
|
webpMinSize(false),
|
|
346
353
|
webpMixed(false),
|
|
354
|
+
webpExact(false),
|
|
347
355
|
gifBitdepth(8),
|
|
348
356
|
gifEffort(7),
|
|
349
357
|
gifDither(1.0),
|
|
@@ -357,7 +365,7 @@ struct PipelineBaton {
|
|
|
357
365
|
tiffBigtiff(false),
|
|
358
366
|
tiffPredictor(VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL),
|
|
359
367
|
tiffPyramid(false),
|
|
360
|
-
tiffBitdepth(
|
|
368
|
+
tiffBitdepth(0),
|
|
361
369
|
tiffMiniswhite(false),
|
|
362
370
|
tiffTile(false),
|
|
363
371
|
tiffTileHeight(256),
|
|
@@ -371,6 +379,7 @@ struct PipelineBaton {
|
|
|
371
379
|
heifChromaSubsampling("4:4:4"),
|
|
372
380
|
heifLossless(false),
|
|
373
381
|
heifBitdepth(8),
|
|
382
|
+
heifTune("ssim"),
|
|
374
383
|
jxlDistance(1.0),
|
|
375
384
|
jxlDecodingTier(0),
|
|
376
385
|
jxlEffort(7),
|
|
@@ -381,6 +390,7 @@ struct PipelineBaton {
|
|
|
381
390
|
withMetadataOrientation(-1),
|
|
382
391
|
withMetadataDensity(0.0),
|
|
383
392
|
withExifMerge(true),
|
|
393
|
+
withGainMap(false),
|
|
384
394
|
timeoutSeconds(0),
|
|
385
395
|
convKernelWidth(0),
|
|
386
396
|
convKernelHeight(0),
|
package/src/stats.cc
CHANGED
|
@@ -39,7 +39,7 @@ class StatsWorker : public Napi::AsyncWorker {
|
|
|
39
39
|
sharp::ImageType imageType = sharp::ImageType::UNKNOWN;
|
|
40
40
|
try {
|
|
41
41
|
std::tie(image, imageType) = OpenInput(baton->input);
|
|
42
|
-
} catch (
|
|
42
|
+
} catch (std::runtime_error const &err) {
|
|
43
43
|
(baton->err).append(err.what());
|
|
44
44
|
}
|
|
45
45
|
if (imageType != sharp::ImageType::UNKNOWN) {
|
|
@@ -92,7 +92,7 @@ class StatsWorker : public Napi::AsyncWorker {
|
|
|
92
92
|
baton->dominantRed = dx * 16 + 8;
|
|
93
93
|
baton->dominantGreen = dy * 16 + 8;
|
|
94
94
|
baton->dominantBlue = dz * 16 + 8;
|
|
95
|
-
} catch (
|
|
95
|
+
} catch (std::runtime_error const &err) {
|
|
96
96
|
(baton->err).append(err.what());
|
|
97
97
|
}
|
|
98
98
|
}
|
|
@@ -112,7 +112,6 @@ class StatsWorker : public Napi::AsyncWorker {
|
|
|
112
112
|
debuglog.Call(Receiver().Value(), { Napi::String::New(env, warning) });
|
|
113
113
|
warning = sharp::VipsWarningPop();
|
|
114
114
|
}
|
|
115
|
-
|
|
116
115
|
if (baton->err.empty()) {
|
|
117
116
|
// Stats Object
|
|
118
117
|
Napi::Object info = Napi::Object::New(env);
|
package/src/utilities.cc
CHANGED
|
@@ -123,6 +123,7 @@ Napi::Value format(const Napi::CallbackInfo& info) {
|
|
|
123
123
|
"jpeg", "png", "webp", "tiff", "magick", "openslide", "dz",
|
|
124
124
|
"ppm", "fits", "gif", "svg", "heif", "pdf", "vips", "jp2k", "jxl", "rad", "dcraw"
|
|
125
125
|
}) {
|
|
126
|
+
std::string id = f == "jp2k" ? "jp2" : f;
|
|
126
127
|
// Input
|
|
127
128
|
const VipsObjectClass *oc = vips_class_find("VipsOperation", (f + "load").c_str());
|
|
128
129
|
Napi::Boolean hasInputFile = Napi::Boolean::New(env, oc);
|
|
@@ -154,11 +155,11 @@ Napi::Value format(const Napi::CallbackInfo& info) {
|
|
|
154
155
|
output.Set("stream", hasOutputBuffer);
|
|
155
156
|
// Other attributes
|
|
156
157
|
Napi::Object container = Napi::Object::New(env);
|
|
157
|
-
container.Set("id",
|
|
158
|
+
container.Set("id", id);
|
|
158
159
|
container.Set("input", input);
|
|
159
160
|
container.Set("output", output);
|
|
160
161
|
// Add to set of formats
|
|
161
|
-
format.Set(
|
|
162
|
+
format.Set(id, container);
|
|
162
163
|
}
|
|
163
164
|
|
|
164
165
|
// Raw, uncompressed data
|
|
@@ -243,7 +244,7 @@ Napi::Value _maxColourDistance(const Napi::CallbackInfo& info) {
|
|
|
243
244
|
}
|
|
244
245
|
// Calculate colour distance
|
|
245
246
|
maxColourDistance = image1.dE00(image2).max();
|
|
246
|
-
} catch (
|
|
247
|
+
} catch (std::runtime_error const &err) {
|
|
247
248
|
throw Napi::Error::New(env, err.what());
|
|
248
249
|
}
|
|
249
250
|
|
package/install/check.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
Copyright 2013 Lovell Fuller and others.
|
|
3
|
-
SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
try {
|
|
7
|
-
const { useGlobalLibvips } = require('../lib/libvips');
|
|
8
|
-
if (useGlobalLibvips() || process.env.npm_config_build_from_source) {
|
|
9
|
-
process.exit(1);
|
|
10
|
-
}
|
|
11
|
-
} catch (err) {
|
|
12
|
-
const summary = err.message.split(/\n/).slice(0, 1);
|
|
13
|
-
console.log(`sharp: skipping install check: ${summary}`);
|
|
14
|
-
}
|