sharp 0.25.4 → 0.26.0

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/common.cc CHANGED
@@ -17,6 +17,7 @@
17
17
  #include <string.h>
18
18
  #include <vector>
19
19
  #include <queue>
20
+ #include <map>
20
21
  #include <mutex> // NOLINT(build/c++11)
21
22
 
22
23
  #include <napi.h>
@@ -41,6 +42,9 @@ namespace sharp {
41
42
  int32_t AttrAsInt32(Napi::Object obj, std::string attr) {
42
43
  return obj.Get(attr).As<Napi::Number>().Int32Value();
43
44
  }
45
+ int32_t AttrAsInt32(Napi::Object obj, unsigned int const attr) {
46
+ return obj.Get(attr).As<Napi::Number>().Int32Value();
47
+ }
44
48
  double AttrAsDouble(Napi::Object obj, std::string attr) {
45
49
  return obj.Get(attr).As<Napi::Number>().DoubleValue();
46
50
  }
@@ -58,6 +62,14 @@ namespace sharp {
58
62
  }
59
63
  return rgba;
60
64
  }
65
+ std::vector<int32_t> AttrAsInt32Vector(Napi::Object obj, std::string attr) {
66
+ Napi::Array array = obj.Get(attr).As<Napi::Array>();
67
+ std::vector<int32_t> vector(array.Length());
68
+ for (unsigned int i = 0; i < array.Length(); i++) {
69
+ vector[i] = AttrAsInt32(array, i);
70
+ }
71
+ return vector;
72
+ }
61
73
 
62
74
  // Create an InputDescriptor instance from a Napi::Object describing an input image
