@revizly/sharp 0.34.1-revizly8 → 0.34.4-revizly1
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/lib/channel.js +2 -0
- package/lib/constructor.js +19 -7
- package/lib/index.d.ts +115 -20
- package/lib/input.js +113 -23
- package/lib/libvips.js +2 -2
- package/lib/output.js +66 -0
- package/lib/resize.js +10 -5
- package/lib/utility.js +3 -9
- package/package.json +20 -25
- package/src/binding.gyp +7 -4
- package/src/common.cc +76 -68
- package/src/common.h +20 -21
- package/src/metadata.cc +4 -0
- package/src/pipeline.cc +60 -69
- package/src/pipeline.h +5 -1
- package/src/stats.cc +1 -1
- package/src/utilities.cc +1 -1
package/src/pipeline.cc
CHANGED
|
@@ -92,31 +92,22 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
92
92
|
// Calculate angle of rotation
|
|
93
93
|
VipsAngle rotation = VIPS_ANGLE_D0;
|
|
94
94
|
VipsAngle autoRotation = VIPS_ANGLE_D0;
|
|
95
|
-
bool autoFlip = false;
|
|
96
95
|
bool autoFlop = false;
|
|
97
96
|
|
|
98
97
|
if (baton->input->autoOrient) {
|
|
99
98
|
// Rotate and flip image according to Exif orientation
|
|
100
|
-
std::tie(autoRotation,
|
|
101
|
-
image = sharp::RemoveExifOrientation(image);
|
|
99
|
+
std::tie(autoRotation, autoFlop) = CalculateExifRotationAndFlop(sharp::ExifOrientation(image));
|
|
102
100
|
}
|
|
103
101
|
|
|
104
102
|
rotation = CalculateAngleRotation(baton->angle);
|
|
105
103
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
baton->rotationAngle != 0.0);
|
|
111
|
-
|
|
112
|
-
if (shouldRotateBefore) {
|
|
113
|
-
image = sharp::StaySequential(image,
|
|
114
|
-
rotation != VIPS_ANGLE_D0 ||
|
|
115
|
-
autoRotation != VIPS_ANGLE_D0 ||
|
|
116
|
-
autoFlip ||
|
|
117
|
-
baton->flip ||
|
|
118
|
-
baton->rotationAngle != 0.0);
|
|
104
|
+
bool const shouldRotateBefore = baton->rotateBefore &&
|
|
105
|
+
(rotation != VIPS_ANGLE_D0 || baton->flip || baton->flop || baton->rotationAngle != 0.0);
|
|
106
|
+
bool const shouldOrientBefore = (shouldRotateBefore || baton->orientBefore) &&
|
|
107
|
+
(autoRotation != VIPS_ANGLE_D0 || autoFlop);
|
|
119
108
|
|
|
109
|
+
if (shouldOrientBefore) {
|
|
110
|
+
image = sharp::StaySequential(image, autoRotation != VIPS_ANGLE_D0);
|
|
120
111
|
if (autoRotation != VIPS_ANGLE_D0) {
|
|
121
112
|
if (autoRotation != VIPS_ANGLE_D180) {
|
|
122
113
|
MultiPageUnsupported(nPages, "Rotate");
|
|
@@ -124,14 +115,20 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
124
115
|
image = image.rot(autoRotation);
|
|
125
116
|
autoRotation = VIPS_ANGLE_D0;
|
|
126
117
|
}
|
|
127
|
-
if (
|
|
118
|
+
if (autoFlop) {
|
|
119
|
+
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
|
120
|
+
autoFlop = false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (shouldRotateBefore) {
|
|
125
|
+
image = sharp::StaySequential(image, rotation != VIPS_ANGLE_D0 || baton->flip || baton->rotationAngle != 0.0);
|
|
126
|
+
if (baton->flip) {
|
|
128
127
|
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
|
129
|
-
autoFlip = false;
|
|
130
128
|
baton->flip = false;
|
|
131
129
|
}
|
|
132
|
-
if (
|
|
130
|
+
if (baton->flop) {
|
|
133
131
|
image = image.flip(VIPS_DIRECTION_HORIZONTAL);
|
|
134
|
-
autoFlop = false;
|
|
135
132
|
baton->flop = false;
|
|
136
133
|
}
|
|
137
134
|
if (rotation != VIPS_ANGLE_D0) {
|
|
@@ -146,6 +143,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
146
143
|
std::vector<double> background;
|
|
147
144
|
std::tie(image, background) = sharp::ApplyAlpha(image, baton->rotationBackground, false);
|
|
148
145
|
image = image.rotate(baton->rotationAngle, VImage::option()->set("background", background)).copy_memory();
|
|
146
|
+
baton->rotationAngle = 0.0;
|
|
149
147
|
}
|
|
150
148
|
}
|
|
151
149
|
|
|
@@ -184,8 +182,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
184
182
|
// When auto-rotating by 90 or 270 degrees, swap the target width and
|
|
185
183
|
// height to ensure the behavior aligns with how it would have been if
|
|
186
184
|
// the rotation had taken place *before* resizing.
|
|
187
|
-
if (
|
|
188
|
-
(autoRotation == VIPS_ANGLE_D90 || autoRotation == VIPS_ANGLE_D270)) {
|
|
185
|
+
if (autoRotation == VIPS_ANGLE_D90 || autoRotation == VIPS_ANGLE_D270) {
|
|
189
186
|
std::swap(targetResizeWidth, targetResizeHeight);
|
|
190
187
|
}
|
|
191
188
|
|
|
@@ -207,7 +204,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
207
204
|
// - input colourspace is not specified;
|
|
208
205
|
bool const shouldPreShrink = (targetResizeWidth > 0 || targetResizeHeight > 0) &&
|
|
209
206
|
baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold < 0.0 &&
|
|
210
|
-
baton->colourspacePipeline == VIPS_INTERPRETATION_LAST && !shouldRotateBefore;
|
|
207
|
+
baton->colourspacePipeline == VIPS_INTERPRETATION_LAST && !(shouldOrientBefore || shouldRotateBefore);
|
|
211
208
|
|
|
212
209
|
if (shouldPreShrink) {
|
|
213
210
|
// The common part of the shrink: the bit by which both axes must be shrunk
|
|
@@ -241,11 +238,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
241
238
|
// factor for jpegload*, a double scale factor for webpload*,
|
|
242
239
|
// pdfload* and svgload*
|
|
243
240
|
if (jpegShrinkOnLoad > 1) {
|
|
244
|
-
vips::VOption *option =
|
|
245
|
-
->set("access", access)
|
|
246
|
-
->set("shrink", jpegShrinkOnLoad)
|
|
247
|
-
->set("unlimited", baton->input->unlimited)
|
|
248
|
-
->set("fail_on", baton->input->failOn);
|
|
241
|
+
vips::VOption *option = GetOptionsForImageType(inputImageType, baton->input)->set("shrink", jpegShrinkOnLoad);
|
|
249
242
|
if (baton->input->buffer != nullptr) {
|
|
250
243
|
// Reload JPEG buffer
|
|
251
244
|
VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);
|
|
@@ -256,14 +249,8 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
256
249
|
image = VImage::jpegload(const_cast<char*>(baton->input->file.data()), option);
|
|
257
250
|
}
|
|
258
251
|
} else if (scale != 1.0) {
|
|
259
|
-
vips::VOption *option =
|
|
260
|
-
->set("access", access)
|
|
261
|
-
->set("scale", scale)
|
|
262
|
-
->set("fail_on", baton->input->failOn);
|
|
252
|
+
vips::VOption *option = GetOptionsForImageType(inputImageType, baton->input)->set("scale", scale);
|
|
263
253
|
if (inputImageType == sharp::ImageType::WEBP) {
|
|
264
|
-
option->set("n", baton->input->pages);
|
|
265
|
-
option->set("page", baton->input->page);
|
|
266
|
-
|
|
267
254
|
if (baton->input->buffer != nullptr) {
|
|
268
255
|
// Reload WebP buffer
|
|
269
256
|
VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);
|
|
@@ -274,9 +261,6 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
274
261
|
image = VImage::webpload(const_cast<char*>(baton->input->file.data()), option);
|
|
275
262
|
}
|
|
276
263
|
} else if (inputImageType == sharp::ImageType::SVG) {
|
|
277
|
-
option->set("unlimited", baton->input->unlimited);
|
|
278
|
-
option->set("dpi", baton->input->density);
|
|
279
|
-
|
|
280
264
|
if (baton->input->buffer != nullptr) {
|
|
281
265
|
// Reload SVG buffer
|
|
282
266
|
VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);
|
|
@@ -291,10 +275,6 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
291
275
|
throw vips::VError("Input SVG image will exceed 32767x32767 pixel limit when scaled");
|
|
292
276
|
}
|
|
293
277
|
} else if (inputImageType == sharp::ImageType::PDF) {
|
|
294
|
-
option->set("n", baton->input->pages);
|
|
295
|
-
option->set("page", baton->input->page);
|
|
296
|
-
option->set("dpi", baton->input->density);
|
|
297
|
-
|
|
298
278
|
if (baton->input->buffer != nullptr) {
|
|
299
279
|
// Reload PDF buffer
|
|
300
280
|
VipsBlob *blob = vips_blob_new(nullptr, baton->input->buffer, baton->input->bufferLength);
|
|
@@ -304,7 +284,6 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
304
284
|
// Reload PDF file
|
|
305
285
|
image = VImage::pdfload(const_cast<char*>(baton->input->file.data()), option);
|
|
306
286
|
}
|
|
307
|
-
|
|
308
287
|
sharp::SetDensity(image, baton->input->density);
|
|
309
288
|
}
|
|
310
289
|
} else {
|
|
@@ -312,6 +291,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
312
291
|
throw vips::VError("Input SVG image exceeds 32767x32767 pixel limit");
|
|
313
292
|
}
|
|
314
293
|
}
|
|
294
|
+
if (baton->input->autoOrient) {
|
|
295
|
+
image = sharp::RemoveExifOrientation(image);
|
|
296
|
+
}
|
|
315
297
|
|
|
316
298
|
// Any pre-shrinking may already have been done
|
|
317
299
|
inputWidth = image.width();
|
|
@@ -414,7 +396,6 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
414
396
|
image = sharp::StaySequential(image,
|
|
415
397
|
autoRotation != VIPS_ANGLE_D0 ||
|
|
416
398
|
baton->flip ||
|
|
417
|
-
autoFlip ||
|
|
418
399
|
rotation != VIPS_ANGLE_D0);
|
|
419
400
|
// Auto-rotate post-extract
|
|
420
401
|
if (autoRotation != VIPS_ANGLE_D0) {
|
|
@@ -424,7 +405,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
424
405
|
image = image.rot(autoRotation);
|
|
425
406
|
}
|
|
426
407
|
// Mirror vertically (up-down) about the x-axis
|
|
427
|
-
if (baton->flip
|
|
408
|
+
if (baton->flip) {
|
|
428
409
|
image = image.flip(VIPS_DIRECTION_VERTICAL);
|
|
429
410
|
}
|
|
430
411
|
// Mirror horizontally (left-right) about the y-axis
|
|
@@ -531,7 +512,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
531
512
|
}
|
|
532
513
|
|
|
533
514
|
// Rotate post-extract non-90 angle
|
|
534
|
-
if (!baton->
|
|
515
|
+
if (!baton->rotateBefore && baton->rotationAngle != 0.0) {
|
|
535
516
|
MultiPageUnsupported(nPages, "Rotate");
|
|
536
517
|
image = sharp::StaySequential(image);
|
|
537
518
|
std::vector<double> background;
|
|
@@ -668,26 +649,20 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
668
649
|
sharp::ImageType compositeImageType = sharp::ImageType::UNKNOWN;
|
|
669
650
|
composite->input->access = access;
|
|
670
651
|
std::tie(compositeImage, compositeImageType) = sharp::OpenInput(composite->input);
|
|
671
|
-
compositeImage = sharp::EnsureColourspace(compositeImage, baton->colourspacePipeline);
|
|
672
652
|
|
|
673
653
|
if (composite->input->autoOrient) {
|
|
674
654
|
// Respect EXIF Orientation
|
|
675
655
|
VipsAngle compositeAutoRotation = VIPS_ANGLE_D0;
|
|
676
|
-
bool compositeAutoFlip = false;
|
|
677
656
|
bool compositeAutoFlop = false;
|
|
678
|
-
std::tie(compositeAutoRotation,
|
|
679
|
-
|
|
657
|
+
std::tie(compositeAutoRotation, compositeAutoFlop) =
|
|
658
|
+
CalculateExifRotationAndFlop(sharp::ExifOrientation(compositeImage));
|
|
680
659
|
|
|
681
660
|
compositeImage = sharp::RemoveExifOrientation(compositeImage);
|
|
682
|
-
compositeImage = sharp::StaySequential(compositeImage,
|
|
683
|
-
compositeAutoRotation != VIPS_ANGLE_D0 || compositeAutoFlip);
|
|
661
|
+
compositeImage = sharp::StaySequential(compositeImage, compositeAutoRotation != VIPS_ANGLE_D0);
|
|
684
662
|
|
|
685
663
|
if (compositeAutoRotation != VIPS_ANGLE_D0) {
|
|
686
664
|
compositeImage = compositeImage.rot(compositeAutoRotation);
|
|
687
665
|
}
|
|
688
|
-
if (compositeAutoFlip) {
|
|
689
|
-
compositeImage = compositeImage.flip(VIPS_DIRECTION_VERTICAL);
|
|
690
|
-
}
|
|
691
666
|
if (compositeAutoFlop) {
|
|
692
667
|
compositeImage = compositeImage.flip(VIPS_DIRECTION_HORIZONTAL);
|
|
693
668
|
}
|
|
@@ -733,8 +708,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
733
708
|
// gravity was used for extract_area, set it back to its default value of 0
|
|
734
709
|
composite->gravity = 0;
|
|
735
710
|
}
|
|
736
|
-
// Ensure image to composite is
|
|
737
|
-
compositeImage = compositeImage.colourspace(VIPS_INTERPRETATION_sRGB);
|
|
711
|
+
// Ensure image to composite is with unpremultiplied alpha
|
|
738
712
|
compositeImage = sharp::EnsureAlpha(compositeImage, 1);
|
|
739
713
|
if (composite->premultiplied) compositeImage = compositeImage.unpremultiply();
|
|
740
714
|
// Calculate position
|
|
@@ -759,7 +733,12 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
759
733
|
xs.push_back(left);
|
|
760
734
|
ys.push_back(top);
|
|
761
735
|
}
|
|
762
|
-
image = VImage::composite(images, modes, VImage::option()
|
|
736
|
+
image = VImage::composite(images, modes, VImage::option()
|
|
737
|
+
->set("compositing_space", baton->colourspacePipeline == VIPS_INTERPRETATION_LAST
|
|
738
|
+
? VIPS_INTERPRETATION_sRGB
|
|
739
|
+
: baton->colourspacePipeline)
|
|
740
|
+
->set("x", xs)
|
|
741
|
+
->set("y", ys));
|
|
763
742
|
image = sharp::RemoveGifPalette(image);
|
|
764
743
|
}
|
|
765
744
|
|
|
@@ -891,7 +870,12 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
891
870
|
image.set(s.first.data(), s.second.data());
|
|
892
871
|
}
|
|
893
872
|
}
|
|
894
|
-
|
|
873
|
+
// XMP buffer
|
|
874
|
+
if ((baton->keepMetadata & VIPS_FOREIGN_KEEP_XMP) && !baton->withXmp.empty()) {
|
|
875
|
+
image = image.copy();
|
|
876
|
+
image.set(VIPS_META_XMP_NAME, nullptr,
|
|
877
|
+
const_cast<void*>(static_cast<void const*>(baton->withXmp.c_str())), baton->withXmp.size());
|
|
878
|
+
}
|
|
895
879
|
// Number of channels used in output image
|
|
896
880
|
baton->channels = image.bands();
|
|
897
881
|
baton->width = image.width();
|
|
@@ -1002,6 +986,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1002
986
|
->set("interlace", baton->gifProgressive)
|
|
1003
987
|
->set("interframe_maxerror", baton->gifInterFrameMaxError)
|
|
1004
988
|
->set("interpalette_maxerror", baton->gifInterPaletteMaxError)
|
|
989
|
+
->set("keep_duplicate_frames", baton->gifKeepDuplicateFrames)
|
|
1005
990
|
->set("dither", baton->gifDither)));
|
|
1006
991
|
baton->bufferOut = static_cast<char*>(area->data);
|
|
1007
992
|
baton->bufferOutLength = area->length;
|
|
@@ -1205,6 +1190,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1205
1190
|
->set("effort", baton->gifEffort)
|
|
1206
1191
|
->set("reuse", baton->gifReuse)
|
|
1207
1192
|
->set("interlace", baton->gifProgressive)
|
|
1193
|
+
->set("interframe_maxerror", baton->gifInterFrameMaxError)
|
|
1194
|
+
->set("interpalette_maxerror", baton->gifInterPaletteMaxError)
|
|
1195
|
+
->set("keep_duplicate_frames", baton->gifKeepDuplicateFrames)
|
|
1208
1196
|
->set("dither", baton->gifDither));
|
|
1209
1197
|
baton->formatOut = "gif";
|
|
1210
1198
|
} else if (baton->formatOut == "tiff" || (mightMatchInput && isTiff) ||
|
|
@@ -1359,7 +1347,8 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1359
1347
|
// Add file size to info
|
|
1360
1348
|
if (baton->formatOut != "dz" || sharp::IsDzZip(baton->fileOut)) {
|
|
1361
1349
|
try {
|
|
1362
|
-
uint32_t const size = static_cast<uint32_t>(
|
|
1350
|
+
uint32_t const size = static_cast<uint32_t>(
|
|
1351
|
+
std::filesystem::file_size(std::filesystem::u8path(baton->fileOut)));
|
|
1363
1352
|
info.Set("size", size);
|
|
1364
1353
|
} catch (...) {}
|
|
1365
1354
|
}
|
|
@@ -1405,21 +1394,20 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1405
1394
|
Calculate the angle of rotation and need-to-flip for the given Exif orientation
|
|
1406
1395
|
By default, returns zero, i.e. no rotation.
|
|
1407
1396
|
*/
|
|
1408
|
-
std::tuple<VipsAngle, bool
|
|
1409
|
-
|
|
1397
|
+
std::tuple<VipsAngle, bool>
|
|
1398
|
+
CalculateExifRotationAndFlop(int const exifOrientation) {
|
|
1410
1399
|
VipsAngle rotate = VIPS_ANGLE_D0;
|
|
1411
|
-
bool flip = false;
|
|
1412
1400
|
bool flop = false;
|
|
1413
1401
|
switch (exifOrientation) {
|
|
1414
1402
|
case 6: rotate = VIPS_ANGLE_D90; break;
|
|
1415
1403
|
case 3: rotate = VIPS_ANGLE_D180; break;
|
|
1416
1404
|
case 8: rotate = VIPS_ANGLE_D270; break;
|
|
1417
|
-
case 2: flop = true; break;
|
|
1418
|
-
case 7:
|
|
1419
|
-
case 4: flop = true; rotate = VIPS_ANGLE_D180; break;
|
|
1420
|
-
case 5:
|
|
1405
|
+
case 2: flop = true; break;
|
|
1406
|
+
case 7: flop = true; rotate = VIPS_ANGLE_D270; break;
|
|
1407
|
+
case 4: flop = true; rotate = VIPS_ANGLE_D180; break;
|
|
1408
|
+
case 5: flop = true; rotate = VIPS_ANGLE_D90; break;
|
|
1421
1409
|
}
|
|
1422
|
-
return std::make_tuple(rotate,
|
|
1410
|
+
return std::make_tuple(rotate, flop);
|
|
1423
1411
|
}
|
|
1424
1412
|
|
|
1425
1413
|
/*
|
|
@@ -1644,7 +1632,8 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1644
1632
|
baton->angle = sharp::AttrAsInt32(options, "angle");
|
|
1645
1633
|
baton->rotationAngle = sharp::AttrAsDouble(options, "rotationAngle");
|
|
1646
1634
|
baton->rotationBackground = sharp::AttrAsVectorOfDouble(options, "rotationBackground");
|
|
1647
|
-
baton->
|
|
1635
|
+
baton->rotateBefore = sharp::AttrAsBool(options, "rotateBefore");
|
|
1636
|
+
baton->orientBefore = sharp::AttrAsBool(options, "orientBefore");
|
|
1648
1637
|
baton->flip = sharp::AttrAsBool(options, "flip");
|
|
1649
1638
|
baton->flop = sharp::AttrAsBool(options, "flop");
|
|
1650
1639
|
baton->extendTop = sharp::AttrAsInt32(options, "extendTop");
|
|
@@ -1716,6 +1705,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1716
1705
|
}
|
|
1717
1706
|
}
|
|
1718
1707
|
baton->withExifMerge = sharp::AttrAsBool(options, "withExifMerge");
|
|
1708
|
+
baton->withXmp = sharp::AttrAsStr(options, "withXmp");
|
|
1719
1709
|
baton->timeoutSeconds = sharp::AttrAsUint32(options, "timeoutSeconds");
|
|
1720
1710
|
baton->loop = sharp::AttrAsUint32(options, "loop");
|
|
1721
1711
|
baton->delay = sharp::AttrAsInt32Vector(options, "delay");
|
|
@@ -1756,6 +1746,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1756
1746
|
baton->gifDither = sharp::AttrAsDouble(options, "gifDither");
|
|
1757
1747
|
baton->gifInterFrameMaxError = sharp::AttrAsDouble(options, "gifInterFrameMaxError");
|
|
1758
1748
|
baton->gifInterPaletteMaxError = sharp::AttrAsDouble(options, "gifInterPaletteMaxError");
|
|
1749
|
+
baton->gifKeepDuplicateFrames = sharp::AttrAsBool(options, "gifKeepDuplicateFrames");
|
|
1759
1750
|
baton->gifReuse = sharp::AttrAsBool(options, "gifReuse");
|
|
1760
1751
|
baton->gifProgressive = sharp::AttrAsBool(options, "gifProgressive");
|
|
1761
1752
|
baton->tiffQuality = sharp::AttrAsUint32(options, "tiffQuality");
|
package/src/pipeline.h
CHANGED
|
@@ -115,7 +115,8 @@ struct PipelineBaton {
|
|
|
115
115
|
int angle;
|
|
116
116
|
double rotationAngle;
|
|
117
117
|
std::vector<double> rotationBackground;
|
|
118
|
-
bool
|
|
118
|
+
bool rotateBefore;
|
|
119
|
+
bool orientBefore;
|
|
119
120
|
bool flip;
|
|
120
121
|
bool flop;
|
|
121
122
|
int extendTop;
|
|
@@ -169,6 +170,7 @@ struct PipelineBaton {
|
|
|
169
170
|
double gifDither;
|
|
170
171
|
double gifInterFrameMaxError;
|
|
171
172
|
double gifInterPaletteMaxError;
|
|
173
|
+
bool gifKeepDuplicateFrames;
|
|
172
174
|
bool gifReuse;
|
|
173
175
|
bool gifProgressive;
|
|
174
176
|
int tiffQuality;
|
|
@@ -201,6 +203,7 @@ struct PipelineBaton {
|
|
|
201
203
|
std::string withIccProfile;
|
|
202
204
|
std::unordered_map<std::string, std::string> withExif;
|
|
203
205
|
bool withExifMerge;
|
|
206
|
+
std::string withXmp;
|
|
204
207
|
int timeoutSeconds;
|
|
205
208
|
std::vector<double> convKernel;
|
|
206
209
|
int convKernelWidth;
|
|
@@ -342,6 +345,7 @@ struct PipelineBaton {
|
|
|
342
345
|
gifDither(1.0),
|
|
343
346
|
gifInterFrameMaxError(0.0),
|
|
344
347
|
gifInterPaletteMaxError(3.0),
|
|
348
|
+
gifKeepDuplicateFrames(false),
|
|
345
349
|
gifReuse(true),
|
|
346
350
|
gifProgressive(false),
|
|
347
351
|
tiffQuality(80),
|
package/src/stats.cc
CHANGED
|
@@ -60,7 +60,7 @@ class StatsWorker : public Napi::AsyncWorker {
|
|
|
60
60
|
// Image is not opaque when alpha layer is present and contains a non-mamixa value
|
|
61
61
|
if (image.has_alpha()) {
|
|
62
62
|
double const minAlpha = static_cast<double>(stats.getpoint(STAT_MIN_INDEX, bands).front());
|
|
63
|
-
if (minAlpha !=
|
|
63
|
+
if (minAlpha != vips_interpretation_max_alpha(image.interpretation())) {
|
|
64
64
|
baton->isOpaque = false;
|
|
65
65
|
}
|
|
66
66
|
}
|
package/src/utilities.cc
CHANGED
|
@@ -119,7 +119,7 @@ Napi::Value format(const Napi::CallbackInfo& info) {
|
|
|
119
119
|
Napi::Object format = Napi::Object::New(env);
|
|
120
120
|
for (std::string const f : {
|
|
121
121
|
"jpeg", "png", "webp", "tiff", "magick", "openslide", "dz",
|
|
122
|
-
"ppm", "fits", "gif", "svg", "heif", "pdf", "vips", "jp2k", "jxl", "rad"
|
|
122
|
+
"ppm", "fits", "gif", "svg", "heif", "pdf", "vips", "jp2k", "jxl", "rad", "dcraw"
|
|
123
123
|
}) {
|
|
124
124
|
// Input
|
|
125
125
|
const VipsObjectClass *oc = vips_class_find("VipsOperation", (f + "load").c_str());
|