sharp 0.20.8 → 0.21.3

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,4 +1,4 @@
1
- // Copyright 2013, 2014, 2015, 2016, 2017 Lovell Fuller and contributors.
1
+ // Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019 Lovell Fuller and contributors.
2
2
  //
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
@@ -100,8 +100,10 @@ class PipelineWorker : public Nan::AsyncWorker {
100
100
  }
101
101
 
102
102
  // Trim
103
- if (baton->trimTolerance != 0) {
104
- image = sharp::Trim(image, baton->trimTolerance);
103
+ if (baton->trimThreshold > 0.0) {
104
+ image = sharp::Trim(image, baton->trimThreshold);
105
+ baton->trimOffsetLeft = image.xoffset();
106
+ baton->trimOffsetTop = image.yoffset();
105
107
  }
106
108
 
107
109
  // Pre extraction
@@ -233,7 +235,7 @@ class PipelineWorker : public Nan::AsyncWorker {
233
235
  if (
234
236
  xshrink == yshrink && xshrink >= 2 * shrink_on_load_factor &&
235
237
  (inputImageType == ImageType::JPEG || inputImageType == ImageType::WEBP) &&
236
- baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimTolerance == 0
238
+ baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold == 0.0
237
239
  ) {
238
240
  if (xshrink >= 8 * shrink_on_load_factor) {
239
241
  xfactor = xfactor / 8;
@@ -295,7 +297,7 @@ class PipelineWorker : public Nan::AsyncWorker {
295
297
  }
296
298
 
297
299
  // Ensure we're using a device-independent colour space
298
- if (sharp::HasProfile(image)) {
300
+ if (sharp::HasProfile(image) && image.interpretation() != VIPS_INTERPRETATION_LABS) {
299
301
  // Convert to sRGB using embedded profile
300
302
  try {
301
303
  image = image.icc_transform(
@@ -318,9 +320,9 @@ class PipelineWorker : public Nan::AsyncWorker {
318
320
  double const multiplier = sharp::Is16Bit(image.interpretation()) ? 256.0 : 1.0;
319
321
  // Background colour
320
322
  std::vector<double> background {
321
- baton->background[0] * multiplier,
322
- baton->background[1] * multiplier,
323
- baton->background[2] * multiplier
323
+ baton->flattenBackground[0] * multiplier,
324
+ baton->flattenBackground[1] * multiplier,
325
+ baton->flattenBackground[2] * multiplier
324
326
  };
325
327
  image = image.flatten(VImage::option()
326
328
  ->set("background", background));
@@ -379,10 +381,19 @@ class PipelineWorker : public Nan::AsyncWorker {
379
381
  vips_enum_from_nick(nullptr, VIPS_TYPE_KERNEL, baton->kernel.data()));
380
382
  if (
381
383
  kernel != VIPS_KERNEL_NEAREST && kernel != VIPS_KERNEL_CUBIC && kernel != VIPS_KERNEL_LANCZOS2 &&
382
- kernel != VIPS_KERNEL_LANCZOS3
384
+ kernel != VIPS_KERNEL_LANCZOS3 && kernel != VIPS_KERNEL_MITCHELL
383
385
  ) {
384
386
  throw vips::VError("Unknown kernel");
385
387
  }
388
+ // Ensure shortest edge is at least 1 pixel
389
+ if (image.width() / xfactor < 0.5) {
390
+ xfactor = 2 * image.width();
391
+ baton->width = 1;
392
+ }
393
+ if (image.height() / yfactor < 0.5) {
394
+ yfactor = 2 * image.height();
395
+ baton->height = 1;
396
+ }
386
397
  image = image.resize(1.0 / xfactor, VImage::option()
387
398
  ->set("vscale", 1.0 / yfactor)
388
399
  ->set("kernel", kernel));
@@ -421,35 +432,8 @@ class PipelineWorker : public Nan::AsyncWorker {
421
432
  // Crop/embed
422
433
  if (image.width() != baton->width || image.height() != baton->height) {
423
434
  if (baton->canvas == Canvas::EMBED) {
424
- // Scale up 8-bit values to match 16-bit input image
425
- double const multiplier = sharp::Is16Bit(image.interpretation()) ? 256.0 : 1.0;
426
- // Create background colour
427
435
  std::vector<double> background;
428
- if (image.bands() > 2) {
429
- background = {
430
- multiplier * baton->background[0],
431
- multiplier * baton->background[1],
432
- multiplier * baton->background[2]
433
- };
434
- } else {
435
- // Convert sRGB to greyscale
436
- background = { multiplier * (
437
- 0.2126 * baton->background[0] +
438
- 0.7152 * baton->background[1] +
439
- 0.0722 * baton->background[2])
440
- };
441
- }
442
- // Add alpha channel to background colour
443
- if (baton->background[3] < 255.0 || HasAlpha(image)) {
444
- background.push_back(baton->background[3] * multiplier);
445
- }
446
- // Ensure background colour uses correct colourspace
447
- background = sharp::GetRgbaAsColourspace(background, image.interpretation());
448
- // Add non-transparent alpha channel, if required
449
- if (baton->background[3] < 255.0 && !HasAlpha(image)) {
450
- image = image.bandjoin(
451
- VImage::new_matrix(image.width(), image.height()).new_from_image(255 * multiplier));
452
- }
436
+ std::tie(image, background) = sharp::ApplyAlpha(image, baton->resizeBackground);
453
437
 
454
438
  // Embed
455
439
 
@@ -463,7 +447,7 @@ class PipelineWorker : public Nan::AsyncWorker {
463
447
  int width = std::max(image.width(), baton->width);
464
448
  int height = std::max(image.height(), baton->height);
465
449
  std::tie(left, top) = sharp::CalculateEmbedPosition(
466
- image.width(), image.height(), baton->width, baton->height, baton->embed);
450
+ image.width(), image.height(), baton->width, baton->height, baton->position);
467
451
 
468
452
  image = image.embed(left, top, width, height, VImage::option()
469
453
  ->set("extend", VIPS_EXTEND_BACKGROUND)
@@ -474,12 +458,12 @@ class PipelineWorker : public Nan::AsyncWorker {
474
458
  (image.width() > baton->width || image.height() > baton->height)
475
459
  ) {
476
460
  // Crop/max/min
477
- if (baton->crop < 9) {
461
+ if (baton->position < 9) {
478
462
  // Gravity-based crop
479
463
  int left;
480
464
  int top;
481
465
  std::tie(left, top) = sharp::CalculateCrop(
482
- image.width(), image.height(), baton->width, baton->height, baton->crop);
466
+ image.width(), image.height(), baton->width, baton->height, baton->position);
483
467
  int width = std::min(image.width(), baton->width);
484
468
  int height = std::min(image.height(), baton->height);
485
469
  image = image.extract_area(left, top, width, height);
@@ -495,7 +479,7 @@ class PipelineWorker : public Nan::AsyncWorker {
495
479
  ->set("access", baton->accessMethod)
496
480
  ->set("threaded", TRUE));
497
481
  image = image.smartcrop(baton->width, baton->height, VImage::option()
498
- ->set("interesting", baton->crop == 16 ? VIPS_INTERESTING_ENTROPY : VIPS_INTERESTING_ATTENTION));
482
+ ->set("interesting", baton->position == 16 ? VIPS_INTERESTING_ENTROPY : VIPS_INTERESTING_ATTENTION));
499
483
  baton->hasCropOffset = true;
500
484
  baton->cropOffsetLeft = static_cast<int>(image.xoffset());
501
485
  baton->cropOffsetTop = static_cast<int>(image.yoffset());
@@ -503,6 +487,13 @@ class PipelineWorker : public Nan::AsyncWorker {
503
487
  }
504
488
  }
505
489
 
490
+ // Rotate by degree
491
+ if (baton->rotationAngle != 0.0) {
492
+ std::vector<double> background;
493
+ std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground);
494
+ image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background));
495
+ }
496
+
506
497
  // Post extraction
507
498
  if (baton->topOffsetPost != -1) {
508
499
  image = image.extract_area(
@@ -511,35 +502,9 @@ class PipelineWorker : public Nan::AsyncWorker {
511
502
 
512
503
  // Extend edges
513
504
  if (baton->extendTop > 0 || baton->extendBottom > 0 || baton->extendLeft > 0 || baton->extendRight > 0) {
514
- // Scale up 8-bit values to match 16-bit input image
515
- double const multiplier = sharp::Is16Bit(image.interpretation()) ? 256.0 : 1.0;
516
- // Create background colour
517
505
  std::vector<double> background;
518
- if (image.bands() > 2) {
519
- background = {
520
- multiplier * baton->background[0],
521
- multiplier * baton->background[1],
522
- multiplier * baton->background[2]
523
- };
524
- } else {
525
- // Convert sRGB to greyscale
526
- background = { multiplier * (
527
- 0.2126 * baton->background[0] +
528
- 0.7152 * baton->background[1] +
529
- 0.0722 * baton->background[2])
530
- };
531
- }
532
- // Add alpha channel to background colour
533
- if (baton->background[3] < 255.0 || HasAlpha(image)) {
534
- background.push_back(baton->background[3] * multiplier);
535
- }
536
- // Ensure background colour uses correct colourspace
537
- background = sharp::GetRgbaAsColourspace(background, image.interpretation());
538
- // Add non-transparent alpha channel, if required
539
- if (baton->background[3] < 255.0 && !HasAlpha(image)) {
540
- image = image.bandjoin(
541
- VImage::new_matrix(image.width(), image.height()).new_from_image(255 * multiplier));
542
- }
506
+ std::tie(image, background) = sharp::ApplyAlpha(image, baton->extendBackground);
507
+
543
508
  // Embed
544
509
  baton->width = image.width() + baton->extendLeft + baton->extendRight;
545
510
  baton->height = image.height() + baton->extendTop + baton->extendBottom;
@@ -569,6 +534,11 @@ class PipelineWorker : public Nan::AsyncWorker {
569
534
  baton->convKernel);
570
535
  }
571
536
 
537
+ // Recomb
538
+ if (baton->recombMatrix != NULL) {
539
+ image = sharp::Recomb(image, baton->recombMatrix);
540
+ }
541
+
572
542
  // Sharpen
573
543
  if (shouldSharpen) {
574
544
  image = sharp::Sharpen(image, baton->sharpenSigma, baton->sharpenFlat, baton->sharpenJagged);
@@ -656,8 +626,8 @@ class PipelineWorker : public Nan::AsyncWorker {
656
626
  baton->premultiplied = shouldPremultiplyAlpha;
657
627
 
658
628
  // Gamma decoding (brighten)
659
- if (baton->gamma >= 1 && baton->gamma <= 3) {
660
- image = sharp::Gamma(image, baton->gamma);
629
+ if (baton->gammaOut >= 1 && baton->gammaOut <= 3) {
630
+ image = sharp::Gamma(image, baton->gammaOut);
661
631
  }
662
632
 
663
633
  // Linear adjustment (a * in + b)
@@ -707,6 +677,11 @@ class PipelineWorker : public Nan::AsyncWorker {
707
677
  image = sharp::RemoveAlpha(image);
708
678
  }
709
679
 
680
+ // Ensure alpha channel, if missing
681
+ if (baton->ensureAlpha) {
682
+ image = sharp::EnsureAlpha(image);
683
+ }
684
+
710
685
  // Convert image to sRGB, if not already
711
686
  if (sharp::Is16Bit(image.interpretation())) {
712
687
  image = image.cast(VIPS_FORMAT_USHORT);
@@ -760,14 +735,15 @@ class PipelineWorker : public Nan::AsyncWorker {
760
735
  (inputImageType == ImageType::PNG || inputImageType == ImageType::GIF || inputImageType == ImageType::SVG))) {
761
736
  // Write PNG to buffer
762
737
  sharp::AssertImageTypeDimensions(image, ImageType::PNG);
763
- // Strip profile
764
- if (!baton->withMetadata) {
765
- vips_image_remove(image.get_image(), VIPS_META_ICC_NAME);
766
- }
767
738
  VipsArea *area = VIPS_AREA(image.pngsave_buffer(VImage::option()
739
+ ->set("strip", !baton->withMetadata)
768
740
  ->set("interlace", baton->pngProgressive)
769
741
  ->set("compression", baton->pngCompressionLevel)
770
- ->set("filter", baton->pngAdaptiveFiltering ? VIPS_FOREIGN_PNG_FILTER_ALL : VIPS_FOREIGN_PNG_FILTER_NONE)));
742
+ ->set("filter", baton->pngAdaptiveFiltering ? VIPS_FOREIGN_PNG_FILTER_ALL : VIPS_FOREIGN_PNG_FILTER_NONE)
743
+ ->set("palette", baton->pngPalette)
744
+ ->set("Q", baton->pngQuality)
745
+ ->set("colours", baton->pngColours)
746
+ ->set("dither", baton->pngDither)));
771
747
  baton->bufferOut = static_cast<char*>(area->data);
772
748
  baton->bufferOutLength = area->length;
773
749
  area->free_fn = nullptr;
@@ -802,6 +778,10 @@ class PipelineWorker : public Nan::AsyncWorker {
802
778
  ->set("squash", baton->tiffSquash)
803
779
  ->set("compression", baton->tiffCompression)
804
780
  ->set("predictor", baton->tiffPredictor)
781
+ ->set("pyramid", baton->tiffPyramid)
782
+ ->set("tile", baton->tiffTile)
783
+ ->set("tile_height", baton->tiffTileHeight)
784
+ ->set("tile_width", baton->tiffTileWidth)
805
785
  ->set("xres", baton->tiffXres)
806
786
  ->set("yres", baton->tiffYres)));
807
787
  baton->bufferOut = static_cast<char*>(area->data);
@@ -815,6 +795,7 @@ class PipelineWorker : public Nan::AsyncWorker {
815
795
  if (baton->greyscale || image.interpretation() == VIPS_INTERPRETATION_B_W) {
816
796
  // Extract first band for greyscale image
817
797
  image = image[0];
798
+ baton->channels = 1;
818
799
  }
819
800
  if (image.format() != VIPS_FORMAT_UCHAR) {
820
801
  // Cast pixels to uint8 (unsigned char)
@@ -868,14 +849,15 @@ class PipelineWorker : public Nan::AsyncWorker {
868
849
  (inputImageType == ImageType::PNG || inputImageType == ImageType::GIF || inputImageType == ImageType::SVG))) {
869
850
  // Write PNG to file
870
851
  sharp::AssertImageTypeDimensions(image, ImageType::PNG);
871
- // Strip profile
872
- if (!baton->withMetadata) {
873
- vips_image_remove(image.get_image(), VIPS_META_ICC_NAME);
874
- }
875
852
  image.pngsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
853
+ ->set("strip", !baton->withMetadata)
876
854
  ->set("interlace", baton->pngProgressive)
877
855
  ->set("compression", baton->pngCompressionLevel)
878
- ->set("filter", baton->pngAdaptiveFiltering ? VIPS_FOREIGN_PNG_FILTER_ALL : VIPS_FOREIGN_PNG_FILTER_NONE));
856
+ ->set("filter", baton->pngAdaptiveFiltering ? VIPS_FOREIGN_PNG_FILTER_ALL : VIPS_FOREIGN_PNG_FILTER_NONE)
857
+ ->set("palette", baton->pngPalette)
858
+ ->set("Q", baton->pngQuality)
859
+ ->set("colours", baton->pngColours)
860
+ ->set("dither", baton->pngDither));
879
861
  baton->formatOut = "png";
880
862
  } else if (baton->formatOut == "webp" || (mightMatchInput && isWebp) ||
881
863
  (willMatchInput && inputImageType == ImageType::WEBP)) {
@@ -894,16 +876,16 @@ class PipelineWorker : public Nan::AsyncWorker {
894
876
  if (baton->tiffCompression == VIPS_FOREIGN_TIFF_COMPRESSION_JPEG) {
895
877
  sharp::AssertImageTypeDimensions(image, ImageType::JPEG);
896
878
  }
897
- // Cast pixel values to float, if required
898
- if (baton->tiffPredictor == VIPS_FOREIGN_TIFF_PREDICTOR_FLOAT) {
899
- image = image.cast(VIPS_FORMAT_FLOAT);
900
- }
901
879
  image.tiffsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
902
880
  ->set("strip", !baton->withMetadata)
903
881
  ->set("Q", baton->tiffQuality)
904
882
  ->set("squash", baton->tiffSquash)
905
883
  ->set("compression", baton->tiffCompression)
906
884
  ->set("predictor", baton->tiffPredictor)
885
+ ->set("pyramid", baton->tiffPyramid)
886
+ ->set("tile", baton->tiffTile)
887
+ ->set("tile_height", baton->tiffTileHeight)
888
+ ->set("tile_width", baton->tiffTileWidth)
907
889
  ->set("xres", baton->tiffXres)
908
890
  ->set("yres", baton->tiffYres));
909
891
  baton->formatOut = "tiff";
@@ -1016,6 +998,12 @@ class PipelineWorker : public Nan::AsyncWorker {
1016
998
  Set(info, New("cropOffsetTop").ToLocalChecked(),
1017
999
  New<v8::Int32>(static_cast<int32_t>(baton->cropOffsetTop)));
1018
1000
  }
1001
+ if (baton->trimThreshold > 0.0) {
1002
+ Set(info, New("trimOffsetLeft").ToLocalChecked(),
1003
+ New<v8::Int32>(static_cast<int32_t>(baton->trimOffsetLeft)));
1004
+ Set(info, New("trimOffsetTop").ToLocalChecked(),
1005
+ New<v8::Int32>(static_cast<int32_t>(baton->trimOffsetTop)));
1006
+ }
1019
1007
 
1020
1008
  if (baton->bufferOutLength > 0) {
1021
1009
  // Pass ownership of output data to Buffer instance
@@ -1147,6 +1135,7 @@ NAN_METHOD(pipeline) {
1147
1135
  using sharp::AttrTo;
1148
1136
  using sharp::AttrAs;
1149
1137
  using sharp::AttrAsStr;
1138
+ using sharp::AttrAsRgba;
1150
1139
  using sharp::CreateInputDescriptor;
1151
1140
 
1152
1141
  // Input Buffers must not undergo GC compaction during processing
@@ -1190,11 +1179,6 @@ NAN_METHOD(pipeline) {
1190
1179
  } else if (canvas == "ignore_aspect") {
1191
1180
  baton->canvas = Canvas::IGNORE_ASPECT;
1192
1181
  }
1193
- // Background colour
1194
- v8::Local<v8::Object> background = AttrAs<v8::Object>(options, "background");
1195
- for (unsigned int i = 0; i < 4; i++) {
1196
- baton->background[i] = AttrTo<double>(background, i);
1197
- }
1198
1182
  // Tint chroma
1199
1183
  baton->tintA = AttrTo<double>(options, "tintA");
1200
1184
  baton->tintB = AttrTo<double>(options, "tintB");
@@ -1209,8 +1193,8 @@ NAN_METHOD(pipeline) {
1209
1193
  }
1210
1194
  // Resize options
1211
1195
  baton->withoutEnlargement = AttrTo<bool>(options, "withoutEnlargement");
1212
- baton->crop = AttrTo<int32_t>(options, "crop");
1213
- baton->embed = AttrTo<int32_t>(options, "embed");
1196
+ baton->position = AttrTo<int32_t>(options, "position");
1197
+ baton->resizeBackground = AttrAsRgba(options, "resizeBackground");
1214
1198
  baton->kernel = AttrAsStr(options, "kernel");
1215
1199
  baton->fastShrinkOnLoad = AttrTo<bool>(options, "fastShrinkOnLoad");
1216
1200
  // Join Channel Options
@@ -1228,6 +1212,7 @@ NAN_METHOD(pipeline) {
1228
1212
  }
1229
1213
  // Operators
1230
1214
  baton->flatten = AttrTo<bool>(options, "flatten");
1215
+ baton->flattenBackground = AttrAsRgba(options, "flattenBackground");
1231
1216
  baton->negate = AttrTo<bool>(options, "negate");
1232
1217
  baton->blurSigma = AttrTo<double>(options, "blurSigma");
1233
1218
  baton->medianSize = AttrTo<uint32_t>(options, "medianSize");
@@ -1236,14 +1221,17 @@ NAN_METHOD(pipeline) {
1236
1221
  baton->sharpenJagged = AttrTo<double>(options, "sharpenJagged");
1237
1222
  baton->threshold = AttrTo<int32_t>(options, "threshold");
1238
1223
  baton->thresholdGrayscale = AttrTo<bool>(options, "thresholdGrayscale");
1239
- baton->trimTolerance = AttrTo<int32_t>(options, "trimTolerance");
1224
+ baton->trimThreshold = AttrTo<double>(options, "trimThreshold");
1240
1225
  baton->gamma = AttrTo<double>(options, "gamma");
1226
+ baton->gammaOut = AttrTo<double>(options, "gammaOut");
1241
1227
  baton->linearA = AttrTo<double>(options, "linearA");
1242
1228
  baton->linearB = AttrTo<double>(options, "linearB");
1243
1229
  baton->greyscale = AttrTo<bool>(options, "greyscale");
1244
1230
  baton->normalise = AttrTo<bool>(options, "normalise");
1245
1231
  baton->useExifOrientation = AttrTo<bool>(options, "useExifOrientation");
1246
1232
  baton->angle = AttrTo<int32_t>(options, "angle");
1233
+ baton->rotationAngle = AttrTo<double>(options, "rotationAngle");
1234
+ baton->rotationBackground = AttrAsRgba(options, "rotationBackground");
1247
1235
  baton->rotateBeforePreExtract = AttrTo<bool>(options, "rotateBeforePreExtract");
1248
1236
  baton->flip = AttrTo<bool>(options, "flip");
1249
1237
  baton->flop = AttrTo<bool>(options, "flop");
@@ -1251,8 +1239,11 @@ NAN_METHOD(pipeline) {
1251
1239
  baton->extendBottom = AttrTo<int32_t>(options, "extendBottom");
1252
1240
  baton->extendLeft = AttrTo<int32_t>(options, "extendLeft");
1253
1241
  baton->extendRight = AttrTo<int32_t>(options, "extendRight");
1242
+ baton->extendBackground = AttrAsRgba(options, "extendBackground");
1254
1243
  baton->extractChannel = AttrTo<int32_t>(options, "extractChannel");
1244
+
1255
1245
  baton->removeAlpha = AttrTo<bool>(options, "removeAlpha");
1246
+ baton->ensureAlpha = AttrTo<bool>(options, "ensureAlpha");
1256
1247
  if (HasAttr(options, "boolean")) {
1257
1248
  baton->boolean = CreateInputDescriptor(AttrAs<v8::Object>(options, "boolean"), buffersToPersist);
1258
1249
  baton->booleanOp = sharp::GetBooleanOperation(AttrAsStr(options, "booleanOp"));
@@ -1273,6 +1264,13 @@ NAN_METHOD(pipeline) {
1273
1264
  baton->convKernel[i] = AttrTo<double>(kdata, i);
1274
1265
  }
1275
1266
  }
1267
+ if (HasAttr(options, "recombMatrix")) {
1268
+ baton->recombMatrix = std::unique_ptr<double[]>(new double[9]);
1269
+ v8::Local<v8::Array> recombMatrix = AttrAs<v8::Array>(options, "recombMatrix");
1270
+ for (unsigned int i = 0; i < 9; i++) {
1271
+ baton->recombMatrix[i] = AttrTo<double>(recombMatrix, i);
1272
+ }
1273
+ }
1276
1274
  baton->colourspace = sharp::GetInterpretation(AttrAsStr(options, "colourspace"));
1277
1275
  if (baton->colourspace == VIPS_INTERPRETATION_ERROR) {
1278
1276
  baton->colourspace = VIPS_INTERPRETATION_sRGB;
@@ -1294,12 +1292,20 @@ NAN_METHOD(pipeline) {
1294
1292
  baton->pngProgressive = AttrTo<bool>(options, "pngProgressive");
1295
1293
  baton->pngCompressionLevel = AttrTo<uint32_t>(options, "pngCompressionLevel");
1296
1294
  baton->pngAdaptiveFiltering = AttrTo<bool>(options, "pngAdaptiveFiltering");
1295
+ baton->pngPalette = AttrTo<bool>(options, "pngPalette");
1296
+ baton->pngQuality = AttrTo<uint32_t>(options, "pngQuality");
1297
+ baton->pngColours = AttrTo<uint32_t>(options, "pngColours");
1298
+ baton->pngDither = AttrTo<double>(options, "pngDither");
1297
1299
  baton->webpQuality = AttrTo<uint32_t>(options, "webpQuality");
1298
1300
  baton->webpAlphaQuality = AttrTo<uint32_t>(options, "webpAlphaQuality");
1299
1301
  baton->webpLossless = AttrTo<bool>(options, "webpLossless");
1300
1302
  baton->webpNearLossless = AttrTo<bool>(options, "webpNearLossless");
1301
1303
  baton->tiffQuality = AttrTo<uint32_t>(options, "tiffQuality");
1304
+ baton->tiffPyramid = AttrTo<bool>(options, "tiffPyramid");
1302
1305
  baton->tiffSquash = AttrTo<bool>(options, "tiffSquash");
1306
+ baton->tiffTile = AttrTo<bool>(options, "tiffTile");
1307
+ baton->tiffTileWidth = AttrTo<uint32_t>(options, "tiffTileWidth");
1308
+ baton->tiffTileHeight = AttrTo<uint32_t>(options, "tiffTileHeight");
1303
1309
  baton->tiffXres = AttrTo<double>(options, "tiffXres");
1304
1310
  baton->tiffYres = AttrTo<double>(options, "tiffYres");
1305
1311
  // tiff compression options
@@ -1342,8 +1348,8 @@ NAN_METHOD(pipeline) {
1342
1348
  }
1343
1349
  // Force random access for certain operations
1344
1350
  if (baton->accessMethod == VIPS_ACCESS_SEQUENTIAL && (
1345
- baton->trimTolerance != 0 || baton->normalise ||
1346
- baton->crop == 16 || baton->crop == 17)) {
1351
+ baton->trimThreshold > 0.0 || baton->normalise ||
1352
+ baton->position == 16 || baton->position == 17)) {
1347
1353
  baton->accessMethod = VIPS_ACCESS_RANDOM;
1348
1354
  }
1349
1355
 
package/src/pipeline.h CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright 2013, 2014, 2015, 2016, 2017 Lovell Fuller and contributors.
1
+ // Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019 Lovell Fuller and contributors.
2
2
  //
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
@@ -61,18 +61,18 @@ struct PipelineBaton {
61
61
  int height;
62
62
  int channels;
63
63
  Canvas canvas;
64
- int crop;
65
- int embed;
64
+ int position;
65
+ std::vector<double> resizeBackground;
66
66
  bool hasCropOffset;
67
67
  int cropOffsetLeft;
68
68
  int cropOffsetTop;
69
69
  bool premultiplied;
70
70
  std::string kernel;
71
71
  bool fastShrinkOnLoad;
72
- double background[4];
73
72
  double tintA;
74
73
  double tintB;
75
74
  bool flatten;
75
+ std::vector<double> flattenBackground;
76
76
  bool negate;
77
77
  double blurSigma;
78
78
  int medianSize;
@@ -81,14 +81,19 @@ struct PipelineBaton {
81
81
  double sharpenJagged;
82
82
  int threshold;
83
83
  bool thresholdGrayscale;
84
- int trimTolerance;
84
+ double trimThreshold;
85
+ int trimOffsetLeft;
86
+ int trimOffsetTop;
85
87
  double linearA;
86
88
  double linearB;
87
89
  double gamma;
90
+ double gammaOut;
88
91
  bool greyscale;
89
92
  bool normalise;
90
93
  bool useExifOrientation;
91
94
  int angle;
95
+ double rotationAngle;
96
+ std::vector<double> rotationBackground;
92
97
  bool rotateBeforePreExtract;
93
98
  bool flip;
94
99
  bool flop;
@@ -96,6 +101,7 @@ struct PipelineBaton {
96
101
  int extendBottom;
97
102
  int extendLeft;
98
103
  int extendRight;
104
+ std::vector<double> extendBackground;
99
105
  bool withoutEnlargement;
100
106
  VipsAccess accessMethod;
101
107
  int jpegQuality;
@@ -109,6 +115,10 @@ struct PipelineBaton {
109
115
  bool pngProgressive;
110
116
  int pngCompressionLevel;
111
117
  bool pngAdaptiveFiltering;
118
+ bool pngPalette;
119
+ int pngQuality;
120
+ int pngColours;
121
+ double pngDither;
112
122
  int webpQuality;
113
123
  int webpAlphaQuality;
114
124
  bool webpNearLossless;
@@ -116,7 +126,11 @@ struct PipelineBaton {
116
126
  int tiffQuality;
117
127
  VipsForeignTiffCompression tiffCompression;
118
128
  VipsForeignTiffPredictor tiffPredictor;
129
+ bool tiffPyramid;
119
130
  bool tiffSquash;
131
+ bool tiffTile;
132
+ int tiffTileHeight;
133
+ int tiffTileWidth;
120
134
  double tiffXres;
121
135
  double tiffYres;
122
136
  std::string err;
@@ -132,6 +146,7 @@ struct PipelineBaton {
132
146
  VipsOperationBoolean bandBoolOp;
133
147
  int extractChannel;
134
148
  bool removeAlpha;
149
+ bool ensureAlpha;
135
150
  VipsInterpretation colourspace;
136
151
  int tileSize;
137
152
  int tileOverlap;
@@ -140,6 +155,7 @@ struct PipelineBaton {
140
155
  std::string tileFormat;
141
156
  int tileAngle;
142
157
  VipsForeignDzDepth tileDepth;
158
+ std::unique_ptr<double[]> recombMatrix;
143
159
 
144
160
  PipelineBaton():
145
161
  input(nullptr),
@@ -155,8 +171,8 @@ struct PipelineBaton {
155
171
  topOffsetPost(-1),
156
172
  channels(0),
157
173
  canvas(Canvas::CROP),
158
- crop(0),
159
- embed(0),
174
+ position(0),
175
+ resizeBackground{ 0.0, 0.0, 0.0, 255.0 },
160
176
  hasCropOffset(false),
161
177
  cropOffsetLeft(0),
162
178
  cropOffsetTop(0),
@@ -164,6 +180,7 @@ struct PipelineBaton {
164
180
  tintA(128.0),
165
181
  tintB(128.0),
166
182
  flatten(false),
183
+ flattenBackground{ 0.0, 0.0, 0.0 },
167
184
  negate(false),
168
185
  blurSigma(0.0),
169
186
  medianSize(0),
@@ -172,7 +189,9 @@ struct PipelineBaton {
172
189
  sharpenJagged(2.0),
173
190
  threshold(0),
174
191
  thresholdGrayscale(true),
175
- trimTolerance(0),
192
+ trimThreshold(0.0),
193
+ trimOffsetLeft(0),
194
+ trimOffsetTop(0),
176
195
  linearA(1.0),
177
196
  linearB(0.0),
178
197
  gamma(0.0),
@@ -180,12 +199,15 @@ struct PipelineBaton {
180
199
  normalise(false),
181
200
  useExifOrientation(false),
182
201
  angle(0),
202
+ rotationAngle(0.0),
203
+ rotationBackground{ 0.0, 0.0, 0.0, 255.0 },
183
204
  flip(false),
184
205
  flop(false),
185
206
  extendTop(0),
186
207
  extendBottom(0),
187
208
  extendLeft(0),
188
209
  extendRight(0),
210
+ extendBackground{ 0.0, 0.0, 0.0, 255.0 },
189
211
  withoutEnlargement(false),
190
212
  jpegQuality(80),
191
213
  jpegProgressive(false),
@@ -198,11 +220,19 @@ struct PipelineBaton {
198
220
  pngProgressive(false),
199
221
  pngCompressionLevel(9),
200
222
  pngAdaptiveFiltering(false),
223
+ pngPalette(false),
224
+ pngQuality(100),
225
+ pngColours(256),
226
+ pngDither(1.0),
201
227
  webpQuality(80),
202
228
  tiffQuality(80),
203
229
  tiffCompression(VIPS_FOREIGN_TIFF_COMPRESSION_JPEG),
204
230
  tiffPredictor(VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL),
231
+ tiffPyramid(false),
205
232
  tiffSquash(false),
233
+ tiffTile(false),
234
+ tiffTileHeight(256),
235
+ tiffTileWidth(256),
206
236
  tiffXres(1.0),
207
237
  tiffYres(1.0),
208
238
  withMetadata(false),
@@ -216,18 +246,14 @@ struct PipelineBaton {
216
246
  bandBoolOp(VIPS_OPERATION_BOOLEAN_LAST),
217
247
  extractChannel(-1),
218
248
  removeAlpha(false),
249
+ ensureAlpha(false),
219
250
  colourspace(VIPS_INTERPRETATION_LAST),
220
251
  tileSize(256),
221
252
  tileOverlap(0),
222
253
  tileContainer(VIPS_FOREIGN_DZ_CONTAINER_FS),
223
254
  tileLayout(VIPS_FOREIGN_DZ_LAYOUT_DZ),
224
255
  tileAngle(0),
225
- tileDepth(VIPS_FOREIGN_DZ_DEPTH_LAST){
226
- background[0] = 0.0;
227
- background[1] = 0.0;
228
- background[2] = 0.0;
229
- background[3] = 255.0;
230
- }
256
+ tileDepth(VIPS_FOREIGN_DZ_DEPTH_LAST) {}
231
257
  };
232
258
 
233
259
  #endif // SRC_PIPELINE_H_
package/src/sharp.cc CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright 2013, 2014, 2015, 2016, 2017 Lovell Fuller and contributors.
1
+ // Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019 Lovell Fuller and contributors.
2
2
  //
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
package/src/stats.cc CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright 2013, 2014, 2015, 2016, 2017 Lovell Fuller and contributors.
1
+ // Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019 Lovell Fuller and contributors.
2
2
  //
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
package/src/stats.h CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright 2013, 2014, 2015, 2016, 2017 Lovell Fuller and contributors.
1
+ // Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019 Lovell Fuller and contributors.
2
2
  //
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
package/src/utilities.cc CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright 2013, 2014, 2015, 2016, 2017 Lovell Fuller and contributors.
1
+ // Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019 Lovell Fuller and contributors.
2
2
  //
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.
@@ -259,7 +259,7 @@ NAN_METHOD(_maxColourDistance) {
259
259
  }
260
260
  // Calculate colour distance
261
261
  maxColourDistance = image1.dE00(image2).max();
262
- } catch (VError err) {
262
+ } catch (VError const &err) {
263
263
  return ThrowError(err.what());
264
264
  }
265
265
 
package/src/utilities.h CHANGED
@@ -1,4 +1,4 @@
1
- // Copyright 2013, 2014, 2015, 2016, 2017 Lovell Fuller and contributors.
1
+ // Copyright 2013, 2014, 2015, 2016, 2017, 2018, 2019 Lovell Fuller and contributors.
2
2
  //
3
3
  // Licensed under the Apache License, Version 2.0 (the "License");
4
4
  // you may not use this file except in compliance with the License.