sharp 0.31.3 → 0.32.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/pipeline.cc CHANGED
@@ -1,16 +1,5 @@
1
- // Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Lovell Fuller and contributors.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- //
7
- // http://www.apache.org/licenses/LICENSE-2.0
8
- //
9
- // Unless required by applicable law or agreed to in writing, software
10
- // distributed under the License is distributed on an "AS IS" BASIS,
11
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- // See the License for the specific language governing permissions and
13
- // limitations under the License.
1
+ // Copyright 2013 Lovell Fuller and others.
2
+ // SPDX-License-Identifier: Apache-2.0
14
3
 
15
4
  #include <algorithm>
16
5
  #include <cmath>
@@ -85,6 +74,7 @@ class PipelineWorker : public Napi::AsyncWorker {
85
74
  VipsAngle autoRotation = VIPS_ANGLE_D0;
86
75
  bool autoFlip = FALSE;
87
76
  bool autoFlop = FALSE;
77
+
88
78
  if (baton->useExifOrientation) {
89
79
  // Rotate and flip image according to Exif orientation
90
80
  std::tie(autoRotation, autoFlip, autoFlop) = CalculateExifRotationAndFlip(sharp::ExifOrientation(image));
@@ -205,7 +195,7 @@ class PipelineWorker : public Napi::AsyncWorker {
205
195
  if (jpegShrinkOnLoad > 1 && static_cast<int>(shrink) == jpegShrinkOnLoad) {
206
196
  jpegShrinkOnLoad /= 2;
207
197
  }
208
- } else if (inputImageType == sharp::ImageType::WEBP && shrink > 1.0) {
198
+ } else if (inputImageType == sharp::ImageType::WEBP && baton->fastShrinkOnLoad && shrink > 1.0) {
209
199
  // Avoid upscaling via webp
210
200
  scale = 1.0 / shrink;
211
201
  } else if (inputImageType == sharp::ImageType::SVG ||
@@ -320,7 +310,8 @@ class PipelineWorker : public Napi::AsyncWorker {
320
310
  if (
321
311
  sharp::HasProfile(image) &&
322
312
  image.interpretation() != VIPS_INTERPRETATION_LABS &&
323
- image.interpretation() != VIPS_INTERPRETATION_GREY16
313
+ image.interpretation() != VIPS_INTERPRETATION_GREY16 &&
314
+ !baton->input->ignoreIcc
324
315
  ) {
325
316
  // Convert to sRGB/P3 using embedded profile
326
317
  try {
@@ -329,7 +320,7 @@ class PipelineWorker : public Napi::AsyncWorker {
329
320
  ->set("depth", image.interpretation() == VIPS_INTERPRETATION_RGB16 ? 16 : 8)
330
321
  ->set("intent", VIPS_INTENT_PERCEPTUAL));
331
322
  } catch(...) {
332
- // Ignore failure of embedded profile
323
+ sharp::VipsWarningCallback(nullptr, G_LOG_LEVEL_WARNING, "Invalid embedded profile", nullptr);
333
324
  }
334
325
  } else if (image.interpretation() == VIPS_INTERPRETATION_CMYK) {
335
326
  image = image.icc_transform(processingProfile, VImage::option()
@@ -367,11 +358,12 @@ class PipelineWorker : public Napi::AsyncWorker {
367
358
  image = sharp::EnsureAlpha(image, 1);
368
359
  }
369
360
 
361
+ VipsBandFormat premultiplyFormat = image.format();
370
362
  bool const shouldPremultiplyAlpha = sharp::HasAlpha(image) &&
371
363
  (shouldResize || shouldBlur || shouldConv || shouldSharpen);
372
364
 
373
365
  if (shouldPremultiplyAlpha) {
374
- image = image.premultiply();
366
+ image = image.premultiply().cast(premultiplyFormat);
375
367
  }
376
368
 
377
369
  // Resize
@@ -399,7 +391,7 @@ class PipelineWorker : public Napi::AsyncWorker {
399
391
  }
400
392
 
401
393
  // Join additional color channels to the image
402
- if (baton->joinChannelIn.size() > 0) {
394
+ if (!baton->joinChannelIn.empty()) {
403
395
  VImage joinImage;
404
396
  sharp::ImageType joinImageType = sharp::ImageType::UNKNOWN;
405
397
 
@@ -409,6 +401,7 @@ class PipelineWorker : public Napi::AsyncWorker {
409
401
  image = image.bandjoin(joinImage);
410
402
  }
411
403
  image = image.copy(VImage::option()->set("interpretation", baton->colourspace));
404
+ image = sharp::RemoveGifPalette(image);
412
405
  }
413
406
 
414
407
  inputWidth = image.width();
@@ -438,7 +431,7 @@ class PipelineWorker : public Napi::AsyncWorker {
438
431
 
439
432
  image = nPages > 1
440
433
  ? sharp::EmbedMultiPage(image,
441
- left, top, width, height, background, nPages, &targetPageHeight)
434
+ left, top, width, height, VIPS_EXTEND_BACKGROUND, background, nPages, &targetPageHeight)
442
435
  : image.embed(left, top, width, height, VImage::option()
443
436
  ->set("extend", VIPS_EXTEND_BACKGROUND)
444
437
  ->set("background", background));
@@ -455,6 +448,7 @@ class PipelineWorker : public Napi::AsyncWorker {
455
448
  // Gravity-based crop
456
449
  int left;
457
450
  int top;
451
+
458
452
  std::tie(left, top) = sharp::CalculateCrop(
459
453
  inputWidth, inputHeight, baton->width, baton->height, baton->position);
460
454
  int width = std::min(inputWidth, baton->width);
@@ -465,16 +459,25 @@ class PipelineWorker : public Napi::AsyncWorker {
465
459
  left, top, width, height, nPages, &targetPageHeight)
466
460
  : image.extract_area(left, top, width, height);
467
461
  } else {
462
+ int attention_x;
463
+ int attention_y;
464
+
468
465
  // Attention-based or Entropy-based crop
469
466
  MultiPageUnsupported(nPages, "Resize strategy");
470
467
  image = image.tilecache(VImage::option()
471
468
  ->set("access", VIPS_ACCESS_RANDOM)
472
469
  ->set("threaded", TRUE));
470
+
473
471
  image = image.smartcrop(baton->width, baton->height, VImage::option()
474
- ->set("interesting", baton->position == 16 ? VIPS_INTERESTING_ENTROPY : VIPS_INTERESTING_ATTENTION));
472
+ ->set("interesting", baton->position == 16 ? VIPS_INTERESTING_ENTROPY : VIPS_INTERESTING_ATTENTION)
473
+ ->set("attention_x", &attention_x)
474
+ ->set("attention_y", &attention_y));
475
475
  baton->hasCropOffset = true;
476
476
  baton->cropOffsetLeft = static_cast<int>(image.xoffset());
477
477
  baton->cropOffsetTop = static_cast<int>(image.yoffset());
478
+ baton->hasAttentionCenter = true;
479
+ baton->attentionX = static_cast<int>(attention_x * jpegShrinkOnLoad / scale);
480
+ baton->attentionY = static_cast<int>(attention_y * jpegShrinkOnLoad / scale);
478
481
  }
479
482
  }
480
483
  }
@@ -503,7 +506,7 @@ class PipelineWorker : public Napi::AsyncWorker {
503
506
  }
504
507
 
505
508
  // Affine transform
506
- if (baton->affineMatrix.size() > 0) {
509
+ if (!baton->affineMatrix.empty()) {
507
510
  MultiPageUnsupported(nPages, "Affine");
508
511
  std::vector<double> background;
509
512
  std::tie(image, background) = sharp::ApplyAlpha(image, baton->affineBackground, shouldPremultiplyAlpha);
@@ -519,18 +522,29 @@ class PipelineWorker : public Napi::AsyncWorker {
519
522
 
520
523
  // Extend edges
521
524
  if (baton->extendTop > 0 || baton->extendBottom > 0 || baton->extendLeft > 0 || baton->extendRight > 0) {
522
- std::vector<double> background;
523
- std::tie(image, background) = sharp::ApplyAlpha(image, baton->extendBackground, shouldPremultiplyAlpha);
524
-
525
525
  // Embed
526
526
  baton->width = image.width() + baton->extendLeft + baton->extendRight;
527
527
  baton->height = (nPages > 1 ? targetPageHeight : image.height()) + baton->extendTop + baton->extendBottom;
528
528
 
529
- image = nPages > 1
530
- ? sharp::EmbedMultiPage(image,
531
- baton->extendLeft, baton->extendTop, baton->width, baton->height, background, nPages, &targetPageHeight)
532
- : image.embed(baton->extendLeft, baton->extendTop, baton->width, baton->height,
533
- VImage::option()->set("extend", VIPS_EXTEND_BACKGROUND)->set("background", background));
529
+ if (baton->extendWith == VIPS_EXTEND_BACKGROUND) {
530
+ std::vector<double> background;
531
+ std::tie(image, background) = sharp::ApplyAlpha(image, baton->extendBackground, shouldPremultiplyAlpha);
532
+
533
+ image = nPages > 1
534
+ ? sharp::EmbedMultiPage(image,
535
+ baton->extendLeft, baton->extendTop, baton->width, baton->height,
536
+ baton->extendWith, background, nPages, &targetPageHeight)
537
+ : image.embed(baton->extendLeft, baton->extendTop, baton->width, baton->height,
538
+ VImage::option()->set("extend", baton->extendWith)->set("background", background));
539
+ } else {
540
+ std::vector<double> ignoredBackground(1);
541
+ image = nPages > 1
542
+ ? sharp::EmbedMultiPage(image,
543
+ baton->extendLeft, baton->extendTop, baton->width, baton->height,
544
+ baton->extendWith, ignoredBackground, nPages, &targetPageHeight)
545
+ : image.embed(baton->extendLeft, baton->extendTop, baton->width, baton->height,
546
+ VImage::option()->set("extend", baton->extendWith));
547
+ }
534
548
  }
535
549
  // Median - must happen before blurring, due to the utility of blurring after thresholding
536
550
  if (baton->medianSize > 0) {
@@ -572,13 +586,7 @@ class PipelineWorker : public Napi::AsyncWorker {
572
586
 
573
587
  // Reverse premultiplication after all transformations
574
588
  if (shouldPremultiplyAlpha) {
575
- image = image.unpremultiply();
576
- // Cast pixel values to integer
577
- if (sharp::Is16Bit(image.interpretation())) {
578
- image = image.cast(VIPS_FORMAT_USHORT);
579
- } else {
580
- image = image.cast(VIPS_FORMAT_UCHAR);
581
- }
589
+ image = image.unpremultiply().cast(premultiplyFormat);
582
590
  }
583
591
  baton->premultiplied = shouldPremultiplyAlpha;
584
592
 
@@ -660,6 +668,7 @@ class PipelineWorker : public Napi::AsyncWorker {
660
668
  ys.push_back(top);
661
669
  }
662
670
  image = VImage::composite(images, modes, VImage::option()->set("x", xs)->set("y", ys));
671
+ image = sharp::RemoveGifPalette(image);
663
672
  }
664
673
 
665
674
  // Gamma decoding (brighten)
@@ -674,7 +683,7 @@ class PipelineWorker : public Napi::AsyncWorker {
674
683
 
675
684
  // Apply normalisation - stretch luminance to cover full dynamic range
676
685
  if (baton->normalise) {
677
- image = sharp::Normalise(image);
686
+ image = sharp::Normalise(image, baton->normaliseLower, baton->normaliseUpper);
678
687
  }
679
688
 
680
689
  // Apply contrast limiting adaptive histogram equalization (CLAHE)
@@ -689,6 +698,7 @@ class PipelineWorker : public Napi::AsyncWorker {
689
698
  std::tie(booleanImage, booleanImageType) = sharp::OpenInput(baton->boolean);
690
699
  booleanImage = sharp::EnsureColourspace(booleanImage, baton->colourspaceInput);
691
700
  image = sharp::Boolean(image, booleanImage, baton->booleanOp);
701
+ image = sharp::RemoveGifPalette(image);
692
702
  }
693
703
 
694
704
  // Apply per-channel Bandbool bitwise operations after all other operations
@@ -870,7 +880,8 @@ class PipelineWorker : public Napi::AsyncWorker {
870
880
  ->set("strip", !baton->withMetadata)
871
881
  ->set("bitdepth", baton->gifBitdepth)
872
882
  ->set("effort", baton->gifEffort)
873
- ->set("reoptimise", baton->gifReoptimise)
883
+ ->set("reuse", baton->gifReuse)
884
+ ->set("interlace", baton->gifProgressive)
874
885
  ->set("interframe_maxerror", baton->gifInterFrameMaxError)
875
886
  ->set("interpalette_maxerror", baton->gifInterPaletteMaxError)
876
887
  ->set("dither", baton->gifDither)));
@@ -1068,7 +1079,8 @@ class PipelineWorker : public Napi::AsyncWorker {
1068
1079
  ->set("strip", !baton->withMetadata)
1069
1080
  ->set("bitdepth", baton->gifBitdepth)
1070
1081
  ->set("effort", baton->gifEffort)
1071
- ->set("reoptimise", baton->gifReoptimise)
1082
+ ->set("reuse", baton->gifReuse)
1083
+ ->set("interlace", baton->gifProgressive)
1072
1084
  ->set("dither", baton->gifDither));
1073
1085
  baton->formatOut = "gif";
1074
1086
  } else if (baton->formatOut == "tiff" || (mightMatchInput && isTiff) ||
@@ -1164,7 +1176,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1164
1176
  // Handle warnings
1165
1177
  std::string warning = sharp::VipsWarningPop();
1166
1178
  while (!warning.empty()) {
1167
- debuglog.Call({ Napi::String::New(env, warning) });
1179
+ debuglog.MakeCallback(Receiver().Value(), { Napi::String::New(env, warning) });
1168
1180
  warning = sharp::VipsWarningPop();
1169
1181
  }
1170
1182
 
@@ -1193,6 +1205,10 @@ class PipelineWorker : public Napi::AsyncWorker {
1193
1205
  info.Set("cropOffsetLeft", static_cast<int32_t>(baton->cropOffsetLeft));
1194
1206
  info.Set("cropOffsetTop", static_cast<int32_t>(baton->cropOffsetTop));
1195
1207
  }
1208
+ if (baton->hasAttentionCenter) {
1209
+ info.Set("attentionX", static_cast<int32_t>(baton->attentionX));
1210
+ info.Set("attentionY", static_cast<int32_t>(baton->attentionY));
1211
+ }
1196
1212
  if (baton->trimThreshold > 0.0) {
1197
1213
  info.Set("trimOffsetLeft", static_cast<int32_t>(baton->trimOffsetLeft));
1198
1214
  info.Set("trimOffsetTop", static_cast<int32_t>(baton->trimOffsetTop));
@@ -1218,7 +1234,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1218
1234
  Callback().MakeCallback(Receiver().Value(), { env.Null(), info });
1219
1235
  }
1220
1236
  } else {
1221
- Callback().MakeCallback(Receiver().Value(), { Napi::Error::New(env, baton->err).Value() });
1237
+ Callback().MakeCallback(Receiver().Value(), { Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
1222
1238
  }
1223
1239
 
1224
1240
  // Delete baton
@@ -1236,7 +1252,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1236
1252
  // Decrement processing task counter
1237
1253
  g_atomic_int_dec_and_test(&sharp::counterProcess);
1238
1254
  Napi::Number queueLength = Napi::Number::New(env, static_cast<double>(sharp::counterQueue));
1239
- queueListener.Call(Receiver().Value(), { queueLength });
1255
+ queueListener.MakeCallback(Receiver().Value(), { queueLength });
1240
1256
  }
1241
1257
 
1242
1258
  private:
@@ -1382,7 +1398,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1382
1398
  Napi::Value pipeline(const Napi::CallbackInfo& info) {
1383
1399
  // V8 objects are converted to non-V8 types held in the baton struct
1384
1400
  PipelineBaton *baton = new PipelineBaton;
1385
- Napi::Object options = info[0].As<Napi::Object>();
1401
+ Napi::Object options = info[size_t(0)].As<Napi::Object>();
1386
1402
 
1387
1403
  // Input
1388
1404
  baton->input = sharp::CreateInputDescriptor(options.Get("input").As<Napi::Object>());
@@ -1468,6 +1484,8 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1468
1484
  baton->linearB = sharp::AttrAsVectorOfDouble(options, "linearB");
1469
1485
  baton->greyscale = sharp::AttrAsBool(options, "greyscale");
1470
1486
  baton->normalise = sharp::AttrAsBool(options, "normalise");
1487
+ baton->normaliseLower = sharp::AttrAsUint32(options, "normaliseLower");
1488
+ baton->normaliseUpper = sharp::AttrAsUint32(options, "normaliseUpper");
1471
1489
  baton->tintA = sharp::AttrAsDouble(options, "tintA");
1472
1490
  baton->tintB = sharp::AttrAsDouble(options, "tintB");
1473
1491
  baton->claheWidth = sharp::AttrAsUint32(options, "claheWidth");
@@ -1485,6 +1503,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1485
1503
  baton->extendLeft = sharp::AttrAsInt32(options, "extendLeft");
1486
1504
  baton->extendRight = sharp::AttrAsInt32(options, "extendRight");
1487
1505
  baton->extendBackground = sharp::AttrAsVectorOfDouble(options, "extendBackground");
1506
+ baton->extendWith = sharp::AttrAsEnum<VipsExtend>(options, "extendWith", VIPS_TYPE_EXTEND);
1488
1507
  baton->extractChannel = sharp::AttrAsInt32(options, "extractChannel");
1489
1508
  baton->affineMatrix = sharp::AttrAsVectorOfDouble(options, "affineMatrix");
1490
1509
  baton->affineBackground = sharp::AttrAsVectorOfDouble(options, "affineBackground");
@@ -1582,7 +1601,8 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1582
1601
  baton->gifDither = sharp::AttrAsDouble(options, "gifDither");
1583
1602
  baton->gifInterFrameMaxError = sharp::AttrAsDouble(options, "gifInterFrameMaxError");
1584
1603
  baton->gifInterPaletteMaxError = sharp::AttrAsDouble(options, "gifInterPaletteMaxError");
1585
- baton->gifReoptimise = sharp::AttrAsBool(options, "gifReoptimise");
1604
+ baton->gifReuse = sharp::AttrAsBool(options, "gifReuse");
1605
+ baton->gifProgressive = sharp::AttrAsBool(options, "gifProgressive");
1586
1606
  baton->tiffQuality = sharp::AttrAsUint32(options, "tiffQuality");
1587
1607
  baton->tiffPyramid = sharp::AttrAsBool(options, "tiffPyramid");
1588
1608
  baton->tiffBitdepth = sharp::AttrAsUint32(options, "tiffBitdepth");
@@ -1638,9 +1658,12 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1638
1658
  baton->trimThreshold > 0.0 ||
1639
1659
  baton->normalise ||
1640
1660
  baton->position == 16 || baton->position == 17 ||
1641
- baton->angle % 360 != 0 ||
1642
- fmod(baton->rotationAngle, 360.0) != 0.0 ||
1643
- baton->useExifOrientation
1661
+ baton->angle != 0 ||
1662
+ baton->rotationAngle != 0.0 ||
1663
+ baton->tileAngle != 0 ||
1664
+ baton->useExifOrientation ||
1665
+ baton->claheWidth != 0 ||
1666
+ !baton->affineMatrix.empty()
1644
1667
  ) {
1645
1668
  baton->input->access = VIPS_ACCESS_RANDOM;
1646
1669
  }
@@ -1653,7 +1676,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1653
1676
  Napi::Function queueListener = options.Get("queueListener").As<Napi::Function>();
1654
1677
 
1655
1678
  // Join queue for worker thread
1656
- Napi::Function callback = info[1].As<Napi::Function>();
1679
+ Napi::Function callback = info[size_t(1)].As<Napi::Function>();
1657
1680
  PipelineWorker *worker = new PipelineWorker(callback, baton, debuglog, queueListener);
1658
1681
  worker->Receiver().Set("options", options);
1659
1682
  worker->Queue();
@@ -1661,7 +1684,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1661
1684
  // Increment queued task counter
1662
1685
  g_atomic_int_inc(&sharp::counterQueue);
1663
1686
  Napi::Number queueLength = Napi::Number::New(info.Env(), static_cast<double>(sharp::counterQueue));
1664
- queueListener.Call(info.This(), { queueLength });
1687
+ queueListener.MakeCallback(info.This(), { queueLength });
1665
1688
 
1666
1689
  return info.Env().Undefined();
1667
1690
  }
package/src/pipeline.h CHANGED
@@ -1,16 +1,5 @@
1
- // Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Lovell Fuller and contributors.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- //
7
- // http://www.apache.org/licenses/LICENSE-2.0
8
- //
9
- // Unless required by applicable law or agreed to in writing, software
10
- // distributed under the License is distributed on an "AS IS" BASIS,
11
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- // See the License for the specific language governing permissions and
13
- // limitations under the License.
1
+ // Copyright 2013 Lovell Fuller and others.
2
+ // SPDX-License-Identifier: Apache-2.0
14
3
 
15
4
  #ifndef SRC_PIPELINE_H_
16
5
  #define SRC_PIPELINE_H_
@@ -74,6 +63,9 @@ struct PipelineBaton {
74
63
  bool hasCropOffset;
75
64
  int cropOffsetLeft;
76
65
  int cropOffsetTop;
66
+ bool hasAttentionCenter;
67
+ int attentionX;
68
+ int attentionY;
77
69
  bool premultiplied;
78
70
  bool tileCentre;
79
71
  bool fastShrinkOnLoad;
@@ -107,6 +99,8 @@ struct PipelineBaton {
107
99
  double gammaOut;
108
100
  bool greyscale;
109
101
  bool normalise;
102
+ int normaliseLower;
103
+ int normaliseUpper;
110
104
  int claheWidth;
111
105
  int claheHeight;
112
106
  int claheMaxSlope;
@@ -122,6 +116,7 @@ struct PipelineBaton {
122
116
  int extendLeft;
123
117
  int extendRight;
124
118
  std::vector<double> extendBackground;
119
+ VipsExtend extendWith;
125
120
  bool withoutEnlargement;
126
121
  bool withoutReduction;
127
122
  std::vector<double> affineMatrix;
@@ -165,7 +160,8 @@ struct PipelineBaton {
165
160
  double gifDither;
166
161
  double gifInterFrameMaxError;
167
162
  double gifInterPaletteMaxError;
168
- bool gifReoptimise;
163
+ bool gifReuse;
164
+ bool gifProgressive;
169
165
  int tiffQuality;
170
166
  VipsForeignTiffCompression tiffCompression;
171
167
  VipsForeignTiffPredictor tiffPredictor;
@@ -235,6 +231,9 @@ struct PipelineBaton {
235
231
  hasCropOffset(false),
236
232
  cropOffsetLeft(0),
237
233
  cropOffsetTop(0),
234
+ hasAttentionCenter(false),
235
+ attentionX(0),
236
+ attentionY(0),
238
237
  premultiplied(false),
239
238
  tintA(128.0),
240
239
  tintB(128.0),
@@ -265,6 +264,8 @@ struct PipelineBaton {
265
264
  gamma(0.0),
266
265
  greyscale(false),
267
266
  normalise(false),
267
+ normaliseLower(1),
268
+ normaliseUpper(99),
268
269
  claheWidth(0),
269
270
  claheHeight(0),
270
271
  claheMaxSlope(3),
@@ -279,6 +280,7 @@ struct PipelineBaton {
279
280
  extendLeft(0),
280
281
  extendRight(0),
281
282
  extendBackground{ 0.0, 0.0, 0.0, 255.0 },
283
+ extendWith(VIPS_EXTEND_BACKGROUND),
282
284
  withoutEnlargement(false),
283
285
  withoutReduction(false),
284
286
  affineMatrix{ 1.0, 0.0, 0.0, 1.0 },
@@ -322,7 +324,8 @@ struct PipelineBaton {
322
324
  gifDither(1.0),
323
325
  gifInterFrameMaxError(0.0),
324
326
  gifInterPaletteMaxError(3.0),
325
- gifReoptimise(false),
327
+ gifReuse(true),
328
+ gifProgressive(false),
326
329
  tiffQuality(80),
327
330
  tiffCompression(VIPS_FOREIGN_TIFF_COMPRESSION_JPEG),
328
331
  tiffPredictor(VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL),
package/src/sharp.cc CHANGED
@@ -1,16 +1,5 @@
1
- // Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Lovell Fuller and contributors.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- //
7
- // http://www.apache.org/licenses/LICENSE-2.0
8
- //
9
- // Unless required by applicable law or agreed to in writing, software
10
- // distributed under the License is distributed on an "AS IS" BASIS,
11
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- // See the License for the specific language governing permissions and
13
- // limitations under the License.
1
+ // Copyright 2013 Lovell Fuller and others.
2
+ // SPDX-License-Identifier: Apache-2.0
14
3
 
15
4
  #include <napi.h>
16
5
  #include <vips/vips8>
package/src/stats.cc CHANGED
@@ -1,16 +1,5 @@
1
- // Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Lovell Fuller and contributors.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- //
7
- // http://www.apache.org/licenses/LICENSE-2.0
8
- //
9
- // Unless required by applicable law or agreed to in writing, software
10
- // distributed under the License is distributed on an "AS IS" BASIS,
11
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- // See the License for the specific language governing permissions and
13
- // limitations under the License.
1
+ // Copyright 2013 Lovell Fuller and others.
2
+ // SPDX-License-Identifier: Apache-2.0
14
3
 
15
4
  #include <numeric>
16
5
  #include <vector>
@@ -117,7 +106,7 @@ class StatsWorker : public Napi::AsyncWorker {
117
106
  // Handle warnings
118
107
  std::string warning = sharp::VipsWarningPop();
119
108
  while (!warning.empty()) {
120
- debuglog.Call({ Napi::String::New(env, warning) });
109
+ debuglog.MakeCallback(Receiver().Value(), { Napi::String::New(env, warning) });
121
110
  warning = sharp::VipsWarningPop();
122
111
  }
123
112
 
@@ -154,7 +143,7 @@ class StatsWorker : public Napi::AsyncWorker {
154
143
  info.Set("dominant", dominant);
155
144
  Callback().MakeCallback(Receiver().Value(), { env.Null(), info });
156
145
  } else {
157
- Callback().MakeCallback(Receiver().Value(), { Napi::Error::New(env, baton->err).Value() });
146
+ Callback().MakeCallback(Receiver().Value(), { Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
158
147
  }
159
148
 
160
149
  delete baton->input;
@@ -172,7 +161,7 @@ class StatsWorker : public Napi::AsyncWorker {
172
161
  Napi::Value stats(const Napi::CallbackInfo& info) {
173
162
  // V8 objects are converted to non-V8 types held in the baton struct
174
163
  StatsBaton *baton = new StatsBaton;
175
- Napi::Object options = info[0].As<Napi::Object>();
164
+ Napi::Object options = info[size_t(0)].As<Napi::Object>();
176
165
 
177
166
  // Input
178
167
  baton->input = sharp::CreateInputDescriptor(options.Get("input").As<Napi::Object>());
@@ -182,7 +171,7 @@ Napi::Value stats(const Napi::CallbackInfo& info) {
182
171
  Napi::Function debuglog = options.Get("debuglog").As<Napi::Function>();
183
172
 
184
173
  // Join queue for worker thread
185
- Napi::Function callback = info[1].As<Napi::Function>();
174
+ Napi::Function callback = info[size_t(1)].As<Napi::Function>();
186
175
  StatsWorker *worker = new StatsWorker(callback, baton, debuglog);
187
176
  worker->Receiver().Set("options", options);
188
177
  worker->Queue();
package/src/stats.h CHANGED
@@ -1,16 +1,5 @@
1
- // Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Lovell Fuller and contributors.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- //
7
- // http://www.apache.org/licenses/LICENSE-2.0
8
- //
9
- // Unless required by applicable law or agreed to in writing, software
10
- // distributed under the License is distributed on an "AS IS" BASIS,
11
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- // See the License for the specific language governing permissions and
13
- // limitations under the License.
1
+ // Copyright 2013 Lovell Fuller and others.
2
+ // SPDX-License-Identifier: Apache-2.0
14
3
 
15
4
  #ifndef SRC_STATS_H_
16
5
  #define SRC_STATS_H_
package/src/utilities.cc CHANGED
@@ -1,16 +1,5 @@
1
- // Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Lovell Fuller and contributors.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- //
7
- // http://www.apache.org/licenses/LICENSE-2.0
8
- //
9
- // Unless required by applicable law or agreed to in writing, software
10
- // distributed under the License is distributed on an "AS IS" BASIS,
11
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- // See the License for the specific language governing permissions and
13
- // limitations under the License.
1
+ // Copyright 2013 Lovell Fuller and others.
2
+ // SPDX-License-Identifier: Apache-2.0
14
3
 
15
4
  #include <cmath>
16
5
  #include <string>
@@ -30,16 +19,16 @@ Napi::Value cache(const Napi::CallbackInfo& info) {
30
19
  Napi::Env env = info.Env();
31
20
 
32
21
  // Set memory limit
33
- if (info[0].IsNumber()) {
34
- vips_cache_set_max_mem(info[0].As<Napi::Number>().Int32Value() * 1048576);
22
+ if (info[size_t(0)].IsNumber()) {
23
+ vips_cache_set_max_mem(info[size_t(0)].As<Napi::Number>().Int32Value() * 1048576);
35
24
  }
36
25
  // Set file limit
37
- if (info[1].IsNumber()) {
38
- vips_cache_set_max_files(info[1].As<Napi::Number>().Int32Value());
26
+ if (info[size_t(1)].IsNumber()) {
27
+ vips_cache_set_max_files(info[size_t(1)].As<Napi::Number>().Int32Value());
39
28
  }
40
29
  // Set items limit
41
- if (info[2].IsNumber()) {
42
- vips_cache_set_max(info[2].As<Napi::Number>().Int32Value());
30
+ if (info[size_t(2)].IsNumber()) {
31
+ vips_cache_set_max(info[size_t(2)].As<Napi::Number>().Int32Value());
43
32
  }
44
33
 
45
34
  // Get memory stats
@@ -69,8 +58,8 @@ Napi::Value cache(const Napi::CallbackInfo& info) {
69
58
  */
70
59
  Napi::Value concurrency(const Napi::CallbackInfo& info) {
71
60
  // Set concurrency
72
- if (info[0].IsNumber()) {
73
- vips_concurrency_set(info[0].As<Napi::Number>().Int32Value());
61
+ if (info[size_t(0)].IsNumber()) {
62
+ vips_concurrency_set(info[size_t(0)].As<Napi::Number>().Int32Value());
74
63
  }
75
64
  // Get concurrency
76
65
  return Napi::Number::New(info.Env(), vips_concurrency_get());
@@ -91,8 +80,8 @@ Napi::Value counters(const Napi::CallbackInfo& info) {
91
80
  */
92
81
  Napi::Value simd(const Napi::CallbackInfo& info) {
93
82
  // Set state
94
- if (info[0].IsBoolean()) {
95
- vips_vector_set_enabled(info[0].As<Napi::Boolean>().Value());
83
+ if (info[size_t(0)].IsBoolean()) {
84
+ vips_vector_set_enabled(info[size_t(0)].As<Napi::Boolean>().Value());
96
85
  }
97
86
  // Get state
98
87
  return Napi::Boolean::New(info.Env(), vips_vector_isenabled());
@@ -185,10 +174,10 @@ Napi::Value _maxColourDistance(const Napi::CallbackInfo& info) {
185
174
 
186
175
  // Open input files
187
176
  VImage image1;
188
- sharp::ImageType imageType1 = sharp::DetermineImageType(info[0].As<Napi::String>().Utf8Value().data());
177
+ sharp::ImageType imageType1 = sharp::DetermineImageType(info[size_t(0)].As<Napi::String>().Utf8Value().data());
189
178
  if (imageType1 != sharp::ImageType::UNKNOWN) {
190
179
  try {
191
- image1 = VImage::new_from_file(info[0].As<Napi::String>().Utf8Value().c_str());
180
+ image1 = VImage::new_from_file(info[size_t(0)].As<Napi::String>().Utf8Value().c_str());
192
181
  } catch (...) {
193
182
  throw Napi::Error::New(env, "Input file 1 has corrupt header");
194
183
  }
@@ -196,10 +185,10 @@ Napi::Value _maxColourDistance(const Napi::CallbackInfo& info) {
196
185
  throw Napi::Error::New(env, "Input file 1 is of an unsupported image format");
197
186
  }
198
187
  VImage image2;
199
- sharp::ImageType imageType2 = sharp::DetermineImageType(info[1].As<Napi::String>().Utf8Value().data());
188
+ sharp::ImageType imageType2 = sharp::DetermineImageType(info[size_t(1)].As<Napi::String>().Utf8Value().data());
200
189
  if (imageType2 != sharp::ImageType::UNKNOWN) {
201
190
  try {
202
- image2 = VImage::new_from_file(info[1].As<Napi::String>().Utf8Value().c_str());
191
+ image2 = VImage::new_from_file(info[size_t(1)].As<Napi::String>().Utf8Value().c_str());
203
192
  } catch (...) {
204
193
  throw Napi::Error::New(env, "Input file 2 has corrupt header");
205
194
  }
package/src/utilities.h CHANGED
@@ -1,16 +1,5 @@
1
- // Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Lovell Fuller and contributors.
2
- //
3
- // Licensed under the Apache License, Version 2.0 (the "License");
4
- // you may not use this file except in compliance with the License.
5
- // You may obtain a copy of the License at
6
- //
7
- // http://www.apache.org/licenses/LICENSE-2.0
8
- //
9
- // Unless required by applicable law or agreed to in writing, software
10
- // distributed under the License is distributed on an "AS IS" BASIS,
11
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- // See the License for the specific language governing permissions and
13
- // limitations under the License.
1
+ // Copyright 2013 Lovell Fuller and others.
2
+ // SPDX-License-Identifier: Apache-2.0
14
3
 
15
4
  #ifndef SRC_UTILITIES_H_
16
5
  #define SRC_UTILITIES_H_