sharp 0.26.2 → 0.27.2
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 +3 -3
- package/install/libvips.js +14 -2
- package/lib/channel.js +1 -1
- package/lib/colour.js +7 -0
- package/lib/composite.js +10 -7
- package/lib/constructor.js +57 -15
- package/lib/input.js +41 -10
- package/lib/is.js +10 -0
- package/lib/libvips.js +16 -3
- package/lib/operation.js +99 -0
- package/lib/output.js +81 -36
- package/lib/utility.js +25 -8
- package/package.json +24 -18
- package/src/common.cc +77 -57
- package/src/common.h +11 -4
- package/src/metadata.cc +6 -0
- package/src/metadata.h +1 -0
- package/src/operations.cc +1 -1
- package/src/pipeline.cc +50 -17
- package/src/pipeline.h +24 -4
- package/src/sharp.cc +1 -0
package/src/pipeline.cc
CHANGED
|
@@ -485,6 +485,18 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
485
485
|
baton->leftOffsetPost, baton->topOffsetPost, baton->widthPost, baton->heightPost);
|
|
486
486
|
}
|
|
487
487
|
|
|
488
|
+
// Affine transform
|
|
489
|
+
if (baton->affineMatrix.size() > 0) {
|
|
490
|
+
std::vector<double> background;
|
|
491
|
+
std::tie(image, background) = sharp::ApplyAlpha(image, baton->affineBackground);
|
|
492
|
+
image = image.affine(baton->affineMatrix, VImage::option()->set("background", background)
|
|
493
|
+
->set("idx", baton->affineIdx)
|
|
494
|
+
->set("idy", baton->affineIdy)
|
|
495
|
+
->set("odx", baton->affineOdx)
|
|
496
|
+
->set("ody", baton->affineOdy)
|
|
497
|
+
->set("interpolate", baton->affineInterpolator));
|
|
498
|
+
}
|
|
499
|
+
|
|
488
500
|
// Extend edges
|
|
489
501
|
if (baton->extendTop > 0 || baton->extendBottom > 0 || baton->extendLeft > 0 || baton->extendRight > 0) {
|
|
490
502
|
std::vector<double> background;
|
|
@@ -558,7 +570,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
558
570
|
int left;
|
|
559
571
|
int top;
|
|
560
572
|
compositeImage = compositeImage.replicate(across, down);
|
|
561
|
-
if (composite->
|
|
573
|
+
if (composite->hasOffset) {
|
|
562
574
|
std::tie(left, top) = sharp::CalculateCrop(
|
|
563
575
|
compositeImage.width(), compositeImage.height(), image.width(), image.height(),
|
|
564
576
|
composite->left, composite->top);
|
|
@@ -580,7 +592,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
580
592
|
// Calculate position
|
|
581
593
|
int left;
|
|
582
594
|
int top;
|
|
583
|
-
if (composite->
|
|
595
|
+
if (composite->hasOffset) {
|
|
584
596
|
// Composite image at given offsets
|
|
585
597
|
std::tie(left, top) = sharp::CalculateCrop(image.width(), image.height(),
|
|
586
598
|
compositeImage.width(), compositeImage.height(), composite->left, composite->top);
|
|
@@ -718,7 +730,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
718
730
|
if (baton->formatOut == "jpeg" || (baton->formatOut == "input" && inputImageType == sharp::ImageType::JPEG)) {
|
|
719
731
|
// Write JPEG to buffer
|
|
720
732
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::JPEG);
|
|
721
|
-
VipsArea *area =
|
|
733
|
+
VipsArea *area = reinterpret_cast<VipsArea*>(image.jpegsave_buffer(VImage::option()
|
|
722
734
|
->set("strip", !baton->withMetadata)
|
|
723
735
|
->set("Q", baton->jpegQuality)
|
|
724
736
|
->set("interlace", baton->jpegProgressive)
|
|
@@ -745,7 +757,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
745
757
|
inputImageType == sharp::ImageType::SVG))) {
|
|
746
758
|
// Write PNG to buffer
|
|
747
759
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::PNG);
|
|
748
|
-
VipsArea *area =
|
|
760
|
+
VipsArea *area = reinterpret_cast<VipsArea*>(image.pngsave_buffer(VImage::option()
|
|
749
761
|
->set("strip", !baton->withMetadata)
|
|
750
762
|
->set("interlace", baton->pngProgressive)
|
|
751
763
|
->set("compression", baton->pngCompressionLevel)
|
|
@@ -763,7 +775,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
763
775
|
(baton->formatOut == "input" && inputImageType == sharp::ImageType::WEBP)) {
|
|
764
776
|
// Write WEBP to buffer
|
|
765
777
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::WEBP);
|
|
766
|
-
VipsArea *area =
|
|
778
|
+
VipsArea *area = reinterpret_cast<VipsArea*>(image.webpsave_buffer(VImage::option()
|
|
767
779
|
->set("strip", !baton->withMetadata)
|
|
768
780
|
->set("Q", baton->webpQuality)
|
|
769
781
|
->set("lossless", baton->webpLossless)
|
|
@@ -780,7 +792,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
780
792
|
(baton->formatOut == "input" && inputImageType == sharp::ImageType::GIF && supportsGifOutput)) {
|
|
781
793
|
// Write GIF to buffer
|
|
782
794
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::GIF);
|
|
783
|
-
VipsArea *area =
|
|
795
|
+
VipsArea *area = reinterpret_cast<VipsArea*>(image.magicksave_buffer(VImage::option()
|
|
784
796
|
->set("strip", !baton->withMetadata)
|
|
785
797
|
->set("optimize_gif_frames", TRUE)
|
|
786
798
|
->set("optimize_gif_transparency", TRUE)
|
|
@@ -801,7 +813,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
801
813
|
if (baton->tiffPredictor == VIPS_FOREIGN_TIFF_PREDICTOR_FLOAT) {
|
|
802
814
|
image = image.cast(VIPS_FORMAT_FLOAT);
|
|
803
815
|
}
|
|
804
|
-
VipsArea *area =
|
|
816
|
+
VipsArea *area = reinterpret_cast<VipsArea*>(image.tiffsave_buffer(VImage::option()
|
|
805
817
|
->set("strip", !baton->withMetadata)
|
|
806
818
|
->set("Q", baton->tiffQuality)
|
|
807
819
|
->set("bitdepth", baton->tiffBitdepth)
|
|
@@ -821,10 +833,15 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
821
833
|
} else if (baton->formatOut == "heif" ||
|
|
822
834
|
(baton->formatOut == "input" && inputImageType == sharp::ImageType::HEIF)) {
|
|
823
835
|
// Write HEIF to buffer
|
|
824
|
-
VipsArea *area =
|
|
836
|
+
VipsArea *area = reinterpret_cast<VipsArea*>(image.heifsave_buffer(VImage::option()
|
|
825
837
|
->set("strip", !baton->withMetadata)
|
|
826
838
|
->set("compression", baton->heifCompression)
|
|
827
839
|
->set("Q", baton->heifQuality)
|
|
840
|
+
->set("speed", baton->heifSpeed)
|
|
841
|
+
#if defined(VIPS_TYPE_FOREIGN_SUBSAMPLE)
|
|
842
|
+
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
|
843
|
+
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
|
844
|
+
#endif
|
|
828
845
|
->set("lossless", baton->heifLossless)));
|
|
829
846
|
baton->bufferOut = static_cast<char*>(area->data);
|
|
830
847
|
baton->bufferOutLength = area->length;
|
|
@@ -873,7 +890,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
873
890
|
bool const isV = sharp::IsV(baton->fileOut);
|
|
874
891
|
bool const mightMatchInput = baton->formatOut == "input";
|
|
875
892
|
bool const willMatchInput = mightMatchInput &&
|
|
876
|
-
!(isJpeg || isPng || isWebp || isGif || isTiff || isDz || isDzZip || isV);
|
|
893
|
+
!(isJpeg || isPng || isWebp || isGif || isTiff || isHeif || isDz || isDzZip || isV);
|
|
877
894
|
|
|
878
895
|
if (baton->formatOut == "jpeg" || (mightMatchInput && isJpeg) ||
|
|
879
896
|
(willMatchInput && inputImageType == sharp::ImageType::JPEG)) {
|
|
@@ -938,6 +955,10 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
938
955
|
sharp::AssertImageTypeDimensions(image, sharp::ImageType::JPEG);
|
|
939
956
|
baton->channels = std::min(baton->channels, 3);
|
|
940
957
|
}
|
|
958
|
+
// Cast pixel values to float, if required
|
|
959
|
+
if (baton->tiffPredictor == VIPS_FOREIGN_TIFF_PREDICTOR_FLOAT) {
|
|
960
|
+
image = image.cast(VIPS_FORMAT_FLOAT);
|
|
961
|
+
}
|
|
941
962
|
image.tiffsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
|
942
963
|
->set("strip", !baton->withMetadata)
|
|
943
964
|
->set("Q", baton->tiffQuality)
|
|
@@ -954,13 +975,15 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
954
975
|
} else if (baton->formatOut == "heif" || (mightMatchInput && isHeif) ||
|
|
955
976
|
(willMatchInput && inputImageType == sharp::ImageType::HEIF)) {
|
|
956
977
|
// Write HEIF to file
|
|
957
|
-
if (sharp::IsAvif(baton->fileOut)) {
|
|
958
|
-
baton->heifCompression = VIPS_FOREIGN_HEIF_COMPRESSION_AV1;
|
|
959
|
-
}
|
|
960
978
|
image.heifsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
|
|
961
979
|
->set("strip", !baton->withMetadata)
|
|
962
980
|
->set("Q", baton->heifQuality)
|
|
963
981
|
->set("compression", baton->heifCompression)
|
|
982
|
+
->set("speed", baton->heifSpeed)
|
|
983
|
+
#if defined(VIPS_TYPE_FOREIGN_SUBSAMPLE)
|
|
984
|
+
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
|
985
|
+
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
|
986
|
+
#endif
|
|
964
987
|
->set("lossless", baton->heifLossless));
|
|
965
988
|
baton->formatOut = "heif";
|
|
966
989
|
} else if (baton->formatOut == "dz" || isDz || isDzZip) {
|
|
@@ -1242,6 +1265,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1242
1265
|
composite->gravity = sharp::AttrAsUint32(compositeObject, "gravity");
|
|
1243
1266
|
composite->left = sharp::AttrAsInt32(compositeObject, "left");
|
|
1244
1267
|
composite->top = sharp::AttrAsInt32(compositeObject, "top");
|
|
1268
|
+
composite->hasOffset = sharp::AttrAsBool(compositeObject, "hasOffset");
|
|
1245
1269
|
composite->tile = sharp::AttrAsBool(compositeObject, "tile");
|
|
1246
1270
|
composite->premultiplied = sharp::AttrAsBool(compositeObject, "premultiplied");
|
|
1247
1271
|
baton->composite.push_back(composite);
|
|
@@ -1249,7 +1273,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1249
1273
|
// Resize options
|
|
1250
1274
|
baton->withoutEnlargement = sharp::AttrAsBool(options, "withoutEnlargement");
|
|
1251
1275
|
baton->position = sharp::AttrAsInt32(options, "position");
|
|
1252
|
-
baton->resizeBackground = sharp::
|
|
1276
|
+
baton->resizeBackground = sharp::AttrAsVectorOfDouble(options, "resizeBackground");
|
|
1253
1277
|
baton->kernel = sharp::AttrAsStr(options, "kernel");
|
|
1254
1278
|
baton->fastShrinkOnLoad = sharp::AttrAsBool(options, "fastShrinkOnLoad");
|
|
1255
1279
|
// Join Channel Options
|
|
@@ -1262,7 +1286,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1262
1286
|
}
|
|
1263
1287
|
// Operators
|
|
1264
1288
|
baton->flatten = sharp::AttrAsBool(options, "flatten");
|
|
1265
|
-
baton->flattenBackground = sharp::
|
|
1289
|
+
baton->flattenBackground = sharp::AttrAsVectorOfDouble(options, "flattenBackground");
|
|
1266
1290
|
baton->negate = sharp::AttrAsBool(options, "negate");
|
|
1267
1291
|
baton->blurSigma = sharp::AttrAsDouble(options, "blurSigma");
|
|
1268
1292
|
baton->brightness = sharp::AttrAsDouble(options, "brightness");
|
|
@@ -1284,7 +1308,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1284
1308
|
baton->useExifOrientation = sharp::AttrAsBool(options, "useExifOrientation");
|
|
1285
1309
|
baton->angle = sharp::AttrAsInt32(options, "angle");
|
|
1286
1310
|
baton->rotationAngle = sharp::AttrAsDouble(options, "rotationAngle");
|
|
1287
|
-
baton->rotationBackground = sharp::
|
|
1311
|
+
baton->rotationBackground = sharp::AttrAsVectorOfDouble(options, "rotationBackground");
|
|
1288
1312
|
baton->rotateBeforePreExtract = sharp::AttrAsBool(options, "rotateBeforePreExtract");
|
|
1289
1313
|
baton->flip = sharp::AttrAsBool(options, "flip");
|
|
1290
1314
|
baton->flop = sharp::AttrAsBool(options, "flop");
|
|
@@ -1292,8 +1316,15 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1292
1316
|
baton->extendBottom = sharp::AttrAsInt32(options, "extendBottom");
|
|
1293
1317
|
baton->extendLeft = sharp::AttrAsInt32(options, "extendLeft");
|
|
1294
1318
|
baton->extendRight = sharp::AttrAsInt32(options, "extendRight");
|
|
1295
|
-
baton->extendBackground = sharp::
|
|
1319
|
+
baton->extendBackground = sharp::AttrAsVectorOfDouble(options, "extendBackground");
|
|
1296
1320
|
baton->extractChannel = sharp::AttrAsInt32(options, "extractChannel");
|
|
1321
|
+
baton->affineMatrix = sharp::AttrAsVectorOfDouble(options, "affineMatrix");
|
|
1322
|
+
baton->affineBackground = sharp::AttrAsVectorOfDouble(options, "affineBackground");
|
|
1323
|
+
baton->affineIdx = sharp::AttrAsDouble(options, "affineIdx");
|
|
1324
|
+
baton->affineIdy = sharp::AttrAsDouble(options, "affineIdy");
|
|
1325
|
+
baton->affineOdx = sharp::AttrAsDouble(options, "affineOdx");
|
|
1326
|
+
baton->affineOdy = sharp::AttrAsDouble(options, "affineOdy");
|
|
1327
|
+
baton->affineInterpolator = vips::VInterpolate::new_from_name(sharp::AttrAsStr(options, "affineInterpolator").data());
|
|
1297
1328
|
|
|
1298
1329
|
baton->removeAlpha = sharp::AttrAsBool(options, "removeAlpha");
|
|
1299
1330
|
baton->ensureAlpha = sharp::AttrAsBool(options, "ensureAlpha");
|
|
@@ -1376,6 +1407,8 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1376
1407
|
baton->heifCompression = static_cast<VipsForeignHeifCompression>(
|
|
1377
1408
|
vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_HEIF_COMPRESSION,
|
|
1378
1409
|
sharp::AttrAsStr(options, "heifCompression").data()));
|
|
1410
|
+
baton->heifSpeed = sharp::AttrAsUint32(options, "heifSpeed");
|
|
1411
|
+
baton->heifChromaSubsampling = sharp::AttrAsStr(options, "heifChromaSubsampling");
|
|
1379
1412
|
|
|
1380
1413
|
// Animated output
|
|
1381
1414
|
if (sharp::HasAttr(options, "pageHeight")) {
|
|
@@ -1392,7 +1425,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1392
1425
|
baton->tileSize = sharp::AttrAsUint32(options, "tileSize");
|
|
1393
1426
|
baton->tileOverlap = sharp::AttrAsUint32(options, "tileOverlap");
|
|
1394
1427
|
baton->tileAngle = sharp::AttrAsInt32(options, "tileAngle");
|
|
1395
|
-
baton->tileBackground = sharp::
|
|
1428
|
+
baton->tileBackground = sharp::AttrAsVectorOfDouble(options, "tileBackground");
|
|
1396
1429
|
baton->tileSkipBlanks = sharp::AttrAsInt32(options, "tileSkipBlanks");
|
|
1397
1430
|
baton->tileContainer = static_cast<VipsForeignDzContainer>(
|
|
1398
1431
|
vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_DZ_CONTAINER,
|
package/src/pipeline.h
CHANGED
|
@@ -40,6 +40,7 @@ struct Composite {
|
|
|
40
40
|
int gravity;
|
|
41
41
|
int left;
|
|
42
42
|
int top;
|
|
43
|
+
bool hasOffset;
|
|
43
44
|
bool tile;
|
|
44
45
|
bool premultiplied;
|
|
45
46
|
|
|
@@ -47,8 +48,9 @@ struct Composite {
|
|
|
47
48
|
input(nullptr),
|
|
48
49
|
mode(VIPS_BLEND_MODE_OVER),
|
|
49
50
|
gravity(0),
|
|
50
|
-
left(
|
|
51
|
-
top(
|
|
51
|
+
left(0),
|
|
52
|
+
top(0),
|
|
53
|
+
hasOffset(false),
|
|
52
54
|
tile(false),
|
|
53
55
|
premultiplied(false) {}
|
|
54
56
|
};
|
|
@@ -119,6 +121,13 @@ struct PipelineBaton {
|
|
|
119
121
|
int extendRight;
|
|
120
122
|
std::vector<double> extendBackground;
|
|
121
123
|
bool withoutEnlargement;
|
|
124
|
+
std::vector<double> affineMatrix;
|
|
125
|
+
std::vector<double> affineBackground;
|
|
126
|
+
double affineIdx;
|
|
127
|
+
double affineIdy;
|
|
128
|
+
double affineOdx;
|
|
129
|
+
double affineOdy;
|
|
130
|
+
vips::VInterpolate affineInterpolator;
|
|
122
131
|
int jpegQuality;
|
|
123
132
|
bool jpegProgressive;
|
|
124
133
|
std::string jpegChromaSubsampling;
|
|
@@ -152,6 +161,8 @@ struct PipelineBaton {
|
|
|
152
161
|
double tiffYres;
|
|
153
162
|
int heifQuality;
|
|
154
163
|
VipsForeignHeifCompression heifCompression;
|
|
164
|
+
int heifSpeed;
|
|
165
|
+
std::string heifChromaSubsampling;
|
|
155
166
|
bool heifLossless;
|
|
156
167
|
std::string err;
|
|
157
168
|
bool withMetadata;
|
|
@@ -231,6 +242,13 @@ struct PipelineBaton {
|
|
|
231
242
|
extendRight(0),
|
|
232
243
|
extendBackground{ 0.0, 0.0, 0.0, 255.0 },
|
|
233
244
|
withoutEnlargement(false),
|
|
245
|
+
affineMatrix{ 1.0, 0.0, 0.0, 1.0 },
|
|
246
|
+
affineBackground{ 0.0, 0.0, 0.0, 255.0 },
|
|
247
|
+
affineIdx(0),
|
|
248
|
+
affineIdy(0),
|
|
249
|
+
affineOdx(0),
|
|
250
|
+
affineOdy(0),
|
|
251
|
+
affineInterpolator(vips::VInterpolate::new_from_name("bicubic")),
|
|
234
252
|
jpegQuality(80),
|
|
235
253
|
jpegProgressive(false),
|
|
236
254
|
jpegChromaSubsampling("4:2:0"),
|
|
@@ -262,8 +280,10 @@ struct PipelineBaton {
|
|
|
262
280
|
tiffTileWidth(256),
|
|
263
281
|
tiffXres(1.0),
|
|
264
282
|
tiffYres(1.0),
|
|
265
|
-
heifQuality(
|
|
266
|
-
heifCompression(
|
|
283
|
+
heifQuality(50),
|
|
284
|
+
heifCompression(VIPS_FOREIGN_HEIF_COMPRESSION_AV1),
|
|
285
|
+
heifSpeed(5),
|
|
286
|
+
heifChromaSubsampling("4:2:0"),
|
|
267
287
|
heifLossless(false),
|
|
268
288
|
withMetadata(false),
|
|
269
289
|
withMetadataOrientation(-1),
|