sharp 0.33.5 → 0.34.0-rc.1
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/lib/channel.js +2 -1
- package/lib/colour.js +3 -2
- package/lib/composite.js +4 -2
- package/lib/constructor.js +33 -2
- package/lib/index.d.ts +166 -55
- package/lib/input.js +92 -16
- package/lib/libvips.js +3 -1
- package/lib/operation.js +92 -25
- package/lib/output.js +11 -9
- package/lib/resize.js +5 -2
- package/lib/sharp.js +10 -2
- package/lib/utility.js +1 -0
- package/package.json +39 -39
- package/src/binding.gyp +15 -8
- package/src/common.cc +42 -15
- package/src/common.h +26 -19
- package/src/metadata.cc +26 -8
- package/src/metadata.h +4 -2
- package/src/operations.cc +31 -9
- package/src/operations.h +9 -0
- package/src/pipeline.cc +109 -45
- package/src/pipeline.h +8 -3
- package/src/sharp.cc +1 -0
- package/src/stats.cc +1 -1
- package/src/utilities.cc +20 -3
- package/src/utilities.h +1 -0
package/src/binding.gyp
CHANGED
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
'sharp_libvips_lib_dir': '<!(node -p "require(\'../lib/libvips\').buildSharpLibvipsLibDir()")'
|
|
13
13
|
},
|
|
14
14
|
'targets': [{
|
|
15
|
-
'target_name': 'libvips-cpp',
|
|
15
|
+
'target_name': 'libvips-cpp-<(vips_version)',
|
|
16
16
|
'conditions': [
|
|
17
17
|
['OS == "win"', {
|
|
18
18
|
# Build libvips C++ binding for Windows due to MSVC std library ABI changes
|
|
19
19
|
'type': 'shared_library',
|
|
20
20
|
'defines': [
|
|
21
|
-
'
|
|
21
|
+
'_VIPS_PUBLIC=__declspec(dllexport)',
|
|
22
22
|
'_ALLOW_KEYWORD_MACROS'
|
|
23
23
|
],
|
|
24
24
|
'sources': [
|
|
@@ -45,6 +45,9 @@
|
|
|
45
45
|
'Release': {
|
|
46
46
|
'msvs_settings': {
|
|
47
47
|
'VCCLCompilerTool': {
|
|
48
|
+
"AdditionalOptions": [
|
|
49
|
+
"/std:c++17"
|
|
50
|
+
],
|
|
48
51
|
'ExceptionHandling': 1,
|
|
49
52
|
'Optimization': 1,
|
|
50
53
|
'WholeProgramOptimization': 'true'
|
|
@@ -83,7 +86,7 @@
|
|
|
83
86
|
],
|
|
84
87
|
'dependencies': [
|
|
85
88
|
'<!(node -p "require(\'node-addon-api\').gyp")',
|
|
86
|
-
'libvips-cpp'
|
|
89
|
+
'libvips-cpp-<(vips_version)'
|
|
87
90
|
],
|
|
88
91
|
'variables': {
|
|
89
92
|
'conditions': [
|
|
@@ -149,7 +152,7 @@
|
|
|
149
152
|
['OS == "mac"', {
|
|
150
153
|
'link_settings': {
|
|
151
154
|
'libraries': [
|
|
152
|
-
'libvips-cpp.
|
|
155
|
+
'libvips-cpp.<(vips_version).dylib'
|
|
153
156
|
]
|
|
154
157
|
},
|
|
155
158
|
'xcode_settings': {
|
|
@@ -169,9 +172,10 @@
|
|
|
169
172
|
],
|
|
170
173
|
'link_settings': {
|
|
171
174
|
'libraries': [
|
|
172
|
-
'-l:libvips-cpp.so
|
|
175
|
+
'-l:libvips-cpp.so.<(vips_version)'
|
|
173
176
|
],
|
|
174
177
|
'ldflags': [
|
|
178
|
+
'-lstdc++fs',
|
|
175
179
|
'-Wl,-s',
|
|
176
180
|
'-Wl,--disable-new-dtags',
|
|
177
181
|
'-Wl,-z,nodelete',
|
|
@@ -207,14 +211,14 @@
|
|
|
207
211
|
}]
|
|
208
212
|
],
|
|
209
213
|
'cflags_cc': [
|
|
210
|
-
'-std=c++
|
|
214
|
+
'-std=c++17',
|
|
211
215
|
'-fexceptions',
|
|
212
216
|
'-Wall',
|
|
213
217
|
'-Os'
|
|
214
218
|
],
|
|
215
219
|
'xcode_settings': {
|
|
216
|
-
'CLANG_CXX_LANGUAGE_STANDARD': 'c++
|
|
217
|
-
'MACOSX_DEPLOYMENT_TARGET': '10.
|
|
220
|
+
'CLANG_CXX_LANGUAGE_STANDARD': 'c++17',
|
|
221
|
+
'MACOSX_DEPLOYMENT_TARGET': '10.15',
|
|
218
222
|
'GCC_ENABLE_CPP_EXCEPTIONS': 'YES',
|
|
219
223
|
'GCC_ENABLE_CPP_RTTI': 'YES',
|
|
220
224
|
'OTHER_CPLUSPLUSFLAGS': [
|
|
@@ -234,6 +238,9 @@
|
|
|
234
238
|
['OS == "win"', {
|
|
235
239
|
'msvs_settings': {
|
|
236
240
|
'VCCLCompilerTool': {
|
|
241
|
+
"AdditionalOptions": [
|
|
242
|
+
"/std:c++17"
|
|
243
|
+
],
|
|
237
244
|
'ExceptionHandling': 1,
|
|
238
245
|
'Optimization': 1,
|
|
239
246
|
'WholeProgramOptimization': 'true'
|
package/src/common.cc
CHANGED
|
@@ -109,6 +109,10 @@ namespace sharp {
|
|
|
109
109
|
if (HasAttr(input, "subifd")) {
|
|
110
110
|
descriptor->subifd = AttrAsInt32(input, "subifd");
|
|
111
111
|
}
|
|
112
|
+
// // PDF background color
|
|
113
|
+
if (HasAttr(input, "pdfBackground")) {
|
|
114
|
+
descriptor->pdfBackground = AttrAsVectorOfDouble(input, "pdfBackground");
|
|
115
|
+
}
|
|
112
116
|
// Create new image
|
|
113
117
|
if (HasAttr(input, "createChannels")) {
|
|
114
118
|
descriptor->createChannels = AttrAsUint32(input, "createChannels");
|
|
@@ -156,12 +160,34 @@ namespace sharp {
|
|
|
156
160
|
descriptor->textWrap = AttrAsEnum<VipsTextWrap>(input, "textWrap", VIPS_TYPE_TEXT_WRAP);
|
|
157
161
|
}
|
|
158
162
|
}
|
|
163
|
+
// Join images together
|
|
164
|
+
if (HasAttr(input, "joinAnimated")) {
|
|
165
|
+
descriptor->joinAnimated = AttrAsBool(input, "joinAnimated");
|
|
166
|
+
}
|
|
167
|
+
if (HasAttr(input, "joinAcross")) {
|
|
168
|
+
descriptor->joinAcross = AttrAsUint32(input, "joinAcross");
|
|
169
|
+
}
|
|
170
|
+
if (HasAttr(input, "joinShim")) {
|
|
171
|
+
descriptor->joinShim = AttrAsUint32(input, "joinShim");
|
|
172
|
+
}
|
|
173
|
+
if (HasAttr(input, "joinBackground")) {
|
|
174
|
+
descriptor->joinBackground = AttrAsVectorOfDouble(input, "joinBackground");
|
|
175
|
+
}
|
|
176
|
+
if (HasAttr(input, "joinHalign")) {
|
|
177
|
+
descriptor->joinHalign = AttrAsEnum<VipsAlign>(input, "joinHalign", VIPS_TYPE_ALIGN);
|
|
178
|
+
}
|
|
179
|
+
if (HasAttr(input, "joinValign")) {
|
|
180
|
+
descriptor->joinValign = AttrAsEnum<VipsAlign>(input, "joinValign", VIPS_TYPE_ALIGN);
|
|
181
|
+
}
|
|
159
182
|
// Limit input images to a given number of pixels, where pixels = width * height
|
|
160
183
|
descriptor->limitInputPixels = static_cast<uint64_t>(AttrAsInt64(input, "limitInputPixels"));
|
|
161
|
-
|
|
162
|
-
|
|
184
|
+
if (HasAttr(input, "access")) {
|
|
185
|
+
descriptor->access = AttrAsBool(input, "sequentialRead") ? VIPS_ACCESS_SEQUENTIAL : VIPS_ACCESS_RANDOM;
|
|
186
|
+
}
|
|
163
187
|
// Remove safety features and allow unlimited input
|
|
164
188
|
descriptor->unlimited = AttrAsBool(input, "unlimited");
|
|
189
|
+
// Use the EXIF orientation to auto orient the image
|
|
190
|
+
descriptor->autoOrient = AttrAsBool(input, "autoOrient");
|
|
165
191
|
return descriptor;
|
|
166
192
|
}
|
|
167
193
|
|
|
@@ -244,6 +270,7 @@ namespace sharp {
|
|
|
244
270
|
case ImageType::FITS: id = "fits"; break;
|
|
245
271
|
case ImageType::EXR: id = "exr"; break;
|
|
246
272
|
case ImageType::JXL: id = "jxl"; break;
|
|
273
|
+
case ImageType::RAD: id = "rad"; break;
|
|
247
274
|
case ImageType::VIPS: id = "vips"; break;
|
|
248
275
|
case ImageType::RAW: id = "raw"; break;
|
|
249
276
|
case ImageType::UNKNOWN: id = "unknown"; break;
|
|
@@ -290,6 +317,8 @@ namespace sharp {
|
|
|
290
317
|
{ "VipsForeignLoadOpenexr", ImageType::EXR },
|
|
291
318
|
{ "VipsForeignLoadJxlFile", ImageType::JXL },
|
|
292
319
|
{ "VipsForeignLoadJxlBuffer", ImageType::JXL },
|
|
320
|
+
{ "VipsForeignLoadRadFile", ImageType::RAD },
|
|
321
|
+
{ "VipsForeignLoadRadBuffer", ImageType::RAD },
|
|
293
322
|
{ "VipsForeignLoadVips", ImageType::VIPS },
|
|
294
323
|
{ "VipsForeignLoadVipsFile", ImageType::VIPS },
|
|
295
324
|
{ "VipsForeignLoadRaw", ImageType::RAW }
|
|
@@ -402,6 +431,9 @@ namespace sharp {
|
|
|
402
431
|
if (imageType == ImageType::TIFF) {
|
|
403
432
|
option->set("subifd", descriptor->subifd);
|
|
404
433
|
}
|
|
434
|
+
if (imageType == ImageType::PDF) {
|
|
435
|
+
option->set("background", descriptor->pdfBackground);
|
|
436
|
+
}
|
|
405
437
|
image = VImage::new_from_buffer(descriptor->buffer, descriptor->bufferLength, nullptr, option);
|
|
406
438
|
if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
|
|
407
439
|
image = SetDensity(image, descriptor->density);
|
|
@@ -506,6 +538,9 @@ namespace sharp {
|
|
|
506
538
|
if (imageType == ImageType::TIFF) {
|
|
507
539
|
option->set("subifd", descriptor->subifd);
|
|
508
540
|
}
|
|
541
|
+
if (imageType == ImageType::PDF) {
|
|
542
|
+
option->set("background", descriptor->pdfBackground);
|
|
543
|
+
}
|
|
509
544
|
image = VImage::new_from_file(descriptor->file.data(), option);
|
|
510
545
|
if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
|
|
511
546
|
image = SetDensity(image, descriptor->density);
|
|
@@ -560,14 +595,6 @@ namespace sharp {
|
|
|
560
595
|
return image;
|
|
561
596
|
}
|
|
562
597
|
|
|
563
|
-
/*
|
|
564
|
-
Does this image have an alpha channel?
|
|
565
|
-
Uses colour space interpretation with number of channels to guess this.
|
|
566
|
-
*/
|
|
567
|
-
bool HasAlpha(VImage image) {
|
|
568
|
-
return image.has_alpha();
|
|
569
|
-
}
|
|
570
|
-
|
|
571
598
|
static void* RemoveExifCallback(VipsImage *image, char const *field, GValue *value, void *data) {
|
|
572
599
|
std::vector<std::string> *fieldNames = static_cast<std::vector<std::string> *>(data);
|
|
573
600
|
std::string fieldName(field);
|
|
@@ -976,13 +1003,13 @@ namespace sharp {
|
|
|
976
1003
|
};
|
|
977
1004
|
}
|
|
978
1005
|
// Add alpha channel to alphaColour colour
|
|
979
|
-
if (colour[3] < 255.0 ||
|
|
1006
|
+
if (colour[3] < 255.0 || image.has_alpha()) {
|
|
980
1007
|
alphaColour.push_back(colour[3] * multiplier);
|
|
981
1008
|
}
|
|
982
1009
|
// Ensure alphaColour colour uses correct colourspace
|
|
983
1010
|
alphaColour = sharp::GetRgbaAsColourspace(alphaColour, image.interpretation(), premultiply);
|
|
984
1011
|
// Add non-transparent alpha channel, if required
|
|
985
|
-
if (colour[3] < 255.0 && !
|
|
1012
|
+
if (colour[3] < 255.0 && !image.has_alpha()) {
|
|
986
1013
|
image = image.bandjoin(
|
|
987
1014
|
VImage::new_matrix(image.width(), image.height()).new_from_image(255 * multiplier).cast(image.format()));
|
|
988
1015
|
}
|
|
@@ -990,10 +1017,10 @@ namespace sharp {
|
|
|
990
1017
|
}
|
|
991
1018
|
|
|
992
1019
|
/*
|
|
993
|
-
Removes alpha
|
|
1020
|
+
Removes alpha channels, if any.
|
|
994
1021
|
*/
|
|
995
1022
|
VImage RemoveAlpha(VImage image) {
|
|
996
|
-
|
|
1023
|
+
while (image.bands() > 1 && image.has_alpha()) {
|
|
997
1024
|
image = image.extract_band(0, VImage::option()->set("n", image.bands() - 1));
|
|
998
1025
|
}
|
|
999
1026
|
return image;
|
|
@@ -1003,7 +1030,7 @@ namespace sharp {
|
|
|
1003
1030
|
Ensures alpha channel, if missing.
|
|
1004
1031
|
*/
|
|
1005
1032
|
VImage EnsureAlpha(VImage image, double const value) {
|
|
1006
|
-
if (!
|
|
1033
|
+
if (!image.has_alpha()) {
|
|
1007
1034
|
std::vector<double> alpha;
|
|
1008
1035
|
alpha.push_back(value * sharp::MaximumImageAlpha(image.interpretation()));
|
|
1009
1036
|
image = image.bandjoin_const(alpha);
|
package/src/common.h
CHANGED
|
@@ -15,18 +15,14 @@
|
|
|
15
15
|
// Verify platform and compiler compatibility
|
|
16
16
|
|
|
17
17
|
#if (VIPS_MAJOR_VERSION < 8) || \
|
|
18
|
-
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION <
|
|
19
|
-
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION ==
|
|
20
|
-
#error "libvips version 8.
|
|
18
|
+
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 16) || \
|
|
19
|
+
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 16 && VIPS_MICRO_VERSION < 1)
|
|
20
|
+
#error "libvips version 8.16.1+ is required - please see https://sharp.pixelplumbing.com/install"
|
|
21
21
|
#endif
|
|
22
22
|
|
|
23
|
-
#if
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
|
|
27
|
-
#if (defined(__clang__) && defined(__has_feature))
|
|
28
|
-
#if (!__has_feature(cxx_range_for))
|
|
29
|
-
#error "clang version 3.0+ is required for C++11 features - please see https://sharp.pixelplumbing.com/install"
|
|
23
|
+
#if defined(__has_include)
|
|
24
|
+
#if !__has_include(<filesystem>)
|
|
25
|
+
#error "C++17 compiler required - please see https://sharp.pixelplumbing.com/install"
|
|
30
26
|
#endif
|
|
31
27
|
#endif
|
|
32
28
|
|
|
@@ -37,6 +33,7 @@ namespace sharp {
|
|
|
37
33
|
struct InputDescriptor { // NOLINT(runtime/indentation_namespace)
|
|
38
34
|
std::string name;
|
|
39
35
|
std::string file;
|
|
36
|
+
bool autoOrient;
|
|
40
37
|
char *buffer;
|
|
41
38
|
VipsFailOn failOn;
|
|
42
39
|
uint64_t limitInputPixels;
|
|
@@ -74,13 +71,21 @@ namespace sharp {
|
|
|
74
71
|
int textSpacing;
|
|
75
72
|
VipsTextWrap textWrap;
|
|
76
73
|
int textAutofitDpi;
|
|
74
|
+
bool joinAnimated;
|
|
75
|
+
int joinAcross;
|
|
76
|
+
int joinShim;
|
|
77
|
+
std::vector<double> joinBackground;
|
|
78
|
+
VipsAlign joinHalign;
|
|
79
|
+
VipsAlign joinValign;
|
|
80
|
+
std::vector<double> pdfBackground;
|
|
77
81
|
|
|
78
82
|
InputDescriptor():
|
|
83
|
+
autoOrient(false),
|
|
79
84
|
buffer(nullptr),
|
|
80
85
|
failOn(VIPS_FAIL_ON_WARNING),
|
|
81
86
|
limitInputPixels(0x3FFF * 0x3FFF),
|
|
82
87
|
unlimited(false),
|
|
83
|
-
access(
|
|
88
|
+
access(VIPS_ACCESS_SEQUENTIAL),
|
|
84
89
|
bufferLength(0),
|
|
85
90
|
isBuffer(false),
|
|
86
91
|
density(72.0),
|
|
@@ -108,7 +113,14 @@ namespace sharp {
|
|
|
108
113
|
textRgba(false),
|
|
109
114
|
textSpacing(0),
|
|
110
115
|
textWrap(VIPS_TEXT_WRAP_WORD),
|
|
111
|
-
textAutofitDpi(0)
|
|
116
|
+
textAutofitDpi(0),
|
|
117
|
+
joinAnimated(false),
|
|
118
|
+
joinAcross(1),
|
|
119
|
+
joinShim(0),
|
|
120
|
+
joinBackground{ 0.0, 0.0, 0.0, 255.0 },
|
|
121
|
+
joinHalign(VIPS_ALIGN_LOW),
|
|
122
|
+
joinValign(VIPS_ALIGN_LOW),
|
|
123
|
+
pdfBackground{ 255.0, 255.0, 255.0, 255.0 } {}
|
|
112
124
|
};
|
|
113
125
|
|
|
114
126
|
// Convenience methods to access the attributes of a Napi::Object
|
|
@@ -147,6 +159,7 @@ namespace sharp {
|
|
|
147
159
|
FITS,
|
|
148
160
|
EXR,
|
|
149
161
|
JXL,
|
|
162
|
+
RAD,
|
|
150
163
|
VIPS,
|
|
151
164
|
RAW,
|
|
152
165
|
UNKNOWN,
|
|
@@ -232,12 +245,6 @@ namespace sharp {
|
|
|
232
245
|
*/
|
|
233
246
|
VImage SetProfile(VImage image, std::pair<char*, size_t> icc);
|
|
234
247
|
|
|
235
|
-
/*
|
|
236
|
-
Does this image have an alpha channel?
|
|
237
|
-
Uses colour space interpretation with number of channels to guess this.
|
|
238
|
-
*/
|
|
239
|
-
bool HasAlpha(VImage image);
|
|
240
|
-
|
|
241
248
|
/*
|
|
242
249
|
Remove all EXIF-related image fields.
|
|
243
250
|
*/
|
|
@@ -368,7 +375,7 @@ namespace sharp {
|
|
|
368
375
|
std::tuple<VImage, std::vector<double>> ApplyAlpha(VImage image, std::vector<double> colour, bool premultiply);
|
|
369
376
|
|
|
370
377
|
/*
|
|
371
|
-
Removes alpha
|
|
378
|
+
Removes alpha channels, if any.
|
|
372
379
|
*/
|
|
373
380
|
VImage RemoveAlpha(VImage image);
|
|
374
381
|
|
package/src/metadata.cc
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
#include <numeric>
|
|
5
5
|
#include <vector>
|
|
6
|
+
#include <cmath>
|
|
6
7
|
|
|
7
8
|
#include <napi.h>
|
|
8
9
|
#include <vips/vips8>
|
|
@@ -47,8 +48,11 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|
|
47
48
|
if (image.get_typeof("interlaced") == G_TYPE_INT) {
|
|
48
49
|
baton->isProgressive = image.get_int("interlaced") == 1;
|
|
49
50
|
}
|
|
50
|
-
if (image.get_typeof(
|
|
51
|
-
baton->
|
|
51
|
+
if (image.get_typeof(VIPS_META_PALETTE) == G_TYPE_INT) {
|
|
52
|
+
baton->isPalette = image.get_int(VIPS_META_PALETTE);
|
|
53
|
+
}
|
|
54
|
+
if (image.get_typeof(VIPS_META_BITS_PER_SAMPLE) == G_TYPE_INT) {
|
|
55
|
+
baton->bitsPerSample = image.get_int(VIPS_META_BITS_PER_SAMPLE);
|
|
52
56
|
}
|
|
53
57
|
if (image.get_typeof(VIPS_META_N_PAGES) == G_TYPE_INT) {
|
|
54
58
|
baton->pages = image.get_int(VIPS_META_N_PAGES);
|
|
@@ -91,7 +95,7 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|
|
91
95
|
baton->background = image.get_array_double("background");
|
|
92
96
|
}
|
|
93
97
|
// Derived attributes
|
|
94
|
-
baton->hasAlpha =
|
|
98
|
+
baton->hasAlpha = image.has_alpha();
|
|
95
99
|
baton->orientation = sharp::ExifOrientation(image);
|
|
96
100
|
// EXIF
|
|
97
101
|
if (image.get_typeof(VIPS_META_EXIF_NAME) == VIPS_TYPE_BLOB) {
|
|
@@ -171,8 +175,13 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|
|
171
175
|
info.Set("chromaSubsampling", baton->chromaSubsampling);
|
|
172
176
|
}
|
|
173
177
|
info.Set("isProgressive", baton->isProgressive);
|
|
174
|
-
|
|
175
|
-
|
|
178
|
+
info.Set("isPalette", baton->isPalette);
|
|
179
|
+
if (baton->bitsPerSample > 0) {
|
|
180
|
+
info.Set("bitsPerSample", baton->bitsPerSample);
|
|
181
|
+
if (baton->isPalette) {
|
|
182
|
+
// Deprecated, remove with libvips 8.17.0
|
|
183
|
+
info.Set("paletteBitDepth", baton->bitsPerSample);
|
|
184
|
+
}
|
|
176
185
|
}
|
|
177
186
|
if (baton->pages > 0) {
|
|
178
187
|
info.Set("pages", baton->pages);
|
|
@@ -218,21 +227,30 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|
|
218
227
|
info.Set("subifds", baton->subifds);
|
|
219
228
|
}
|
|
220
229
|
if (!baton->background.empty()) {
|
|
230
|
+
Napi::Object background = Napi::Object::New(env);
|
|
221
231
|
if (baton->background.size() == 3) {
|
|
222
|
-
Napi::Object background = Napi::Object::New(env);
|
|
223
232
|
background.Set("r", baton->background[0]);
|
|
224
233
|
background.Set("g", baton->background[1]);
|
|
225
234
|
background.Set("b", baton->background[2]);
|
|
226
|
-
info.Set("background", background);
|
|
227
235
|
} else {
|
|
228
|
-
|
|
236
|
+
background.Set("gray", round(baton->background[0] * 100 / 255));
|
|
229
237
|
}
|
|
238
|
+
info.Set("background", background);
|
|
230
239
|
}
|
|
231
240
|
info.Set("hasProfile", baton->hasProfile);
|
|
232
241
|
info.Set("hasAlpha", baton->hasAlpha);
|
|
233
242
|
if (baton->orientation > 0) {
|
|
234
243
|
info.Set("orientation", baton->orientation);
|
|
235
244
|
}
|
|
245
|
+
Napi::Object autoOrient = Napi::Object::New(env);
|
|
246
|
+
info.Set("autoOrient", autoOrient);
|
|
247
|
+
if (baton->orientation >= 5) {
|
|
248
|
+
autoOrient.Set("width", baton->height);
|
|
249
|
+
autoOrient.Set("height", baton->width);
|
|
250
|
+
} else {
|
|
251
|
+
autoOrient.Set("width", baton->width);
|
|
252
|
+
autoOrient.Set("height", baton->height);
|
|
253
|
+
}
|
|
236
254
|
if (baton->exifLength > 0) {
|
|
237
255
|
info.Set("exif", Napi::Buffer<char>::NewOrCopy(env, baton->exif, baton->exifLength, sharp::FreeCallback));
|
|
238
256
|
}
|
package/src/metadata.h
CHANGED
|
@@ -24,7 +24,8 @@ struct MetadataBaton {
|
|
|
24
24
|
int density;
|
|
25
25
|
std::string chromaSubsampling;
|
|
26
26
|
bool isProgressive;
|
|
27
|
-
|
|
27
|
+
bool isPalette;
|
|
28
|
+
int bitsPerSample;
|
|
28
29
|
int pages;
|
|
29
30
|
int pageHeight;
|
|
30
31
|
int loop;
|
|
@@ -59,7 +60,8 @@ struct MetadataBaton {
|
|
|
59
60
|
channels(0),
|
|
60
61
|
density(0),
|
|
61
62
|
isProgressive(false),
|
|
62
|
-
|
|
63
|
+
isPalette(false),
|
|
64
|
+
bitsPerSample(0),
|
|
63
65
|
pages(0),
|
|
64
66
|
pageHeight(0),
|
|
65
67
|
loop(-1),
|
package/src/operations.cc
CHANGED
|
@@ -40,7 +40,7 @@ namespace sharp {
|
|
|
40
40
|
typeBeforeTint = VIPS_INTERPRETATION_sRGB;
|
|
41
41
|
}
|
|
42
42
|
// Apply lookup table
|
|
43
|
-
if (
|
|
43
|
+
if (image.has_alpha()) {
|
|
44
44
|
VImage alpha = image[image.bands() - 1];
|
|
45
45
|
image = RemoveAlpha(image)
|
|
46
46
|
.colourspace(VIPS_INTERPRETATION_B_W)
|
|
@@ -83,7 +83,7 @@ namespace sharp {
|
|
|
83
83
|
// Scale luminance, join to chroma, convert back to original colourspace
|
|
84
84
|
VImage normalized = luminance.linear(f, a).bandjoin(chroma).colourspace(typeBeforeNormalize);
|
|
85
85
|
// Attach original alpha channel, if any
|
|
86
|
-
if (
|
|
86
|
+
if (image.has_alpha()) {
|
|
87
87
|
// Extract original alpha channel
|
|
88
88
|
VImage alpha = image[image.bands() - 1];
|
|
89
89
|
// Join alpha channel to normalised image
|
|
@@ -106,7 +106,7 @@ namespace sharp {
|
|
|
106
106
|
* Gamma encoding/decoding
|
|
107
107
|
*/
|
|
108
108
|
VImage Gamma(VImage image, double const exponent) {
|
|
109
|
-
if (
|
|
109
|
+
if (image.has_alpha()) {
|
|
110
110
|
// Separate alpha channel
|
|
111
111
|
VImage alpha = image[image.bands() - 1];
|
|
112
112
|
return RemoveAlpha(image).gamma(VImage::option()->set("exponent", exponent)).bandjoin(alpha);
|
|
@@ -132,7 +132,7 @@ namespace sharp {
|
|
|
132
132
|
* Produce the "negative" of the image.
|
|
133
133
|
*/
|
|
134
134
|
VImage Negate(VImage image, bool const negateAlpha) {
|
|
135
|
-
if (
|
|
135
|
+
if (image.has_alpha() && !negateAlpha) {
|
|
136
136
|
// Separate alpha channel
|
|
137
137
|
VImage alpha = image[image.bands() - 1];
|
|
138
138
|
return RemoveAlpha(image).invert().bandjoin(alpha);
|
|
@@ -205,7 +205,7 @@ namespace sharp {
|
|
|
205
205
|
VImage Modulate(VImage image, double const brightness, double const saturation,
|
|
206
206
|
int const hue, double const lightness) {
|
|
207
207
|
VipsInterpretation colourspaceBeforeModulate = image.interpretation();
|
|
208
|
-
if (
|
|
208
|
+
if (image.has_alpha()) {
|
|
209
209
|
// Separate alpha channel
|
|
210
210
|
VImage alpha = image[image.bands() - 1];
|
|
211
211
|
return RemoveAlpha(image)
|
|
@@ -297,7 +297,7 @@ namespace sharp {
|
|
|
297
297
|
threshold *= 256.0;
|
|
298
298
|
}
|
|
299
299
|
std::vector<double> backgroundAlpha({ background.back() });
|
|
300
|
-
if (
|
|
300
|
+
if (image.has_alpha()) {
|
|
301
301
|
background.pop_back();
|
|
302
302
|
} else {
|
|
303
303
|
background.resize(image.bands());
|
|
@@ -307,7 +307,7 @@ namespace sharp {
|
|
|
307
307
|
->set("background", background)
|
|
308
308
|
->set("line_art", lineArt)
|
|
309
309
|
->set("threshold", threshold));
|
|
310
|
-
if (
|
|
310
|
+
if (image.has_alpha()) {
|
|
311
311
|
// Search alpha channel (A)
|
|
312
312
|
int leftA, topA, widthA, heightA;
|
|
313
313
|
VImage alpha = image[image.bands() - 1];
|
|
@@ -344,7 +344,7 @@ namespace sharp {
|
|
|
344
344
|
throw VError("Band expansion using linear is unsupported");
|
|
345
345
|
}
|
|
346
346
|
bool const uchar = !Is16Bit(image.interpretation());
|
|
347
|
-
if (
|
|
347
|
+
if (image.has_alpha() && a.size() != bands && (a.size() == 1 || a.size() == bands - 1 || bands - 1 == 1)) {
|
|
348
348
|
// Separate alpha channel
|
|
349
349
|
VImage alpha = image[bands - 1];
|
|
350
350
|
return RemoveAlpha(image).linear(a, b, VImage::option()->set("uchar", uchar)).bandjoin(alpha);
|
|
@@ -357,7 +357,7 @@ namespace sharp {
|
|
|
357
357
|
* Unflatten
|
|
358
358
|
*/
|
|
359
359
|
VImage Unflatten(VImage image) {
|
|
360
|
-
if (
|
|
360
|
+
if (image.has_alpha()) {
|
|
361
361
|
VImage alpha = image[image.bands() - 1];
|
|
362
362
|
VImage noAlpha = RemoveAlpha(image);
|
|
363
363
|
return noAlpha.bandjoin(alpha & (noAlpha.colourspace(VIPS_INTERPRETATION_B_W) < 255));
|
|
@@ -472,4 +472,26 @@ namespace sharp {
|
|
|
472
472
|
}
|
|
473
473
|
}
|
|
474
474
|
|
|
475
|
+
/*
|
|
476
|
+
* Dilate an image
|
|
477
|
+
*/
|
|
478
|
+
VImage Dilate(VImage image, int const width) {
|
|
479
|
+
int const maskWidth = 2 * width + 1;
|
|
480
|
+
VImage mask = VImage::new_matrix(maskWidth, maskWidth);
|
|
481
|
+
return image.morph(
|
|
482
|
+
mask,
|
|
483
|
+
VIPS_OPERATION_MORPHOLOGY_DILATE).invert();
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/*
|
|
487
|
+
* Erode an image
|
|
488
|
+
*/
|
|
489
|
+
VImage Erode(VImage image, int const width) {
|
|
490
|
+
int const maskWidth = 2 * width + 1;
|
|
491
|
+
VImage mask = VImage::new_matrix(maskWidth, maskWidth);
|
|
492
|
+
return image.morph(
|
|
493
|
+
mask,
|
|
494
|
+
VIPS_OPERATION_MORPHOLOGY_ERODE).invert();
|
|
495
|
+
}
|
|
496
|
+
|
|
475
497
|
} // namespace sharp
|
package/src/operations.h
CHANGED
|
@@ -120,6 +120,15 @@ namespace sharp {
|
|
|
120
120
|
VImage EmbedMultiPage(VImage image, int left, int top, int width, int height,
|
|
121
121
|
VipsExtend extendWith, std::vector<double> background, int nPages, int *pageHeight);
|
|
122
122
|
|
|
123
|
+
/*
|
|
124
|
+
* Dilate an image
|
|
125
|
+
*/
|
|
126
|
+
VImage Dilate(VImage image, int const maskWidth);
|
|
127
|
+
|
|
128
|
+
/*
|
|
129
|
+
* Erode an image
|
|
130
|
+
*/
|
|
131
|
+
VImage Erode(VImage image, int const maskWidth);
|
|
123
132
|
} // namespace sharp
|
|
124
133
|
|
|
125
134
|
#endif // SRC_OPERATIONS_H_
|