@revizly/sharp 0.35.0-revizly6 → 0.35.0-revizly8

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
@@ -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 vips::VError("Input SVG image will exceed 32767x32767 pixel limit when scaled");
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 vips::VError("Input SVG image exceeds 32767x32767 pixel limit");
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 {
@@ -667,7 +675,7 @@ class PipelineWorker : public Napi::AsyncWorker {
667
675
 
668
676
  // Verify within current dimensions
669
677
  if (compositeImage.width() > image.width() || compositeImage.height() > image.height()) {
670
- throw vips::VError("Image to composite must have same dimensions or smaller");
678
+ throw std::runtime_error("Image to composite must have same dimensions or smaller");
671
679
  }
672
680
  // Check if overlay is tiled
673
681
  if (composite->tile) {
@@ -957,6 +965,7 @@ class PipelineWorker : public Napi::AsyncWorker {
957
965
  ->set("effort", baton->webpEffort)
958
966
  ->set("min_size", baton->webpMinSize)
959
967
  ->set("mixed", baton->webpMixed)
968
+ ->set("exact", baton->webpExact)
960
969
  ->set("alpha_q", baton->webpAlphaQuality)));
961
970
  baton->bufferOut = static_cast<char*>(area->data);
962
971
  baton->bufferOutLength = area->length;
@@ -1024,6 +1033,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1024
1033
  ->set("compression", baton->heifCompression)
1025
1034
  ->set("effort", baton->heifEffort)
1026
1035
  ->set("bitdepth", baton->heifBitdepth)
1036
+ ->set("tune", baton->heifTune.c_str())
1027
1037
  ->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
1028
1038
  ? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
1029
1039
  ->set("lossless", baton->heifLossless)));
@@ -1076,20 +1086,19 @@ class PipelineWorker : public Napi::AsyncWorker {
1076
1086
  // Get raw image data
1077
1087
  baton->bufferOut = static_cast<char*>(image.write_to_memory(&baton->bufferOutLength));
1078
1088
  if (baton->bufferOut == nullptr) {
1079
- (baton->err).append("Could not allocate enough memory for raw output");
1080
- return Error();
1089
+ throw std::runtime_error("Could not allocate enough memory for raw output");
1081
1090
  }
1082
1091
  baton->formatOut = "raw";
1083
1092
  } else {
1084
1093
  // Unsupported output format
1085
- (baton->err).append("Unsupported output format ");
1094
+ auto unsupported = std::string("Unsupported output format ");
1086
1095
  if (baton->formatOut == "input") {
1087
- (baton->err).append("when trying to match input format of ");
1088
- (baton->err).append(ImageTypeId(inputImageType));
1096
+ unsupported.append("when trying to match input format of ");
1097
+ unsupported.append(ImageTypeId(inputImageType));
1089
1098
  } else {
1090
- (baton->err).append(baton->formatOut);
1099
+ unsupported.append(baton->formatOut);
1091
1100
  }
1092
- return Error();
1101
+ throw std::runtime_error(unsupported);
1093
1102
  }
1094
1103
  } else {
1095
1104
  // File output
@@ -1168,6 +1177,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1168
1177
  ->set("effort", baton->webpEffort)
1169
1178
  ->set("min_size", baton->webpMinSize)
1170
1179
  ->set("mixed", baton->webpMixed)
1180
+ ->set("exact", baton->webpExact)
1171
1181
  ->set("alpha_q", baton->webpAlphaQuality));
1172
1182
  baton->formatOut = "webp";
1173
1183
  } else if (baton->formatOut == "gif" || (mightMatchInput && isGif) ||
@@ -1223,6 +1233,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1223
1233
  ->set("compression", baton->heifCompression)
1224
1234
  ->set("effort", baton->heifEffort)
1225
1235
  ->set("bitdepth", baton->heifBitdepth)
1236
+ ->set("tune", baton->heifTune.c_str())
1226
1237
  ->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
1227
1238
  ? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
1228
1239
  ->set("lossless", baton->heifLossless));
@@ -1262,7 +1273,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1262
1273
  return Error();
1263
1274
  }
1264
1275
  }
