@depup/sharp 0.34.5-depup.0 → 0.35.4-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -109
- package/changes.json +5 -0
- 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} +8 -7
- package/dist/composite.mjs +213 -0
- package/{lib/constructor.js → dist/constructor.cjs} +42 -30
- package/dist/constructor.mjs +511 -0
- package/dist/index.cjs +25 -0
- package/dist/index.d.cts +1999 -0
- package/dist/index.d.mts +2046 -0
- package/dist/index.mjs +25 -0
- package/{lib/input.js → dist/input.cjs} +47 -37
- package/dist/input.mjs +819 -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} +37 -51
- package/dist/operation.mjs +1002 -0
- package/{lib/output.js → dist/output.cjs} +166 -47
- package/dist/output.mjs +1785 -0
- package/{lib/resize.js → dist/resize.cjs} +54 -32
- package/dist/resize.mjs +617 -0
- package/dist/sharp.cjs +174 -0
- package/dist/sharp.mjs +174 -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 +111 -83
- package/package.json +95 -54
- package/src/binding.gyp +19 -14
- package/src/common.cc +77 -21
- package/src/common.h +23 -4
- 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 +203 -69
- package/src/pipeline.h +15 -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,7 @@ 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())
|
|
1027
1108
|
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
|
1028
1109
|
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
|
1029
1110
|
->set("lossless", baton->heifLossless)));
|
|
@@ -1046,6 +1127,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1046
1127
|
area->free_fn = nullptr;
|
|
1047
1128
|
vips_area_unref(area);
|
|
1048
1129
|
baton->formatOut = "dz";
|
|
1130
|
+
if (baton->tileFormat == "jpeg") {
|
|
1131
|
+
baton->hasAlphaOut = false;
|
|
1132
|
+
}
|
|
1049
1133
|
} else if (baton->formatOut == "jxl" ||
|
|
1050
1134
|
(baton->formatOut == "input" && inputImageType == sharp::ImageType::JXL)) {
|
|
1051
1135
|
// Write JXL to buffer
|
|
@@ -1076,20 +1160,19 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1076
1160
|
// Get raw image data
|
|
1077
1161
|
baton->bufferOut = static_cast<char*>(image.write_to_memory(&baton->bufferOutLength));
|
|
1078
1162
|
if (baton->bufferOut == nullptr) {
|
|
1079
|
-
(
|
|
1080
|
-
return Error();
|
|
1163
|
+
throw std::runtime_error("Could not allocate enough memory for raw output");
|
|
1081
1164
|
}
|
|
1082
1165
|
baton->formatOut = "raw";
|
|
1083
1166
|
} else {
|
|
1084
1167
|
// Unsupported output format
|
|
1085
|
-
(
|
|
1168
|
+
auto unsupported = std::string("Unsupported output format ");
|
|
1086
1169
|
if (baton->formatOut == "input") {
|
|
1087
|
-
|
|
1088
|
-
|
|
1170
|
+
unsupported.append("when trying to match input format of ");
|
|
1171
|
+
unsupported.append(ImageTypeId(inputImageType));
|
|
1089
1172
|
} else {
|
|
1090
|
-
|
|
1173
|
+
unsupported.append(baton->formatOut);
|
|
1091
1174
|
}
|
|
1092
|
-
|
|
1175
|
+
throw std::runtime_error(unsupported);
|
|
1093
1176
|
}
|
|
1094
1177
|
} else {
|
|
1095
1178
|
// File output
|
|
@@ -1112,20 +1195,29 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1112
1195
|
(willMatchInput && inputImageType == sharp::ImageType::JPEG)) {
|
|
1113
1196
|
// Write JPEG to file
|
|
1114
1197
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::JPEG);
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
->
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
->
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1198
|
+
if (baton->keepGainMap) {
|
|
1199
|
+
image = ReattachGainMap(image, gainMap, baton);
|
|
1200
|
+
image.uhdrsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
|
1201
|
+
->set("keep", baton->keepMetadata)
|
|
1202
|
+
->set("Q", baton->jpegQuality)
|
|
1203
|
+
->set("gainmap_scale_factor", gainMapScaleFactor));
|
|
1204
|
+
} else {
|
|
1205
|
+
image.jpegsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
|
1206
|
+
->set("keep", baton->keepMetadata)
|
|
1207
|
+
->set("Q", baton->jpegQuality)
|
|
1208
|
+
->set("interlace", baton->jpegProgressive)
|
|
1209
|
+
->set("subsample_mode", baton->jpegChromaSubsampling == "4:4:4"
|
|
1210
|
+
? VIPS_FOREIGN_SUBSAMPLE_OFF
|
|
1211
|
+
: VIPS_FOREIGN_SUBSAMPLE_ON)
|
|
1212
|
+
->set("trellis_quant", baton->jpegTrellisQuantisation)
|
|
1213
|
+
->set("quant_table", baton->jpegQuantisationTable)
|
|
1214
|
+
->set("overshoot_deringing", baton->jpegOvershootDeringing)
|
|
1215
|
+
->set("optimize_scans", baton->jpegOptimiseScans)
|
|
1216
|
+
->set("optimize_coding", baton->jpegOptimiseCoding));
|
|
1217
|
+
}
|
|
1127
1218
|
baton->formatOut = "jpeg";
|
|
1128
1219
|
baton->channels = std::min(baton->channels, 3);
|
|
1220
|
+
baton->hasAlphaOut = false;
|
|
1129
1221
|
} else if (baton->formatOut == "jp2" || (mightMatchInput && isJp2) ||
|
|
1130
1222
|
(willMatchInput && (inputImageType == sharp::ImageType::JP2))) {
|
|
1131
1223
|
// Write JP2 to file
|
|
@@ -1168,6 +1260,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1168
1260
|
->set("effort", baton->webpEffort)
|
|
1169
1261
|
->set("min_size", baton->webpMinSize)
|
|
1170
1262
|
->set("mixed", baton->webpMixed)
|
|
1263
|
+
->set("exact", baton->webpExact)
|
|
1171
1264
|
->set("alpha_q", baton->webpAlphaQuality));
|
|
1172
1265
|
baton->formatOut = "webp";
|
|
1173
1266
|
} else if (baton->formatOut == "gif" || (mightMatchInput && isGif) ||
|
|
@@ -1191,6 +1284,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1191
1284
|
if (baton->tiffCompression == VIPS_FOREIGN_TIFF_COMPRESSION_JPEG) {
|
|
1192
1285
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::JPEG);
|
|
1193
1286
|
baton->channels = std::min(baton->channels, 3);
|
|
1287
|
+
baton->hasAlphaOut = false;
|
|
1194
1288
|
}
|
|
1195
1289
|
// Cast pixel values to float, if required
|
|
1196
1290
|
if (baton->tiffPredictor == VIPS_FOREIGN_TIFF_PREDICTOR_FLOAT) {
|
|
@@ -1223,6 +1317,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1223
1317
|
->set("compression", baton->heifCompression)
|
|
1224
1318
|
->set("effort", baton->heifEffort)
|
|
1225
1319
|
->set("bitdepth", baton->heifBitdepth)
|
|
1320
|
+
->set("tune", baton->heifTune.c_str())
|
|
1226
1321
|
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
|
1227
1322
|
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
|
1228
1323
|
->set("lossless", baton->heifLossless));
|
|
@@ -1250,6 +1345,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1250
1345
|
vips::VOption *options = BuildOptionsDZ(baton);
|
|
1251
1346
|
image.dzsave(const_cast<char*>(baton->fileOut.data()), options);
|
|
1252
1347
|
baton->formatOut = "dz";
|
|
1348
|
+
if (baton->tileFormat == "jpeg") {
|
|
1349
|
+
baton->hasAlphaOut = false;
|
|
1350
|
+
}
|
|
1253
1351
|
} else if (baton->formatOut == "v" || (mightMatchInput && isV) ||
|
|
1254
1352
|
(willMatchInput && inputImageType == sharp::ImageType::VIPS)) {
|
|
1255
1353
|
// Write V to file
|
|
@@ -1262,7 +1360,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1262
1360
|
return Error();
|
|
1263
1361
|
}
|
|
1264
1362
|
}
|
|
1265
|
-
} catch (
|
|
1363
|
+
} catch (std::runtime_error const &err) {
|
|
1266
1364
|
char const *what = err.what();
|
|
1267
1365
|
if (what && what[0]) {
|
|
1268
1366
|
(baton->err).append(what);
|
|
@@ -1290,11 +1388,10 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1290
1388
|
if (baton->errUseWarning) {
|
|
1291
1389
|
(baton->err).append("\n").append(warning);
|
|
1292
1390
|
} else {
|
|
1293
|
-
debuglog.
|
|
1391
|
+
debuglog.SHARP_CALLBACK_FN_NAME(Receiver().Value(), { Napi::String::New(env, warning) });
|
|
1294
1392
|
}
|
|
1295
1393
|
warning = sharp::VipsWarningPop();
|
|
1296
1394
|
}
|
|
1297
|
-
|
|
1298
1395
|
if (baton->err.empty()) {
|
|
1299
1396
|
int width = baton->width;
|
|
1300
1397
|
int height = baton->height;
|
|
@@ -1335,14 +1432,22 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1335
1432
|
info.Set("pageHeight", static_cast<int32_t>(baton->pageHeightOut));
|
|
1336
1433
|
info.Set("pages", static_cast<int32_t>(baton->pagesOut));
|
|
1337
1434
|
}
|
|
1435
|
+
info.Set("hasAlpha", baton->hasAlphaOut);
|
|
1338
1436
|
|
|
1339
1437
|
if (baton->bufferOutLength > 0) {
|
|
1340
|
-
// Add buffer size to info
|
|
1341
1438
|
info.Set("size", static_cast<uint32_t>(baton->bufferOutLength));
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1439
|
+
if (baton->typedArrayOut) {
|
|
1440
|
+
// ECMAScript ArrayBuffer with Uint8Array view
|
|
1441
|
+
Napi::TypedArrayOf<uint8_t> data = Napi::Buffer<char>::Copy(env,
|
|
1442
|
+
static_cast<char*>(baton->bufferOut), baton->bufferOutLength);
|
|
1443
|
+
sharp::FreeCallback(static_cast<char*>(baton->bufferOut), nullptr);
|
|
1444
|
+
Callback().SHARP_CALLBACK_FN_NAME(Receiver().Value(), { env.Null(), data, info });
|
|
1445
|
+
} else {
|
|
1446
|
+
// Node.js Buffer
|
|
1447
|
+
Napi::Buffer<char> data = Napi::Buffer<char>::NewOrCopy(env, static_cast<char*>(baton->bufferOut),
|
|
1448
|
+
baton->bufferOutLength, sharp::FreeCallback);
|
|
1449
|
+
Callback().SHARP_CALLBACK_FN_NAME(Receiver().Value(), { env.Null(), data, info });
|
|
1450
|
+
}
|
|
1346
1451
|
} else {
|
|
1347
1452
|
// Add file size to info
|
|
1348
1453
|
if (baton->formatOut != "dz" || sharp::IsDzZip(baton->fileOut)) {
|
|
@@ -1352,10 +1457,11 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1352
1457
|
info.Set("size", size);
|
|
1353
1458
|
} catch (...) {}
|
|
1354
1459
|
}
|
|
1355
|
-
Callback().
|
|
1460
|
+
Callback().SHARP_CALLBACK_FN_NAME(Receiver().Value(), { env.Null(), info });
|
|
1356
1461
|
}
|
|
1357
1462
|
} else {
|
|
1358
|
-
Callback().
|
|
1463
|
+
Callback().SHARP_CALLBACK_FN_NAME(Receiver().Value(),
|
|
1464
|
+
{ Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
|
|
1359
1465
|
}
|
|
1360
1466
|
|
|
1361
1467
|
// Delete baton
|
|
@@ -1376,7 +1482,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1376
1482
|
// Decrement processing task counter
|
|
1377
1483
|
sharp::counterProcess--;
|
|
1378
1484
|
Napi::Number queueLength = Napi::Number::New(env, static_cast<int>(sharp::counterQueue));
|
|
1379
|
-
queueListener.
|
|
1485
|
+
queueListener.SHARP_CALLBACK_FN_NAME(Receiver().Value(), { queueLength });
|
|
1380
1486
|
}
|
|
1381
1487
|
|
|
1382
1488
|
private:
|
|
@@ -1386,7 +1492,13 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1386
1492
|
|
|
1387
1493
|
void MultiPageUnsupported(int const pages, std::string op) {
|
|
1388
1494
|
if (pages > 1) {
|
|
1389
|
-
throw
|
|
1495
|
+
throw std::runtime_error(op + " is not supported for multi-page images");
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
void KeepGainMapUnsupported(bool const keepGainMap, std::string op) {
|
|
1500
|
+
if (keepGainMap) {
|
|
1501
|
+
throw std::runtime_error(op + " is not supported when keeping gain maps");
|
|
1390
1502
|
}
|
|
1391
1503
|
}
|
|
1392
1504
|
|
|
@@ -1469,6 +1581,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1469
1581
|
{"preset", vips_enum_nick(VIPS_TYPE_FOREIGN_WEBP_PRESET, baton->webpPreset)},
|
|
1470
1582
|
{"min_size", baton->webpMinSize ? "true" : "false"},
|
|
1471
1583
|
{"mixed", baton->webpMixed ? "true" : "false"},
|
|
1584
|
+
{"exact", baton->webpExact ? "true" : "false"},
|
|
1472
1585
|
{"effort", std::to_string(baton->webpEffort)}
|
|
1473
1586
|
};
|
|
1474
1587
|
suffix = AssembleSuffixString(".webp", options);
|
|
@@ -1507,6 +1620,21 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1507
1620
|
return options;
|
|
1508
1621
|
}
|
|
1509
1622
|
|
|
1623
|
+
VImage ReattachGainMap(VImage image, VImage gainMap, PipelineBaton *baton) {
|
|
1624
|
+
VipsArea *gainMapJpeg = reinterpret_cast<VipsArea*>(gainMap.jpegsave_buffer(VImage::option()
|
|
1625
|
+
->set("keep", FALSE)
|
|
1626
|
+
->set("Q", baton->jpegQuality)
|
|
1627
|
+
->set("subsample_mode", VIPS_FOREIGN_SUBSAMPLE_OFF)
|
|
1628
|
+
->set("trellis_quant", baton->jpegTrellisQuantisation)
|
|
1629
|
+
->set("quant_table", baton->jpegQuantisationTable)
|
|
1630
|
+
->set("overshoot_deringing", baton->jpegOvershootDeringing)
|
|
1631
|
+
->set("optimize_coding", baton->jpegOptimiseCoding)));
|
|
1632
|
+
image = image.copy();
|
|
1633
|
+
image.set("gainmap-data", reinterpret_cast<VipsCallbackFn>(vips_area_free_cb),
|
|
1634
|
+
gainMapJpeg->data, gainMapJpeg->length);
|
|
1635
|
+
return image;
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1510
1638
|
/*
|
|
1511
1639
|
Clear all thread-local data.
|
|
1512
1640
|
*/
|
|
@@ -1615,6 +1743,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1615
1743
|
baton->trimBackground = sharp::AttrAsVectorOfDouble(options, "trimBackground");
|
|
1616
1744
|
baton->trimThreshold = sharp::AttrAsDouble(options, "trimThreshold");
|
|
1617
1745
|
baton->trimLineArt = sharp::AttrAsBool(options, "trimLineArt");
|
|
1746
|
+
baton->trimMargin = sharp::AttrAsUint32(options, "trimMargin");
|
|
1618
1747
|
baton->gamma = sharp::AttrAsDouble(options, "gamma");
|
|
1619
1748
|
baton->gammaOut = sharp::AttrAsDouble(options, "gammaOut");
|
|
1620
1749
|
baton->linearA = sharp::AttrAsVectorOfDouble(options, "linearA");
|
|
@@ -1692,6 +1821,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1692
1821
|
// Output
|
|
1693
1822
|
baton->formatOut = sharp::AttrAsStr(options, "formatOut");
|
|
1694
1823
|
baton->fileOut = sharp::AttrAsStr(options, "fileOut");
|
|
1824
|
+
baton->typedArrayOut = sharp::AttrAsBool(options, "typedArrayOut");
|
|
1695
1825
|
baton->keepMetadata = sharp::AttrAsUint32(options, "keepMetadata");
|
|
1696
1826
|
baton->withMetadataOrientation = sharp::AttrAsUint32(options, "withMetadataOrientation");
|
|
1697
1827
|
baton->withMetadataDensity = sharp::AttrAsDouble(options, "withMetadataDensity");
|
|
@@ -1706,6 +1836,8 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1706
1836
|
}
|
|
1707
1837
|
baton->withExifMerge = sharp::AttrAsBool(options, "withExifMerge");
|
|
1708
1838
|
baton->withXmp = sharp::AttrAsStr(options, "withXmp");
|
|
1839
|
+
baton->keepGainMap = sharp::AttrAsBool(options, "keepGainMap");
|
|
1840
|
+
baton->withGainMap = sharp::AttrAsBool(options, "withGainMap");
|
|
1709
1841
|
baton->timeoutSeconds = sharp::AttrAsUint32(options, "timeoutSeconds");
|
|
1710
1842
|
baton->loop = sharp::AttrAsUint32(options, "loop");
|
|
1711
1843
|
baton->delay = sharp::AttrAsInt32Vector(options, "delay");
|
|
@@ -1741,6 +1873,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1741
1873
|
baton->webpEffort = sharp::AttrAsUint32(options, "webpEffort");
|
|
1742
1874
|
baton->webpMinSize = sharp::AttrAsBool(options, "webpMinSize");
|
|
1743
1875
|
baton->webpMixed = sharp::AttrAsBool(options, "webpMixed");
|
|
1876
|
+
baton->webpExact = sharp::AttrAsBool(options, "webpExact");
|
|
1744
1877
|
baton->gifBitdepth = sharp::AttrAsUint32(options, "gifBitdepth");
|
|
1745
1878
|
baton->gifEffort = sharp::AttrAsUint32(options, "gifEffort");
|
|
1746
1879
|
baton->gifDither = sharp::AttrAsDouble(options, "gifDither");
|
|
@@ -1775,6 +1908,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1775
1908
|
baton->heifEffort = sharp::AttrAsUint32(options, "heifEffort");
|
|
1776
1909
|
baton->heifChromaSubsampling = sharp::AttrAsStr(options, "heifChromaSubsampling");
|
|
1777
1910
|
baton->heifBitdepth = sharp::AttrAsUint32(options, "heifBitdepth");
|
|
1911
|
+
baton->heifTune = sharp::AttrAsStr(options, "heifTune");
|
|
1778
1912
|
baton->jxlDistance = sharp::AttrAsDouble(options, "jxlDistance");
|
|
1779
1913
|
baton->jxlDecodingTier = sharp::AttrAsUint32(options, "jxlDecodingTier");
|
|
1780
1914
|
baton->jxlEffort = sharp::AttrAsUint32(options, "jxlEffort");
|
|
@@ -1808,7 +1942,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1808
1942
|
|
|
1809
1943
|
// Increment queued task counter
|
|
1810
1944
|
Napi::Number queueLength = Napi::Number::New(info.Env(), static_cast<int>(++sharp::counterQueue));
|
|
1811
|
-
queueListener.
|
|
1945
|
+
queueListener.SHARP_CALLBACK_FN_NAME(info.This(), { queueLength });
|
|
1812
1946
|
|
|
1813
1947
|
return info.Env().Undefined();
|
|
1814
1948
|
}
|