sharp 0.33.0-alpha.8 → 0.33.0-rc.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/src/pipeline.cc CHANGED
@@ -126,10 +126,10 @@ class PipelineWorker : public Napi::AsyncWorker {
126
126
  }
127
127
 
128
128
  // Trim
129
- if (baton->trimThreshold > 0.0) {
129
+ if (baton->trimThreshold >= 0.0) {
130
130
  MultiPageUnsupported(nPages, "Trim");
131
131
  image = sharp::StaySequential(image, access);
132
- image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold);
132
+ image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold, baton->trimLineArt);
133
133
  baton->trimOffsetLeft = image.xoffset();
134
134
  baton->trimOffsetTop = image.yoffset();
135
135
  }
@@ -182,7 +182,7 @@ class PipelineWorker : public Napi::AsyncWorker {
182
182
  // - trimming or pre-resize extract isn't required;
183
183
  // - input colourspace is not specified;
184
184
  bool const shouldPreShrink = (targetResizeWidth > 0 || targetResizeHeight > 0) &&
185
- baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold == 0.0 &&
185
+ baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold < 0.0 &&
186
186
  baton->colourspaceInput == VIPS_INTERPRETATION_LAST && !shouldRotateBefore;
187
187
 
188
188
  if (shouldPreShrink) {
@@ -315,6 +315,11 @@ class PipelineWorker : public Napi::AsyncWorker {
315
315
  }
316
316
 
317
317
  // Ensure we're using a device-independent colour space
318
+ std::pair<char*, size_t> inputProfile(nullptr, 0);
319
+ if ((baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) && baton->withIccProfile.empty()) {
320
+ // Cache input profile for use with output
321
+ inputProfile = sharp::GetProfile(image);
322
+ }
318
323
  char const *processingProfile = image.interpretation() == VIPS_INTERPRETATION_RGB16 ? "p3" : "srgb";
319
324
  if (
320
325
  sharp::HasProfile(image) &&
@@ -485,9 +490,7 @@ class PipelineWorker : public Napi::AsyncWorker {
485
490
  image = sharp::StaySequential(image, access);
486
491
  image = image.smartcrop(baton->width, baton->height, VImage::option()
487
492
  ->set("interesting", baton->position == 16 ? VIPS_INTERESTING_ENTROPY : VIPS_INTERESTING_ATTENTION)
488
- #if (VIPS_MAJOR_VERSION >= 8 && VIPS_MINOR_VERSION >= 15)
489
493
  ->set("premultiplied", shouldPremultiplyAlpha)
490
- #endif
491
494
  ->set("attention_x", &attention_x)
492
495
  ->set("attention_y", &attention_y));
493
496
  baton->hasCropOffset = true;
@@ -738,8 +741,8 @@ class PipelineWorker : public Napi::AsyncWorker {
738
741
  }
739
742
 
740
743
  // Tint the image
741
- if (baton->tintA < 128.0 || baton->tintB < 128.0) {
742
- image = sharp::Tint(image, baton->tintA, baton->tintB);
744
+ if (baton->tint[0] >= 0.0) {
745
+ image = sharp::Tint(image, baton->tint);
743
746
  }
744
747
 
745
748
  // Remove alpha channel, if any
@@ -760,7 +763,8 @@ class PipelineWorker : public Napi::AsyncWorker {
760
763
  // Convert colourspace, pass the current known interpretation so libvips doesn't have to guess
761
764
  image = image.colourspace(baton->colourspace, VImage::option()->set("source_space", image.interpretation()));
762
765
  // Transform colours from embedded profile to output profile
763
- if (baton->withMetadata && sharp::HasProfile(image) && baton->withMetadataIcc.empty()) {
766
+ if ((baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) &&
767
+ baton->withIccProfile.empty() && sharp::HasProfile(image)) {
764
768
  image = image.icc_transform("srgb", VImage::option()
765
769
  ->set("embedded", TRUE)
766
770
  ->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
@@ -789,27 +793,30 @@ class PipelineWorker : public Napi::AsyncWorker {
789
793
  }
790
794
 
791
795
  // Apply output ICC profile
792
- if (baton->withMetadata) {
793
- image = image.icc_transform(
794
- baton->withMetadataIcc.empty() ? "srgb" : const_cast<char*>(baton->withMetadataIcc.data()),
795
- VImage::option()
796
- ->set("input_profile", processingProfile)
797
- ->set("embedded", TRUE)
798
- ->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
799
- ->set("intent", VIPS_INTENT_PERCEPTUAL));
796
+ if (!baton->withIccProfile.empty()) {
797
+ image = image.icc_transform(const_cast<char*>(baton->withIccProfile.data()), VImage::option()
798
+ ->set("input_profile", processingProfile)
799
+ ->set("embedded", TRUE)
800
+ ->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
801
+ ->set("intent", VIPS_INTENT_PERCEPTUAL));
802
+ } else if (baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) {
803
+ image = sharp::SetProfile(image, inputProfile);
800
804
  }
801
805
  // Override EXIF Orientation tag
802
- if (baton->withMetadata && baton->withMetadataOrientation != -1) {
806
+ if (baton->withMetadataOrientation != -1) {
803
807
  image = sharp::SetExifOrientation(image, baton->withMetadataOrientation);
804
808
  }
805
809
  // Override pixel density
806
810
  if (baton->withMetadataDensity > 0) {
807
811
  image = sharp::SetDensity(image, baton->withMetadataDensity);
808
812
  }
809
- // Metadata key/value pairs, e.g. EXIF
810
- if (!baton->withMetadataStrs.empty()) {
813
+ // EXIF key/value pairs
814
+ if (baton->keepMetadata & VIPS_FOREIGN_KEEP_EXIF) {
811
815
  image = image.copy();
812
- for (const auto& s : baton->withMetadataStrs) {
816
+ if (!baton->withExifMerge) {
817
+ image = sharp::RemoveExif(image);
818
+ }
819
+ for (const auto& s : baton->withExif) {
813
820
  image.set(s.first.data(), s.second.data());
814
821
  }
815
822
  }
@@ -830,7 +837,7 @@ class PipelineWorker : public Napi::AsyncWorker {
830
837
  // Write JPEG to buffer
831
838
  sharp::AssertImageTypeDimensions(image, sharp::ImageType::JPEG);
832
839
  VipsArea *area = reinterpret_cast<VipsArea*>(image.jpegsave_buffer(VImage::option()
833
- ->set("strip", !baton->withMetadata)
840
+ ->set("keep", baton->keepMetadata)
834
841
  ->set("Q", baton->jpegQuality)
835
842
  ->set("interlace", baton->jpegProgressive)
836
843
  ->set("subsample_mode", baton->jpegChromaSubsampling == "4:4:4"
@@ -872,7 +879,7 @@ class PipelineWorker : public Napi::AsyncWorker {
872
879
  // Write PNG to buffer
873
880
  sharp::AssertImageTypeDimensions(image, sharp::ImageType::PNG);
874
881
  VipsArea *area = reinterpret_cast<VipsArea*>(image.pngsave_buffer(VImage::option()
875
- ->set("strip", !baton->withMetadata)
882
+ ->set("keep", baton->keepMetadata)
876
883
  ->set("interlace", baton->pngProgressive)
877
884
  ->set("compression", baton->pngCompressionLevel)
878
885
  ->set("filter", baton->pngAdaptiveFiltering ? VIPS_FOREIGN_PNG_FILTER_ALL : VIPS_FOREIGN_PNG_FILTER_NONE)
@@ -891,7 +898,7 @@ class PipelineWorker : public Napi::AsyncWorker {
891
898
  // Write WEBP to buffer
892
899
  sharp::AssertImageTypeDimensions(image, sharp::ImageType::WEBP);
893
900
  VipsArea *area = reinterpret_cast<VipsArea*>(image.webpsave_buffer(VImage::option()
894
- ->set("strip", !baton->withMetadata)
901
+ ->set("keep", baton->keepMetadata)
895
902
  ->set("Q", baton->webpQuality)
896
903
  ->set("lossless", baton->webpLossless)
897
904
  ->set("near_lossless", baton->webpNearLossless)
@@ -911,7 +918,7 @@ class PipelineWorker : public Napi::AsyncWorker {
911
918
  // Write GIF to buffer
912
919
  sharp::AssertImageTypeDimensions(image, sharp::ImageType::GIF);
913
920
  VipsArea *area = reinterpret_cast<VipsArea*>(image.gifsave_buffer(VImage::option()
914
- ->set("strip", !baton->withMetadata)
921
+ ->set("keep", baton->keepMetadata)
915
922
  ->set("bitdepth", baton->gifBitdepth)
916
923
  ->set("effort", baton->gifEffort)
917
924
  ->set("reuse", baton->gifReuse)
@@ -936,10 +943,11 @@ class PipelineWorker : public Napi::AsyncWorker {
936
943
  image = image.cast(VIPS_FORMAT_FLOAT);
937
944
  }
938
945
  VipsArea *area = reinterpret_cast<VipsArea*>(image.tiffsave_buffer(VImage::option()
939
- ->set("strip", !baton->withMetadata)
946
+ ->set("keep", baton->keepMetadata)
940
947
  ->set("Q", baton->tiffQuality)
941
948
  ->set("bitdepth", baton->tiffBitdepth)
942
949
  ->set("compression", baton->tiffCompression)
950
+ ->set("miniswhite", baton->tiffMiniswhite)
943
951
  ->set("predictor", baton->tiffPredictor)
944
952
  ->set("pyramid", baton->tiffPyramid)
945
953
  ->set("tile", baton->tiffTile)
@@ -959,7 +967,7 @@ class PipelineWorker : public Napi::AsyncWorker {
959
967
  sharp::AssertImageTypeDimensions(image, sharp::ImageType::HEIF);
960
968
  image = sharp::RemoveAnimationProperties(image).cast(VIPS_FORMAT_UCHAR);
961
969
  VipsArea *area = reinterpret_cast<VipsArea*>(image.heifsave_buffer(VImage::option()
962
- ->set("strip", !baton->withMetadata)
970
+ ->set("keep", baton->keepMetadata)
963
971
  ->set("Q", baton->heifQuality)
964
972
  ->set("compression", baton->heifCompression)
965
973
  ->set("effort", baton->heifEffort)
@@ -991,7 +999,7 @@ class PipelineWorker : public Napi::AsyncWorker {
991
999
  // Write JXL to buffer
992
1000
  image = sharp::RemoveAnimationProperties(image);
993
1001
  VipsArea *area = reinterpret_cast<VipsArea*>(image.jxlsave_buffer(VImage::option()
994
- ->set("strip", !baton->withMetadata)
1002
+ ->set("keep", baton->keepMetadata)
995
1003
  ->set("distance", baton->jxlDistance)
996
1004
  ->set("tier", baton->jxlDecodingTier)
997
1005
  ->set("effort", baton->jxlEffort)
@@ -1052,7 +1060,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1052
1060
  // Write JPEG to file
1053
1061
  sharp::AssertImageTypeDimensions(image, sharp::ImageType::JPEG);
1054
1062
  image.jpegsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
1055
- ->set("strip", !baton->withMetadata)
1063
+ ->set("keep", baton->keepMetadata)
1056
1064
  ->set("Q", baton->jpegQuality)
1057
1065
  ->set("interlace", baton->jpegProgressive)
1058
1066
  ->set("subsample_mode", baton->jpegChromaSubsampling == "4:4:4"
@@ -1082,7 +1090,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1082
1090
  // Write PNG to file
1083
1091
  sharp::AssertImageTypeDimensions(image, sharp::ImageType::PNG);
1084
1092
  image.pngsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
1085
- ->set("strip", !baton->withMetadata)
1093
+ ->set("keep", baton->keepMetadata)
1086
1094
  ->set("interlace", baton->pngProgressive)
1087
1095
  ->set("compression", baton->pngCompressionLevel)
1088
1096
  ->set("filter", baton->pngAdaptiveFiltering ? VIPS_FOREIGN_PNG_FILTER_ALL : VIPS_FOREIGN_PNG_FILTER_NONE)
@@ -1097,7 +1105,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1097
1105
  // Write WEBP to file
1098
1106
  sharp::AssertImageTypeDimensions(image, sharp::ImageType::WEBP);
1099
1107
  image.webpsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
1100
- ->set("strip", !baton->withMetadata)
1108
+ ->set("keep", baton->keepMetadata)
1101
1109
  ->set("Q", baton->webpQuality)
1102
1110
  ->set("lossless", baton->webpLossless)
1103
1111
  ->set("near_lossless", baton->webpNearLossless)
@@ -1113,7 +1121,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1113
1121
  // Write GIF to file
1114
1122
  sharp::AssertImageTypeDimensions(image, sharp::ImageType::GIF);
1115
1123
  image.gifsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
1116
- ->set("strip", !baton->withMetadata)
1124
+ ->set("keep", baton->keepMetadata)
1117
1125
  ->set("bitdepth", baton->gifBitdepth)
1118
1126
  ->set("effort", baton->gifEffort)
1119
1127
  ->set("reuse", baton->gifReuse)
@@ -1132,10 +1140,11 @@ class PipelineWorker : public Napi::AsyncWorker {
1132
1140
  image = image.cast(VIPS_FORMAT_FLOAT);
1133
1141
  }
1134
1142
  image.tiffsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
1135
- ->set("strip", !baton->withMetadata)
1143
+ ->set("keep", baton->keepMetadata)
1136
1144
  ->set("Q", baton->tiffQuality)
1137
1145
  ->set("bitdepth", baton->tiffBitdepth)
1138
1146
  ->set("compression", baton->tiffCompression)
1147
+ ->set("miniswhite", baton->tiffMiniswhite)
1139
1148
  ->set("predictor", baton->tiffPredictor)
1140
1149
  ->set("pyramid", baton->tiffPyramid)
1141
1150
  ->set("tile", baton->tiffTile)
@@ -1151,7 +1160,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1151
1160
  sharp::AssertImageTypeDimensions(image, sharp::ImageType::HEIF);
1152
1161
  image = sharp::RemoveAnimationProperties(image).cast(VIPS_FORMAT_UCHAR);
1153
1162
  image.heifsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
1154
- ->set("strip", !baton->withMetadata)
1163
+ ->set("keep", baton->keepMetadata)
1155
1164
  ->set("Q", baton->heifQuality)
1156
1165
  ->set("compression", baton->heifCompression)
1157
1166
  ->set("effort", baton->heifEffort)
@@ -1165,7 +1174,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1165
1174
  // Write JXL to file
1166
1175
  image = sharp::RemoveAnimationProperties(image);
1167
1176
  image.jxlsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
1168
- ->set("strip", !baton->withMetadata)
1177
+ ->set("keep", baton->keepMetadata)
1169
1178
  ->set("distance", baton->jxlDistance)
1170
1179
  ->set("tier", baton->jxlDecodingTier)
1171
1180
  ->set("effort", baton->jxlEffort)
@@ -1187,7 +1196,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1187
1196
  (willMatchInput && inputImageType == sharp::ImageType::VIPS)) {
1188
1197
  // Write V to file
1189
1198
  image.vipssave(const_cast<char*>(baton->fileOut.data()), VImage::option()
1190
- ->set("strip", !baton->withMetadata));
1199
+ ->set("keep", baton->keepMetadata));
1191
1200
  baton->formatOut = "v";
1192
1201
  } else {
1193
1202
  // Unsupported output format
@@ -1215,7 +1224,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1215
1224
  // Handle warnings
1216
1225
  std::string warning = sharp::VipsWarningPop();
1217
1226
  while (!warning.empty()) {
1218
- debuglog.MakeCallback(Receiver().Value(), { Napi::String::New(env, warning) });
1227
+ debuglog.Call(Receiver().Value(), { Napi::String::New(env, warning) });
1219
1228
  warning = sharp::VipsWarningPop();
1220
1229
  }
1221
1230
 
@@ -1248,11 +1257,10 @@ class PipelineWorker : public Napi::AsyncWorker {
1248
1257
  info.Set("attentionX", static_cast<int32_t>(baton->attentionX));
1249
1258
  info.Set("attentionY", static_cast<int32_t>(baton->attentionY));
1250
1259
  }
1251
- if (baton->trimThreshold > 0.0) {
1260
+ if (baton->trimThreshold >= 0.0) {
1252
1261
  info.Set("trimOffsetLeft", static_cast<int32_t>(baton->trimOffsetLeft));
1253
1262
  info.Set("trimOffsetTop", static_cast<int32_t>(baton->trimOffsetTop));
1254
1263
  }
1255
-
1256
1264
  if (baton->input->textAutofitDpi) {
1257
1265
  info.Set("textAutofitDpi", static_cast<uint32_t>(baton->input->textAutofitDpi));
1258
1266
  }
@@ -1263,17 +1271,17 @@ class PipelineWorker : public Napi::AsyncWorker {
1263
1271
  // Pass ownership of output data to Buffer instance
1264
1272
  Napi::Buffer<char> data = Napi::Buffer<char>::NewOrCopy(env, static_cast<char*>(baton->bufferOut),
1265
1273
  baton->bufferOutLength, sharp::FreeCallback);
1266
- Callback().MakeCallback(Receiver().Value(), { env.Null(), data, info });
1274
+ Callback().Call(Receiver().Value(), { env.Null(), data, info });
1267
1275
  } else {
1268
1276
  // Add file size to info
1269
1277
  struct STAT64_STRUCT st;
1270
1278
  if (STAT64_FUNCTION(baton->fileOut.data(), &st) == 0) {
1271
1279
  info.Set("size", static_cast<uint32_t>(st.st_size));
1272
1280
  }
1273
- Callback().MakeCallback(Receiver().Value(), { env.Null(), info });
1281
+ Callback().Call(Receiver().Value(), { env.Null(), info });
1274
1282
  }
1275
1283
  } else {
1276
- Callback().MakeCallback(Receiver().Value(), { Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
1284
+ Callback().Call(Receiver().Value(), { Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
1277
1285
  }
1278
1286
 
1279
1287
  // Delete baton
@@ -1291,7 +1299,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1291
1299
  // Decrement processing task counter
1292
1300
  sharp::counterProcess--;
1293
1301
  Napi::Number queueLength = Napi::Number::New(env, static_cast<int>(sharp::counterQueue));
1294
- queueListener.MakeCallback(Receiver().Value(), { queueLength });
1302
+ queueListener.Call(Receiver().Value(), { queueLength });
1295
1303
  }
1296
1304
 
1297
1305
  private:
@@ -1402,7 +1410,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1402
1410
  suffix = AssembleSuffixString(extname, options);
1403
1411
  }
1404
1412
  vips::VOption *options = VImage::option()
1405
- ->set("strip", !baton->withMetadata)
1413
+ ->set("keep", baton->keepMetadata)
1406
1414
  ->set("tile_size", baton->tileSize)
1407
1415
  ->set("overlap", baton->tileOverlap)
1408
1416
  ->set("container", baton->tileContainer)
@@ -1519,6 +1527,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1519
1527
  baton->thresholdGrayscale = sharp::AttrAsBool(options, "thresholdGrayscale");
1520
1528
  baton->trimBackground = sharp::AttrAsVectorOfDouble(options, "trimBackground");
1521
1529
  baton->trimThreshold = sharp::AttrAsDouble(options, "trimThreshold");
1530
+ baton->trimLineArt = sharp::AttrAsBool(options, "trimLineArt");
1522
1531
  baton->gamma = sharp::AttrAsDouble(options, "gamma");
1523
1532
  baton->gammaOut = sharp::AttrAsDouble(options, "gammaOut");
1524
1533
  baton->linearA = sharp::AttrAsVectorOfDouble(options, "linearA");
@@ -1527,8 +1536,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1527
1536
  baton->normalise = sharp::AttrAsBool(options, "normalise");
1528
1537
  baton->normaliseLower = sharp::AttrAsUint32(options, "normaliseLower");
1529
1538
  baton->normaliseUpper = sharp::AttrAsUint32(options, "normaliseUpper");
1530
- baton->tintA = sharp::AttrAsDouble(options, "tintA");
1531
- baton->tintB = sharp::AttrAsDouble(options, "tintB");
1539
+ baton->tint = sharp::AttrAsVectorOfDouble(options, "tint");
1532
1540
  baton->claheWidth = sharp::AttrAsUint32(options, "claheWidth");
1533
1541
  baton->claheHeight = sharp::AttrAsUint32(options, "claheHeight");
1534
1542
  baton->claheMaxSlope = sharp::AttrAsUint32(options, "claheMaxSlope");
@@ -1594,18 +1602,19 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1594
1602
  // Output
1595
1603
  baton->formatOut = sharp::AttrAsStr(options, "formatOut");
1596
1604
  baton->fileOut = sharp::AttrAsStr(options, "fileOut");
1597
- baton->withMetadata = sharp::AttrAsBool(options, "withMetadata");
1605
+ baton->keepMetadata = sharp::AttrAsUint32(options, "keepMetadata");
1598
1606
  baton->withMetadataOrientation = sharp::AttrAsUint32(options, "withMetadataOrientation");
1599
1607
  baton->withMetadataDensity = sharp::AttrAsDouble(options, "withMetadataDensity");
1600
- baton->withMetadataIcc = sharp::AttrAsStr(options, "withMetadataIcc");
1601
- Napi::Object mdStrs = options.Get("withMetadataStrs").As<Napi::Object>();
1602
- Napi::Array mdStrKeys = mdStrs.GetPropertyNames();
1603
- for (unsigned int i = 0; i < mdStrKeys.Length(); i++) {
1604
- std::string k = sharp::AttrAsStr(mdStrKeys, i);
1605
- if (mdStrs.HasOwnProperty(k)) {
1606
- baton->withMetadataStrs.insert(std::make_pair(k, sharp::AttrAsStr(mdStrs, k)));
1608
+ baton->withIccProfile = sharp::AttrAsStr(options, "withIccProfile");
1609
+ Napi::Object withExif = options.Get("withExif").As<Napi::Object>();
1610
+ Napi::Array withExifKeys = withExif.GetPropertyNames();
1611
+ for (unsigned int i = 0; i < withExifKeys.Length(); i++) {
1612
+ std::string k = sharp::AttrAsStr(withExifKeys, i);
1613
+ if (withExif.HasOwnProperty(k)) {
1614
+ baton->withExif.insert(std::make_pair(k, sharp::AttrAsStr(withExif, k)));
1607
1615
  }
1608
1616
  }
1617
+ baton->withExifMerge = sharp::AttrAsBool(options, "withExifMerge");
1609
1618
  baton->timeoutSeconds = sharp::AttrAsUint32(options, "timeoutSeconds");
1610
1619
  // Format-specific
1611
1620
  baton->jpegQuality = sharp::AttrAsUint32(options, "jpegQuality");
@@ -1647,6 +1656,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1647
1656
  baton->gifProgressive = sharp::AttrAsBool(options, "gifProgressive");
1648
1657
  baton->tiffQuality = sharp::AttrAsUint32(options, "tiffQuality");
1649
1658
  baton->tiffPyramid = sharp::AttrAsBool(options, "tiffPyramid");
1659
+ baton->tiffMiniswhite = sharp::AttrAsBool(options, "tiffMiniswhite");
1650
1660
  baton->tiffBitdepth = sharp::AttrAsUint32(options, "tiffBitdepth");
1651
1661
  baton->tiffTile = sharp::AttrAsBool(options, "tiffTile");
1652
1662
  baton->tiffTileWidth = sharp::AttrAsUint32(options, "tiffTileWidth");
@@ -1708,7 +1718,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1708
1718
 
1709
1719
  // Increment queued task counter
1710
1720
  Napi::Number queueLength = Napi::Number::New(info.Env(), static_cast<int>(++sharp::counterQueue));
1711
- queueListener.MakeCallback(info.This(), { queueLength });
1721
+ queueListener.Call(info.This(), { queueLength });
1712
1722
 
1713
1723
  return info.Env().Undefined();
1714
1724
  }
package/src/pipeline.h CHANGED
@@ -69,8 +69,7 @@ struct PipelineBaton {
69
69
  bool premultiplied;
70
70
  bool tileCentre;
71
71
  bool fastShrinkOnLoad;
72
- double tintA;
73
- double tintB;
72
+ std::vector<double> tint;
74
73
  bool flatten;
75
74
  std::vector<double> flattenBackground;
76
75
  bool unflatten;
@@ -92,6 +91,7 @@ struct PipelineBaton {
92
91
  bool thresholdGrayscale;
93
92
  std::vector<double> trimBackground;
94
93
  double trimThreshold;
94
+ bool trimLineArt;
95
95
  int trimOffsetLeft;
96
96
  int trimOffsetTop;
97
97
  std::vector<double> linearA;
@@ -169,6 +169,7 @@ struct PipelineBaton {
169
169
  VipsForeignTiffPredictor tiffPredictor;
170
170
  bool tiffPyramid;
171
171
  int tiffBitdepth;
172
+ bool tiffMiniswhite;
172
173
  bool tiffTile;
173
174
  int tiffTileHeight;
174
175
  int tiffTileWidth;
@@ -186,11 +187,12 @@ struct PipelineBaton {
186
187
  bool jxlLossless;
187
188
  VipsBandFormat rawDepth;
188
189
  std::string err;
189
- bool withMetadata;
190
+ int keepMetadata;
190
191
  int withMetadataOrientation;
191
192
  double withMetadataDensity;
192
- std::string withMetadataIcc;
193
- std::unordered_map<std::string, std::string> withMetadataStrs;
193
+ std::string withIccProfile;
194
+ std::unordered_map<std::string, std::string> withExif;
195
+ bool withExifMerge;
194
196
  int timeoutSeconds;
195
197
  std::unique_ptr<double[]> convKernel;
196
198
  int convKernelWidth;
@@ -237,8 +239,7 @@ struct PipelineBaton {
237
239
  attentionX(0),
238
240
  attentionY(0),
239
241
  premultiplied(false),
240
- tintA(128.0),
241
- tintB(128.0),
242
+ tint{ -1.0, 0.0, 0.0, 0.0 },
242
243
  flatten(false),
243
244
  flattenBackground{ 0.0, 0.0, 0.0 },
244
245
  unflatten(false),
@@ -259,7 +260,8 @@ struct PipelineBaton {
259
260
  threshold(0),
260
261
  thresholdGrayscale(true),
261
262
  trimBackground{},
262
- trimThreshold(0.0),
263
+ trimThreshold(-1.0),
264
+ trimLineArt(false),
263
265
  trimOffsetLeft(0),
264
266
  trimOffsetTop(0),
265
267
  linearA{},
@@ -335,6 +337,7 @@ struct PipelineBaton {
335
337
  tiffPredictor(VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL),
336
338
  tiffPyramid(false),
337
339
  tiffBitdepth(8),
340
+ tiffMiniswhite(false),
338
341
  tiffTile(false),
339
342
  tiffTileHeight(256),
340
343
  tiffTileWidth(256),
@@ -351,9 +354,10 @@ struct PipelineBaton {
351
354
  jxlEffort(7),
352
355
  jxlLossless(false),
353
356
  rawDepth(VIPS_FORMAT_UCHAR),
354
- withMetadata(false),
357
+ keepMetadata(0),
355
358
  withMetadataOrientation(-1),
356
359
  withMetadataDensity(0.0),
360
+ withExifMerge(true),
357
361
  timeoutSeconds(0),
358
362
  convKernelWidth(0),
359
363
  convKernelHeight(0),
package/src/stats.cc CHANGED
@@ -106,7 +106,7 @@ class StatsWorker : public Napi::AsyncWorker {
106
106
  // Handle warnings
107
107
  std::string warning = sharp::VipsWarningPop();
108
108
  while (!warning.empty()) {
109
- debuglog.MakeCallback(Receiver().Value(), { Napi::String::New(env, warning) });
109
+ debuglog.Call(Receiver().Value(), { Napi::String::New(env, warning) });
110
110
  warning = sharp::VipsWarningPop();
111
111
  }
112
112
 
@@ -141,9 +141,9 @@ class StatsWorker : public Napi::AsyncWorker {
141
141
  dominant.Set("g", baton->dominantGreen);
142
142
  dominant.Set("b", baton->dominantBlue);
143
143
  info.Set("dominant", dominant);
144
- Callback().MakeCallback(Receiver().Value(), { env.Null(), info });
144
+ Callback().Call(Receiver().Value(), { env.Null(), info });
145
145
  } else {
146
- Callback().MakeCallback(Receiver().Value(), { Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
146
+ Callback().Call(Receiver().Value(), { Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
147
147
  }
148
148
 
149
149
  delete baton->input;
package/src/utilities.cc CHANGED
@@ -102,6 +102,11 @@ Napi::Value libvipsVersion(const Napi::CallbackInfo& info) {
102
102
  version.Set("isGlobal", Napi::Boolean::New(env, true));
103
103
  #else
104
104
  version.Set("isGlobal", Napi::Boolean::New(env, false));
105
+ #endif
106
+ #ifdef __EMSCRIPTEN__
107
+ version.Set("isWasm", Napi::Boolean::New(env, true));
108
+ #else
109
+ version.Set("isWasm", Napi::Boolean::New(env, false));
105
110
  #endif
106
111
  return version;
107
112
  }