63
75
  InputDescriptor* CreateInputDescriptor(Napi::Object input) {
@@ -125,6 +137,9 @@ namespace sharp {
125
137
  bool IsWebp(std::string const &str) {
126
138
  return EndsWith(str, ".webp") || EndsWith(str, ".WEBP");
127
139
  }
140
+ bool IsGif(std::string const &str) {
141
+ return EndsWith(str, ".gif") || EndsWith(str, ".GIF");
142
+ }
128
143
  bool IsTiff(std::string const &str) {
129
144
  return EndsWith(str, ".tif") || EndsWith(str, ".tiff") || EndsWith(str, ".TIF") || EndsWith(str, ".TIFF");
130
145
  }
@@ -173,32 +188,42 @@ namespace sharp {
173
188
  return id;
174
189
  }
175
190
 
191
+ std::map<std::string, ImageType> loaderToType = {
192
+ { "jpegload", ImageType::JPEG },
193
+ { "jpegload_buffer", ImageType::JPEG },
194
+ { "pngload", ImageType::PNG },
195
+ { "pngload_buffer", ImageType::PNG },
196
+ { "webpload", ImageType::WEBP },
197
+ { "webpload_buffer", ImageType::WEBP },
198
+ { "tiffload", ImageType::TIFF },
199
+ { "tiffload_buffer", ImageType::TIFF },
200
+ { "gifload", ImageType::GIF },
201
+ { "gifload_buffer", ImageType::GIF },
202
+ { "svgload", ImageType::SVG },
203
+ { "svgload_buffer", ImageType::SVG },
204
+ { "heifload", ImageType::HEIF },
205
+ { "heifload_buffer", ImageType::HEIF },
206
+ { "pdfload", ImageType::PDF },
207
+ { "pdfload_buffer", ImageType::PDF },
208
+ { "magickload", ImageType::MAGICK },
209
+ { "magickload_buffer", ImageType::MAGICK },
210
+ { "openslideload", ImageType::OPENSLIDE },
211
+ { "ppmload", ImageType::PPM },
212
+ { "fitsload", ImageType::FITS },
213
+ { "vipsload", ImageType::VIPS },
214
+ { "rawload", ImageType::RAW }
215
+ };
216
+
176
217
  /*
177
218
  Determine image format of a buffer.
178
219
  */
179
220
  ImageType DetermineImageType(void *buffer, size_t const length) {
180
221
  ImageType imageType = ImageType::UNKNOWN;
181
222
  char const *load = vips_foreign_find_load_buffer(buffer, length);
182
- if (load != NULL) {
183
- std::string const loader = load;
184
- if (EndsWith(loader, "JpegBuffer")) {
185
- imageType = ImageType::JPEG;
186
- } else if (EndsWith(loader, "PngBuffer")) {
187
- imageType = ImageType::PNG;
188
- } else if (EndsWith(loader, "WebpBuffer")) {
189
- imageType = ImageType::WEBP;
190
- } else if (EndsWith(loader, "TiffBuffer")) {
191
- imageType = ImageType::TIFF;
192
- } else if (EndsWith(loader, "GifBuffer")) {
193
- imageType = ImageType::GIF;
194
- } else if (EndsWith(loader, "SvgBuffer")) {
195
- imageType = ImageType::SVG;
196
- } else if (EndsWith(loader, "HeifBuffer")) {
197
- imageType = ImageType::HEIF;
198
- } else if (EndsWith(loader, "PdfBuffer")) {
199
- imageType = ImageType::PDF;
200
- } else if (EndsWith(loader, "MagickBuffer")) {
201
- imageType = ImageType::MAGICK;
223
+ if (load != nullptr) {
224
+ auto it = loaderToType.find(vips_nickname_find(g_type_from_name(load)));
225
+ if (it != loaderToType.end()) {
226
+ imageType = it->second;
202
227
  }
203
228
  }
204
229
  return imageType;
@@ -211,36 +236,12 @@ namespace sharp {
211
236
  ImageType imageType = ImageType::UNKNOWN;
212
237
  char const *load = vips_foreign_find_load(file);
213
238
  if (load != nullptr) {
214
- std::string const loader = load;
215
- if (EndsWith(loader, "JpegFile")) {
216
- imageType = ImageType::JPEG;
217
- } else if (EndsWith(loader, "PngFile")) {
218
- imageType = ImageType::PNG;
219
- } else if (EndsWith(loader, "WebpFile")) {
220
- imageType = ImageType::WEBP;
221
- } else if (EndsWith(loader, "Openslide")) {
222
- imageType = ImageType::OPENSLIDE;
223
- } else if (EndsWith(loader, "TiffFile")) {
224
- imageType = ImageType::TIFF;
225
- } else if (EndsWith(loader, "GifFile")) {
226
- imageType = ImageType::GIF;
227
- } else if (EndsWith(loader, "SvgFile")) {
228
- imageType = ImageType::SVG;
229
- } else if (EndsWith(loader, "HeifFile")) {
230
- imageType = ImageType::HEIF;
231
- } else if (EndsWith(loader, "PdfFile")) {
232
- imageType = ImageType::PDF;
233
- } else if (EndsWith(loader, "Ppm")) {
234
- imageType = ImageType::PPM;
235
- } else if (EndsWith(loader, "Fits")) {
236
- imageType = ImageType::FITS;
237
- } else if (EndsWith(loader, "Vips")) {
238
- imageType = ImageType::VIPS;
239
- } else if (EndsWith(loader, "Magick") || EndsWith(loader, "MagickFile")) {
240
- imageType = ImageType::MAGICK;
239
+ auto it = loaderToType.find(vips_nickname_find(g_type_from_name(load)));
240
+ if (it != loaderToType.end()) {
241
+ imageType = it->second;
241
242
  }
242
243
  } else {
243
- if (EndsWith(vips::VError().what(), " not found\n")) {
244
+ if (EndsWith(vips::VError().what(), " does not exist\n")) {
244
245
  imageType = ImageType::MISSING;
245
246
  }
246
247
  }
@@ -252,6 +253,8 @@ namespace sharp {
252
253
  */
253
254
  bool ImageTypeSupportsPage(ImageType imageType) {
254
255
  return
256
+ imageType == ImageType::WEBP ||
257
+ imageType == ImageType::MAGICK ||
255
258
  imageType == ImageType::GIF ||
256
259
  imageType == ImageType::TIFF ||
257
260
  imageType == ImageType::HEIF ||
@@ -420,6 +423,38 @@ namespace sharp {
420
423
  return copy;
421
424
  }
422
425
 
426
+ /*
427
+ Set animation properties if necessary.
428
+ Non-provided properties will be loaded from image.
429
+ */
430
+ VImage SetAnimationProperties(VImage image, int pageHeight, std::vector<int> delay, int loop) {
431
+ bool hasDelay = delay.size() != 1 || delay.front() != -1;
432
+
433
+ if (pageHeight == 0 && image.get_typeof(VIPS_META_PAGE_HEIGHT) == G_TYPE_INT) {
434
+ pageHeight = image.get_int(VIPS_META_PAGE_HEIGHT);
435
+ }
436
+
437
+ if (!hasDelay && image.get_typeof("delay") == VIPS_TYPE_ARRAY_INT) {
438
+ delay = image.get_array_int("delay");
439
+ hasDelay = true;
440
+ }
441
+
442
+ if (loop == -1 && image.get_typeof("loop") == G_TYPE_INT) {
443
+ loop = image.get_int("loop");
444
+ }
445
+
446
+ if (pageHeight == 0) return image;
447
+
448
+ // It is necessary to create the copy as otherwise, pageHeight will be ignored!
449
+ VImage copy = image.copy();
450
+
451
+ copy.set(VIPS_META_PAGE_HEIGHT, pageHeight);
452
+ if (hasDelay) copy.set("delay", delay);
453
+ if (loop != -1) copy.set("loop", loop);
454
+
455
+ return copy;
456
+ }
457
+
423
458
  /*
424
459
  Does this image have a non-default density?
425
460
  */
@@ -450,14 +485,21 @@ namespace sharp {
450
485
  Check the proposed format supports the current dimensions.
451
486
  */
452
487
  void AssertImageTypeDimensions(VImage image, ImageType const imageType) {
488
+ const int height = image.get_typeof("pageHeight") == G_TYPE_INT
489
+ ? image.get_int("pageHeight")
490
+ : image.height();
453
491
  if (imageType == ImageType::JPEG) {
454
- if (image.width() > 65535 || image.height() > 65535) {
492
+ if (image.width() > 65535 || height > 65535) {
455
493
  throw vips::VError("Processed image is too large for the JPEG format");
456
494
  }
457
495
  } else if (imageType == ImageType::WEBP) {
458
- if (image.width() > 16383 || image.height() > 16383) {
496
+ if (image.width() > 16383 || height > 16383) {
459
497
  throw vips::VError("Processed image is too large for the WebP format");
460
498
  }
499
+ } else if (imageType == ImageType::GIF) {
500
+ if (image.width() > 65535 || height > 65535) {
501
+ throw vips::VError("Processed image is too large for the GIF format");
502
+ }
461
503
  }
462
504
  }
463
505
 
@@ -720,4 +762,25 @@ namespace sharp {
720
762
  return std::make_tuple(image, alphaColour);
721
763
  }
722
764
 
765
+ /*
766
+ Removes alpha channel, if any.
767
+ */
768
+ VImage RemoveAlpha(VImage image) {
769
+ if (HasAlpha(image)) {
770
+ image = image.extract_band(0, VImage::option()->set("n", image.bands() - 1));
771
+ }
772
+ return image;
773
+ }
774
+
775
+ /*
776
+ Ensures alpha channel, if missing.
777
+ */
778
+ VImage EnsureAlpha(VImage image) {
779
+ if (!HasAlpha(image)) {
780
+ std::vector<double> alpha;
781
+ alpha.push_back(sharp::MaximumImageAlpha(image.interpretation()));
782
+ image = image.bandjoin_const(alpha);
783
+ }
784
+ return image;
785
+ }
723
786
  } // namespace sharp
package/src/common.h CHANGED
@@ -24,8 +24,8 @@
24
24
 
25
25
  // Verify platform and compiler compatibility
26
26
 
27
- #if (VIPS_MAJOR_VERSION < 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 9))
28
- #error "libvips version 8.9.1+ is required - please see https://sharp.pixelplumbing.com/install"
27
+ #if (VIPS_MAJOR_VERSION < 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 10))
28
+ #error "libvips version 8.10.0+ is required - please see https://sharp.pixelplumbing.com/install"
29
29
  #endif
30
30
 
31
31
  #if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))
@@ -88,10 +88,12 @@ namespace sharp {
88
88
  std::string AttrAsStr(Napi::Object obj, std::string attr);
89
89
  uint32_t AttrAsUint32(Napi::Object obj, std::string attr);
90
90
  int32_t AttrAsInt32(Napi::Object obj, std::string attr);
91
+ int32_t AttrAsInt32(Napi::Object obj, unsigned int const attr);
91
92
  double AttrAsDouble(Napi::Object obj, std::string attr);
92
93
  double AttrAsDouble(Napi::Object obj, unsigned int const attr);
93
94
  bool AttrAsBool(Napi::Object obj, std::string attr);
94
95
  std::vector<double> AttrAsRgba(Napi::Object obj, std::string attr);
96
+ std::vector<int32_t> AttrAsInt32Vector(Napi::Object obj, std::string attr);
95
97
 
96
98
  // Create an InputDescriptor instance from a Napi::Object describing an input image
97
99
  InputDescriptor* CreateInputDescriptor(Napi::Object input);
@@ -125,6 +127,7 @@ namespace sharp {
125
127
  bool IsJpeg(std::string const &str);
126
128
  bool IsPng(std::string const &str);
127
129
  bool IsWebp(std::string const &str);
130
+ bool IsGif(std::string const &str);
128
131
  bool IsTiff(std::string const &str);
129
132
  bool IsHeic(std::string const &str);
130
133
  bool IsHeif(std::string const &str);
@@ -184,6 +187,12 @@ namespace sharp {
184
187
  */
185
188
  VImage RemoveExifOrientation(VImage image);
186
189
 
190
+ /*
191
+ Set animation properties if necessary.
192
+ Non-provided properties will be loaded from image.
193
+ */
194
+ VImage SetAnimationProperties(VImage image, int pageHeight, std::vector<int> delay, int loop);
195
+
187
196
  /*
188
197
  Does this image have a non-default density?
189
198
  */
@@ -271,6 +280,16 @@ namespace sharp {
271
280
  */
272
281
  std::tuple<VImage, std::vector<double>> ApplyAlpha(VImage image, std::vector<double> colour);
273
282
 
283
+ /*
284
+ Removes alpha channel, if any.
285
+ */
286
+ VImage RemoveAlpha(VImage image);
287
+
288
+ /*
289
+ Ensures alpha channel, if missing.
290
+ */
291
+ VImage EnsureAlpha(VImage image);
292
+
274
293
  } // namespace sharp
275
294
 
276
295
  #endif // SRC_COMMON_H_