1265
- } catch (vips::VError const &err) {
1276
+ } catch (std::runtime_error const &err) {
1266
1277
  char const *what = err.what();
1267
1278
  if (what && what[0]) {
1268
1279
  (baton->err).append(what);
@@ -1294,7 +1305,6 @@ class PipelineWorker : public Napi::AsyncWorker {
1294
1305
  }
1295
1306
  warning = sharp::VipsWarningPop();
1296
1307
  }
1297
-
1298
1308
  if (baton->err.empty()) {
1299
1309
  int width = baton->width;
1300
1310
  int height = baton->height;
@@ -1337,12 +1347,21 @@ class PipelineWorker : public Napi::AsyncWorker {
1337
1347
  }
1338
1348
 
1339
1349
  if (baton->bufferOutLength > 0) {
1340
- // Add buffer size to info
1341
1350
  info.Set("size", static_cast<uint32_t>(baton->bufferOutLength));
1342
- // Pass ownership of output data to Buffer instance
1343
- Napi::Buffer<char> data = Napi::Buffer<char>::NewOrCopy(env, static_cast<char*>(baton->bufferOut),
1344
- baton->bufferOutLength, sharp::FreeCallback);
1345
- Callback().Call(Receiver().Value(), { env.Null(), data, info });
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
+ }
1346
1365
  } else {
1347
1366
  // Add file size to info
1348
1367
  if (baton->formatOut != "dz" || sharp::IsDzZip(baton->fileOut)) {
@@ -1386,7 +1405,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1386
1405
 
1387
1406
  void MultiPageUnsupported(int const pages, std::string op) {
1388
1407
  if (pages > 1) {
1389
- throw vips::VError(op + " is not supported for multi-page images");
1408
+ throw std::runtime_error(op + " is not supported for multi-page images");
1390
1409
  }
1391
1410
  }
1392
1411
 
@@ -1469,6 +1488,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1469
1488
  {"preset", vips_enum_nick(VIPS_TYPE_FOREIGN_WEBP_PRESET, baton->webpPreset)},
1470
1489
  {"min_size", baton->webpMinSize ? "true" : "false"},
1471
1490
  {"mixed", baton->webpMixed ? "true" : "false"},
1491
+ {"exact", baton->webpExact ? "true" : "false"},
1472
1492
  {"effort", std::to_string(baton->webpEffort)}
1473
1493
  };
1474
1494
  suffix = AssembleSuffixString(".webp", options);
@@ -1615,6 +1635,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1615
1635
  baton->trimBackground = sharp::AttrAsVectorOfDouble(options, "trimBackground");
1616
1636
  baton->trimThreshold = sharp::AttrAsDouble(options, "trimThreshold");
1617
1637
  baton->trimLineArt = sharp::AttrAsBool(options, "trimLineArt");
1638
+ baton->trimMargin = sharp::AttrAsUint32(options, "trimMargin");
1618
1639
  baton->gamma = sharp::AttrAsDouble(options, "gamma");
1619
1640
  baton->gammaOut = sharp::AttrAsDouble(options, "gammaOut");
1620
1641
  baton->linearA = sharp::AttrAsVectorOfDouble(options, "linearA");
@@ -1692,6 +1713,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1692
1713
  // Output
1693
1714
  baton->formatOut = sharp::AttrAsStr(options, "formatOut");
1694
1715
  baton->fileOut = sharp::AttrAsStr(options, "fileOut");
1716
+ baton->typedArrayOut = sharp::AttrAsBool(options, "typedArrayOut");
1695
1717
  baton->keepMetadata = sharp::AttrAsUint32(options, "keepMetadata");
1696
1718
  baton->withMetadataOrientation = sharp::AttrAsUint32(options, "withMetadataOrientation");
1697
1719
  baton->withMetadataDensity = sharp::AttrAsDouble(options, "withMetadataDensity");
@@ -1706,6 +1728,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1706
1728
  }
1707
1729
  baton->withExifMerge = sharp::AttrAsBool(options, "withExifMerge");
1708
1730
  baton->withXmp = sharp::AttrAsStr(options, "withXmp");
1731
+ baton->withGainMap = sharp::AttrAsBool(options, "withGainMap");
1709
1732
  baton->timeoutSeconds = sharp::AttrAsUint32(options, "timeoutSeconds");
1710
1733
  baton->loop = sharp::AttrAsUint32(options, "loop");
1711
1734
  baton->delay = sharp::AttrAsInt32Vector(options, "delay");
@@ -1741,6 +1764,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1741
1764
  baton->webpEffort = sharp::AttrAsUint32(options, "webpEffort");
1742
1765
  baton->webpMinSize = sharp::AttrAsBool(options, "webpMinSize");
1743
1766
  baton->webpMixed = sharp::AttrAsBool(options, "webpMixed");
1767
+ baton->webpExact = sharp::AttrAsBool(options, "webpExact");
1744
1768
  baton->gifBitdepth = sharp::AttrAsUint32(options, "gifBitdepth");
1745
1769
  baton->gifEffort = sharp::AttrAsUint32(options, "gifEffort");
1746
1770
  baton->gifDither = sharp::AttrAsDouble(options, "gifDither");
@@ -1775,6 +1799,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1775
1799
  baton->heifEffort = sharp::AttrAsUint32(options, "heifEffort");
1776
1800
  baton->heifChromaSubsampling = sharp::AttrAsStr(options, "heifChromaSubsampling");
1777
1801
  baton->heifBitdepth = sharp::AttrAsUint32(options, "heifBitdepth");
1802
+ baton->heifTune = sharp::AttrAsStr(options, "heifTune");
1778
1803
  baton->jxlDistance = sharp::AttrAsDouble(options, "jxlDistance");
1779
1804
  baton->jxlDecodingTier = sharp::AttrAsUint32(options, "jxlDecodingTier");
1780
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(8),
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 (vips::VError const &err) {
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 (vips::VError const &err) {
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", f);
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(f, container);
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 (vips::VError const &err) {
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
- }