sharp 0.23.0 → 0.23.4

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/operations.cc CHANGED
@@ -191,12 +191,20 @@ namespace sharp {
191
191
  VImage alpha = image[image.bands() - 1];
192
192
  return RemoveAlpha(image)
193
193
  .colourspace(VIPS_INTERPRETATION_LCH)
194
- .linear({brightness, saturation, 1}, {0, 0, static_cast<double>(hue)})
194
+ .linear(
195
+ { brightness, saturation, 1},
196
+ { 0.0, 0.0, static_cast<double>(hue) }
197
+ )
198
+ .colourspace(VIPS_INTERPRETATION_sRGB)
195
199
  .bandjoin(alpha);
196
200
  } else {
197
201
  return image
198
202
  .colourspace(VIPS_INTERPRETATION_LCH)
199
- .linear({brightness, saturation, 1}, {0, 0, static_cast<double>(hue)});
203
+ .linear(
204
+ { brightness, saturation, 1 },
205
+ { 0.0, 0.0, static_cast<double>(hue) }
206
+ )
207
+ .colourspace(VIPS_INTERPRETATION_sRGB);
200
208
  }
201
209
  }
202
210
 
@@ -250,17 +258,30 @@ namespace sharp {
250
258
  Trim an image
251
259
  */
252
260
  VImage Trim(VImage image, double const threshold) {
261
+ if (image.width() < 3 && image.height() < 3) {
262
+ throw VError("Image to trim must be at least 3x3 pixels");
263
+ }
253
264
  // Top-left pixel provides the background colour
254
265
  VImage background = image.extract_area(0, 0, 1, 1);
255
266
  if (HasAlpha(background)) {
256
267
  background = background.flatten();
257
268
  }
258
- int top, width, height;
259
- int const left = image.find_trim(&top, &width, &height, VImage::option()
269
+ int left, top, width, height;
270
+ left = image.find_trim(&top, &width, &height, VImage::option()
260
271
  ->set("background", background(0, 0))
261
272
  ->set("threshold", threshold));
262
273
  if (width == 0 || height == 0) {
263
- throw VError("Unexpected error while trimming. Try to lower the tolerance");
274
+ if (HasAlpha(image)) {
275
+ // Search alpha channel
276
+ VImage alpha = image[image.bands() - 1];
277
+ VImage backgroundAlpha = alpha.extract_area(0, 0, 1, 1);
278
+ left = alpha.find_trim(&top, &width, &height, VImage::option()
279
+ ->set("background", backgroundAlpha(0, 0))
280
+ ->set("threshold", threshold));
281
+ }
282
+ if (width == 0 || height == 0) {
283
+ throw VError("Unexpected error while trimming. Try to lower the tolerance");
284
+ }
264
285
  }
265
286
  return image.extract_area(left, top, width, height);
266
287
  }
package/src/pipeline.cc CHANGED
@@ -38,6 +38,9 @@
38
38
  #elif defined(__APPLE__)
39
39
  #define STAT64_STRUCT stat
40
40
  #define STAT64_FUNCTION stat
41
+ #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
42
+ #define STAT64_STRUCT stat
43
+ #define STAT64_FUNCTION stat
41
44
  #else
42
45
  #define STAT64_STRUCT stat64
43
46
  #define STAT64_FUNCTION stat64
@@ -101,7 +104,7 @@ class PipelineWorker : public Nan::AsyncWorker {
101
104
  if (baton->rotateBeforePreExtract) {
102
105
  if (rotation != VIPS_ANGLE_D0) {
103
106
  image = image.rot(rotation);
104
- sharp::RemoveExifOrientation(image);
107
+ image = sharp::RemoveExifOrientation(image);
105
108
  }
106
109
  if (baton->rotationAngle != 0.0) {
107
110
  std::vector<double> background;
@@ -401,20 +404,20 @@ class PipelineWorker : public Nan::AsyncWorker {
401
404
  // Rotate post-extract 90-angle
402
405
  if (!baton->rotateBeforePreExtract && rotation != VIPS_ANGLE_D0) {
403
406
  image = image.rot(rotation);
404
- sharp::RemoveExifOrientation(image);
407
+ image = sharp::RemoveExifOrientation(image);
405
408
  }
406
409
 
407
410
 
408
411
  // Flip (mirror about Y axis)
409
412
  if (baton->flip) {
410
413
  image = image.flip(VIPS_DIRECTION_VERTICAL);
411
- sharp::RemoveExifOrientation(image);
414
+ image = sharp::RemoveExifOrientation(image);
412
415
  }
413
416
 
414
417
  // Flop (mirror about X axis)
415
418
  if (baton->flop) {
416
419
  image = image.flip(VIPS_DIRECTION_HORIZONTAL);
417
- sharp::RemoveExifOrientation(image);
420
+ image = sharp::RemoveExifOrientation(image);
418
421
  }
419
422
 
420
423
  // Join additional color channels to the image
@@ -591,7 +594,7 @@ class PipelineWorker : public Nan::AsyncWorker {
591
594
  if (!HasAlpha(compositeImage)) {
592
595
  compositeImage = sharp::EnsureAlpha(compositeImage);
593
596
  }
594
- compositeImage = compositeImage.premultiply();
597
+ if (!composite->premultiplied) compositeImage = compositeImage.premultiply();
595
598
  // Calculate position
596
599
  int left;
597
600
  int top;
@@ -697,7 +700,7 @@ class PipelineWorker : public Nan::AsyncWorker {
697
700
 
698
701
  // Override EXIF Orientation tag
699
702
  if (baton->withMetadata && baton->withMetadataOrientation != -1) {
700
- sharp::SetExifOrientation(image, baton->withMetadataOrientation);
703
+ image = sharp::SetExifOrientation(image, baton->withMetadataOrientation);
701
704
  }
702
705
 
703
706
  // Number of channels used in output image
@@ -959,6 +962,11 @@ class PipelineWorker : public Nan::AsyncWorker {
959
962
  };
960
963
  suffix = AssembleSuffixString(extname, options);
961
964
  }
965
+
966
+ // Remove alpha channel from tile background if image does not contain an alpha channel
967
+ if (!HasAlpha(image)) {
968
+ baton->tileBackground.pop_back();
969
+ }
962
970
  // Write DZ to file
963
971
  vips::VOption *options = VImage::option()
964
972
  ->set("strip", !baton->withMetadata)
@@ -968,6 +976,7 @@ class PipelineWorker : public Nan::AsyncWorker {
968
976
  ->set("layout", baton->tileLayout)
969
977
  ->set("suffix", const_cast<char*>(suffix.data()))
970
978
  ->set("angle", CalculateAngleRotation(baton->tileAngle))
979
+ ->set("background", baton->tileBackground)
971
980
  ->set("skip_blanks", baton->tileSkipBlanks);
972
981
 
973
982
  // libvips chooses a default depth based on layout. Instead of replicating that logic here by
@@ -1230,6 +1239,7 @@ NAN_METHOD(pipeline) {
1230
1239
  composite->left = AttrTo<int32_t>(compositeObject, "left");
1231
1240
  composite->top = AttrTo<int32_t>(compositeObject, "top");
1232
1241
  composite->tile = AttrTo<bool>(compositeObject, "tile");
1242
+ composite->premultiplied = AttrTo<bool>(compositeObject, "premultiplied");
1233
1243
  baton->composite.push_back(composite);
1234
1244
  }
1235
1245
  // Resize options
@@ -1373,6 +1383,7 @@ NAN_METHOD(pipeline) {
1373
1383
  baton->tileOverlap = AttrTo<uint32_t>(options, "tileOverlap");
1374
1384
  std::string tileContainer = AttrAsStr(options, "tileContainer");
1375
1385
  baton->tileAngle = AttrTo<int32_t>(options, "tileAngle");
1386
+ baton->tileBackground = AttrAsRgba(options, "tileBackground");
1376
1387
  baton->tileSkipBlanks = AttrTo<int32_t>(options, "tileSkipBlanks");
1377
1388
  if (tileContainer == "zip") {
1378
1389
  baton->tileContainer = VIPS_FOREIGN_DZ_CONTAINER_ZIP;
package/src/pipeline.h CHANGED
@@ -41,6 +41,7 @@ struct Composite {
41
41
  int left;
42
42
  int top;
43
43
  bool tile;
44
+ bool premultiplied;
44
45
 
45
46
  Composite():
46
47
  input(nullptr),
@@ -48,7 +49,8 @@ struct Composite {
48
49
  gravity(0),
49
50
  left(-1),
50
51
  top(-1),
51
- tile(false) {}
52
+ tile(false),
53
+ premultiplied(false) {}
52
54
  };
53
55
 
54
56
  struct PipelineBaton {
@@ -173,6 +175,7 @@ struct PipelineBaton {
173
175
  VipsForeignDzLayout tileLayout;
174
176
  std::string tileFormat;
175
177
  int tileAngle;
178
+ std::vector<double> tileBackground;
176
179
  int tileSkipBlanks;
177
180
  VipsForeignDzDepth tileDepth;
178
181
  std::unique_ptr<double[]> recombMatrix;
@@ -278,6 +281,7 @@ struct PipelineBaton {
278
281
  tileContainer(VIPS_FOREIGN_DZ_CONTAINER_FS),
279
282
  tileLayout(VIPS_FOREIGN_DZ_LAYOUT_DZ),
280
283
  tileAngle(0),
284
+ tileBackground{ 255.0, 255.0, 255.0, 255.0 },
281
285
  tileSkipBlanks(-1),
282
286
  tileDepth(VIPS_FOREIGN_DZ_DEPTH_LAST) {}
283
287
  };
package/src/utilities.cc CHANGED
@@ -150,8 +150,9 @@ NAN_METHOD(format) {
150
150
 
151
151
  // Which load/save operations are available for each compressed format?
152
152
  Local<Object> format = New<Object>();
153
- for (std::string f : {
154
- "jpeg", "png", "webp", "tiff", "magick", "openslide", "dz", "ppm", "fits", "gif", "svg", "heif", "pdf", "v"
153
+ for (std::string const f : {
154
+ "jpeg", "png", "webp", "tiff", "magick", "openslide", "dz",
155
+ "ppm", "fits", "gif", "svg", "heif", "pdf", "vips"
155
156
  }) {
156
157
  // Input
157
158
  Local<Boolean> hasInputFile =