sharp 0.30.5 → 0.31.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 +4 -3
- package/lib/composite.js +14 -0
- package/lib/constructor.js +41 -4
- package/lib/input.js +95 -3
- package/lib/libvips.js +1 -0
- package/lib/operation.js +57 -12
- package/lib/output.js +87 -23
- package/lib/resize.js +90 -13
- package/lib/sharp.js +3 -0
- package/lib/utility.js +4 -0
- package/package.json +25 -23
- package/src/common.cc +95 -45
- package/src/common.h +33 -15
- package/src/libvips/cplusplus/VConnection.cpp +0 -1
- package/src/libvips/cplusplus/VError.cpp +0 -1
- package/src/libvips/cplusplus/VImage.cpp +27 -2
- package/src/libvips/cplusplus/VInterpolate.cpp +0 -1
- package/src/libvips/cplusplus/VRegion.cpp +27 -0
- package/src/libvips/cplusplus/vips-operators.cpp +16 -1
- package/src/operations.cc +69 -25
- package/src/operations.h +7 -2
- package/src/pipeline.cc +162 -164
- package/src/pipeline.h +18 -5
- package/src/sharp.cc +0 -1
- package/src/utilities.cc +13 -2
package/src/common.cc
CHANGED
|
@@ -48,6 +48,9 @@ namespace sharp {
|
|
|
48
48
|
int32_t AttrAsInt32(Napi::Object obj, unsigned int const attr) {
|
|
49
49
|
return obj.Get(attr).As<Napi::Number>().Int32Value();
|
|
50
50
|
}
|
|
51
|
+
int64_t AttrAsInt64(Napi::Object obj, std::string attr) {
|
|
52
|
+
return obj.Get(attr).As<Napi::Number>().Int64Value();
|
|
53
|
+
}
|
|
51
54
|
double AttrAsDouble(Napi::Object obj, std::string attr) {
|
|
52
55
|
return obj.Get(attr).As<Napi::Number>().DoubleValue();
|
|
53
56
|
}
|
|
@@ -85,18 +88,14 @@ namespace sharp {
|
|
|
85
88
|
descriptor->buffer = buffer.Data();
|
|
86
89
|
descriptor->isBuffer = TRUE;
|
|
87
90
|
}
|
|
88
|
-
descriptor->failOn =
|
|
89
|
-
vips_enum_from_nick(nullptr, VIPS_TYPE_FAIL_ON,
|
|
90
|
-
AttrAsStr(input, "failOn").data()));
|
|
91
|
+
descriptor->failOn = AttrAsEnum<VipsFailOn>(input, "failOn", VIPS_TYPE_FAIL_ON);
|
|
91
92
|
// Density for vector-based input
|
|
92
93
|
if (HasAttr(input, "density")) {
|
|
93
94
|
descriptor->density = AttrAsDouble(input, "density");
|
|
94
95
|
}
|
|
95
96
|
// Raw pixel input
|
|
96
97
|
if (HasAttr(input, "rawChannels")) {
|
|
97
|
-
descriptor->rawDepth =
|
|
98
|
-
vips_enum_from_nick(nullptr, VIPS_TYPE_BAND_FORMAT,
|
|
99
|
-
AttrAsStr(input, "rawDepth").data()));
|
|
98
|
+
descriptor->rawDepth = AttrAsEnum<VipsBandFormat>(input, "rawDepth", VIPS_TYPE_BAND_FORMAT);
|
|
100
99
|
descriptor->rawChannels = AttrAsUint32(input, "rawChannels");
|
|
101
100
|
descriptor->rawWidth = AttrAsUint32(input, "rawWidth");
|
|
102
101
|
descriptor->rawHeight = AttrAsUint32(input, "rawHeight");
|
|
@@ -130,11 +129,42 @@ namespace sharp {
|
|
|
130
129
|
descriptor->createBackground = AttrAsVectorOfDouble(input, "createBackground");
|
|
131
130
|
}
|
|
132
131
|
}
|
|
132
|
+
// Create new image with text
|
|
133
|
+
if (HasAttr(input, "textValue")) {
|
|
134
|
+
descriptor->textValue = AttrAsStr(input, "textValue");
|
|
135
|
+
if (HasAttr(input, "textFont")) {
|
|
136
|
+
descriptor->textFont = AttrAsStr(input, "textFont");
|
|
137
|
+
}
|
|
138
|
+
if (HasAttr(input, "textFontfile")) {
|
|
139
|
+
descriptor->textFontfile = AttrAsStr(input, "textFontfile");
|
|
140
|
+
}
|
|
141
|
+
if (HasAttr(input, "textWidth")) {
|
|
142
|
+
descriptor->textWidth = AttrAsUint32(input, "textWidth");
|
|
143
|
+
}
|
|
144
|
+
if (HasAttr(input, "textHeight")) {
|
|
145
|
+
descriptor->textHeight = AttrAsUint32(input, "textHeight");
|
|
146
|
+
}
|
|
147
|
+
if (HasAttr(input, "textAlign")) {
|
|
148
|
+
descriptor->textAlign = AttrAsEnum<VipsAlign>(input, "textAlign", VIPS_TYPE_ALIGN);
|
|
149
|
+
}
|
|
150
|
+
if (HasAttr(input, "textJustify")) {
|
|
151
|
+
descriptor->textJustify = AttrAsBool(input, "textJustify");
|
|
152
|
+
}
|
|
153
|
+
if (HasAttr(input, "textDpi")) {
|
|
154
|
+
descriptor->textDpi = AttrAsUint32(input, "textDpi");
|
|
155
|
+
}
|
|
156
|
+
if (HasAttr(input, "textRgba")) {
|
|
157
|
+
descriptor->textRgba = AttrAsBool(input, "textRgba");
|
|
158
|
+
}
|
|
159
|
+
if (HasAttr(input, "textSpacing")) {
|
|
160
|
+
descriptor->textSpacing = AttrAsUint32(input, "textSpacing");
|
|
161
|
+
}
|
|
162
|
+
}
|
|
133
163
|
// Limit input images to a given number of pixels, where pixels = width * height
|
|
134
|
-
descriptor->limitInputPixels =
|
|
164
|
+
descriptor->limitInputPixels = static_cast<uint64_t>(AttrAsInt64(input, "limitInputPixels"));
|
|
135
165
|
// Allow switch from random to sequential access
|
|
136
166
|
descriptor->access = AttrAsBool(input, "sequentialRead") ? VIPS_ACCESS_SEQUENTIAL : VIPS_ACCESS_RANDOM;
|
|
137
|
-
// Remove safety features and allow unlimited
|
|
167
|
+
// Remove safety features and allow unlimited input
|
|
138
168
|
descriptor->unlimited = AttrAsBool(input, "unlimited");
|
|
139
169
|
return descriptor;
|
|
140
170
|
}
|
|
@@ -247,9 +277,9 @@ namespace sharp {
|
|
|
247
277
|
{ "VipsForeignLoadMagickBuffer", ImageType::MAGICK },
|
|
248
278
|
{ "VipsForeignLoadMagick7File", ImageType::MAGICK },
|
|
249
279
|
{ "VipsForeignLoadMagick7Buffer", ImageType::MAGICK },
|
|
250
|
-
{ "
|
|
280
|
+
{ "VipsForeignLoadOpenslideFile", ImageType::OPENSLIDE },
|
|
251
281
|
{ "VipsForeignLoadPpmFile", ImageType::PPM },
|
|
252
|
-
{ "
|
|
282
|
+
{ "VipsForeignLoadFitsFile", ImageType::FITS },
|
|
253
283
|
{ "VipsForeignLoadOpenexr", ImageType::EXR },
|
|
254
284
|
{ "VipsForeignLoadVips", ImageType::VIPS },
|
|
255
285
|
{ "VipsForeignLoadVipsFile", ImageType::VIPS },
|
|
@@ -304,6 +334,17 @@ namespace sharp {
|
|
|
304
334
|
imageType == ImageType::PDF;
|
|
305
335
|
}
|
|
306
336
|
|
|
337
|
+
/*
|
|
338
|
+
Does this image type support removal of safety limits?
|
|
339
|
+
*/
|
|
340
|
+
bool ImageTypeSupportsUnlimited(ImageType imageType) {
|
|
341
|
+
return
|
|
342
|
+
imageType == ImageType::JPEG ||
|
|
343
|
+
imageType == ImageType::PNG ||
|
|
344
|
+
imageType == ImageType::SVG ||
|
|
345
|
+
imageType == ImageType::HEIF;
|
|
346
|
+
}
|
|
347
|
+
|
|
307
348
|
/*
|
|
308
349
|
Open an image from the given InputDescriptor (filesystem, compressed buffer, raw pixel data)
|
|
309
350
|
*/
|
|
@@ -332,7 +373,7 @@ namespace sharp {
|
|
|
332
373
|
vips::VOption *option = VImage::option()
|
|
333
374
|
->set("access", descriptor->access)
|
|
334
375
|
->set("fail_on", descriptor->failOn);
|
|
335
|
-
if (descriptor->unlimited && (imageType
|
|
376
|
+
if (descriptor->unlimited && ImageTypeSupportsUnlimited(imageType)) {
|
|
336
377
|
option->set("unlimited", TRUE);
|
|
337
378
|
}
|
|
338
379
|
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
|
|
@@ -363,34 +404,63 @@ namespace sharp {
|
|
|
363
404
|
}
|
|
364
405
|
}
|
|
365
406
|
} else {
|
|
366
|
-
|
|
407
|
+
int const channels = descriptor->createChannels;
|
|
408
|
+
if (channels > 0) {
|
|
367
409
|
// Create new image
|
|
368
410
|
if (descriptor->createNoiseType == "gaussian") {
|
|
369
|
-
int const channels = descriptor->createChannels;
|
|
370
|
-
image = VImage::new_matrix(descriptor->createWidth, descriptor->createHeight);
|
|
371
411
|
std::vector<VImage> bands = {};
|
|
372
412
|
bands.reserve(channels);
|
|
373
413
|
for (int _band = 0; _band < channels; _band++) {
|
|
374
|
-
bands.push_back(
|
|
375
|
-
descriptor->
|
|
376
|
-
descriptor->
|
|
377
|
-
VImage::option()->set("mean", descriptor->createNoiseMean)->set("sigma", descriptor->createNoiseSigma)));
|
|
414
|
+
bands.push_back(VImage::gaussnoise(descriptor->createWidth, descriptor->createHeight, VImage::option()
|
|
415
|
+
->set("mean", descriptor->createNoiseMean)
|
|
416
|
+
->set("sigma", descriptor->createNoiseSigma)));
|
|
378
417
|
}
|
|
379
|
-
image =
|
|
418
|
+
image = VImage::bandjoin(bands).copy(VImage::option()->set("interpretation",
|
|
419
|
+
channels < 3 ? VIPS_INTERPRETATION_B_W: VIPS_INTERPRETATION_sRGB));
|
|
380
420
|
} else {
|
|
381
421
|
std::vector<double> background = {
|
|
382
422
|
descriptor->createBackground[0],
|
|
383
423
|
descriptor->createBackground[1],
|
|
384
424
|
descriptor->createBackground[2]
|
|
385
425
|
};
|
|
386
|
-
if (
|
|
426
|
+
if (channels == 4) {
|
|
387
427
|
background.push_back(descriptor->createBackground[3]);
|
|
388
428
|
}
|
|
389
|
-
image = VImage::new_matrix(descriptor->createWidth, descriptor->createHeight)
|
|
429
|
+
image = VImage::new_matrix(descriptor->createWidth, descriptor->createHeight)
|
|
430
|
+
.copy(VImage::option()->set("interpretation",
|
|
431
|
+
channels < 3 ? VIPS_INTERPRETATION_B_W : VIPS_INTERPRETATION_sRGB))
|
|
432
|
+
.new_from_image(background);
|
|
390
433
|
}
|
|
391
|
-
image.get_image()->Type = image.guess_interpretation();
|
|
392
434
|
image = image.cast(VIPS_FORMAT_UCHAR);
|
|
393
435
|
imageType = ImageType::RAW;
|
|
436
|
+
} else if (descriptor->textValue.length() > 0) {
|
|
437
|
+
// Create a new image with text
|
|
438
|
+
vips::VOption *textOptions = VImage::option()
|
|
439
|
+
->set("align", descriptor->textAlign)
|
|
440
|
+
->set("justify", descriptor->textJustify)
|
|
441
|
+
->set("rgba", descriptor->textRgba)
|
|
442
|
+
->set("spacing", descriptor->textSpacing)
|
|
443
|
+
->set("autofit_dpi", &descriptor->textAutofitDpi);
|
|
444
|
+
if (descriptor->textWidth > 0) {
|
|
445
|
+
textOptions->set("width", descriptor->textWidth);
|
|
446
|
+
}
|
|
447
|
+
// Ignore dpi if height is set
|
|
448
|
+
if (descriptor->textWidth > 0 && descriptor->textHeight > 0) {
|
|
449
|
+
textOptions->set("height", descriptor->textHeight);
|
|
450
|
+
} else if (descriptor->textDpi > 0) {
|
|
451
|
+
textOptions->set("dpi", descriptor->textDpi);
|
|
452
|
+
}
|
|
453
|
+
if (descriptor->textFont.length() > 0) {
|
|
454
|
+
textOptions->set("font", const_cast<char*>(descriptor->textFont.data()));
|
|
455
|
+
}
|
|
456
|
+
if (descriptor->textFontfile.length() > 0) {
|
|
457
|
+
textOptions->set("fontfile", const_cast<char*>(descriptor->textFontfile.data()));
|
|
458
|
+
}
|
|
459
|
+
image = VImage::text(const_cast<char *>(descriptor->textValue.data()), textOptions);
|
|
460
|
+
if (!descriptor->textRgba) {
|
|
461
|
+
image = image.copy(VImage::option()->set("interpretation", VIPS_INTERPRETATION_B_W));
|
|
462
|
+
}
|
|
463
|
+
imageType = ImageType::RAW;
|
|
394
464
|
} else {
|
|
395
465
|
// From filesystem
|
|
396
466
|
imageType = DetermineImageType(descriptor->file.data());
|
|
@@ -406,7 +476,7 @@ namespace sharp {
|
|
|
406
476
|
vips::VOption *option = VImage::option()
|
|
407
477
|
->set("access", descriptor->access)
|
|
408
478
|
->set("fail_on", descriptor->failOn);
|
|
409
|
-
if (descriptor->unlimited && (imageType
|
|
479
|
+
if (descriptor->unlimited && ImageTypeSupportsUnlimited(imageType)) {
|
|
410
480
|
option->set("unlimited", TRUE);
|
|
411
481
|
}
|
|
412
482
|
if (imageType == ImageType::SVG || imageType == ImageType::PDF) {
|
|
@@ -439,7 +509,7 @@ namespace sharp {
|
|
|
439
509
|
}
|
|
440
510
|
// Limit input images to a given number of pixels, where pixels = width * height
|
|
441
511
|
if (descriptor->limitInputPixels > 0 &&
|
|
442
|
-
static_cast<uint64_t>(image.width() * image.height()) >
|
|
512
|
+
static_cast<uint64_t>(image.width() * image.height()) > descriptor->limitInputPixels) {
|
|
443
513
|
throw vips::VError("Input image exceeds pixel limit");
|
|
444
514
|
}
|
|
445
515
|
return std::make_tuple(image, imageType);
|
|
@@ -634,7 +704,6 @@ namespace sharp {
|
|
|
634
704
|
Event listener for progress updates, used to detect timeout
|
|
635
705
|
*/
|
|
636
706
|
void VipsProgressCallBack(VipsImage *im, VipsProgress *progress, int *timeout) {
|
|
637
|
-
// printf("VipsProgressCallBack progress=%d run=%d timeout=%d\n", progress->percent, progress->run, *timeout);
|
|
638
707
|
if (*timeout > 0 && progress->run >= *timeout) {
|
|
639
708
|
vips_image_set_kill(im, TRUE);
|
|
640
709
|
vips_error("timeout", "%d%% complete", progress->percent);
|
|
@@ -791,22 +860,6 @@ namespace sharp {
|
|
|
791
860
|
return Is16Bit(interpretation) ? 65535.0 : 255.0;
|
|
792
861
|
}
|
|
793
862
|
|
|
794
|
-
/*
|
|
795
|
-
Get boolean operation type from string
|
|
796
|
-
*/
|
|
797
|
-
VipsOperationBoolean GetBooleanOperation(std::string const opStr) {
|
|
798
|
-
return static_cast<VipsOperationBoolean>(
|
|
799
|
-
vips_enum_from_nick(nullptr, VIPS_TYPE_OPERATION_BOOLEAN, opStr.data()));
|
|
800
|
-
}
|
|
801
|
-
|
|
802
|
-
/*
|
|
803
|
-
Get interpretation type from string
|
|
804
|
-
*/
|
|
805
|
-
VipsInterpretation GetInterpretation(std::string const typeStr) {
|
|
806
|
-
return static_cast<VipsInterpretation>(
|
|
807
|
-
vips_enum_from_nick(nullptr, VIPS_TYPE_INTERPRETATION, typeStr.data()));
|
|
808
|
-
}
|
|
809
|
-
|
|
810
863
|
/*
|
|
811
864
|
Convert RGBA value to another colourspace
|
|
812
865
|
*/
|
|
@@ -887,7 +940,7 @@ namespace sharp {
|
|
|
887
940
|
|
|
888
941
|
std::pair<double, double> ResolveShrink(int width, int height, int targetWidth, int targetHeight,
|
|
889
942
|
Canvas canvas, bool swap, bool withoutEnlargement, bool withoutReduction) {
|
|
890
|
-
if (swap) {
|
|
943
|
+
if (swap && canvas != Canvas::IGNORE_ASPECT) {
|
|
891
944
|
// Swap input width and height when requested.
|
|
892
945
|
std::swap(width, height);
|
|
893
946
|
}
|
|
@@ -918,9 +971,6 @@ namespace sharp {
|
|
|
918
971
|
}
|
|
919
972
|
break;
|
|
920
973
|
case Canvas::IGNORE_ASPECT:
|
|
921
|
-
if (swap) {
|
|
922
|
-
std::swap(hshrink, vshrink);
|
|
923
|
-
}
|
|
924
974
|
break;
|
|
925
975
|
}
|
|
926
976
|
} else if (targetWidth > 0) {
|
package/src/common.h
CHANGED
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
// Verify platform and compiler compatibility
|
|
26
26
|
|
|
27
27
|
#if (VIPS_MAJOR_VERSION < 8) || \
|
|
28
|
-
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION <
|
|
29
|
-
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION ==
|
|
30
|
-
#error "libvips version 8.
|
|
28
|
+
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 13) || \
|
|
29
|
+
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 13 && VIPS_MICRO_VERSION < 1)
|
|
30
|
+
#error "libvips version 8.13.1+ is required - please see https://sharp.pixelplumbing.com/install"
|
|
31
31
|
#endif
|
|
32
32
|
|
|
33
33
|
#if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))
|
|
@@ -49,7 +49,7 @@ namespace sharp {
|
|
|
49
49
|
std::string file;
|
|
50
50
|
char *buffer;
|
|
51
51
|
VipsFailOn failOn;
|
|
52
|
-
|
|
52
|
+
uint64_t limitInputPixels;
|
|
53
53
|
bool unlimited;
|
|
54
54
|
VipsAccess access;
|
|
55
55
|
size_t bufferLength;
|
|
@@ -71,6 +71,17 @@ namespace sharp {
|
|
|
71
71
|
std::string createNoiseType;
|
|
72
72
|
double createNoiseMean;
|
|
73
73
|
double createNoiseSigma;
|
|
74
|
+
std::string textValue;
|
|
75
|
+
std::string textFont;
|
|
76
|
+
std::string textFontfile;
|
|
77
|
+
int textWidth;
|
|
78
|
+
int textHeight;
|
|
79
|
+
VipsAlign textAlign;
|
|
80
|
+
bool textJustify;
|
|
81
|
+
int textDpi;
|
|
82
|
+
bool textRgba;
|
|
83
|
+
int textSpacing;
|
|
84
|
+
int textAutofitDpi;
|
|
74
85
|
|
|
75
86
|
InputDescriptor():
|
|
76
87
|
buffer(nullptr),
|
|
@@ -95,7 +106,15 @@ namespace sharp {
|
|
|
95
106
|
createHeight(0),
|
|
96
107
|
createBackground{ 0.0, 0.0, 0.0, 255.0 },
|
|
97
108
|
createNoiseMean(0.0),
|
|
98
|
-
createNoiseSigma(0.0)
|
|
109
|
+
createNoiseSigma(0.0),
|
|
110
|
+
textWidth(0),
|
|
111
|
+
textHeight(0),
|
|
112
|
+
textAlign(VIPS_ALIGN_LOW),
|
|
113
|
+
textJustify(FALSE),
|
|
114
|
+
textDpi(72),
|
|
115
|
+
textRgba(FALSE),
|
|
116
|
+
textSpacing(0),
|
|
117
|
+
textAutofitDpi(0) {}
|
|
99
118
|
};
|
|
100
119
|
|
|
101
120
|
// Convenience methods to access the attributes of a Napi::Object
|
|
@@ -110,6 +129,10 @@ namespace sharp {
|
|
|
110
129
|
bool AttrAsBool(Napi::Object obj, std::string attr);
|
|
111
130
|
std::vector<double> AttrAsVectorOfDouble(Napi::Object obj, std::string attr);
|
|
112
131
|
std::vector<int32_t> AttrAsInt32Vector(Napi::Object obj, std::string attr);
|
|
132
|
+
template <class T> T AttrAsEnum(Napi::Object obj, std::string attr, GType type) {
|
|
133
|
+
return static_cast<T>(
|
|
134
|
+
vips_enum_from_nick(nullptr, type, AttrAsStr(obj, attr).data()));
|
|
135
|
+
}
|
|
113
136
|
|
|
114
137
|
// Create an InputDescriptor instance from a Napi::Object describing an input image
|
|
115
138
|
InputDescriptor* CreateInputDescriptor(Napi::Object input);
|
|
@@ -183,6 +206,11 @@ namespace sharp {
|
|
|
183
206
|
*/
|
|
184
207
|
bool ImageTypeSupportsPage(ImageType imageType);
|
|
185
208
|
|
|
209
|
+
/*
|
|
210
|
+
Does this image type support removal of safety limits?
|
|
211
|
+
*/
|
|
212
|
+
bool ImageTypeSupportsUnlimited(ImageType imageType);
|
|
213
|
+
|
|
186
214
|
/*
|
|
187
215
|
Open an image from the given InputDescriptor (filesystem, compressed buffer, raw pixel data)
|
|
188
216
|
*/
|
|
@@ -307,16 +335,6 @@ namespace sharp {
|
|
|
307
335
|
*/
|
|
308
336
|
double MaximumImageAlpha(VipsInterpretation const interpretation);
|
|
309
337
|
|
|
310
|
-
/*
|
|
311
|
-
Get boolean operation type from string
|
|
312
|
-
*/
|
|
313
|
-
VipsOperationBoolean GetBooleanOperation(std::string const opStr);
|
|
314
|
-
|
|
315
|
-
/*
|
|
316
|
-
Get interpretation type from string
|
|
317
|
-
*/
|
|
318
|
-
VipsInterpretation GetInterpretation(std::string const typeStr);
|
|
319
|
-
|
|
320
338
|
/*
|
|
321
339
|
Convert RGBA value to another colourspace
|
|
322
340
|
*/
|
|
@@ -38,7 +38,6 @@
|
|
|
38
38
|
#ifdef HAVE_CONFIG_H
|
|
39
39
|
#include <config.h>
|
|
40
40
|
#endif /*HAVE_CONFIG_H*/
|
|
41
|
-
#include <vips/intl.h>
|
|
42
41
|
|
|
43
42
|
#include <vips/vips8>
|
|
44
43
|
|
|
@@ -733,7 +732,7 @@ VImage::write_to_buffer( const char *suffix, void **buf, size_t *size,
|
|
|
733
732
|
set( "in", *this )->
|
|
734
733
|
set( "target", target ) );
|
|
735
734
|
|
|
736
|
-
g_object_get( target.get_target(), "blob", &blob, NULL );
|
|
735
|
+
g_object_get( target.get_target(), "blob", &blob, (void *) NULL );
|
|
737
736
|
}
|
|
738
737
|
else if( (operation_name = vips_foreign_find_save_buffer( filename )) ) {
|
|
739
738
|
call_option_string( operation_name, option_string,
|
|
@@ -778,6 +777,32 @@ VImage::write_to_target( const char *suffix, VTarget target,
|
|
|
778
777
|
set( "target", target ) );
|
|
779
778
|
}
|
|
780
779
|
|
|
780
|
+
VRegion
|
|
781
|
+
VImage::region() const
|
|
782
|
+
{
|
|
783
|
+
return VRegion::new_from_image( *this );
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
VRegion
|
|
787
|
+
VImage::region( VipsRect *rect ) const
|
|
788
|
+
{
|
|
789
|
+
VRegion region = VRegion::new_from_image( *this );
|
|
790
|
+
|
|
791
|
+
region.prepare( rect );
|
|
792
|
+
|
|
793
|
+
return region;
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
VRegion
|
|
797
|
+
VImage::region( int left, int top, int width, int height ) const
|
|
798
|
+
{
|
|
799
|
+
VRegion region = VRegion::new_from_image( *this );
|
|
800
|
+
|
|
801
|
+
region.prepare( left, top, width, height );
|
|
802
|
+
|
|
803
|
+
return region;
|
|
804
|
+
}
|
|
805
|
+
|
|
781
806
|
#include "vips-operators.cpp"
|
|
782
807
|
|
|
783
808
|
std::vector<VImage>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Object part of VRegion class
|
|
2
|
+
|
|
3
|
+
#ifdef HAVE_CONFIG_H
|
|
4
|
+
#include <config.h>
|
|
5
|
+
#endif /*HAVE_CONFIG_H*/
|
|
6
|
+
|
|
7
|
+
#include <vips/vips8>
|
|
8
|
+
|
|
9
|
+
#include <vips/debug.h>
|
|
10
|
+
|
|
11
|
+
VIPS_NAMESPACE_START
|
|
12
|
+
|
|
13
|
+
VRegion
|
|
14
|
+
VRegion::new_from_image( VImage image )
|
|
15
|
+
{
|
|
16
|
+
VipsRegion *region;
|
|
17
|
+
|
|
18
|
+
if( !(region = vips_region_new( image.get_image() )) ) {
|
|
19
|
+
throw VError();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
VRegion out( region );
|
|
23
|
+
|
|
24
|
+
return( out );
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
VIPS_NAMESPACE_END
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
// bodies for vips operations
|
|
2
|
-
// Mon Nov 1 03:31:09 PM CET 2021
|
|
3
2
|
// this file is generated automatically, do not edit!
|
|
4
3
|
|
|
5
4
|
VImage VImage::CMC2LCh( VOption *options ) const
|
|
@@ -943,6 +942,14 @@ VipsBlob *VImage::dzsave_buffer( VOption *options ) const
|
|
|
943
942
|
return( buffer );
|
|
944
943
|
}
|
|
945
944
|
|
|
945
|
+
void VImage::dzsave_target( VTarget target, VOption *options ) const
|
|
946
|
+
{
|
|
947
|
+
call( "dzsave_target",
|
|
948
|
+
(options ? options : VImage::option())->
|
|
949
|
+
set( "in", *this )->
|
|
950
|
+
set( "target", target ) );
|
|
951
|
+
}
|
|
952
|
+
|
|
946
953
|
VImage VImage::embed( int x, int y, int width, int height, VOption *options ) const
|
|
947
954
|
{
|
|
948
955
|
VImage out;
|
|
@@ -3521,6 +3528,14 @@ VipsBlob *VImage::tiffsave_buffer( VOption *options ) const
|
|
|
3521
3528
|
return( buffer );
|
|
3522
3529
|
}
|
|
3523
3530
|
|
|
3531
|
+
void VImage::tiffsave_target( VTarget target, VOption *options ) const
|
|
3532
|
+
{
|
|
3533
|
+
call( "tiffsave_target",
|
|
3534
|
+
(options ? options : VImage::option())->
|
|
3535
|
+
set( "in", *this )->
|
|
3536
|
+
set( "target", target ) );
|
|
3537
|
+
}
|
|
3538
|
+
|
|
3524
3539
|
VImage VImage::tilecache( VOption *options ) const
|
|
3525
3540
|
{
|
|
3526
3541
|
VImage out;
|
package/src/operations.cc
CHANGED
|
@@ -68,10 +68,9 @@ namespace sharp {
|
|
|
68
68
|
// Extract luminance
|
|
69
69
|
VImage luminance = lab[0];
|
|
70
70
|
// Find luminance range
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (min != max) {
|
|
71
|
+
int const min = luminance.percent(1);
|
|
72
|
+
int const max = luminance.percent(99);
|
|
73
|
+
if (std::abs(max - min) > 1) {
|
|
75
74
|
// Extract chroma
|
|
76
75
|
VImage chroma = lab.extract_band(1, VImage::option()->set("n", 2));
|
|
77
76
|
// Calculate multiplication factor and addition
|
|
@@ -112,6 +111,19 @@ namespace sharp {
|
|
|
112
111
|
}
|
|
113
112
|
}
|
|
114
113
|
|
|
114
|
+
/*
|
|
115
|
+
* Flatten image to remove alpha channel
|
|
116
|
+
*/
|
|
117
|
+
VImage Flatten(VImage image, std::vector<double> flattenBackground) {
|
|
118
|
+
double const multiplier = sharp::Is16Bit(image.interpretation()) ? 256.0 : 1.0;
|
|
119
|
+
std::vector<double> background {
|
|
120
|
+
flattenBackground[0] * multiplier,
|
|
121
|
+
flattenBackground[1] * multiplier,
|
|
122
|
+
flattenBackground[2] * multiplier
|
|
123
|
+
};
|
|
124
|
+
return image.flatten(VImage::option()->set("background", background));
|
|
125
|
+
}
|
|
126
|
+
|
|
115
127
|
/**
|
|
116
128
|
* Produce the "negative" of the image.
|
|
117
129
|
*/
|
|
@@ -262,42 +274,74 @@ namespace sharp {
|
|
|
262
274
|
/*
|
|
263
275
|
Trim an image
|
|
264
276
|
*/
|
|
265
|
-
VImage Trim(VImage image, double
|
|
277
|
+
VImage Trim(VImage image, std::vector<double> background, double threshold) {
|
|
266
278
|
if (image.width() < 3 && image.height() < 3) {
|
|
267
279
|
throw VError("Image to trim must be at least 3x3 pixels");
|
|
268
280
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
281
|
+
|
|
282
|
+
// Scale up 8-bit values to match 16-bit input image
|
|
283
|
+
double multiplier = sharp::Is16Bit(image.interpretation()) ? 256.0 : 1.0;
|
|
284
|
+
threshold *= multiplier;
|
|
285
|
+
|
|
286
|
+
std::vector<double> backgroundAlpha(1);
|
|
287
|
+
if (background.size() == 0) {
|
|
288
|
+
// Top-left pixel provides the default background colour if none is given
|
|
289
|
+
background = image.extract_area(0, 0, 1, 1)(0, 0);
|
|
290
|
+
multiplier = 1.0;
|
|
291
|
+
}
|
|
292
|
+
if (background.size() == 4) {
|
|
293
|
+
// Just discard the alpha because flattening the background colour with
|
|
294
|
+
// itself (effectively what find_trim() does) gives the same result
|
|
295
|
+
backgroundAlpha[0] = background[3] * multiplier;
|
|
273
296
|
}
|
|
297
|
+
background = {
|
|
298
|
+
background[0] * multiplier,
|
|
299
|
+
background[1] * multiplier,
|
|
300
|
+
background[2] * multiplier
|
|
301
|
+
};
|
|
302
|
+
|
|
274
303
|
int left, top, width, height;
|
|
275
304
|
left = image.find_trim(&top, &width, &height, VImage::option()
|
|
276
|
-
->set("background", background
|
|
305
|
+
->set("background", background)
|
|
277
306
|
->set("threshold", threshold));
|
|
278
|
-
if (
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
307
|
+
if (HasAlpha(image)) {
|
|
308
|
+
// Search alpha channel (A)
|
|
309
|
+
int leftA, topA, widthA, heightA;
|
|
310
|
+
VImage alpha = image[image.bands() - 1];
|
|
311
|
+
leftA = alpha.find_trim(&topA, &widthA, &heightA, VImage::option()
|
|
312
|
+
->set("background", backgroundAlpha)
|
|
313
|
+
->set("threshold", threshold));
|
|
314
|
+
if (widthA > 0 && heightA > 0) {
|
|
315
|
+
if (width > 0 && height > 0) {
|
|
316
|
+
// Combined bounding box (B)
|
|
317
|
+
int const leftB = std::min(left, leftA);
|
|
318
|
+
int const topB = std::min(top, topA);
|
|
319
|
+
int const widthB = std::max(left + width, leftA + widthA) - leftB;
|
|
320
|
+
int const heightB = std::max(top + height, topA + heightA) - topB;
|
|
321
|
+
return image.extract_area(leftB, topB, widthB, heightB);
|
|
322
|
+
} else {
|
|
323
|
+
// Use alpha only
|
|
324
|
+
return image.extract_area(leftA, topA, widthA, heightA);
|
|
325
|
+
}
|
|
289
326
|
}
|
|
290
327
|
}
|
|
291
|
-
|
|
328
|
+
if (width > 0 && height > 0) {
|
|
329
|
+
return image.extract_area(left, top, width, height);
|
|
330
|
+
}
|
|
331
|
+
return image;
|
|
292
332
|
}
|
|
293
333
|
|
|
294
334
|
/*
|
|
295
335
|
* Calculate (a * in + b)
|
|
296
336
|
*/
|
|
297
|
-
VImage Linear(VImage image, double const a, double const b) {
|
|
298
|
-
|
|
337
|
+
VImage Linear(VImage image, std::vector<double> const a, std::vector<double> const b) {
|
|
338
|
+
size_t const bands = static_cast<size_t>(image.bands());
|
|
339
|
+
if (a.size() > bands) {
|
|
340
|
+
throw VError("Band expansion using linear is unsupported");
|
|
341
|
+
}
|
|
342
|
+
if (HasAlpha(image) && a.size() != bands && (a.size() == 1 || a.size() == bands - 1 || bands - 1 == 1)) {
|
|
299
343
|
// Separate alpha channel
|
|
300
|
-
VImage alpha = image[
|
|
344
|
+
VImage alpha = image[bands - 1];
|
|
301
345
|
return RemoveAlpha(image).linear(a, b).bandjoin(alpha);
|
|
302
346
|
} else {
|
|
303
347
|
return image.linear(a, b);
|
package/src/operations.h
CHANGED
|
@@ -45,6 +45,11 @@ namespace sharp {
|
|
|
45
45
|
*/
|
|
46
46
|
VImage Gamma(VImage image, double const exponent);
|
|
47
47
|
|
|
48
|
+
/*
|
|
49
|
+
* Flatten image to remove alpha channel
|
|
50
|
+
*/
|
|
51
|
+
VImage Flatten(VImage image, std::vector<double> flattenBackground);
|
|
52
|
+
|
|
48
53
|
/*
|
|
49
54
|
* Produce the "negative" of the image.
|
|
50
55
|
*/
|
|
@@ -85,12 +90,12 @@ namespace sharp {
|
|
|
85
90
|
/*
|
|
86
91
|
Trim an image
|
|
87
92
|
*/
|
|
88
|
-
VImage Trim(VImage image, double const threshold);
|
|
93
|
+
VImage Trim(VImage image, std::vector<double> background, double const threshold);
|
|
89
94
|
|
|
90
95
|
/*
|
|
91
96
|
* Linear adjustment (a * in + b)
|
|
92
97
|
*/
|
|
93
|
-
VImage Linear(VImage image, double const a,
|
|
98
|
+
VImage Linear(VImage image, std::vector<double> const a, std::vector<double> const b);
|
|
94
99
|
|
|
95
100
|
/*
|
|
96
101
|
* Recomb with a Matrix of the given bands/channel size.
|