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/README.md +13 -11
- package/binding.gyp +16 -1
- package/docs/api-channel.md +16 -0
- package/docs/api-colour.md +1 -19
- package/docs/api-composite.md +2 -3
- package/docs/api-constructor.md +2 -3
- package/docs/api-input.md +7 -2
- package/docs/api-operation.md +73 -115
- package/docs/api-output.md +9 -0
- package/docs/api-resize.md +160 -108
- package/docs/api-utility.md +4 -7
- package/docs/changelog.md +102 -0
- package/docs/image/sharp-logo.svg +5 -0
- package/docs/index.md +12 -6
- package/docs/install.md +41 -42
- package/docs/performance.md +14 -21
- package/install/libvips.js +28 -24
- package/lib/channel.js +20 -4
- package/lib/colour.js +35 -18
- package/lib/composite.js +2 -3
- package/lib/constructor.js +27 -42
- package/lib/input.js +9 -6
- package/lib/libvips.js +7 -1
- package/lib/operation.js +81 -123
- package/lib/output.js +128 -60
- package/lib/platform.js +4 -1
- package/lib/resize.js +310 -107
- package/lib/utility.js +5 -8
- package/package.json +30 -21
- package/src/common.cc +59 -14
- package/src/common.h +15 -12
- package/src/libvips/cplusplus/VImage.cpp +95 -95
- package/src/libvips/cplusplus/vips-operators.cpp +268 -185
- package/src/metadata.cc +34 -1
- package/src/metadata.h +10 -1
- package/src/operations.cc +47 -49
- package/src/operations.h +13 -2
- package/src/pipeline.cc +101 -95
- package/src/pipeline.h +40 -14
- package/src/sharp.cc +1 -1
- package/src/stats.cc +1 -1
- package/src/stats.h +1 -1
- package/src/utilities.cc +2 -2
- package/src/utilities.h +1 -1
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->
|
|
104
|
-
image = sharp::Trim(image, baton->
|
|
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->
|
|
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->
|
|
322
|
-
baton->
|
|
323
|
-
baton->
|
|
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
|
-
|
|
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->
|
|
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->
|
|
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->
|
|
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->
|
|
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
|
-
|
|
519
|
-
|
|
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->
|
|
660
|
-
image = sharp::Gamma(image, baton->
|
|
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->
|
|
1213
|
-
baton->
|
|
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->
|
|
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->
|
|
1346
|
-
baton->
|
|
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
|
|
65
|
-
|
|
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
|
-
|
|
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
|
-
|
|
159
|
-
|
|
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
|
-
|
|
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.
|