@revizly/sharp 0.35.0-revizly4 → 0.35.0-revizly41
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 +12 -18
- package/{lib/channel.js → dist/channel.cjs} +1 -1
- package/dist/channel.mjs +177 -0
- package/{lib/colour.js → dist/colour.cjs} +11 -7
- package/dist/colour.mjs +199 -0
- package/{lib/composite.js → dist/composite.cjs} +2 -1
- package/dist/composite.mjs +213 -0
- package/{lib/constructor.js → dist/constructor.cjs} +42 -29
- package/dist/constructor.mjs +512 -0
- package/dist/index.cjs +25 -0
- package/dist/index.d.cts +2001 -0
- package/dist/index.d.mts +2048 -0
- package/dist/index.mjs +25 -0
- package/{lib/input.js → dist/input.cjs} +26 -21
- package/dist/input.mjs +814 -0
- package/{lib/is.js → dist/is.cjs} +1 -1
- package/dist/is.mjs +143 -0
- package/{lib/libvips.js → dist/libvips.cjs} +35 -30
- package/dist/libvips.mjs +212 -0
- package/{lib/operation.js → dist/operation.cjs} +33 -51
- package/dist/operation.mjs +998 -0
- package/{lib/output.js → dist/output.cjs} +161 -28
- package/dist/output.mjs +1799 -0
- package/{lib/resize.js → dist/resize.cjs} +46 -24
- package/dist/resize.mjs +617 -0
- package/dist/sharp.cjs +125 -0
- package/dist/sharp.mjs +125 -0
- package/{lib/utility.js → dist/utility.cjs} +18 -8
- package/dist/utility.mjs +301 -0
- package/install/build.js +3 -3
- package/lib/index.d.ts +105 -75
- package/package.json +46 -27
- package/src/binding.gyp +18 -13
- package/src/common.cc +70 -17
- package/src/common.h +22 -3
- package/src/metadata.cc +66 -8
- package/src/metadata.h +6 -1
- package/src/operations.cc +25 -8
- package/src/operations.h +1 -1
- package/src/pipeline.cc +206 -69
- package/src/pipeline.h +16 -1
- package/src/stats.cc +6 -6
- package/src/utilities.cc +7 -6
- package/install/check.js +0 -14
- package/lib/index.js +0 -16
- package/lib/sharp.js +0 -121
package/src/pipeline.cc
CHANGED
|
@@ -84,7 +84,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
84
84
|
if (nPages == -1) {
|
|
85
85
|
// Resolve the number of pages if we need to render until the end of the document
|
|
86
86
|
nPages = image.get_typeof(VIPS_META_N_PAGES) != 0
|
|
87
|
-
? image.get_int(VIPS_META_N_PAGES) - baton->input->page
|
|
87
|
+
? image.get_int(VIPS_META_N_PAGES) - std::max(0, baton->input->page)
|
|
88
88
|
: 1;
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -153,7 +153,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
153
153
|
if (baton->trimThreshold >= 0.0) {
|
|
154
154
|
MultiPageUnsupported(nPages, "Trim");
|
|
155
155
|
image = sharp::StaySequential(image);
|
|
156
|
-
image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold, baton->trimLineArt);
|
|
156
|
+
image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold, baton->trimLineArt, baton->trimMargin);
|
|
157
157
|
baton->trimOffsetLeft = image.xoffset();
|
|
158
158
|
baton->trimOffsetTop = image.yoffset();
|
|
159
159
|
}
|
|
@@ -203,9 +203,11 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
203
203
|
// - the width or height parameters are specified;
|
|
204
204
|
// - gamma correction doesn't need to be applied;
|
|
205
205
|
// - trimming or pre-resize extract isn't required;
|
|
206
|
+
// - gain map processing is not required;
|
|
206
207
|
// - input colourspace is not specified;
|
|
207
208
|
bool const shouldPreShrink = (targetResizeWidth > 0 || targetResizeHeight > 0) &&
|
|
208
209
|
baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold < 0.0 &&
|
|
210
|
+
!baton->keepGainMap && !baton->withGainMap &&
|
|
209
211
|
baton->colourspacePipeline == VIPS_INTERPRETATION_LAST && !(shouldOrientBefore || shouldRotateBefore);
|
|
210
212
|
|
|
211
213
|
if (shouldPreShrink) {
|
|
@@ -274,7 +276,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
274
276
|
}
|
|
275
277
|
sharp::SetDensity(image, baton->input->density);
|
|
276
278
|
if (image.width() > 32767 || image.height() > 32767) {
|
|
277
|
-
throw
|
|
279
|
+
throw std::runtime_error("Input SVG image will exceed 32767x32767 pixel limit when scaled");
|
|
278
280
|
}
|
|
279
281
|
} else if (inputImageType == sharp::ImageType::PDF) {
|
|
280
282
|
if (baton->input->buffer != nullptr) {
|
|
@@ -290,12 +292,28 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
290
292
|
}
|
|
291
293
|
} else {
|
|
292
294
|
if (inputImageType == sharp::ImageType::SVG && (image.width() > 32767 || image.height() > 32767)) {
|
|
293
|
-
throw
|
|
295
|
+
throw std::runtime_error("Input SVG image exceeds 32767x32767 pixel limit");
|
|
294
296
|
}
|
|
295
297
|
}
|
|
296
298
|
if (baton->input->autoOrient) {
|
|
297
299
|
image = sharp::RemoveExifOrientation(image);
|
|
298
300
|
}
|
|
301
|
+
VImage gainMap;
|
|
302
|
+
int gainMapScaleFactor = 1;
|
|
303
|
+
if (sharp::HasGainMap(image)) {
|
|
304
|
+
if (baton->keepGainMap) {
|
|
305
|
+
gainMap = image.gainmap();
|
|
306
|
+
if (image.get_typeof("gainmap-scale-factor") == G_TYPE_INT) {
|
|
307
|
+
gainMapScaleFactor = image.get_int("gainmap-scale-factor");
|
|
308
|
+
}
|
|
309
|
+
} else if (baton->withGainMap) {
|
|
310
|
+
image = image.uhdr2scRGB();
|
|
311
|
+
}
|
|
312
|
+
image = sharp::RemoveGainMap(image);
|
|
313
|
+
} else {
|
|
314
|
+
baton->keepGainMap = false;
|
|
315
|
+
baton->withGainMap = false;
|
|
316
|
+
}
|
|
299
317
|
|
|
300
318
|
// Any pre-shrinking may already have been done
|
|
301
319
|
inputWidth = image.width();
|
|
@@ -335,7 +353,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
335
353
|
image.interpretation() != VIPS_INTERPRETATION_LABS &&
|
|
336
354
|
image.interpretation() != VIPS_INTERPRETATION_GREY16 &&
|
|
337
355
|
baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK &&
|
|
338
|
-
!baton->input->ignoreIcc
|
|
356
|
+
!baton->input->ignoreIcc && !baton->withGainMap
|
|
339
357
|
) {
|
|
340
358
|
// Convert to sRGB/P3 using embedded profile
|
|
341
359
|
try {
|
|
@@ -393,6 +411,11 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
393
411
|
image = image.resize(1.0 / hshrink, VImage::option()
|
|
394
412
|
->set("vscale", 1.0 / vshrink)
|
|
395
413
|
->set("kernel", baton->kernel));
|
|
414
|
+
if (baton->keepGainMap) {
|
|
415
|
+
gainMap = gainMap.resize(1.0 / hshrink, VImage::option()
|
|
416
|
+
->set("vscale", 1.0 / vshrink)
|
|
417
|
+
->set("kernel", baton->kernel));
|
|
418
|
+
}
|
|
396
419
|
}
|
|
397
420
|
|
|
398
421
|
image = sharp::StaySequential(image,
|
|
@@ -405,14 +428,23 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
405
428
|
MultiPageUnsupported(nPages, "Rotate");
|
|
406
429
|
}
|
|
407
430
|
image = image.rot(autoRotation);
|
|
431
|
+
if (baton->keepGainMap) {
|
|
432
|
+
gainMap = gainMap.rot(autoRotation);
|
|
433
|
+
}
|
|
408
434
|
}
|
|
409
435
|
// Mirror vertically (up-down) about the x-axis
|
|
410
436
|
if (baton->flip) {
|
|
411
437
|
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
|
438
|
+
if (baton->keepGainMap) {
|
|
439
|
+
gainMap = gainMap.flip(VIPS_DIRECTION_VERTICAL);
|
|
440
|
+
}
|
|
412
441
|
}
|
|
413
442
|
// Mirror horizontally (left-right) about the y-axis
|
|
414
443
|
if (baton->flop != autoFlop) {
|
|
415
444
|
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
|
445
|
+
if (baton->keepGainMap) {
|
|
446
|
+
gainMap = gainMap.flip(VIPS_DIRECTION_HORIZONTAL);
|
|
447
|
+
}
|
|
416
448
|
}
|
|
417
449
|
// Rotate post-extract 90-angle
|
|
418
450
|
if (rotation != VIPS_ANGLE_D0) {
|
|
@@ -420,6 +452,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
420
452
|
MultiPageUnsupported(nPages, "Rotate");
|
|
421
453
|
}
|
|
422
454
|
image = image.rot(rotation);
|
|
455
|
+
if (baton->keepGainMap) {
|
|
456
|
+
gainMap = gainMap.rot(rotation);
|
|
457
|
+
}
|
|
423
458
|
}
|
|
424
459
|
|
|
425
460
|
// Join additional color channels to the image
|
|
@@ -466,6 +501,12 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
466
501
|
: image.embed(left, top, width, height, VImage::option()
|
|
467
502
|
->set("extend", VIPS_EXTEND_BACKGROUND)
|
|
468
503
|
->set("background", background));
|
|
504
|
+
if (baton->keepGainMap) {
|
|
505
|
+
gainMap = gainMap.embed(left / gainMapScaleFactor, top / gainMapScaleFactor,
|
|
506
|
+
width / gainMapScaleFactor, height / gainMapScaleFactor, VImage::option()
|
|
507
|
+
->set("extend", VIPS_EXTEND_BACKGROUND)
|
|
508
|
+
->set("background", 0));
|
|
509
|
+
}
|
|
469
510
|
} else if (baton->canvas == sharp::Canvas::CROP) {
|
|
470
511
|
if (baton->width > inputWidth) {
|
|
471
512
|
baton->width = inputWidth;
|
|
@@ -486,12 +527,17 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
486
527
|
? sharp::CropMultiPage(image,
|
|
487
528
|
left, top, width, height, nPages, &targetPageHeight)
|
|
488
529
|
: image.extract_area(left, top, width, height);
|
|
530
|
+
if (baton->keepGainMap) {
|
|
531
|
+
gainMap = gainMap.extract_area(left / gainMapScaleFactor, top / gainMapScaleFactor,
|
|
532
|
+
width / gainMapScaleFactor, height / gainMapScaleFactor);
|
|
533
|
+
}
|
|
489
534
|
} else {
|
|
490
535
|
int attention_x;
|
|
491
536
|
int attention_y;
|
|
492
537
|
|
|
493
538
|
// Attention-based or Entropy-based crop
|
|
494
539
|
MultiPageUnsupported(nPages, "Resize strategy");
|
|
540
|
+
KeepGainMapUnsupported(baton->keepGainMap, "Resize strategy");
|
|
495
541
|
image = sharp::StaySequential(image);
|
|
496
542
|
image = image.smartcrop(baton->width, baton->height, VImage::option()
|
|
497
543
|
->set("interesting", baton->position == 16 ? VIPS_INTERESTING_ENTROPY : VIPS_INTERESTING_ATTENTION)
|
|
@@ -515,6 +561,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
515
561
|
std::vector<double> background;
|
|
516
562
|
std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground, shouldPremultiplyAlpha);
|
|
517
563
|
image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background));
|
|
564
|
+
if (baton->keepGainMap) {
|
|
565
|
+
gainMap = gainMap.rotate(baton->rotationAngle, VImage::option()->set("background", 0));
|
|
566
|
+
}
|
|
518
567
|
}
|
|
519
568
|
|
|
520
569
|
// Post extraction
|
|
@@ -523,18 +572,23 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
523
572
|
image = sharp::CropMultiPage(image,
|
|
524
573
|
baton->leftOffsetPost, baton->topOffsetPost, baton->widthPost, baton->heightPost,
|
|
525
574
|
nPages, &targetPageHeight);
|
|
526
|
-
|
|
527
575
|
// heightPost is used in the info object, so update to reflect the number of pages
|
|
528
576
|
baton->heightPost *= nPages;
|
|
529
577
|
} else {
|
|
530
578
|
image = image.extract_area(
|
|
531
579
|
baton->leftOffsetPost, baton->topOffsetPost, baton->widthPost, baton->heightPost);
|
|
580
|
+
if (baton->keepGainMap) {
|
|
581
|
+
gainMap = gainMap.extract_area(baton->leftOffsetPost / gainMapScaleFactor,
|
|
582
|
+
baton->topOffsetPost / gainMapScaleFactor, baton->widthPost / gainMapScaleFactor,
|
|
583
|
+
baton->heightPost / gainMapScaleFactor);
|
|
584
|
+
}
|
|
532
585
|
}
|
|
533
586
|
}
|
|
534
587
|
|
|
535
588
|
// Affine transform
|
|
536
589
|
if (!baton->affineMatrix.empty()) {
|
|
537
590
|
MultiPageUnsupported(nPages, "Affine");
|
|
591
|
+
KeepGainMapUnsupported(baton->keepGainMap, "Affine");
|
|
538
592
|
image = sharp::StaySequential(image);
|
|
539
593
|
std::vector<double> background;
|
|
540
594
|
std::tie(image, background) = sharp::ApplyAlpha(image, baton->affineBackground, shouldPremultiplyAlpha);
|
|
@@ -554,26 +608,25 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
554
608
|
baton->width = image.width() + baton->extendLeft + baton->extendRight;
|
|
555
609
|
baton->height = (nPages > 1 ? targetPageHeight : image.height()) + baton->extendTop + baton->extendBottom;
|
|
556
610
|
|
|
611
|
+
std::vector<double> background;
|
|
557
612
|
if (baton->extendWith == VIPS_EXTEND_BACKGROUND) {
|
|
558
|
-
std::vector<double> background;
|
|
559
613
|
std::tie(image, background) = sharp::ApplyAlpha(image, baton->extendBackground, shouldPremultiplyAlpha);
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
image
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
VImage::option()->set("extend", baton->extendWith));
|
|
614
|
+
}
|
|
615
|
+
image = sharp::StaySequential(image, nPages > 1 || baton->extendWith != VIPS_EXTEND_BACKGROUND);
|
|
616
|
+
auto options = VImage::option()->set("extend", baton->extendWith);
|
|
617
|
+
if (baton->extendWith == VIPS_EXTEND_BACKGROUND) {
|
|
618
|
+
options->set("background", background);
|
|
619
|
+
}
|
|
620
|
+
image = nPages > 1
|
|
621
|
+
? sharp::EmbedMultiPage(image,
|
|
622
|
+
baton->extendLeft, baton->extendTop, baton->width, baton->height,
|
|
623
|
+
baton->extendWith, background, nPages, &targetPageHeight)
|
|
624
|
+
: image.embed(baton->extendLeft, baton->extendTop, baton->width, baton->height, options);
|
|
625
|
+
if (baton->keepGainMap) {
|
|
626
|
+
gainMap = gainMap.embed(baton->extendLeft / gainMapScaleFactor, baton->extendTop / gainMapScaleFactor,
|
|
627
|
+
baton->width / gainMapScaleFactor, baton->height / gainMapScaleFactor, VImage::option()
|
|
628
|
+
->set("extend", baton->extendWith)
|
|
629
|
+
->set("background", 0));
|
|
577
630
|
}
|
|
578
631
|
}
|
|
579
632
|
// Median - must happen before blurring, due to the utility of blurring after thresholding
|
|
@@ -600,6 +653,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
600
653
|
// Blur
|
|
601
654
|
if (shouldBlur) {
|
|
602
655
|
image = sharp::Blur(image, baton->blurSigma, baton->precision, baton->minAmpl);
|
|
656
|
+
if (baton->keepGainMap) {
|
|
657
|
+
gainMap = sharp::Blur(gainMap, baton->blurSigma, baton->precision, baton->minAmpl);
|
|
658
|
+
}
|
|
603
659
|
}
|
|
604
660
|
|
|
605
661
|
// Unflatten the image
|
|
@@ -609,6 +665,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
609
665
|
|
|
610
666
|
// Convolve
|
|
611
667
|
if (shouldConv) {
|
|
668
|
+
KeepGainMapUnsupported(baton->keepGainMap, "Convolve");
|
|
612
669
|
image = sharp::Convolve(image,
|
|
613
670
|
baton->convKernelWidth, baton->convKernelHeight,
|
|
614
671
|
baton->convKernelScale, baton->convKernelOffset,
|
|
@@ -617,11 +674,13 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
617
674
|
|
|
618
675
|
// Recomb
|
|
619
676
|
if (!baton->recombMatrix.empty()) {
|
|
677
|
+
KeepGainMapUnsupported(baton->keepGainMap, "Recomb");
|
|
620
678
|
image = sharp::Recomb(image, baton->recombMatrix);
|
|
621
679
|
}
|
|
622
680
|
|
|
623
681
|
// Modulate
|
|
624
682
|
if (baton->brightness != 1.0 || baton->saturation != 1.0 || baton->hue != 0.0 || baton->lightness != 0.0) {
|
|
683
|
+
KeepGainMapUnsupported(baton->keepGainMap, "Modulate");
|
|
625
684
|
image = sharp::Modulate(image, baton->brightness, baton->saturation, baton->hue, baton->lightness);
|
|
626
685
|
}
|
|
627
686
|
|
|
@@ -639,6 +698,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
639
698
|
|
|
640
699
|
// Composite
|
|
641
700
|
if (shouldComposite) {
|
|
701
|
+
KeepGainMapUnsupported(baton->keepGainMap, "Composite");
|
|
642
702
|
std::vector<VImage> images = { image };
|
|
643
703
|
std::vector<int> modes, xs, ys;
|
|
644
704
|
for (Composite *composite : baton->composite) {
|
|
@@ -667,7 +727,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
667
727
|
|
|
668
728
|
// Verify within current dimensions
|
|
669
729
|
if (compositeImage.width() > image.width() || compositeImage.height() > image.height()) {
|
|
670
|
-
throw
|
|
730
|
+
throw std::runtime_error("Image to composite must have same dimensions or smaller");
|
|
671
731
|
}
|
|
672
732
|
// Check if overlay is tiled
|
|
673
733
|
if (composite->tile) {
|
|
@@ -751,18 +811,21 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
751
811
|
|
|
752
812
|
// Apply normalisation - stretch luminance to cover full dynamic range
|
|
753
813
|
if (baton->normalise) {
|
|
814
|
+
KeepGainMapUnsupported(baton->keepGainMap, "Normalise");
|
|
754
815
|
image = sharp::StaySequential(image);
|
|
755
816
|
image = sharp::Normalise(image, baton->normaliseLower, baton->normaliseUpper);
|
|
756
817
|
}
|
|
757
818
|
|
|
758
819
|
// Apply contrast limiting adaptive histogram equalization (CLAHE)
|
|
759
820
|
if (baton->claheWidth != 0 && baton->claheHeight != 0) {
|
|
821
|
+
KeepGainMapUnsupported(baton->keepGainMap, "Clahe");
|
|
760
822
|
image = sharp::StaySequential(image);
|
|
761
823
|
image = sharp::Clahe(image, baton->claheWidth, baton->claheHeight, baton->claheMaxSlope);
|
|
762
824
|
}
|
|
763
825
|
|
|
764
826
|
// Apply bitwise boolean operation between images
|
|
765
827
|
if (baton->boolean != nullptr) {
|
|
828
|
+
KeepGainMapUnsupported(baton->keepGainMap, "Boolean");
|
|
766
829
|
VImage booleanImage;
|
|
767
830
|
sharp::ImageType booleanImageType = sharp::ImageType::UNKNOWN;
|
|
768
831
|
baton->boolean->access = access;
|
|
@@ -805,6 +868,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
805
868
|
|
|
806
869
|
// Extract channel
|
|
807
870
|
if (baton->extractChannel > -1) {
|
|
871
|
+
KeepGainMapUnsupported(baton->keepGainMap, "Extract channel");
|
|
808
872
|
if (baton->extractChannel >= image.bands()) {
|
|
809
873
|
if (baton->extractChannel == 3 && image.has_alpha()) {
|
|
810
874
|
baton->extractChannel = image.bands() - 1;
|
|
@@ -839,6 +903,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
839
903
|
// Negate the colours in the image
|
|
840
904
|
if (baton->negate) {
|
|
841
905
|
image = sharp::Negate(image, baton->negateAlpha);
|
|
906
|
+
if (baton->keepGainMap) {
|
|
907
|
+
gainMap = sharp::Negate(gainMap, false);
|
|
908
|
+
}
|
|
842
909
|
}
|
|
843
910
|
|
|
844
911
|
// Override EXIF Orientation tag
|
|
@@ -877,6 +944,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
877
944
|
baton->pageHeightOut = image.get_int(VIPS_META_PAGE_HEIGHT);
|
|
878
945
|
baton->pagesOut = image.get_int(VIPS_META_N_PAGES);
|
|
879
946
|
}
|
|
947
|
+
baton->hasAlphaOut = image.has_alpha();
|
|
880
948
|
|
|
881
949
|
// Output
|
|
882
950
|
sharp::SetTimeout(image, baton->timeoutSeconds);
|
|
@@ -885,18 +953,27 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
885
953
|
if (baton->formatOut == "jpeg" || (baton->formatOut == "input" && inputImageType == sharp::ImageType::JPEG)) {
|
|
886
954
|
// Write JPEG to buffer
|
|
887
955
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::JPEG);
|
|
888
|
-
VipsArea *area
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
956
|
+
VipsArea *area;
|
|
957
|
+
if (baton->keepGainMap) {
|
|
958
|
+
image = ReattachGainMap(image, gainMap, baton);
|
|
959
|
+
area = reinterpret_cast<VipsArea*>(image.uhdrsave_buffer(VImage::option()
|
|
960
|
+
->set("keep", baton->keepMetadata)
|
|
961
|
+
->set("Q", baton->jpegQuality)
|
|
962
|
+
->set("gainmap_scale_factor", gainMapScaleFactor)));
|
|
963
|
+
} else {
|
|
964
|
+
area = reinterpret_cast<VipsArea*>(image.jpegsave_buffer(VImage::option()
|
|
965
|
+
->set("keep", baton->keepMetadata)
|
|
966
|
+
->set("Q", baton->jpegQuality)
|
|
967
|
+
->set("interlace", baton->jpegProgressive)
|
|
968
|
+
->set("subsample_mode", baton->jpegChromaSubsampling == "4:4:4"
|
|
969
|
+
? VIPS_FOREIGN_SUBSAMPLE_OFF
|
|
970
|
+
: VIPS_FOREIGN_SUBSAMPLE_ON)
|
|
971
|
+
->set("trellis_quant", baton->jpegTrellisQuantisation)
|
|
972
|
+
->set("quant_table", baton->jpegQuantisationTable)
|
|
973
|
+
->set("overshoot_deringing", baton->jpegOvershootDeringing)
|
|
974
|
+
->set("optimize_scans", baton->jpegOptimiseScans)
|
|
975
|
+
->set("optimize_coding", baton->jpegOptimiseCoding)));
|
|
976
|
+
}
|
|
900
977
|
baton->bufferOut = static_cast<char*>(area->data);
|
|
901
978
|
baton->bufferOutLength = area->length;
|
|
902
979
|
area->free_fn = nullptr;
|
|
@@ -907,6 +984,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
907
984
|
} else {
|
|
908
985
|
baton->channels = std::min(baton->channels, 3);
|
|
909
986
|
}
|
|
987
|
+
baton->hasAlphaOut = false;
|
|
910
988
|
} else if (baton->formatOut == "jp2" || (baton->formatOut == "input"
|
|
911
989
|
&& inputImageType == sharp::ImageType::JP2)) {
|
|
912
990
|
// Write JP2 to Buffer
|
|
@@ -957,6 +1035,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
957
1035
|
->set("effort", baton->webpEffort)
|
|
958
1036
|
->set("min_size", baton->webpMinSize)
|
|
959
1037
|
->set("mixed", baton->webpMixed)
|
|
1038
|
+
->set("exact", baton->webpExact)
|
|
960
1039
|
->set("alpha_q", baton->webpAlphaQuality)));
|
|
961
1040
|
baton->bufferOut = static_cast<char*>(area->data);
|
|
962
1041
|
baton->bufferOutLength = area->length;
|
|
@@ -988,6 +1067,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
988
1067
|
if (baton->tiffCompression == VIPS_FOREIGN_TIFF_COMPRESSION_JPEG) {
|
|
989
1068
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::JPEG);
|
|
990
1069
|
baton->channels = std::min(baton->channels, 3);
|
|
1070
|
+
baton->hasAlphaOut = false;
|
|
991
1071
|
}
|
|
992
1072
|
// Cast pixel values to float, if required
|
|
993
1073
|
if (baton->tiffPredictor == VIPS_FOREIGN_TIFF_PREDICTOR_FLOAT) {
|
|
@@ -1024,6 +1104,8 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1024
1104
|
->set("compression", baton->heifCompression)
|
|
1025
1105
|
->set("effort", baton->heifEffort)
|
|
1026
1106
|
->set("bitdepth", baton->heifBitdepth)
|
|
1107
|
+
->set("tune", baton->heifTune.c_str())
|
|
1108
|
+
->set("encoder", baton->heifEncoder.c_str())
|
|
1027
1109
|
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
|
1028
1110
|
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
|
1029
1111
|
->set("lossless", baton->heifLossless)));
|
|
@@ -1046,6 +1128,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1046
1128
|
area->free_fn = nullptr;
|
|
1047
1129
|
vips_area_unref(area);
|
|
1048
1130
|
baton->formatOut = "dz";
|
|
1131
|
+
if (baton->tileFormat == "jpeg") {
|
|
1132
|
+
baton->hasAlphaOut = false;
|
|
1133
|
+
}
|
|
1049
1134
|
} else if (baton->formatOut == "jxl" ||
|
|
1050
1135
|
(baton->formatOut == "input" && inputImageType == sharp::ImageType::JXL)) {
|
|
1051
1136
|
// Write JXL to buffer
|
|
@@ -1076,20 +1161,19 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1076
1161
|
// Get raw image data
|
|
1077
1162
|
baton->bufferOut = static_cast<char*>(image.write_to_memory(&baton->bufferOutLength));
|
|
1078
1163
|
if (baton->bufferOut == nullptr) {
|
|
1079
|
-
(
|
|
1080
|
-
return Error();
|
|
1164
|
+
throw std::runtime_error("Could not allocate enough memory for raw output");
|
|
1081
1165
|
}
|
|
1082
1166
|
baton->formatOut = "raw";
|
|
1083
1167
|
} else {
|
|
1084
1168
|
// Unsupported output format
|
|
1085
|
-
(
|
|
1169
|
+
auto unsupported = std::string("Unsupported output format ");
|
|
1086
1170
|
if (baton->formatOut == "input") {
|
|
1087
|
-
|
|
1088
|
-
|
|
1171
|
+
unsupported.append("when trying to match input format of ");
|
|
1172
|
+
unsupported.append(ImageTypeId(inputImageType));
|
|
1089
1173
|
} else {
|
|
1090
|
-
|
|
1174
|
+
unsupported.append(baton->formatOut);
|
|
1091
1175
|
}
|
|
1092
|
-
|
|
1176
|
+
throw std::runtime_error(unsupported);
|
|
1093
1177
|
}
|
|
1094
1178
|
} else {
|
|
1095
1179
|
// File output
|
|
@@ -1112,20 +1196,29 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1112
1196
|
(willMatchInput && inputImageType == sharp::ImageType::JPEG)) {
|
|
1113
1197
|
// Write JPEG to file
|
|
1114
1198
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::JPEG);
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
->
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
->
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1199
|
+
if (baton->keepGainMap) {
|
|
1200
|
+
image = ReattachGainMap(image, gainMap, baton);
|
|
1201
|
+
image.uhdrsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
|
1202
|
+
->set("keep", baton->keepMetadata)
|
|
1203
|
+
->set("Q", baton->jpegQuality)
|
|
1204
|
+
->set("gainmap_scale_factor", gainMapScaleFactor));
|
|
1205
|
+
} else {
|
|
1206
|
+
image.jpegsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
|
1207
|
+
->set("keep", baton->keepMetadata)
|
|
1208
|
+
->set("Q", baton->jpegQuality)
|
|
1209
|
+
->set("interlace", baton->jpegProgressive)
|
|
1210
|
+
->set("subsample_mode", baton->jpegChromaSubsampling == "4:4:4"
|
|
1211
|
+
? VIPS_FOREIGN_SUBSAMPLE_OFF
|
|
1212
|
+
: VIPS_FOREIGN_SUBSAMPLE_ON)
|
|
1213
|
+
->set("trellis_quant", baton->jpegTrellisQuantisation)
|
|
1214
|
+
->set("quant_table", baton->jpegQuantisationTable)
|
|
1215
|
+
->set("overshoot_deringing", baton->jpegOvershootDeringing)
|
|
1216
|
+
->set("optimize_scans", baton->jpegOptimiseScans)
|
|
1217
|
+
->set("optimize_coding", baton->jpegOptimiseCoding));
|
|
1218
|
+
}
|
|
1127
1219
|
baton->formatOut = "jpeg";
|
|
1128
1220
|
baton->channels = std::min(baton->channels, 3);
|
|
1221
|
+
baton->hasAlphaOut = false;
|
|
1129
1222
|
} else if (baton->formatOut == "jp2" || (mightMatchInput && isJp2) ||
|
|
1130
1223
|
(willMatchInput && (inputImageType == sharp::ImageType::JP2))) {
|
|
1131
1224
|
// Write JP2 to file
|
|
@@ -1168,6 +1261,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1168
1261
|
->set("effort", baton->webpEffort)
|
|
1169
1262
|
->set("min_size", baton->webpMinSize)
|
|
1170
1263
|
->set("mixed", baton->webpMixed)
|
|
1264
|
+
->set("exact", baton->webpExact)
|
|
1171
1265
|
->set("alpha_q", baton->webpAlphaQuality));
|
|
1172
1266
|
baton->formatOut = "webp";
|
|
1173
1267
|
} else if (baton->formatOut == "gif" || (mightMatchInput && isGif) ||
|
|
@@ -1191,6 +1285,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1191
1285
|
if (baton->tiffCompression == VIPS_FOREIGN_TIFF_COMPRESSION_JPEG) {
|
|
1192
1286
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::JPEG);
|
|
1193
1287
|
baton->channels = std::min(baton->channels, 3);
|
|
1288
|
+
baton->hasAlphaOut = false;
|
|
1194
1289
|
}
|
|
1195
1290
|
// Cast pixel values to float, if required
|
|
1196
1291
|
if (baton->tiffPredictor == VIPS_FOREIGN_TIFF_PREDICTOR_FLOAT) {
|
|
@@ -1223,6 +1318,8 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1223
1318
|
->set("compression", baton->heifCompression)
|
|
1224
1319
|
->set("effort", baton->heifEffort)
|
|
1225
1320
|
->set("bitdepth", baton->heifBitdepth)
|
|
1321
|
+
->set("tune", baton->heifTune.c_str())
|
|
1322
|
+
->set("encoder", baton->heifEncoder.c_str())
|
|
1226
1323
|
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
|
1227
1324
|
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
|
1228
1325
|
->set("lossless", baton->heifLossless));
|
|
@@ -1250,6 +1347,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1250
1347
|
vips::VOption *options = BuildOptionsDZ(baton);
|
|
1251
1348
|
image.dzsave(const_cast<char*>(baton->fileOut.data()), options);
|
|
1252
1349
|
baton->formatOut = "dz";
|
|
1350
|
+
if (baton->tileFormat == "jpeg") {
|
|
1351
|
+
baton->hasAlphaOut = false;
|
|
1352
|
+
}
|
|
1253
1353
|
} else if (baton->formatOut == "v" || (mightMatchInput && isV) ||
|
|
1254
1354
|
(willMatchInput && inputImageType == sharp::ImageType::VIPS)) {
|
|
1255
1355
|
// Write V to file
|
|
@@ -1262,7 +1362,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1262
1362
|
return Error();
|
|
1263
1363
|
}
|
|
1264
1364
|
}
|
|
1265
|
-
} catch (
|
|
1365
|
+
} catch (std::runtime_error const &err) {
|
|
1266
1366
|
char const *what = err.what();
|
|
1267
1367
|
if (what && what[0]) {
|
|
1268
1368
|
(baton->err).append(what);
|
|
@@ -1290,11 +1390,10 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1290
1390
|
if (baton->errUseWarning) {
|
|
1291
1391
|
(baton->err).append("\n").append(warning);
|
|
1292
1392
|
} else {
|
|
1293
|
-
debuglog.
|
|
1393
|
+
debuglog.SHARP_CALLBACK_FN_NAME(Receiver().Value(), { Napi::String::New(env, warning) });
|
|
1294
1394
|
}
|
|
1295
1395
|
warning = sharp::VipsWarningPop();
|
|
1296
1396
|
}
|
|
1297
|
-
|
|
1298
1397
|
if (baton->err.empty()) {
|
|
1299
1398
|
int width = baton->width;
|
|
1300
1399
|
int height = baton->height;
|
|
@@ -1335,14 +1434,22 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1335
1434
|
info.Set("pageHeight", static_cast<int32_t>(baton->pageHeightOut));
|
|
1336
1435
|
info.Set("pages", static_cast<int32_t>(baton->pagesOut));
|
|
1337
1436
|
}
|
|
1437
|
+
info.Set("hasAlpha", baton->hasAlphaOut);
|
|
1338
1438
|
|
|
1339
1439
|
if (baton->bufferOutLength > 0) {
|
|
1340
|
-
// Add buffer size to info
|
|
1341
1440
|
info.Set("size", static_cast<uint32_t>(baton->bufferOutLength));
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1441
|
+
if (baton->typedArrayOut) {
|
|
1442
|
+
// ECMAScript ArrayBuffer with Uint8Array view
|
|
1443
|
+
Napi::TypedArrayOf<uint8_t> data = Napi::Buffer<char>::Copy(env,
|
|
1444
|
+
static_cast<char*>(baton->bufferOut), baton->bufferOutLength);
|
|
1445
|
+
sharp::FreeCallback(static_cast<char*>(baton->bufferOut), nullptr);
|
|
1446
|
+
Callback().SHARP_CALLBACK_FN_NAME(Receiver().Value(), { env.Null(), data, info });
|
|
1447
|
+
} else {
|
|
1448
|
+
// Node.js Buffer
|
|
1449
|
+
Napi::Buffer<char> data = Napi::Buffer<char>::NewOrCopy(env, static_cast<char*>(baton->bufferOut),
|
|
1450
|
+
baton->bufferOutLength, sharp::FreeCallback);
|
|
1451
|
+
Callback().SHARP_CALLBACK_FN_NAME(Receiver().Value(), { env.Null(), data, info });
|
|
1452
|
+
}
|
|
1346
1453
|
} else {
|
|
1347
1454
|
// Add file size to info
|
|
1348
1455
|
if (baton->formatOut != "dz" || sharp::IsDzZip(baton->fileOut)) {
|
|
@@ -1352,10 +1459,11 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1352
1459
|
info.Set("size", size);
|
|
1353
1460
|
} catch (...) {}
|
|
1354
1461
|
}
|
|
1355
|
-
Callback().
|
|
1462
|
+
Callback().SHARP_CALLBACK_FN_NAME(Receiver().Value(), { env.Null(), info });
|
|
1356
1463
|
}
|
|
1357
1464
|
} else {
|
|
1358
|
-
Callback().
|
|
1465
|
+
Callback().SHARP_CALLBACK_FN_NAME(Receiver().Value(),
|
|
1466
|
+
{ Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
|
|
1359
1467
|
}
|
|
1360
1468
|
|
|
1361
1469
|
// Delete baton
|
|
@@ -1376,7 +1484,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1376
1484
|
// Decrement processing task counter
|
|
1377
1485
|
sharp::counterProcess--;
|
|
1378
1486
|
Napi::Number queueLength = Napi::Number::New(env, static_cast<int>(sharp::counterQueue));
|
|
1379
|
-
queueListener.
|
|
1487
|
+
queueListener.SHARP_CALLBACK_FN_NAME(Receiver().Value(), { queueLength });
|
|
1380
1488
|
}
|
|
1381
1489
|
|
|
1382
1490
|
private:
|
|
@@ -1386,7 +1494,13 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1386
1494
|
|
|
1387
1495
|
void MultiPageUnsupported(int const pages, std::string op) {
|
|
1388
1496
|
if (pages > 1) {
|
|
1389
|
-
throw
|
|
1497
|
+
throw std::runtime_error(op + " is not supported for multi-page images");
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
void KeepGainMapUnsupported(bool const keepGainMap, std::string op) {
|
|
1502
|
+
if (keepGainMap) {
|
|
1503
|
+
throw std::runtime_error(op + " is not supported when keeping gain maps");
|
|
1390
1504
|
}
|
|
1391
1505
|
}
|
|
1392
1506
|
|
|
@@ -1469,6 +1583,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1469
1583
|
{"preset", vips_enum_nick(VIPS_TYPE_FOREIGN_WEBP_PRESET, baton->webpPreset)},
|
|
1470
1584
|
{"min_size", baton->webpMinSize ? "true" : "false"},
|
|
1471
1585
|
{"mixed", baton->webpMixed ? "true" : "false"},
|
|
1586
|
+
{"exact", baton->webpExact ? "true" : "false"},
|
|
1472
1587
|
{"effort", std::to_string(baton->webpEffort)}
|
|
1473
1588
|
};
|
|
1474
1589
|
suffix = AssembleSuffixString(".webp", options);
|
|
@@ -1507,6 +1622,21 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1507
1622
|
return options;
|
|
1508
1623
|
}
|
|
1509
1624
|
|
|
1625
|
+
VImage ReattachGainMap(VImage image, VImage gainMap, PipelineBaton *baton) {
|
|
1626
|
+
VipsArea *gainMapJpeg = reinterpret_cast<VipsArea*>(gainMap.jpegsave_buffer(VImage::option()
|
|
1627
|
+
->set("keep", FALSE)
|
|
1628
|
+
->set("Q", baton->jpegQuality)
|
|
1629
|
+
->set("subsample_mode", VIPS_FOREIGN_SUBSAMPLE_OFF)
|
|
1630
|
+
->set("trellis_quant", baton->jpegTrellisQuantisation)
|
|
1631
|
+
->set("quant_table", baton->jpegQuantisationTable)
|
|
1632
|
+
->set("overshoot_deringing", baton->jpegOvershootDeringing)
|
|
1633
|
+
->set("optimize_coding", baton->jpegOptimiseCoding)));
|
|
1634
|
+
image = image.copy();
|
|
1635
|
+
image.set("gainmap-data", reinterpret_cast<VipsCallbackFn>(vips_area_free_cb),
|
|
1636
|
+
gainMapJpeg->data, gainMapJpeg->length);
|
|
1637
|
+
return image;
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1510
1640
|
/*
|
|
1511
1641
|
Clear all thread-local data.
|
|
1512
1642
|
*/
|
|
@@ -1615,6 +1745,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1615
1745
|
baton->trimBackground = sharp::AttrAsVectorOfDouble(options, "trimBackground");
|
|
1616
1746
|
baton->trimThreshold = sharp::AttrAsDouble(options, "trimThreshold");
|
|
1617
1747
|
baton->trimLineArt = sharp::AttrAsBool(options, "trimLineArt");
|
|
1748
|
+
baton->trimMargin = sharp::AttrAsUint32(options, "trimMargin");
|
|
1618
1749
|
baton->gamma = sharp::AttrAsDouble(options, "gamma");
|
|
1619
1750
|
baton->gammaOut = sharp::AttrAsDouble(options, "gammaOut");
|
|
1620
1751
|
baton->linearA = sharp::AttrAsVectorOfDouble(options, "linearA");
|
|
@@ -1692,6 +1823,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1692
1823
|
// Output
|
|
1693
1824
|
baton->formatOut = sharp::AttrAsStr(options, "formatOut");
|
|
1694
1825
|
baton->fileOut = sharp::AttrAsStr(options, "fileOut");
|
|
1826
|
+
baton->typedArrayOut = sharp::AttrAsBool(options, "typedArrayOut");
|
|
1695
1827
|
baton->keepMetadata = sharp::AttrAsUint32(options, "keepMetadata");
|
|
1696
1828
|
baton->withMetadataOrientation = sharp::AttrAsUint32(options, "withMetadataOrientation");
|
|
1697
1829
|
baton->withMetadataDensity = sharp::AttrAsDouble(options, "withMetadataDensity");
|
|
@@ -1706,6 +1838,8 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1706
1838
|
}
|
|
1707
1839
|
baton->withExifMerge = sharp::AttrAsBool(options, "withExifMerge");
|
|
1708
1840
|
baton->withXmp = sharp::AttrAsStr(options, "withXmp");
|
|
1841
|
+
baton->keepGainMap = sharp::AttrAsBool(options, "keepGainMap");
|
|
1842
|
+
baton->withGainMap = sharp::AttrAsBool(options, "withGainMap");
|
|
1709
1843
|
baton->timeoutSeconds = sharp::AttrAsUint32(options, "timeoutSeconds");
|
|
1710
1844
|
baton->loop = sharp::AttrAsUint32(options, "loop");
|
|
1711
1845
|
baton->delay = sharp::AttrAsInt32Vector(options, "delay");
|
|
@@ -1741,6 +1875,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1741
1875
|
baton->webpEffort = sharp::AttrAsUint32(options, "webpEffort");
|
|
1742
1876
|
baton->webpMinSize = sharp::AttrAsBool(options, "webpMinSize");
|
|
1743
1877
|
baton->webpMixed = sharp::AttrAsBool(options, "webpMixed");
|
|
1878
|
+
baton->webpExact = sharp::AttrAsBool(options, "webpExact");
|
|
1744
1879
|
baton->gifBitdepth = sharp::AttrAsUint32(options, "gifBitdepth");
|
|
1745
1880
|
baton->gifEffort = sharp::AttrAsUint32(options, "gifEffort");
|
|
1746
1881
|
baton->gifDither = sharp::AttrAsDouble(options, "gifDither");
|
|
@@ -1775,6 +1910,8 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1775
1910
|
baton->heifEffort = sharp::AttrAsUint32(options, "heifEffort");
|
|
1776
1911
|
baton->heifChromaSubsampling = sharp::AttrAsStr(options, "heifChromaSubsampling");
|
|
1777
1912
|
baton->heifBitdepth = sharp::AttrAsUint32(options, "heifBitdepth");
|
|
1913
|
+
baton->heifTune = sharp::AttrAsStr(options, "heifTune");
|
|
1914
|
+
baton->heifEncoder = sharp::AttrAsStr(options, "heifEncoder");
|
|
1778
1915
|
baton->jxlDistance = sharp::AttrAsDouble(options, "jxlDistance");
|
|
1779
1916
|
baton->jxlDecodingTier = sharp::AttrAsUint32(options, "jxlDecodingTier");
|
|
1780
1917
|
baton->jxlEffort = sharp::AttrAsUint32(options, "jxlEffort");
|
|
@@ -1808,7 +1945,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1808
1945
|
|
|
1809
1946
|
// Increment queued task counter
|
|
1810
1947
|
Napi::Number queueLength = Napi::Number::New(info.Env(), static_cast<int>(++sharp::counterQueue));
|
|
1811
|
-
queueListener.
|
|
1948
|
+
queueListener.SHARP_CALLBACK_FN_NAME(info.This(), { queueLength });
|
|
1812
1949
|
|
|
1813
1950
|
return info.Env().Undefined();
|
|
1814
1951
|
}
|