sharp 0.32.6 → 0.33.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/install/check.js +41 -0
- package/lib/colour.js +5 -9
- package/lib/constructor.js +29 -18
- package/lib/index.d.ts +100 -26
- package/lib/input.js +44 -18
- package/lib/is.js +28 -14
- package/lib/libvips.js +118 -57
- package/lib/operation.js +2 -0
- package/lib/output.js +247 -75
- package/lib/resize.js +54 -49
- package/lib/sharp.js +100 -23
- package/lib/utility.js +31 -29
- package/package.json +62 -47
- package/{binding.gyp → src/binding.gyp} +92 -48
- package/src/common.cc +62 -13
- package/src/common.h +27 -11
- package/src/metadata.cc +5 -5
- package/src/operations.cc +35 -18
- package/src/operations.h +3 -3
- package/src/pipeline.cc +142 -112
- package/src/pipeline.h +17 -11
- package/src/sharp.cc +6 -7
- package/src/stats.cc +5 -5
- package/src/utilities.cc +20 -5
- package/install/can-compile.js +0 -14
- package/install/dll-copy.js +0 -40
- package/install/libvips.js +0 -222
- package/lib/agent.js +0 -44
- package/lib/platform.js +0 -30
- package/src/libvips/cplusplus/VConnection.cpp +0 -151
- package/src/libvips/cplusplus/VError.cpp +0 -49
- package/src/libvips/cplusplus/VImage.cpp +0 -1548
- package/src/libvips/cplusplus/VInterpolate.cpp +0 -62
- package/src/libvips/cplusplus/VRegion.cpp +0 -27
- package/src/libvips/cplusplus/vips-operators.cpp +0 -3760
package/src/pipeline.cc
CHANGED
|
@@ -44,9 +44,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
44
44
|
// libuv worker
|
|
45
45
|
void Execute() {
|
|
46
46
|
// Decrement queued task counter
|
|
47
|
-
|
|
47
|
+
sharp::counterQueue--;
|
|
48
48
|
// Increment processing task counter
|
|
49
|
-
|
|
49
|
+
sharp::counterProcess++;
|
|
50
50
|
|
|
51
51
|
try {
|
|
52
52
|
// Open input
|
|
@@ -54,7 +54,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
54
54
|
sharp::ImageType inputImageType;
|
|
55
55
|
std::tie(image, inputImageType) = sharp::OpenInput(baton->input);
|
|
56
56
|
VipsAccess access = baton->input->access;
|
|
57
|
-
image = sharp::EnsureColourspace(image, baton->
|
|
57
|
+
image = sharp::EnsureColourspace(image, baton->colourspacePipeline);
|
|
58
58
|
|
|
59
59
|
int nPages = baton->input->pages;
|
|
60
60
|
if (nPages == -1) {
|
|
@@ -70,8 +70,8 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
70
70
|
// Calculate angle of rotation
|
|
71
71
|
VipsAngle rotation = VIPS_ANGLE_D0;
|
|
72
72
|
VipsAngle autoRotation = VIPS_ANGLE_D0;
|
|
73
|
-
bool autoFlip =
|
|
74
|
-
bool autoFlop =
|
|
73
|
+
bool autoFlip = false;
|
|
74
|
+
bool autoFlop = false;
|
|
75
75
|
|
|
76
76
|
if (baton->useExifOrientation) {
|
|
77
77
|
// Rotate and flip image according to Exif orientation
|
|
@@ -88,7 +88,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
88
88
|
baton->rotationAngle != 0.0);
|
|
89
89
|
|
|
90
90
|
if (shouldRotateBefore) {
|
|
91
|
-
image = sharp::StaySequential(image,
|
|
91
|
+
image = sharp::StaySequential(image,
|
|
92
92
|
rotation != VIPS_ANGLE_D0 ||
|
|
93
93
|
autoRotation != VIPS_ANGLE_D0 ||
|
|
94
94
|
autoFlip ||
|
|
@@ -96,40 +96,46 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
96
96
|
baton->rotationAngle != 0.0);
|
|
97
97
|
|
|
98
98
|
if (autoRotation != VIPS_ANGLE_D0) {
|
|
99
|
+
if (autoRotation != VIPS_ANGLE_D180) {
|
|
100
|
+
MultiPageUnsupported(nPages, "Rotate");
|
|
101
|
+
}
|
|
99
102
|
image = image.rot(autoRotation);
|
|
100
103
|
autoRotation = VIPS_ANGLE_D0;
|
|
101
104
|
}
|
|
102
105
|
if (autoFlip) {
|
|
103
106
|
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
|
104
|
-
autoFlip =
|
|
107
|
+
autoFlip = false;
|
|
105
108
|
} else if (baton->flip) {
|
|
106
109
|
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
|
107
|
-
baton->flip =
|
|
110
|
+
baton->flip = false;
|
|
108
111
|
}
|
|
109
112
|
if (autoFlop) {
|
|
110
113
|
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
|
111
|
-
autoFlop =
|
|
114
|
+
autoFlop = false;
|
|
112
115
|
} else if (baton->flop) {
|
|
113
116
|
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
|
114
|
-
baton->flop =
|
|
117
|
+
baton->flop = false;
|
|
115
118
|
}
|
|
116
119
|
if (rotation != VIPS_ANGLE_D0) {
|
|
120
|
+
if (rotation != VIPS_ANGLE_D180) {
|
|
121
|
+
MultiPageUnsupported(nPages, "Rotate");
|
|
122
|
+
}
|
|
117
123
|
image = image.rot(rotation);
|
|
118
124
|
rotation = VIPS_ANGLE_D0;
|
|
119
125
|
}
|
|
120
126
|
if (baton->rotationAngle != 0.0) {
|
|
121
127
|
MultiPageUnsupported(nPages, "Rotate");
|
|
122
128
|
std::vector<double> background;
|
|
123
|
-
std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground,
|
|
129
|
+
std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground, false);
|
|
124
130
|
image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background)).copy_memory();
|
|
125
131
|
}
|
|
126
132
|
}
|
|
127
133
|
|
|
128
134
|
// Trim
|
|
129
|
-
if (baton->trimThreshold
|
|
135
|
+
if (baton->trimThreshold >= 0.0) {
|
|
130
136
|
MultiPageUnsupported(nPages, "Trim");
|
|
131
|
-
image = sharp::StaySequential(image
|
|
132
|
-
image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold);
|
|
137
|
+
image = sharp::StaySequential(image);
|
|
138
|
+
image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold, baton->trimLineArt);
|
|
133
139
|
baton->trimOffsetLeft = image.xoffset();
|
|
134
140
|
baton->trimOffsetTop = image.yoffset();
|
|
135
141
|
}
|
|
@@ -182,8 +188,8 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
182
188
|
// - trimming or pre-resize extract isn't required;
|
|
183
189
|
// - input colourspace is not specified;
|
|
184
190
|
bool const shouldPreShrink = (targetResizeWidth > 0 || targetResizeHeight > 0) &&
|
|
185
|
-
baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold
|
|
186
|
-
baton->
|
|
191
|
+
baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold < 0.0 &&
|
|
192
|
+
baton->colourspacePipeline == VIPS_INTERPRETATION_LAST && !shouldRotateBefore;
|
|
187
193
|
|
|
188
194
|
if (shouldPreShrink) {
|
|
189
195
|
// The common part of the shrink: the bit by which both axes must be shrunk
|
|
@@ -315,17 +321,23 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
315
321
|
}
|
|
316
322
|
|
|
317
323
|
// Ensure we're using a device-independent colour space
|
|
324
|
+
std::pair<char*, size_t> inputProfile(nullptr, 0);
|
|
325
|
+
if ((baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) && baton->withIccProfile.empty()) {
|
|
326
|
+
// Cache input profile for use with output
|
|
327
|
+
inputProfile = sharp::GetProfile(image);
|
|
328
|
+
}
|
|
318
329
|
char const *processingProfile = image.interpretation() == VIPS_INTERPRETATION_RGB16 ? "p3" : "srgb";
|
|
319
330
|
if (
|
|
320
331
|
sharp::HasProfile(image) &&
|
|
321
332
|
image.interpretation() != VIPS_INTERPRETATION_LABS &&
|
|
322
333
|
image.interpretation() != VIPS_INTERPRETATION_GREY16 &&
|
|
334
|
+
baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK &&
|
|
323
335
|
!baton->input->ignoreIcc
|
|
324
336
|
) {
|
|
325
337
|
// Convert to sRGB/P3 using embedded profile
|
|
326
338
|
try {
|
|
327
339
|
image = image.icc_transform(processingProfile, VImage::option()
|
|
328
|
-
->set("embedded",
|
|
340
|
+
->set("embedded", true)
|
|
329
341
|
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
|
330
342
|
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
|
331
343
|
} catch(...) {
|
|
@@ -333,7 +345,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
333
345
|
}
|
|
334
346
|
} else if (
|
|
335
347
|
image.interpretation() == VIPS_INTERPRETATION_CMYK &&
|
|
336
|
-
baton->
|
|
348
|
+
baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK
|
|
337
349
|
) {
|
|
338
350
|
image = image.icc_transform(processingProfile, VImage::option()
|
|
339
351
|
->set("input_profile", "cmyk")
|
|
@@ -345,11 +357,6 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
345
357
|
image = sharp::Flatten(image, baton->flattenBackground);
|
|
346
358
|
}
|
|
347
359
|
|
|
348
|
-
// Negate the colours in the image
|
|
349
|
-
if (baton->negate) {
|
|
350
|
-
image = sharp::Negate(image, baton->negateAlpha);
|
|
351
|
-
}
|
|
352
|
-
|
|
353
360
|
// Gamma encoding (darken)
|
|
354
361
|
if (baton->gamma >= 1 && baton->gamma <= 3) {
|
|
355
362
|
image = sharp::Gamma(image, 1.0 / baton->gamma);
|
|
@@ -385,13 +392,16 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
385
392
|
->set("kernel", baton->kernel));
|
|
386
393
|
}
|
|
387
394
|
|
|
388
|
-
image = sharp::StaySequential(image,
|
|
395
|
+
image = sharp::StaySequential(image,
|
|
389
396
|
autoRotation != VIPS_ANGLE_D0 ||
|
|
390
397
|
baton->flip ||
|
|
391
398
|
autoFlip ||
|
|
392
399
|
rotation != VIPS_ANGLE_D0);
|
|
393
400
|
// Auto-rotate post-extract
|
|
394
401
|
if (autoRotation != VIPS_ANGLE_D0) {
|
|
402
|
+
if (autoRotation != VIPS_ANGLE_D180) {
|
|
403
|
+
MultiPageUnsupported(nPages, "Rotate");
|
|
404
|
+
}
|
|
395
405
|
image = image.rot(autoRotation);
|
|
396
406
|
}
|
|
397
407
|
// Mirror vertically (up-down) about the x-axis
|
|
@@ -404,6 +414,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
404
414
|
}
|
|
405
415
|
// Rotate post-extract 90-angle
|
|
406
416
|
if (rotation != VIPS_ANGLE_D0) {
|
|
417
|
+
if (rotation != VIPS_ANGLE_D180) {
|
|
418
|
+
MultiPageUnsupported(nPages, "Rotate");
|
|
419
|
+
}
|
|
407
420
|
image = image.rot(rotation);
|
|
408
421
|
}
|
|
409
422
|
|
|
@@ -415,7 +428,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
415
428
|
for (unsigned int i = 0; i < baton->joinChannelIn.size(); i++) {
|
|
416
429
|
baton->joinChannelIn[i]->access = access;
|
|
417
430
|
std::tie(joinImage, joinImageType) = sharp::OpenInput(baton->joinChannelIn[i]);
|
|
418
|
-
joinImage = sharp::EnsureColourspace(joinImage, baton->
|
|
431
|
+
joinImage = sharp::EnsureColourspace(joinImage, baton->colourspacePipeline);
|
|
419
432
|
image = image.bandjoin(joinImage);
|
|
420
433
|
}
|
|
421
434
|
image = image.copy(VImage::option()->set("interpretation", baton->colourspace));
|
|
@@ -482,12 +495,10 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
482
495
|
|
|
483
496
|
// Attention-based or Entropy-based crop
|
|
484
497
|
MultiPageUnsupported(nPages, "Resize strategy");
|
|
485
|
-
image = sharp::StaySequential(image
|
|
498
|
+
image = sharp::StaySequential(image);
|
|
486
499
|
image = image.smartcrop(baton->width, baton->height, VImage::option()
|
|
487
500
|
->set("interesting", baton->position == 16 ? VIPS_INTERESTING_ENTROPY : VIPS_INTERESTING_ATTENTION)
|
|
488
|
-
#if (VIPS_MAJOR_VERSION >= 8 && VIPS_MINOR_VERSION >= 15)
|
|
489
501
|
->set("premultiplied", shouldPremultiplyAlpha)
|
|
490
|
-
#endif
|
|
491
502
|
->set("attention_x", &attention_x)
|
|
492
503
|
->set("attention_y", &attention_y));
|
|
493
504
|
baton->hasCropOffset = true;
|
|
@@ -503,7 +514,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
503
514
|
// Rotate post-extract non-90 angle
|
|
504
515
|
if (!baton->rotateBeforePreExtract && baton->rotationAngle != 0.0) {
|
|
505
516
|
MultiPageUnsupported(nPages, "Rotate");
|
|
506
|
-
image = sharp::StaySequential(image
|
|
517
|
+
image = sharp::StaySequential(image);
|
|
507
518
|
std::vector<double> background;
|
|
508
519
|
std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground, shouldPremultiplyAlpha);
|
|
509
520
|
image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background));
|
|
@@ -527,7 +538,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
527
538
|
// Affine transform
|
|
528
539
|
if (!baton->affineMatrix.empty()) {
|
|
529
540
|
MultiPageUnsupported(nPages, "Affine");
|
|
530
|
-
image = sharp::StaySequential(image
|
|
541
|
+
image = sharp::StaySequential(image);
|
|
531
542
|
std::vector<double> background;
|
|
532
543
|
std::tie(image, background) = sharp::ApplyAlpha(image, baton->affineBackground, shouldPremultiplyAlpha);
|
|
533
544
|
vips::VInterpolate interp = vips::VInterpolate::new_from_name(
|
|
@@ -550,6 +561,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
550
561
|
std::vector<double> background;
|
|
551
562
|
std::tie(image, background) = sharp::ApplyAlpha(image, baton->extendBackground, shouldPremultiplyAlpha);
|
|
552
563
|
|
|
564
|
+
image = sharp::StaySequential(image, nPages > 1);
|
|
553
565
|
image = nPages > 1
|
|
554
566
|
? sharp::EmbedMultiPage(image,
|
|
555
567
|
baton->extendLeft, baton->extendTop, baton->width, baton->height,
|
|
@@ -558,6 +570,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
558
570
|
VImage::option()->set("extend", baton->extendWith)->set("background", background));
|
|
559
571
|
} else {
|
|
560
572
|
std::vector<double> ignoredBackground(1);
|
|
573
|
+
image = sharp::StaySequential(image);
|
|
561
574
|
image = nPages > 1
|
|
562
575
|
? sharp::EmbedMultiPage(image,
|
|
563
576
|
baton->extendLeft, baton->extendTop, baton->width, baton->height,
|
|
@@ -626,7 +639,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
626
639
|
sharp::ImageType compositeImageType = sharp::ImageType::UNKNOWN;
|
|
627
640
|
composite->input->access = access;
|
|
628
641
|
std::tie(compositeImage, compositeImageType) = sharp::OpenInput(composite->input);
|
|
629
|
-
compositeImage = sharp::EnsureColourspace(compositeImage, baton->
|
|
642
|
+
compositeImage = sharp::EnsureColourspace(compositeImage, baton->colourspacePipeline);
|
|
630
643
|
// Verify within current dimensions
|
|
631
644
|
if (compositeImage.width() > image.width() || compositeImage.height() > image.height()) {
|
|
632
645
|
throw vips::VError("Image to composite must have same dimensions or smaller");
|
|
@@ -653,7 +666,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
653
666
|
if (across != 0 || down != 0) {
|
|
654
667
|
int left;
|
|
655
668
|
int top;
|
|
656
|
-
compositeImage = sharp::StaySequential(compositeImage
|
|
669
|
+
compositeImage = sharp::StaySequential(compositeImage).replicate(across, down);
|
|
657
670
|
if (composite->hasOffset) {
|
|
658
671
|
std::tie(left, top) = sharp::CalculateCrop(
|
|
659
672
|
compositeImage.width(), compositeImage.height(), image.width(), image.height(),
|
|
@@ -711,13 +724,13 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
711
724
|
|
|
712
725
|
// Apply normalisation - stretch luminance to cover full dynamic range
|
|
713
726
|
if (baton->normalise) {
|
|
714
|
-
image = sharp::StaySequential(image
|
|
727
|
+
image = sharp::StaySequential(image);
|
|
715
728
|
image = sharp::Normalise(image, baton->normaliseLower, baton->normaliseUpper);
|
|
716
729
|
}
|
|
717
730
|
|
|
718
731
|
// Apply contrast limiting adaptive histogram equalization (CLAHE)
|
|
719
732
|
if (baton->claheWidth != 0 && baton->claheHeight != 0) {
|
|
720
|
-
image = sharp::StaySequential(image
|
|
733
|
+
image = sharp::StaySequential(image);
|
|
721
734
|
image = sharp::Clahe(image, baton->claheWidth, baton->claheHeight, baton->claheMaxSlope);
|
|
722
735
|
}
|
|
723
736
|
|
|
@@ -727,7 +740,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
727
740
|
sharp::ImageType booleanImageType = sharp::ImageType::UNKNOWN;
|
|
728
741
|
baton->boolean->access = access;
|
|
729
742
|
std::tie(booleanImage, booleanImageType) = sharp::OpenInput(baton->boolean);
|
|
730
|
-
booleanImage = sharp::EnsureColourspace(booleanImage, baton->
|
|
743
|
+
booleanImage = sharp::EnsureColourspace(booleanImage, baton->colourspacePipeline);
|
|
731
744
|
image = sharp::Boolean(image, booleanImage, baton->booleanOp);
|
|
732
745
|
image = sharp::RemoveGifPalette(image);
|
|
733
746
|
}
|
|
@@ -738,8 +751,8 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
738
751
|
}
|
|
739
752
|
|
|
740
753
|
// Tint the image
|
|
741
|
-
if (baton->
|
|
742
|
-
image = sharp::Tint(image, baton->
|
|
754
|
+
if (baton->tint[0] >= 0.0) {
|
|
755
|
+
image = sharp::Tint(image, baton->tint);
|
|
743
756
|
}
|
|
744
757
|
|
|
745
758
|
// Remove alpha channel, if any
|
|
@@ -760,9 +773,10 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
760
773
|
// Convert colourspace, pass the current known interpretation so libvips doesn't have to guess
|
|
761
774
|
image = image.colourspace(baton->colourspace, VImage::option()->set("source_space", image.interpretation()));
|
|
762
775
|
// Transform colours from embedded profile to output profile
|
|
763
|
-
if (baton->
|
|
764
|
-
|
|
765
|
-
|
|
776
|
+
if ((baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) && baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK &&
|
|
777
|
+
baton->withIccProfile.empty() && sharp::HasProfile(image)) {
|
|
778
|
+
image = image.icc_transform(processingProfile, VImage::option()
|
|
779
|
+
->set("embedded", true)
|
|
766
780
|
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
|
767
781
|
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
|
768
782
|
}
|
|
@@ -789,27 +803,40 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
789
803
|
}
|
|
790
804
|
|
|
791
805
|
// Apply output ICC profile
|
|
792
|
-
if (baton->
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
VImage::option()
|
|
806
|
+
if (!baton->withIccProfile.empty()) {
|
|
807
|
+
try {
|
|
808
|
+
image = image.icc_transform(const_cast<char*>(baton->withIccProfile.data()), VImage::option()
|
|
796
809
|
->set("input_profile", processingProfile)
|
|
797
|
-
->set("embedded",
|
|
810
|
+
->set("embedded", true)
|
|
798
811
|
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
|
799
812
|
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
|
813
|
+
} catch(...) {
|
|
814
|
+
sharp::VipsWarningCallback(nullptr, G_LOG_LEVEL_WARNING, "Invalid profile", nullptr);
|
|
815
|
+
}
|
|
816
|
+
} else if (baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) {
|
|
817
|
+
image = sharp::SetProfile(image, inputProfile);
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
// Negate the colours in the image
|
|
821
|
+
if (baton->negate) {
|
|
822
|
+
image = sharp::Negate(image, baton->negateAlpha);
|
|
800
823
|
}
|
|
824
|
+
|
|
801
825
|
// Override EXIF Orientation tag
|
|
802
|
-
if (baton->
|
|
826
|
+
if (baton->withMetadataOrientation != -1) {
|
|
803
827
|
image = sharp::SetExifOrientation(image, baton->withMetadataOrientation);
|
|
804
828
|
}
|
|
805
829
|
// Override pixel density
|
|
806
830
|
if (baton->withMetadataDensity > 0) {
|
|
807
831
|
image = sharp::SetDensity(image, baton->withMetadataDensity);
|
|
808
832
|
}
|
|
809
|
-
//
|
|
810
|
-
if (
|
|
833
|
+
// EXIF key/value pairs
|
|
834
|
+
if (baton->keepMetadata & VIPS_FOREIGN_KEEP_EXIF) {
|
|
811
835
|
image = image.copy();
|
|
812
|
-
|
|
836
|
+
if (!baton->withExifMerge) {
|
|
837
|
+
image = sharp::RemoveExif(image);
|
|
838
|
+
}
|
|
839
|
+
for (const auto& s : baton->withExif) {
|
|
813
840
|
image.set(s.first.data(), s.second.data());
|
|
814
841
|
}
|
|
815
842
|
}
|
|
@@ -830,7 +857,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
830
857
|
// Write JPEG to buffer
|
|
831
858
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::JPEG);
|
|
832
859
|
VipsArea *area = reinterpret_cast<VipsArea*>(image.jpegsave_buffer(VImage::option()
|
|
833
|
-
->set("
|
|
860
|
+
->set("keep", baton->keepMetadata)
|
|
834
861
|
->set("Q", baton->jpegQuality)
|
|
835
862
|
->set("interlace", baton->jpegProgressive)
|
|
836
863
|
->set("subsample_mode", baton->jpegChromaSubsampling == "4:4:4"
|
|
@@ -872,7 +899,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
872
899
|
// Write PNG to buffer
|
|
873
900
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::PNG);
|
|
874
901
|
VipsArea *area = reinterpret_cast<VipsArea*>(image.pngsave_buffer(VImage::option()
|
|
875
|
-
->set("
|
|
902
|
+
->set("keep", baton->keepMetadata)
|
|
876
903
|
->set("interlace", baton->pngProgressive)
|
|
877
904
|
->set("compression", baton->pngCompressionLevel)
|
|
878
905
|
->set("filter", baton->pngAdaptiveFiltering ? VIPS_FOREIGN_PNG_FILTER_ALL : VIPS_FOREIGN_PNG_FILTER_NONE)
|
|
@@ -891,7 +918,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
891
918
|
// Write WEBP to buffer
|
|
892
919
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::WEBP);
|
|
893
920
|
VipsArea *area = reinterpret_cast<VipsArea*>(image.webpsave_buffer(VImage::option()
|
|
894
|
-
->set("
|
|
921
|
+
->set("keep", baton->keepMetadata)
|
|
895
922
|
->set("Q", baton->webpQuality)
|
|
896
923
|
->set("lossless", baton->webpLossless)
|
|
897
924
|
->set("near_lossless", baton->webpNearLossless)
|
|
@@ -911,7 +938,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
911
938
|
// Write GIF to buffer
|
|
912
939
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::GIF);
|
|
913
940
|
VipsArea *area = reinterpret_cast<VipsArea*>(image.gifsave_buffer(VImage::option()
|
|
914
|
-
->set("
|
|
941
|
+
->set("keep", baton->keepMetadata)
|
|
915
942
|
->set("bitdepth", baton->gifBitdepth)
|
|
916
943
|
->set("effort", baton->gifEffort)
|
|
917
944
|
->set("reuse", baton->gifReuse)
|
|
@@ -936,10 +963,11 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
936
963
|
image = image.cast(VIPS_FORMAT_FLOAT);
|
|
937
964
|
}
|
|
938
965
|
VipsArea *area = reinterpret_cast<VipsArea*>(image.tiffsave_buffer(VImage::option()
|
|
939
|
-
->set("
|
|
966
|
+
->set("keep", baton->keepMetadata)
|
|
940
967
|
->set("Q", baton->tiffQuality)
|
|
941
968
|
->set("bitdepth", baton->tiffBitdepth)
|
|
942
969
|
->set("compression", baton->tiffCompression)
|
|
970
|
+
->set("miniswhite", baton->tiffMiniswhite)
|
|
943
971
|
->set("predictor", baton->tiffPredictor)
|
|
944
972
|
->set("pyramid", baton->tiffPyramid)
|
|
945
973
|
->set("tile", baton->tiffTile)
|
|
@@ -959,11 +987,11 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
959
987
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::HEIF);
|
|
960
988
|
image = sharp::RemoveAnimationProperties(image).cast(VIPS_FORMAT_UCHAR);
|
|
961
989
|
VipsArea *area = reinterpret_cast<VipsArea*>(image.heifsave_buffer(VImage::option()
|
|
962
|
-
->set("
|
|
990
|
+
->set("keep", baton->keepMetadata)
|
|
963
991
|
->set("Q", baton->heifQuality)
|
|
964
992
|
->set("compression", baton->heifCompression)
|
|
965
993
|
->set("effort", baton->heifEffort)
|
|
966
|
-
->set("bitdepth",
|
|
994
|
+
->set("bitdepth", baton->heifBitdepth)
|
|
967
995
|
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
|
968
996
|
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
|
969
997
|
->set("lossless", baton->heifLossless)));
|
|
@@ -978,7 +1006,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
978
1006
|
if (!sharp::HasAlpha(image)) {
|
|
979
1007
|
baton->tileBackground.pop_back();
|
|
980
1008
|
}
|
|
981
|
-
image = sharp::StaySequential(image,
|
|
1009
|
+
image = sharp::StaySequential(image, baton->tileAngle != 0);
|
|
982
1010
|
vips::VOption *options = BuildOptionsDZ(baton);
|
|
983
1011
|
VipsArea *area = reinterpret_cast<VipsArea*>(image.dzsave_buffer(options));
|
|
984
1012
|
baton->bufferOut = static_cast<char*>(area->data);
|
|
@@ -991,7 +1019,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
991
1019
|
// Write JXL to buffer
|
|
992
1020
|
image = sharp::RemoveAnimationProperties(image);
|
|
993
1021
|
VipsArea *area = reinterpret_cast<VipsArea*>(image.jxlsave_buffer(VImage::option()
|
|
994
|
-
->set("
|
|
1022
|
+
->set("keep", baton->keepMetadata)
|
|
995
1023
|
->set("distance", baton->jxlDistance)
|
|
996
1024
|
->set("tier", baton->jxlDecodingTier)
|
|
997
1025
|
->set("effort", baton->jxlEffort)
|
|
@@ -1052,7 +1080,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1052
1080
|
// Write JPEG to file
|
|
1053
1081
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::JPEG);
|
|
1054
1082
|
image.jpegsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
|
1055
|
-
->set("
|
|
1083
|
+
->set("keep", baton->keepMetadata)
|
|
1056
1084
|
->set("Q", baton->jpegQuality)
|
|
1057
1085
|
->set("interlace", baton->jpegProgressive)
|
|
1058
1086
|
->set("subsample_mode", baton->jpegChromaSubsampling == "4:4:4"
|
|
@@ -1082,7 +1110,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1082
1110
|
// Write PNG to file
|
|
1083
1111
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::PNG);
|
|
1084
1112
|
image.pngsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
|
1085
|
-
->set("
|
|
1113
|
+
->set("keep", baton->keepMetadata)
|
|
1086
1114
|
->set("interlace", baton->pngProgressive)
|
|
1087
1115
|
->set("compression", baton->pngCompressionLevel)
|
|
1088
1116
|
->set("filter", baton->pngAdaptiveFiltering ? VIPS_FOREIGN_PNG_FILTER_ALL : VIPS_FOREIGN_PNG_FILTER_NONE)
|
|
@@ -1097,7 +1125,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1097
1125
|
// Write WEBP to file
|
|
1098
1126
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::WEBP);
|
|
1099
1127
|
image.webpsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
|
1100
|
-
->set("
|
|
1128
|
+
->set("keep", baton->keepMetadata)
|
|
1101
1129
|
->set("Q", baton->webpQuality)
|
|
1102
1130
|
->set("lossless", baton->webpLossless)
|
|
1103
1131
|
->set("near_lossless", baton->webpNearLossless)
|
|
@@ -1113,7 +1141,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1113
1141
|
// Write GIF to file
|
|
1114
1142
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::GIF);
|
|
1115
1143
|
image.gifsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
|
1116
|
-
->set("
|
|
1144
|
+
->set("keep", baton->keepMetadata)
|
|
1117
1145
|
->set("bitdepth", baton->gifBitdepth)
|
|
1118
1146
|
->set("effort", baton->gifEffort)
|
|
1119
1147
|
->set("reuse", baton->gifReuse)
|
|
@@ -1132,10 +1160,11 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1132
1160
|
image = image.cast(VIPS_FORMAT_FLOAT);
|
|
1133
1161
|
}
|
|
1134
1162
|
image.tiffsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
|
1135
|
-
->set("
|
|
1163
|
+
->set("keep", baton->keepMetadata)
|
|
1136
1164
|
->set("Q", baton->tiffQuality)
|
|
1137
1165
|
->set("bitdepth", baton->tiffBitdepth)
|
|
1138
1166
|
->set("compression", baton->tiffCompression)
|
|
1167
|
+
->set("miniswhite", baton->tiffMiniswhite)
|
|
1139
1168
|
->set("predictor", baton->tiffPredictor)
|
|
1140
1169
|
->set("pyramid", baton->tiffPyramid)
|
|
1141
1170
|
->set("tile", baton->tiffTile)
|
|
@@ -1151,11 +1180,11 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1151
1180
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::HEIF);
|
|
1152
1181
|
image = sharp::RemoveAnimationProperties(image).cast(VIPS_FORMAT_UCHAR);
|
|
1153
1182
|
image.heifsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
|
1154
|
-
->set("
|
|
1183
|
+
->set("keep", baton->keepMetadata)
|
|
1155
1184
|
->set("Q", baton->heifQuality)
|
|
1156
1185
|
->set("compression", baton->heifCompression)
|
|
1157
1186
|
->set("effort", baton->heifEffort)
|
|
1158
|
-
->set("bitdepth",
|
|
1187
|
+
->set("bitdepth", baton->heifBitdepth)
|
|
1159
1188
|
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
|
1160
1189
|
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
|
1161
1190
|
->set("lossless", baton->heifLossless));
|
|
@@ -1165,7 +1194,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1165
1194
|
// Write JXL to file
|
|
1166
1195
|
image = sharp::RemoveAnimationProperties(image);
|
|
1167
1196
|
image.jxlsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
|
1168
|
-
->set("
|
|
1197
|
+
->set("keep", baton->keepMetadata)
|
|
1169
1198
|
->set("distance", baton->jxlDistance)
|
|
1170
1199
|
->set("tier", baton->jxlDecodingTier)
|
|
1171
1200
|
->set("effort", baton->jxlEffort)
|
|
@@ -1179,7 +1208,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1179
1208
|
if (!sharp::HasAlpha(image)) {
|
|
1180
1209
|
baton->tileBackground.pop_back();
|
|
1181
1210
|
}
|
|
1182
|
-
image = sharp::StaySequential(image,
|
|
1211
|
+
image = sharp::StaySequential(image, baton->tileAngle != 0);
|
|
1183
1212
|
vips::VOption *options = BuildOptionsDZ(baton);
|
|
1184
1213
|
image.dzsave(const_cast<char*>(baton->fileOut.data()), options);
|
|
1185
1214
|
baton->formatOut = "dz";
|
|
@@ -1187,7 +1216,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1187
1216
|
(willMatchInput && inputImageType == sharp::ImageType::VIPS)) {
|
|
1188
1217
|
// Write V to file
|
|
1189
1218
|
image.vipssave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
|
1190
|
-
->set("
|
|
1219
|
+
->set("keep", baton->keepMetadata));
|
|
1191
1220
|
baton->formatOut = "v";
|
|
1192
1221
|
} else {
|
|
1193
1222
|
// Unsupported output format
|
|
@@ -1215,7 +1244,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1215
1244
|
// Handle warnings
|
|
1216
1245
|
std::string warning = sharp::VipsWarningPop();
|
|
1217
1246
|
while (!warning.empty()) {
|
|
1218
|
-
debuglog.
|
|
1247
|
+
debuglog.Call(Receiver().Value(), { Napi::String::New(env, warning) });
|
|
1219
1248
|
warning = sharp::VipsWarningPop();
|
|
1220
1249
|
}
|
|
1221
1250
|
|
|
@@ -1248,11 +1277,10 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1248
1277
|
info.Set("attentionX", static_cast<int32_t>(baton->attentionX));
|
|
1249
1278
|
info.Set("attentionY", static_cast<int32_t>(baton->attentionY));
|
|
1250
1279
|
}
|
|
1251
|
-
if (baton->trimThreshold
|
|
1280
|
+
if (baton->trimThreshold >= 0.0) {
|
|
1252
1281
|
info.Set("trimOffsetLeft", static_cast<int32_t>(baton->trimOffsetLeft));
|
|
1253
1282
|
info.Set("trimOffsetTop", static_cast<int32_t>(baton->trimOffsetTop));
|
|
1254
1283
|
}
|
|
1255
|
-
|
|
1256
1284
|
if (baton->input->textAutofitDpi) {
|
|
1257
1285
|
info.Set("textAutofitDpi", static_cast<uint32_t>(baton->input->textAutofitDpi));
|
|
1258
1286
|
}
|
|
@@ -1263,17 +1291,17 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1263
1291
|
// Pass ownership of output data to Buffer instance
|
|
1264
1292
|
Napi::Buffer<char> data = Napi::Buffer<char>::NewOrCopy(env, static_cast<char*>(baton->bufferOut),
|
|
1265
1293
|
baton->bufferOutLength, sharp::FreeCallback);
|
|
1266
|
-
Callback().
|
|
1294
|
+
Callback().Call(Receiver().Value(), { env.Null(), data, info });
|
|
1267
1295
|
} else {
|
|
1268
1296
|
// Add file size to info
|
|
1269
1297
|
struct STAT64_STRUCT st;
|
|
1270
1298
|
if (STAT64_FUNCTION(baton->fileOut.data(), &st) == 0) {
|
|
1271
1299
|
info.Set("size", static_cast<uint32_t>(st.st_size));
|
|
1272
1300
|
}
|
|
1273
|
-
Callback().
|
|
1301
|
+
Callback().Call(Receiver().Value(), { env.Null(), info });
|
|
1274
1302
|
}
|
|
1275
1303
|
} else {
|
|
1276
|
-
Callback().
|
|
1304
|
+
Callback().Call(Receiver().Value(), { Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
|
|
1277
1305
|
}
|
|
1278
1306
|
|
|
1279
1307
|
// Delete baton
|
|
@@ -1289,9 +1317,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1289
1317
|
delete baton;
|
|
1290
1318
|
|
|
1291
1319
|
// Decrement processing task counter
|
|
1292
|
-
|
|
1293
|
-
Napi::Number queueLength = Napi::Number::New(env, static_cast<
|
|
1294
|
-
queueListener.
|
|
1320
|
+
sharp::counterProcess--;
|
|
1321
|
+
Napi::Number queueLength = Napi::Number::New(env, static_cast<int>(sharp::counterQueue));
|
|
1322
|
+
queueListener.Call(Receiver().Value(), { queueLength });
|
|
1295
1323
|
}
|
|
1296
1324
|
|
|
1297
1325
|
private:
|
|
@@ -1312,16 +1340,16 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1312
1340
|
std::tuple<VipsAngle, bool, bool>
|
|
1313
1341
|
CalculateExifRotationAndFlip(int const exifOrientation) {
|
|
1314
1342
|
VipsAngle rotate = VIPS_ANGLE_D0;
|
|
1315
|
-
bool flip =
|
|
1316
|
-
bool flop =
|
|
1343
|
+
bool flip = false;
|
|
1344
|
+
bool flop = false;
|
|
1317
1345
|
switch (exifOrientation) {
|
|
1318
1346
|
case 6: rotate = VIPS_ANGLE_D90; break;
|
|
1319
1347
|
case 3: rotate = VIPS_ANGLE_D180; break;
|
|
1320
1348
|
case 8: rotate = VIPS_ANGLE_D270; break;
|
|
1321
|
-
case 2: flop =
|
|
1322
|
-
case 7: flip =
|
|
1323
|
-
case 4: flop =
|
|
1324
|
-
case 5: flip =
|
|
1349
|
+
case 2: flop = true; break; // flop 1
|
|
1350
|
+
case 7: flip = true; rotate = VIPS_ANGLE_D90; break; // flip 6
|
|
1351
|
+
case 4: flop = true; rotate = VIPS_ANGLE_D180; break; // flop 3
|
|
1352
|
+
case 5: flip = true; rotate = VIPS_ANGLE_D270; break; // flip 8
|
|
1325
1353
|
}
|
|
1326
1354
|
return std::make_tuple(rotate, flip, flop);
|
|
1327
1355
|
}
|
|
@@ -1369,7 +1397,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1369
1397
|
std::string suffix;
|
|
1370
1398
|
if (baton->tileFormat == "png") {
|
|
1371
1399
|
std::vector<std::pair<std::string, std::string>> options {
|
|
1372
|
-
{"interlace", baton->pngProgressive ? "
|
|
1400
|
+
{"interlace", baton->pngProgressive ? "true" : "false"},
|
|
1373
1401
|
{"compression", std::to_string(baton->pngCompressionLevel)},
|
|
1374
1402
|
{"filter", baton->pngAdaptiveFiltering ? "all" : "none"}
|
|
1375
1403
|
};
|
|
@@ -1378,31 +1406,31 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1378
1406
|
std::vector<std::pair<std::string, std::string>> options {
|
|
1379
1407
|
{"Q", std::to_string(baton->webpQuality)},
|
|
1380
1408
|
{"alpha_q", std::to_string(baton->webpAlphaQuality)},
|
|
1381
|
-
{"lossless", baton->webpLossless ? "
|
|
1382
|
-
{"near_lossless", baton->webpNearLossless ? "
|
|
1383
|
-
{"smart_subsample", baton->webpSmartSubsample ? "
|
|
1409
|
+
{"lossless", baton->webpLossless ? "true" : "false"},
|
|
1410
|
+
{"near_lossless", baton->webpNearLossless ? "true" : "false"},
|
|
1411
|
+
{"smart_subsample", baton->webpSmartSubsample ? "true" : "false"},
|
|
1384
1412
|
{"preset", vips_enum_nick(VIPS_TYPE_FOREIGN_WEBP_PRESET, baton->webpPreset)},
|
|
1385
|
-
{"min_size", baton->webpMinSize ? "
|
|
1386
|
-
{"mixed", baton->webpMixed ? "
|
|
1413
|
+
{"min_size", baton->webpMinSize ? "true" : "false"},
|
|
1414
|
+
{"mixed", baton->webpMixed ? "true" : "false"},
|
|
1387
1415
|
{"effort", std::to_string(baton->webpEffort)}
|
|
1388
1416
|
};
|
|
1389
1417
|
suffix = AssembleSuffixString(".webp", options);
|
|
1390
1418
|
} else {
|
|
1391
1419
|
std::vector<std::pair<std::string, std::string>> options {
|
|
1392
1420
|
{"Q", std::to_string(baton->jpegQuality)},
|
|
1393
|
-
{"interlace", baton->jpegProgressive ? "
|
|
1421
|
+
{"interlace", baton->jpegProgressive ? "true" : "false"},
|
|
1394
1422
|
{"subsample_mode", baton->jpegChromaSubsampling == "4:4:4" ? "off" : "on"},
|
|
1395
|
-
{"trellis_quant", baton->jpegTrellisQuantisation ? "
|
|
1423
|
+
{"trellis_quant", baton->jpegTrellisQuantisation ? "true" : "false"},
|
|
1396
1424
|
{"quant_table", std::to_string(baton->jpegQuantisationTable)},
|
|
1397
|
-
{"overshoot_deringing", baton->jpegOvershootDeringing ? "
|
|
1398
|
-
{"optimize_scans", baton->jpegOptimiseScans ? "
|
|
1399
|
-
{"optimize_coding", baton->jpegOptimiseCoding ? "
|
|
1425
|
+
{"overshoot_deringing", baton->jpegOvershootDeringing ? "true": "false"},
|
|
1426
|
+
{"optimize_scans", baton->jpegOptimiseScans ? "true": "false"},
|
|
1427
|
+
{"optimize_coding", baton->jpegOptimiseCoding ? "true": "false"}
|
|
1400
1428
|
};
|
|
1401
1429
|
std::string extname = baton->tileLayout == VIPS_FOREIGN_DZ_LAYOUT_DZ ? ".jpeg" : ".jpg";
|
|
1402
1430
|
suffix = AssembleSuffixString(extname, options);
|
|
1403
1431
|
}
|
|
1404
1432
|
vips::VOption *options = VImage::option()
|
|
1405
|
-
->set("
|
|
1433
|
+
->set("keep", baton->keepMetadata)
|
|
1406
1434
|
->set("tile_size", baton->tileSize)
|
|
1407
1435
|
->set("overlap", baton->tileOverlap)
|
|
1408
1436
|
->set("container", baton->tileContainer)
|
|
@@ -1519,6 +1547,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1519
1547
|
baton->thresholdGrayscale = sharp::AttrAsBool(options, "thresholdGrayscale");
|
|
1520
1548
|
baton->trimBackground = sharp::AttrAsVectorOfDouble(options, "trimBackground");
|
|
1521
1549
|
baton->trimThreshold = sharp::AttrAsDouble(options, "trimThreshold");
|
|
1550
|
+
baton->trimLineArt = sharp::AttrAsBool(options, "trimLineArt");
|
|
1522
1551
|
baton->gamma = sharp::AttrAsDouble(options, "gamma");
|
|
1523
1552
|
baton->gammaOut = sharp::AttrAsDouble(options, "gammaOut");
|
|
1524
1553
|
baton->linearA = sharp::AttrAsVectorOfDouble(options, "linearA");
|
|
@@ -1527,8 +1556,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1527
1556
|
baton->normalise = sharp::AttrAsBool(options, "normalise");
|
|
1528
1557
|
baton->normaliseLower = sharp::AttrAsUint32(options, "normaliseLower");
|
|
1529
1558
|
baton->normaliseUpper = sharp::AttrAsUint32(options, "normaliseUpper");
|
|
1530
|
-
baton->
|
|
1531
|
-
baton->tintB = sharp::AttrAsDouble(options, "tintB");
|
|
1559
|
+
baton->tint = sharp::AttrAsVectorOfDouble(options, "tint");
|
|
1532
1560
|
baton->claheWidth = sharp::AttrAsUint32(options, "claheWidth");
|
|
1533
1561
|
baton->claheHeight = sharp::AttrAsUint32(options, "claheHeight");
|
|
1534
1562
|
baton->claheMaxSlope = sharp::AttrAsUint32(options, "claheMaxSlope");
|
|
@@ -1582,10 +1610,10 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1582
1610
|
baton->recombMatrix[i] = sharp::AttrAsDouble(recombMatrix, i);
|
|
1583
1611
|
}
|
|
1584
1612
|
}
|
|
1585
|
-
baton->
|
|
1586
|
-
options, "
|
|
1587
|
-
if (baton->
|
|
1588
|
-
baton->
|
|
1613
|
+
baton->colourspacePipeline = sharp::AttrAsEnum<VipsInterpretation>(
|
|
1614
|
+
options, "colourspacePipeline", VIPS_TYPE_INTERPRETATION);
|
|
1615
|
+
if (baton->colourspacePipeline == VIPS_INTERPRETATION_ERROR) {
|
|
1616
|
+
baton->colourspacePipeline = VIPS_INTERPRETATION_LAST;
|
|
1589
1617
|
}
|
|
1590
1618
|
baton->colourspace = sharp::AttrAsEnum<VipsInterpretation>(options, "colourspace", VIPS_TYPE_INTERPRETATION);
|
|
1591
1619
|
if (baton->colourspace == VIPS_INTERPRETATION_ERROR) {
|
|
@@ -1594,18 +1622,19 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1594
1622
|
// Output
|
|
1595
1623
|
baton->formatOut = sharp::AttrAsStr(options, "formatOut");
|
|
1596
1624
|
baton->fileOut = sharp::AttrAsStr(options, "fileOut");
|
|
1597
|
-
baton->
|
|
1625
|
+
baton->keepMetadata = sharp::AttrAsUint32(options, "keepMetadata");
|
|
1598
1626
|
baton->withMetadataOrientation = sharp::AttrAsUint32(options, "withMetadataOrientation");
|
|
1599
1627
|
baton->withMetadataDensity = sharp::AttrAsDouble(options, "withMetadataDensity");
|
|
1600
|
-
baton->
|
|
1601
|
-
Napi::Object
|
|
1602
|
-
Napi::Array
|
|
1603
|
-
for (unsigned int i = 0; i <
|
|
1604
|
-
std::string k = sharp::AttrAsStr(
|
|
1605
|
-
if (
|
|
1606
|
-
baton->
|
|
1628
|
+
baton->withIccProfile = sharp::AttrAsStr(options, "withIccProfile");
|
|
1629
|
+
Napi::Object withExif = options.Get("withExif").As<Napi::Object>();
|
|
1630
|
+
Napi::Array withExifKeys = withExif.GetPropertyNames();
|
|
1631
|
+
for (unsigned int i = 0; i < withExifKeys.Length(); i++) {
|
|
1632
|
+
std::string k = sharp::AttrAsStr(withExifKeys, i);
|
|
1633
|
+
if (withExif.HasOwnProperty(k)) {
|
|
1634
|
+
baton->withExif.insert(std::make_pair(k, sharp::AttrAsStr(withExif, k)));
|
|
1607
1635
|
}
|
|
1608
1636
|
}
|
|
1637
|
+
baton->withExifMerge = sharp::AttrAsBool(options, "withExifMerge");
|
|
1609
1638
|
baton->timeoutSeconds = sharp::AttrAsUint32(options, "timeoutSeconds");
|
|
1610
1639
|
// Format-specific
|
|
1611
1640
|
baton->jpegQuality = sharp::AttrAsUint32(options, "jpegQuality");
|
|
@@ -1647,6 +1676,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1647
1676
|
baton->gifProgressive = sharp::AttrAsBool(options, "gifProgressive");
|
|
1648
1677
|
baton->tiffQuality = sharp::AttrAsUint32(options, "tiffQuality");
|
|
1649
1678
|
baton->tiffPyramid = sharp::AttrAsBool(options, "tiffPyramid");
|
|
1679
|
+
baton->tiffMiniswhite = sharp::AttrAsBool(options, "tiffMiniswhite");
|
|
1650
1680
|
baton->tiffBitdepth = sharp::AttrAsUint32(options, "tiffBitdepth");
|
|
1651
1681
|
baton->tiffTile = sharp::AttrAsBool(options, "tiffTile");
|
|
1652
1682
|
baton->tiffTileWidth = sharp::AttrAsUint32(options, "tiffTileWidth");
|
|
@@ -1668,6 +1698,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1668
1698
|
options, "heifCompression", VIPS_TYPE_FOREIGN_HEIF_COMPRESSION);
|
|
1669
1699
|
baton->heifEffort = sharp::AttrAsUint32(options, "heifEffort");
|
|
1670
1700
|
baton->heifChromaSubsampling = sharp::AttrAsStr(options, "heifChromaSubsampling");
|
|
1701
|
+
baton->heifBitdepth = sharp::AttrAsUint32(options, "heifBitdepth");
|
|
1671
1702
|
baton->jxlDistance = sharp::AttrAsDouble(options, "jxlDistance");
|
|
1672
1703
|
baton->jxlDecodingTier = sharp::AttrAsUint32(options, "jxlDecodingTier");
|
|
1673
1704
|
baton->jxlEffort = sharp::AttrAsUint32(options, "jxlEffort");
|
|
@@ -1707,9 +1738,8 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1707
1738
|
worker->Queue();
|
|
1708
1739
|
|
|
1709
1740
|
// Increment queued task counter
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
queueListener.MakeCallback(info.This(), { queueLength });
|
|
1741
|
+
Napi::Number queueLength = Napi::Number::New(info.Env(), static_cast<int>(++sharp::counterQueue));
|
|
1742
|
+
queueListener.Call(info.This(), { queueLength });
|
|
1713
1743
|
|
|
1714
1744
|
return info.Env().Undefined();
|
|
1715
1745
|
}
|