sharp 0.25.4 → 0.26.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 +1 -1
- package/binding.gyp +53 -66
- package/install/dll-copy.js +3 -1
- package/install/libvips.js +18 -13
- package/lib/constructor.js +7 -1
- package/lib/input.js +10 -1
- package/lib/libvips.js +1 -7
- package/lib/output.js +89 -7
- package/lib/platform.js +2 -1
- package/lib/utility.js +1 -1
- package/package.json +19 -15
- package/src/common.cc +113 -50
- package/src/common.h +21 -2
- package/src/libvips/cplusplus/VImage.cpp +451 -450
- package/src/libvips/cplusplus/vips-operators.cpp +117 -1
- package/src/metadata.cc +1 -1
- package/src/operations.cc +0 -23
- package/src/operations.h +0 -10
- package/src/pipeline.cc +70 -11
- package/src/pipeline.h +9 -2
- package/src/stats.cc +17 -0
- package/src/stats.h +7 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// bodies for vips operations
|
|
2
|
-
//
|
|
2
|
+
// Sun 5 Jul 22:36:37 BST 2020
|
|
3
3
|
// this file is generated automatically, do not edit!
|
|
4
4
|
|
|
5
5
|
VImage VImage::CMC2LCh( VOption *options ) const
|
|
@@ -754,6 +754,18 @@ VImage VImage::csvload( const char *filename, VOption *options )
|
|
|
754
754
|
return( out );
|
|
755
755
|
}
|
|
756
756
|
|
|
757
|
+
VImage VImage::csvload_source( VSource source, VOption *options )
|
|
758
|
+
{
|
|
759
|
+
VImage out;
|
|
760
|
+
|
|
761
|
+
call( "csvload_source",
|
|
762
|
+
(options ? options : VImage::option())->
|
|
763
|
+
set( "out", &out )->
|
|
764
|
+
set( "source", source ) );
|
|
765
|
+
|
|
766
|
+
return( out );
|
|
767
|
+
}
|
|
768
|
+
|
|
757
769
|
void VImage::csvsave( const char *filename, VOption *options ) const
|
|
758
770
|
{
|
|
759
771
|
call( "csvsave",
|
|
@@ -762,6 +774,14 @@ void VImage::csvsave( const char *filename, VOption *options ) const
|
|
|
762
774
|
set( "filename", filename ) );
|
|
763
775
|
}
|
|
764
776
|
|
|
777
|
+
void VImage::csvsave_target( VTarget target, VOption *options ) const
|
|
778
|
+
{
|
|
779
|
+
call( "csvsave_target",
|
|
780
|
+
(options ? options : VImage::option())->
|
|
781
|
+
set( "in", *this )->
|
|
782
|
+
set( "target", target ) );
|
|
783
|
+
}
|
|
784
|
+
|
|
765
785
|
VImage VImage::dE00( VImage right, VOption *options ) const
|
|
766
786
|
{
|
|
767
787
|
VImage out;
|
|
@@ -1218,6 +1238,18 @@ VImage VImage::gifload_buffer( VipsBlob *buffer, VOption *options )
|
|
|
1218
1238
|
return( out );
|
|
1219
1239
|
}
|
|
1220
1240
|
|
|
1241
|
+
VImage VImage::gifload_source( VSource source, VOption *options )
|
|
1242
|
+
{
|
|
1243
|
+
VImage out;
|
|
1244
|
+
|
|
1245
|
+
call( "gifload_source",
|
|
1246
|
+
(options ? options : VImage::option())->
|
|
1247
|
+
set( "out", &out )->
|
|
1248
|
+
set( "source", source ) );
|
|
1249
|
+
|
|
1250
|
+
return( out );
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1221
1253
|
VImage VImage::globalbalance( VOption *options ) const
|
|
1222
1254
|
{
|
|
1223
1255
|
VImage out;
|
|
@@ -1297,6 +1329,18 @@ VImage VImage::heifload_buffer( VipsBlob *buffer, VOption *options )
|
|
|
1297
1329
|
return( out );
|
|
1298
1330
|
}
|
|
1299
1331
|
|
|
1332
|
+
VImage VImage::heifload_source( VSource source, VOption *options )
|
|
1333
|
+
{
|
|
1334
|
+
VImage out;
|
|
1335
|
+
|
|
1336
|
+
call( "heifload_source",
|
|
1337
|
+
(options ? options : VImage::option())->
|
|
1338
|
+
set( "out", &out )->
|
|
1339
|
+
set( "source", source ) );
|
|
1340
|
+
|
|
1341
|
+
return( out );
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1300
1344
|
void VImage::heifsave( const char *filename, VOption *options ) const
|
|
1301
1345
|
{
|
|
1302
1346
|
call( "heifsave",
|
|
@@ -1317,6 +1361,14 @@ VipsBlob *VImage::heifsave_buffer( VOption *options ) const
|
|
|
1317
1361
|
return( buffer );
|
|
1318
1362
|
}
|
|
1319
1363
|
|
|
1364
|
+
void VImage::heifsave_target( VTarget target, VOption *options ) const
|
|
1365
|
+
{
|
|
1366
|
+
call( "heifsave_target",
|
|
1367
|
+
(options ? options : VImage::option())->
|
|
1368
|
+
set( "in", *this )->
|
|
1369
|
+
set( "target", target ) );
|
|
1370
|
+
}
|
|
1371
|
+
|
|
1320
1372
|
VImage VImage::hist_cum( VOption *options ) const
|
|
1321
1373
|
{
|
|
1322
1374
|
VImage out;
|
|
@@ -2028,6 +2080,18 @@ VImage VImage::matload( const char *filename, VOption *options )
|
|
|
2028
2080
|
return( out );
|
|
2029
2081
|
}
|
|
2030
2082
|
|
|
2083
|
+
VImage VImage::matrixinvert( VOption *options ) const
|
|
2084
|
+
{
|
|
2085
|
+
VImage out;
|
|
2086
|
+
|
|
2087
|
+
call( "matrixinvert",
|
|
2088
|
+
(options ? options : VImage::option())->
|
|
2089
|
+
set( "in", *this )->
|
|
2090
|
+
set( "out", &out ) );
|
|
2091
|
+
|
|
2092
|
+
return( out );
|
|
2093
|
+
}
|
|
2094
|
+
|
|
2031
2095
|
VImage VImage::matrixload( const char *filename, VOption *options )
|
|
2032
2096
|
{
|
|
2033
2097
|
VImage out;
|
|
@@ -2040,6 +2104,18 @@ VImage VImage::matrixload( const char *filename, VOption *options )
|
|
|
2040
2104
|
return( out );
|
|
2041
2105
|
}
|
|
2042
2106
|
|
|
2107
|
+
VImage VImage::matrixload_source( VSource source, VOption *options )
|
|
2108
|
+
{
|
|
2109
|
+
VImage out;
|
|
2110
|
+
|
|
2111
|
+
call( "matrixload_source",
|
|
2112
|
+
(options ? options : VImage::option())->
|
|
2113
|
+
set( "out", &out )->
|
|
2114
|
+
set( "source", source ) );
|
|
2115
|
+
|
|
2116
|
+
return( out );
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2043
2119
|
void VImage::matrixprint( VOption *options ) const
|
|
2044
2120
|
{
|
|
2045
2121
|
call( "matrixprint",
|
|
@@ -2055,6 +2131,14 @@ void VImage::matrixsave( const char *filename, VOption *options ) const
|
|
|
2055
2131
|
set( "filename", filename ) );
|
|
2056
2132
|
}
|
|
2057
2133
|
|
|
2134
|
+
void VImage::matrixsave_target( VTarget target, VOption *options ) const
|
|
2135
|
+
{
|
|
2136
|
+
call( "matrixsave_target",
|
|
2137
|
+
(options ? options : VImage::option())->
|
|
2138
|
+
set( "in", *this )->
|
|
2139
|
+
set( "target", target ) );
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2058
2142
|
double VImage::max( VOption *options ) const
|
|
2059
2143
|
{
|
|
2060
2144
|
double out;
|
|
@@ -2256,6 +2340,18 @@ VImage VImage::pdfload_buffer( VipsBlob *buffer, VOption *options )
|
|
|
2256
2340
|
return( out );
|
|
2257
2341
|
}
|
|
2258
2342
|
|
|
2343
|
+
VImage VImage::pdfload_source( VSource source, VOption *options )
|
|
2344
|
+
{
|
|
2345
|
+
VImage out;
|
|
2346
|
+
|
|
2347
|
+
call( "pdfload_source",
|
|
2348
|
+
(options ? options : VImage::option())->
|
|
2349
|
+
set( "out", &out )->
|
|
2350
|
+
set( "source", source ) );
|
|
2351
|
+
|
|
2352
|
+
return( out );
|
|
2353
|
+
}
|
|
2354
|
+
|
|
2259
2355
|
int VImage::percent( double percent, VOption *options ) const
|
|
2260
2356
|
{
|
|
2261
2357
|
int threshold;
|
|
@@ -2371,6 +2467,18 @@ VImage VImage::ppmload( const char *filename, VOption *options )
|
|
|
2371
2467
|
return( out );
|
|
2372
2468
|
}
|
|
2373
2469
|
|
|
2470
|
+
VImage VImage::ppmload_source( VSource source, VOption *options )
|
|
2471
|
+
{
|
|
2472
|
+
VImage out;
|
|
2473
|
+
|
|
2474
|
+
call( "ppmload_source",
|
|
2475
|
+
(options ? options : VImage::option())->
|
|
2476
|
+
set( "out", &out )->
|
|
2477
|
+
set( "source", source ) );
|
|
2478
|
+
|
|
2479
|
+
return( out );
|
|
2480
|
+
}
|
|
2481
|
+
|
|
2374
2482
|
void VImage::ppmsave( const char *filename, VOption *options ) const
|
|
2375
2483
|
{
|
|
2376
2484
|
call( "ppmsave",
|
|
@@ -2379,6 +2487,14 @@ void VImage::ppmsave( const char *filename, VOption *options ) const
|
|
|
2379
2487
|
set( "filename", filename ) );
|
|
2380
2488
|
}
|
|
2381
2489
|
|
|
2490
|
+
void VImage::ppmsave_target( VTarget target, VOption *options ) const
|
|
2491
|
+
{
|
|
2492
|
+
call( "ppmsave_target",
|
|
2493
|
+
(options ? options : VImage::option())->
|
|
2494
|
+
set( "in", *this )->
|
|
2495
|
+
set( "target", target ) );
|
|
2496
|
+
}
|
|
2497
|
+
|
|
2382
2498
|
VImage VImage::premultiply( VOption *options ) const
|
|
2383
2499
|
{
|
|
2384
2500
|
VImage out;
|
package/src/metadata.cc
CHANGED
|
@@ -189,7 +189,7 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|
|
189
189
|
if (!baton->levels.empty()) {
|
|
190
190
|
int i = 0;
|
|
191
191
|
Napi::Array levels = Napi::Array::New(env, static_cast<size_t>(baton->levels.size()));
|
|
192
|
-
for (std::pair<int, int> const l : baton->levels) {
|
|
192
|
+
for (std::pair<int, int> const &l : baton->levels) {
|
|
193
193
|
Napi::Object level = Napi::Object::New(env);
|
|
194
194
|
level.Set("width", l.first);
|
|
195
195
|
level.Set("height", l.second);
|
package/src/operations.cc
CHANGED
|
@@ -27,29 +27,6 @@ using vips::VImage;
|
|
|
27
27
|
using vips::VError;
|
|
28
28
|
|
|
29
29
|
namespace sharp {
|
|
30
|
-
|
|
31
|
-
/*
|
|
32
|
-
Removes alpha channel, if any.
|
|
33
|
-
*/
|
|
34
|
-
VImage RemoveAlpha(VImage image) {
|
|
35
|
-
if (HasAlpha(image)) {
|
|
36
|
-
image = image.extract_band(0, VImage::option()->set("n", image.bands() - 1));
|
|
37
|
-
}
|
|
38
|
-
return image;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/*
|
|
42
|
-
Ensures alpha channel, if missing.
|
|
43
|
-
*/
|
|
44
|
-
VImage EnsureAlpha(VImage image) {
|
|
45
|
-
if (!HasAlpha(image)) {
|
|
46
|
-
std::vector<double> alpha;
|
|
47
|
-
alpha.push_back(sharp::MaximumImageAlpha(image.interpretation()));
|
|
48
|
-
image = image.bandjoin_const(alpha);
|
|
49
|
-
}
|
|
50
|
-
return image;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
30
|
/*
|
|
54
31
|
* Tint an image using the specified chroma, preserving the original image luminance
|
|
55
32
|
*/
|
package/src/operations.h
CHANGED
|
@@ -25,16 +25,6 @@ using vips::VImage;
|
|
|
25
25
|
|
|
26
26
|
namespace sharp {
|
|
27
27
|
|
|
28
|
-
/*
|
|
29
|
-
Removes alpha channel, if any.
|
|
30
|
-
*/
|
|
31
|
-
VImage RemoveAlpha(VImage image);
|
|
32
|
-
|
|
33
|
-
/*
|
|
34
|
-
Ensures alpha channel, if missing.
|
|
35
|
-
*/
|
|
36
|
-
VImage EnsureAlpha(VImage image);
|
|
37
|
-
|
|
38
28
|
/*
|
|
39
29
|
* Tint an image using the specified chroma, preserving the original image luminance
|
|
40
30
|
*/
|
package/src/pipeline.cc
CHANGED
|
@@ -684,6 +684,15 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
684
684
|
}
|
|
685
685
|
}
|
|
686
686
|
|
|
687
|
+
// Apply output ICC profile
|
|
688
|
+
if (!baton->withMetadataIcc.empty()) {
|
|
689
|
+
image = image.icc_transform(
|
|
690
|
+
const_cast<char*>(baton->withMetadataIcc.data()),
|
|
691
|
+
VImage::option()
|
|
692
|
+
->set("input_profile", "srgb")
|
|
693
|
+
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
|
694
|
+
}
|
|
695
|
+
|
|
687
696
|
// Override EXIF Orientation tag
|
|
688
697
|
if (baton->withMetadata && baton->withMetadataOrientation != -1) {
|
|
689
698
|
image = sharp::SetExifOrientation(image, baton->withMetadataOrientation);
|
|
@@ -693,6 +702,16 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
693
702
|
baton->channels = image.bands();
|
|
694
703
|
baton->width = image.width();
|
|
695
704
|
baton->height = image.height();
|
|
705
|
+
|
|
706
|
+
bool const supportsGifOutput = vips_type_find("VipsOperation", "magicksave") != 0 &&
|
|
707
|
+
vips_type_find("VipsOperation", "magicksave_buffer") != 0;
|
|
708
|
+
|
|
709
|
+
image = sharp::SetAnimationProperties(
|
|
710
|
+
image,
|
|
711
|
+
baton->pageHeight,
|
|
712
|
+
baton->delay,
|
|
713
|
+
baton->loop);
|
|
714
|
+
|
|
696
715
|
// Output
|
|
697
716
|
if (baton->fileOut.empty()) {
|
|
698
717
|
// Buffer output
|
|
@@ -703,7 +722,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
703
722
|
->set("strip", !baton->withMetadata)
|
|
704
723
|
->set("Q", baton->jpegQuality)
|
|
705
724
|
->set("interlace", baton->jpegProgressive)
|
|
706
|
-
->set("
|
|
725
|
+
->set("subsample_mode", baton->jpegChromaSubsampling == "4:4:4"
|
|
726
|
+
? VIPS_FOREIGN_JPEG_SUBSAMPLE_OFF
|
|
727
|
+
: VIPS_FOREIGN_JPEG_SUBSAMPLE_ON)
|
|
707
728
|
->set("trellis_quant", baton->jpegTrellisQuantisation)
|
|
708
729
|
->set("quant_table", baton->jpegQuantisationTable)
|
|
709
730
|
->set("overshoot_deringing", baton->jpegOvershootDeringing)
|
|
@@ -720,8 +741,8 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
720
741
|
baton->channels = std::min(baton->channels, 3);
|
|
721
742
|
}
|
|
722
743
|
} else if (baton->formatOut == "png" || (baton->formatOut == "input" &&
|
|
723
|
-
(inputImageType == sharp::ImageType::PNG || inputImageType == sharp::ImageType::GIF ||
|
|
724
|
-
|
|
744
|
+
(inputImageType == sharp::ImageType::PNG || (inputImageType == sharp::ImageType::GIF && !supportsGifOutput) ||
|
|
745
|
+
inputImageType == sharp::ImageType::SVG))) {
|
|
725
746
|
// Write PNG to buffer
|
|
726
747
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::PNG);
|
|
727
748
|
VipsArea *area = VIPS_AREA(image.pngsave_buffer(VImage::option()
|
|
@@ -755,6 +776,18 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
755
776
|
area->free_fn = nullptr;
|
|
756
777
|
vips_area_unref(area);
|
|
757
778
|
baton->formatOut = "webp";
|
|
779
|
+
} else if (baton->formatOut == "gif" ||
|
|
780
|
+
(baton->formatOut == "input" && inputImageType == sharp::ImageType::GIF && supportsGifOutput)) {
|
|
781
|
+
// Write GIF to buffer
|
|
782
|
+
sharp::AssertImageTypeDimensions(image, sharp::ImageType::GIF);
|
|
783
|
+
VipsArea *area = VIPS_AREA(image.magicksave_buffer(VImage::option()
|
|
784
|
+
->set("strip", !baton->withMetadata)
|
|
785
|
+
->set("format", "gif")));
|
|
786
|
+
baton->bufferOut = static_cast<char*>(area->data);
|
|
787
|
+
baton->bufferOutLength = area->length;
|
|
788
|
+
area->free_fn = nullptr;
|
|
789
|
+
vips_area_unref(area);
|
|
790
|
+
baton->formatOut = "gif";
|
|
758
791
|
} else if (baton->formatOut == "tiff" ||
|
|
759
792
|
(baton->formatOut == "input" && inputImageType == sharp::ImageType::TIFF)) {
|
|
760
793
|
// Write TIFF to buffer
|
|
@@ -769,7 +802,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
769
802
|
VipsArea *area = VIPS_AREA(image.tiffsave_buffer(VImage::option()
|
|
770
803
|
->set("strip", !baton->withMetadata)
|
|
771
804
|
->set("Q", baton->tiffQuality)
|
|
772
|
-
->set("
|
|
805
|
+
->set("bitdepth", baton->tiffBitdepth)
|
|
773
806
|
->set("compression", baton->tiffCompression)
|
|
774
807
|
->set("predictor", baton->tiffPredictor)
|
|
775
808
|
->set("pyramid", baton->tiffPyramid)
|
|
@@ -830,13 +863,16 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
830
863
|
bool const isJpeg = sharp::IsJpeg(baton->fileOut);
|
|
831
864
|
bool const isPng = sharp::IsPng(baton->fileOut);
|
|
832
865
|
bool const isWebp = sharp::IsWebp(baton->fileOut);
|
|
866
|
+
bool const isGif = sharp::IsGif(baton->fileOut);
|
|
833
867
|
bool const isTiff = sharp::IsTiff(baton->fileOut);
|
|
834
868
|
bool const isHeif = sharp::IsHeif(baton->fileOut);
|
|
835
869
|
bool const isDz = sharp::IsDz(baton->fileOut);
|
|
836
870
|
bool const isDzZip = sharp::IsDzZip(baton->fileOut);
|
|
837
871
|
bool const isV = sharp::IsV(baton->fileOut);
|
|
838
872
|
bool const mightMatchInput = baton->formatOut == "input";
|
|
839
|
-
bool const willMatchInput = mightMatchInput &&
|
|
873
|
+
bool const willMatchInput = mightMatchInput &&
|
|
874
|
+
!(isJpeg || isPng || isWebp || isGif || isTiff || isDz || isDzZip || isV);
|
|
875
|
+
|
|
840
876
|
if (baton->formatOut == "jpeg" || (mightMatchInput && isJpeg) ||
|
|
841
877
|
(willMatchInput && inputImageType == sharp::ImageType::JPEG)) {
|
|
842
878
|
// Write JPEG to file
|
|
@@ -845,7 +881,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
845
881
|
->set("strip", !baton->withMetadata)
|
|
846
882
|
->set("Q", baton->jpegQuality)
|
|
847
883
|
->set("interlace", baton->jpegProgressive)
|
|
848
|
-
->set("
|
|
884
|
+
->set("subsample_mode", baton->jpegChromaSubsampling == "4:4:4"
|
|
885
|
+
? VIPS_FOREIGN_JPEG_SUBSAMPLE_OFF
|
|
886
|
+
: VIPS_FOREIGN_JPEG_SUBSAMPLE_ON)
|
|
849
887
|
->set("trellis_quant", baton->jpegTrellisQuantisation)
|
|
850
888
|
->set("quant_table", baton->jpegQuantisationTable)
|
|
851
889
|
->set("overshoot_deringing", baton->jpegOvershootDeringing)
|
|
@@ -854,8 +892,8 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
854
892
|
baton->formatOut = "jpeg";
|
|
855
893
|
baton->channels = std::min(baton->channels, 3);
|
|
856
894
|
} else if (baton->formatOut == "png" || (mightMatchInput && isPng) || (willMatchInput &&
|
|
857
|
-
(inputImageType == sharp::ImageType::PNG || inputImageType == sharp::ImageType::GIF ||
|
|
858
|
-
|
|
895
|
+
(inputImageType == sharp::ImageType::PNG || (inputImageType == sharp::ImageType::GIF && !supportsGifOutput) ||
|
|
896
|
+
inputImageType == sharp::ImageType::SVG))) {
|
|
859
897
|
// Write PNG to file
|
|
860
898
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::PNG);
|
|
861
899
|
image.pngsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
|
@@ -881,6 +919,14 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
881
919
|
->set("reduction_effort", baton->webpReductionEffort)
|
|
882
920
|
->set("alpha_q", baton->webpAlphaQuality));
|
|
883
921
|
baton->formatOut = "webp";
|
|
922
|
+
} else if (baton->formatOut == "gif" || (mightMatchInput && isGif) ||
|
|
923
|
+
(willMatchInput && inputImageType == sharp::ImageType::GIF && supportsGifOutput)) {
|
|
924
|
+
// Write GIF to file
|
|
925
|
+
sharp::AssertImageTypeDimensions(image, sharp::ImageType::GIF);
|
|
926
|
+
image.magicksave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
|
927
|
+
->set("strip", !baton->withMetadata)
|
|
928
|
+
->set("format", "gif"));
|
|
929
|
+
baton->formatOut = "gif";
|
|
884
930
|
} else if (baton->formatOut == "tiff" || (mightMatchInput && isTiff) ||
|
|
885
931
|
(willMatchInput && inputImageType == sharp::ImageType::TIFF)) {
|
|
886
932
|
// Write TIFF to file
|
|
@@ -891,7 +937,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
891
937
|
image.tiffsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
|
892
938
|
->set("strip", !baton->withMetadata)
|
|
893
939
|
->set("Q", baton->tiffQuality)
|
|
894
|
-
->set("
|
|
940
|
+
->set("bitdepth", baton->tiffBitdepth)
|
|
895
941
|
->set("compression", baton->tiffCompression)
|
|
896
942
|
->set("predictor", baton->tiffPredictor)
|
|
897
943
|
->set("pyramid", baton->tiffPyramid)
|
|
@@ -940,7 +986,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
940
986
|
std::vector<std::pair<std::string, std::string>> options {
|
|
941
987
|
{"Q", std::to_string(baton->jpegQuality)},
|
|
942
988
|
{"interlace", baton->jpegProgressive ? "TRUE" : "FALSE"},
|
|
943
|
-
{"
|
|
989
|
+
{"subsample_mode", baton->jpegChromaSubsampling == "4:4:4" ? "off" : "on"},
|
|
944
990
|
{"trellis_quant", baton->jpegTrellisQuantisation ? "TRUE" : "FALSE"},
|
|
945
991
|
{"quant_table", std::to_string(baton->jpegQuantisationTable)},
|
|
946
992
|
{"overshoot_deringing", baton->jpegOvershootDeringing ? "TRUE": "FALSE"},
|
|
@@ -1282,6 +1328,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1282
1328
|
baton->fileOut = sharp::AttrAsStr(options, "fileOut");
|
|
1283
1329
|
baton->withMetadata = sharp::AttrAsBool(options, "withMetadata");
|
|
1284
1330
|
baton->withMetadataOrientation = sharp::AttrAsUint32(options, "withMetadataOrientation");
|
|
1331
|
+
baton->withMetadataIcc = sharp::AttrAsStr(options, "withMetadataIcc");
|
|
1285
1332
|
// Format-specific
|
|
1286
1333
|
baton->jpegQuality = sharp::AttrAsUint32(options, "jpegQuality");
|
|
1287
1334
|
baton->jpegProgressive = sharp::AttrAsBool(options, "jpegProgressive");
|
|
@@ -1306,7 +1353,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1306
1353
|
baton->webpReductionEffort = sharp::AttrAsUint32(options, "webpReductionEffort");
|
|
1307
1354
|
baton->tiffQuality = sharp::AttrAsUint32(options, "tiffQuality");
|
|
1308
1355
|
baton->tiffPyramid = sharp::AttrAsBool(options, "tiffPyramid");
|
|
1309
|
-
baton->
|
|
1356
|
+
baton->tiffBitdepth = sharp::AttrAsUint32(options, "tiffBitdepth");
|
|
1310
1357
|
baton->tiffTile = sharp::AttrAsBool(options, "tiffTile");
|
|
1311
1358
|
baton->tiffTileWidth = sharp::AttrAsUint32(options, "tiffTileWidth");
|
|
1312
1359
|
baton->tiffTileHeight = sharp::AttrAsUint32(options, "tiffTileHeight");
|
|
@@ -1324,6 +1371,18 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1324
1371
|
baton->heifCompression = static_cast<VipsForeignHeifCompression>(
|
|
1325
1372
|
vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_HEIF_COMPRESSION,
|
|
1326
1373
|
sharp::AttrAsStr(options, "heifCompression").data()));
|
|
1374
|
+
|
|
1375
|
+
// Animated output
|
|
1376
|
+
if (sharp::HasAttr(options, "pageHeight")) {
|
|
1377
|
+
baton->pageHeight = sharp::AttrAsUint32(options, "pageHeight");
|
|
1378
|
+
}
|
|
1379
|
+
if (sharp::HasAttr(options, "loop")) {
|
|
1380
|
+
baton->loop = sharp::AttrAsUint32(options, "loop");
|
|
1381
|
+
}
|
|
1382
|
+
if (sharp::HasAttr(options, "delay")) {
|
|
1383
|
+
baton->delay = sharp::AttrAsInt32Vector(options, "delay");
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1327
1386
|
// Tile output
|
|
1328
1387
|
baton->tileSize = sharp::AttrAsUint32(options, "tileSize");
|
|
1329
1388
|
baton->tileOverlap = sharp::AttrAsUint32(options, "tileOverlap");
|
package/src/pipeline.h
CHANGED
|
@@ -143,7 +143,7 @@ struct PipelineBaton {
|
|
|
143
143
|
VipsForeignTiffCompression tiffCompression;
|
|
144
144
|
VipsForeignTiffPredictor tiffPredictor;
|
|
145
145
|
bool tiffPyramid;
|
|
146
|
-
|
|
146
|
+
int tiffBitdepth;
|
|
147
147
|
bool tiffTile;
|
|
148
148
|
int tiffTileHeight;
|
|
149
149
|
int tiffTileWidth;
|
|
@@ -155,6 +155,7 @@ struct PipelineBaton {
|
|
|
155
155
|
std::string err;
|
|
156
156
|
bool withMetadata;
|
|
157
157
|
int withMetadataOrientation;
|
|
158
|
+
std::string withMetadataIcc;
|
|
158
159
|
std::unique_ptr<double[]> convKernel;
|
|
159
160
|
int convKernelWidth;
|
|
160
161
|
int convKernelHeight;
|
|
@@ -167,6 +168,9 @@ struct PipelineBaton {
|
|
|
167
168
|
bool removeAlpha;
|
|
168
169
|
bool ensureAlpha;
|
|
169
170
|
VipsInterpretation colourspace;
|
|
171
|
+
int pageHeight;
|
|
172
|
+
std::vector<int> delay;
|
|
173
|
+
int loop;
|
|
170
174
|
int tileSize;
|
|
171
175
|
int tileOverlap;
|
|
172
176
|
VipsForeignDzContainer tileContainer;
|
|
@@ -251,7 +255,7 @@ struct PipelineBaton {
|
|
|
251
255
|
tiffCompression(VIPS_FOREIGN_TIFF_COMPRESSION_JPEG),
|
|
252
256
|
tiffPredictor(VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL),
|
|
253
257
|
tiffPyramid(false),
|
|
254
|
-
|
|
258
|
+
tiffBitdepth(8),
|
|
255
259
|
tiffTile(false),
|
|
256
260
|
tiffTileHeight(256),
|
|
257
261
|
tiffTileWidth(256),
|
|
@@ -273,6 +277,9 @@ struct PipelineBaton {
|
|
|
273
277
|
removeAlpha(false),
|
|
274
278
|
ensureAlpha(false),
|
|
275
279
|
colourspace(VIPS_INTERPRETATION_LAST),
|
|
280
|
+
pageHeight(0),
|
|
281
|
+
delay{-1},
|
|
282
|
+
loop(-1),
|
|
276
283
|
tileSize(256),
|
|
277
284
|
tileOverlap(0),
|
|
278
285
|
tileContainer(VIPS_FOREIGN_DZ_CONTAINER_FS),
|
package/src/stats.cc
CHANGED
|
@@ -86,6 +86,18 @@ class StatsWorker : public Napi::AsyncWorker {
|
|
|
86
86
|
0.0, 1.0, 0.0);
|
|
87
87
|
laplacian.set("scale", 9.0);
|
|
88
88
|
baton->sharpness = greyscale.conv(laplacian).deviate();
|
|
89
|
+
// Most dominant sRGB colour via 4096-bin 3D histogram
|
|
90
|
+
vips::VImage hist = sharp::RemoveAlpha(image)
|
|
91
|
+
.colourspace(VIPS_INTERPRETATION_sRGB)
|
|
92
|
+
.hist_find_ndim(VImage::option()->set("bins", 16));
|
|
93
|
+
std::complex<double> maxpos = hist.maxpos();
|
|
94
|
+
int const dx = static_cast<int>(std::real(maxpos));
|
|
95
|
+
int const dy = static_cast<int>(std::imag(maxpos));
|
|
96
|
+
std::vector<double> pel = hist(dx, dy);
|
|
97
|
+
int const dz = std::distance(pel.begin(), std::find(pel.begin(), pel.end(), hist.max()));
|
|
98
|
+
baton->dominantRed = dx * 16 + 8;
|
|
99
|
+
baton->dominantGreen = dy * 16 + 8;
|
|
100
|
+
baton->dominantBlue = dz * 16 + 8;
|
|
89
101
|
} catch (vips::VError const &err) {
|
|
90
102
|
(baton->err).append(err.what());
|
|
91
103
|
}
|
|
@@ -133,6 +145,11 @@ class StatsWorker : public Napi::AsyncWorker {
|
|
|
133
145
|
info.Set("isOpaque", baton->isOpaque);
|
|
134
146
|
info.Set("entropy", baton->entropy);
|
|
135
147
|
info.Set("sharpness", baton->sharpness);
|
|
148
|
+
Napi::Object dominant = Napi::Object::New(env);
|
|
149
|
+
dominant.Set("r", baton->dominantRed);
|
|
150
|
+
dominant.Set("g", baton->dominantGreen);
|
|
151
|
+
dominant.Set("b", baton->dominantBlue);
|
|
152
|
+
info.Set("dominant", dominant);
|
|
136
153
|
Callback().MakeCallback(Receiver().Value(), { env.Null(), info });
|
|
137
154
|
} else {
|
|
138
155
|
Callback().MakeCallback(Receiver().Value(), { Napi::Error::New(env, baton->err).Value() });
|
package/src/stats.h
CHANGED
|
@@ -48,6 +48,9 @@ struct StatsBaton {
|
|
|
48
48
|
bool isOpaque;
|
|
49
49
|
double entropy;
|
|
50
50
|
double sharpness;
|
|
51
|
+
int dominantRed;
|
|
52
|
+
int dominantGreen;
|
|
53
|
+
int dominantBlue;
|
|
51
54
|
|
|
52
55
|
std::string err;
|
|
53
56
|
|
|
@@ -55,7 +58,10 @@ struct StatsBaton {
|
|
|
55
58
|
input(nullptr),
|
|
56
59
|
isOpaque(true),
|
|
57
60
|
entropy(0.0),
|
|
58
|
-
sharpness(0.0)
|
|
61
|
+
sharpness(0.0),
|
|
62
|
+
dominantRed(0),
|
|
63
|
+
dominantGreen(0),
|
|
64
|
+
dominantBlue(0)
|
|
59
65
|
{}
|
|
60
66
|
};
|
|
61
67
|
|