sharp 0.32.5 → 0.33.0-alpha.10
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 +6 -2
- package/install/check.js +36 -0
- package/lib/constructor.js +6 -5
- package/lib/index.d.ts +59 -16
- package/lib/input.js +34 -8
- package/lib/is.js +28 -14
- package/lib/libvips.js +70 -57
- package/lib/operation.js +1 -5
- package/lib/output.js +44 -26
- package/lib/resize.js +46 -46
- package/lib/sharp.js +58 -27
- package/lib/utility.js +19 -25
- package/package.json +46 -41
- package/{binding.gyp → src/binding.gyp} +68 -42
- package/src/common.cc +5 -4
- package/src/common.h +6 -5
- package/src/metadata.cc +5 -5
- package/src/operations.cc +5 -2
- package/src/operations.h +1 -1
- package/src/pipeline.cc +23 -21
- package/src/pipeline.h +5 -1
- package/src/sharp.cc +6 -7
- package/src/stats.cc +5 -5
- package/src/utilities.cc +15 -5
- package/install/can-compile.js +0 -14
- package/install/dll-copy.js +0 -40
- package/install/libvips.js +0 -222
- package/lib/agent.js +0 -44
- package/lib/platform.js +0 -30
- package/src/libvips/cplusplus/VConnection.cpp +0 -151
- package/src/libvips/cplusplus/VError.cpp +0 -49
- package/src/libvips/cplusplus/VImage.cpp +0 -1548
- package/src/libvips/cplusplus/VInterpolate.cpp +0 -62
- package/src/libvips/cplusplus/VRegion.cpp +0 -27
- package/src/libvips/cplusplus/vips-operators.cpp +0 -3760
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
# Copyright 2013 Lovell Fuller and others.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
1
4
|
{
|
|
2
5
|
'variables': {
|
|
3
|
-
'vips_version': '<!(node -p "require(\'
|
|
4
|
-
'platform_and_arch': '<!(node -p "require(\'
|
|
5
|
-
'
|
|
6
|
+
'vips_version': '<!(node -p "require(\'../lib/libvips\').minimumLibvipsVersion")',
|
|
7
|
+
'platform_and_arch': '<!(node -p "require(\'../lib/libvips\').buildPlatformArch()")',
|
|
8
|
+
'sharp_libvips_version': '<!(node -p "require(\'../package.json\').optionalDependencies[\'@img/sharp-libvips-<(platform_and_arch)\']")',
|
|
9
|
+
'sharp_libvips_include_dir': '<!(node -p "require(\'../lib/libvips\').buildSharpLibvipsIncludeDir()")',
|
|
10
|
+
'sharp_libvips_cplusplus_dir': '<!(node -p "require(\'../lib/libvips\').buildSharpLibvipsCPlusPlusDir()")',
|
|
11
|
+
'sharp_libvips_lib_dir': '<!(node -p "require(\'../lib/libvips\').buildSharpLibvipsLibDir()")'
|
|
6
12
|
},
|
|
7
13
|
'targets': [{
|
|
8
14
|
'target_name': 'libvips-cpp',
|
|
@@ -15,23 +21,23 @@
|
|
|
15
21
|
'_ALLOW_KEYWORD_MACROS'
|
|
16
22
|
],
|
|
17
23
|
'sources': [
|
|
18
|
-
'
|
|
19
|
-
'
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
'
|
|
24
|
+
'<(sharp_libvips_cplusplus_dir)/VConnection.cpp',
|
|
25
|
+
'<(sharp_libvips_cplusplus_dir)/VError.cpp',
|
|
26
|
+
'<(sharp_libvips_cplusplus_dir)/VImage.cpp',
|
|
27
|
+
'<(sharp_libvips_cplusplus_dir)/VInterpolate.cpp',
|
|
28
|
+
'<(sharp_libvips_cplusplus_dir)/VRegion.cpp'
|
|
23
29
|
],
|
|
24
30
|
'include_dirs': [
|
|
25
|
-
'<(
|
|
26
|
-
'<(
|
|
27
|
-
'<(
|
|
31
|
+
'<(sharp_libvips_include_dir)',
|
|
32
|
+
'<(sharp_libvips_include_dir)/glib-2.0',
|
|
33
|
+
'<(sharp_libvips_lib_dir)/glib-2.0/include'
|
|
28
34
|
],
|
|
29
35
|
'link_settings': {
|
|
30
|
-
'library_dirs': [
|
|
36
|
+
'library_dirs': [
|
|
37
|
+
'<(sharp_libvips_lib_dir)'
|
|
38
|
+
],
|
|
31
39
|
'libraries': [
|
|
32
|
-
'libvips.lib'
|
|
33
|
-
'libglib-2.0.lib',
|
|
34
|
-
'libgobject-2.0.lib'
|
|
40
|
+
'libvips.lib'
|
|
35
41
|
],
|
|
36
42
|
},
|
|
37
43
|
'configurations': {
|
|
@@ -70,7 +76,7 @@
|
|
|
70
76
|
}, {
|
|
71
77
|
'target_name': 'sharp-<(platform_and_arch)',
|
|
72
78
|
'defines': [
|
|
73
|
-
'NAPI_VERSION=
|
|
79
|
+
'NAPI_VERSION=9',
|
|
74
80
|
'NODE_ADDON_API_DISABLE_DEPRECATED',
|
|
75
81
|
'NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS'
|
|
76
82
|
],
|
|
@@ -79,11 +85,10 @@
|
|
|
79
85
|
'libvips-cpp'
|
|
80
86
|
],
|
|
81
87
|
'variables': {
|
|
82
|
-
'runtime_link%': 'shared',
|
|
83
88
|
'conditions': [
|
|
84
89
|
['OS != "win"', {
|
|
85
|
-
'pkg_config_path': '<!(node -p "require(\'
|
|
86
|
-
'use_global_libvips': '<!(node -p "Boolean(require(\'
|
|
90
|
+
'pkg_config_path': '<!(node -p "require(\'../lib/libvips\').pkgConfigPath()")',
|
|
91
|
+
'use_global_libvips': '<!(node -p "Boolean(require(\'../lib/libvips\').useGlobalLibvips()).toString()")'
|
|
87
92
|
}, {
|
|
88
93
|
'pkg_config_path': '',
|
|
89
94
|
'use_global_libvips': ''
|
|
@@ -91,13 +96,13 @@
|
|
|
91
96
|
]
|
|
92
97
|
},
|
|
93
98
|
'sources': [
|
|
94
|
-
'
|
|
95
|
-
'
|
|
96
|
-
'
|
|
97
|
-
'
|
|
98
|
-
'
|
|
99
|
-
'
|
|
100
|
-
'
|
|
99
|
+
'common.cc',
|
|
100
|
+
'metadata.cc',
|
|
101
|
+
'stats.cc',
|
|
102
|
+
'operations.cc',
|
|
103
|
+
'pipeline.cc',
|
|
104
|
+
'utilities.cc',
|
|
105
|
+
'sharp.cc'
|
|
101
106
|
],
|
|
102
107
|
'include_dirs': [
|
|
103
108
|
'<!(node -p "require(\'node-addon-api\').include_dir")',
|
|
@@ -106,12 +111,11 @@
|
|
|
106
111
|
['use_global_libvips == "true"', {
|
|
107
112
|
# Use pkg-config for include and lib
|
|
108
113
|
'include_dirs': ['<!@(PKG_CONFIG_PATH="<(pkg_config_path)" pkg-config --cflags-only-I vips-cpp vips glib-2.0 | sed s\/-I//g)'],
|
|
114
|
+
'libraries': ['<!@(PKG_CONFIG_PATH="<(pkg_config_path)" pkg-config --libs vips-cpp)'],
|
|
115
|
+
'defines': [
|
|
116
|
+
'SHARP_USE_GLOBAL_LIBVIPS'
|
|
117
|
+
],
|
|
109
118
|
'conditions': [
|
|
110
|
-
['runtime_link == "static"', {
|
|
111
|
-
'libraries': ['<!@(PKG_CONFIG_PATH="<(pkg_config_path)" pkg-config --libs --static vips-cpp)']
|
|
112
|
-
}, {
|
|
113
|
-
'libraries': ['<!@(PKG_CONFIG_PATH="<(pkg_config_path)" pkg-config --libs vips-cpp)']
|
|
114
|
-
}],
|
|
115
119
|
['OS == "linux"', {
|
|
116
120
|
'defines': [
|
|
117
121
|
# Inspect libvips-cpp.so to determine which C++11 ABI version was used and set _GLIBCXX_USE_CXX11_ABI accordingly. This is quite horrible.
|
|
@@ -122,9 +126,12 @@
|
|
|
122
126
|
}, {
|
|
123
127
|
# Use pre-built libvips stored locally within node_modules
|
|
124
128
|
'include_dirs': [
|
|
125
|
-
'<(
|
|
126
|
-
'<(
|
|
127
|
-
'<(
|
|
129
|
+
'<(sharp_libvips_include_dir)',
|
|
130
|
+
'<(sharp_libvips_include_dir)/glib-2.0',
|
|
131
|
+
'<(sharp_libvips_lib_dir)/glib-2.0/include'
|
|
132
|
+
],
|
|
133
|
+
'library_dirs': [
|
|
134
|
+
'<(sharp_libvips_lib_dir)'
|
|
128
135
|
],
|
|
129
136
|
'conditions': [
|
|
130
137
|
['OS == "win"', {
|
|
@@ -133,17 +140,13 @@
|
|
|
133
140
|
'_FILE_OFFSET_BITS=64'
|
|
134
141
|
],
|
|
135
142
|
'link_settings': {
|
|
136
|
-
'library_dirs': ['<(sharp_vendor_dir)/lib'],
|
|
137
143
|
'libraries': [
|
|
138
|
-
'libvips.lib'
|
|
139
|
-
'libglib-2.0.lib',
|
|
140
|
-
'libgobject-2.0.lib'
|
|
144
|
+
'libvips.lib'
|
|
141
145
|
]
|
|
142
146
|
}
|
|
143
147
|
}],
|
|
144
148
|
['OS == "mac"', {
|
|
145
149
|
'link_settings': {
|
|
146
|
-
'library_dirs': ['../<(sharp_vendor_dir)/lib'],
|
|
147
150
|
'libraries': [
|
|
148
151
|
'libvips-cpp.42.dylib'
|
|
149
152
|
]
|
|
@@ -151,7 +154,10 @@
|
|
|
151
154
|
'xcode_settings': {
|
|
152
155
|
'OTHER_LDFLAGS': [
|
|
153
156
|
# Ensure runtime linking is relative to sharp.node
|
|
154
|
-
'-Wl,-rpath,\'@loader_path
|
|
157
|
+
'-Wl,-rpath,\'@loader_path/../../sharp-libvips-<(platform_and_arch)/lib\'',
|
|
158
|
+
'-Wl,-rpath,\'@loader_path/../../../<(sharp_libvips_version)/sharp-libvips-<(platform_and_arch)/lib\'',
|
|
159
|
+
'-Wl,-rpath,\'@loader_path/../../node_modules/@img/sharp-libvips-<(platform_and_arch)/lib\'',
|
|
160
|
+
'-Wl,-rpath,\'@loader_path/../../../node_modules/@img/sharp-libvips-<(platform_and_arch)/lib\''
|
|
155
161
|
]
|
|
156
162
|
}
|
|
157
163
|
}],
|
|
@@ -160,13 +166,17 @@
|
|
|
160
166
|
'_GLIBCXX_USE_CXX11_ABI=1'
|
|
161
167
|
],
|
|
162
168
|
'link_settings': {
|
|
163
|
-
'library_dirs': ['../<(sharp_vendor_dir)/lib'],
|
|
164
169
|
'libraries': [
|
|
165
170
|
'-l:libvips-cpp.so.42'
|
|
166
171
|
],
|
|
167
172
|
'ldflags': [
|
|
168
173
|
# Ensure runtime linking is relative to sharp.node
|
|
169
|
-
'-Wl,-s
|
|
174
|
+
'-Wl,-s',
|
|
175
|
+
'-Wl,--disable-new-dtags',
|
|
176
|
+
'-Wl,-rpath=\'$$ORIGIN/../../sharp-libvips-<(platform_and_arch)/lib\'',
|
|
177
|
+
'-Wl,-rpath=\'$$ORIGIN/../../../<(sharp_libvips_version)/sharp-libvips-<(platform_and_arch)/lib\'',
|
|
178
|
+
'-Wl,-rpath=\'$$ORIGIN/../../node_modules/@img/sharp-libvips-<(platform_and_arch)/lib\'',
|
|
179
|
+
'-Wl,-rpath=\'$$ORIGIN/../../../node_modules/@img/sharp-libvips-<(platform_and_arch)/lib\''
|
|
170
180
|
]
|
|
171
181
|
}
|
|
172
182
|
}]
|
|
@@ -232,5 +242,21 @@
|
|
|
232
242
|
]
|
|
233
243
|
}
|
|
234
244
|
},
|
|
245
|
+
}, {
|
|
246
|
+
'target_name': 'copy-dll',
|
|
247
|
+
'type': 'none',
|
|
248
|
+
'dependencies': [
|
|
249
|
+
'sharp-<(platform_and_arch)'
|
|
250
|
+
],
|
|
251
|
+
'conditions': [
|
|
252
|
+
['OS == "win"', {
|
|
253
|
+
'copies': [{
|
|
254
|
+
'destination': 'build/Release',
|
|
255
|
+
'files': [
|
|
256
|
+
'<(sharp_libvips_lib_dir)/libvips-42.dll'
|
|
257
|
+
]
|
|
258
|
+
}]
|
|
259
|
+
}]
|
|
260
|
+
]
|
|
235
261
|
}]
|
|
236
262
|
}
|
package/src/common.cc
CHANGED
|
@@ -166,10 +166,10 @@ namespace sharp {
|
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
// How many tasks are in the queue?
|
|
169
|
-
|
|
169
|
+
std::atomic<int> counterQueue{0};
|
|
170
170
|
|
|
171
171
|
// How many tasks are being processed?
|
|
172
|
-
|
|
172
|
+
std::atomic<int> counterProcess{0};
|
|
173
173
|
|
|
174
174
|
// Filename extension checkers
|
|
175
175
|
static bool EndsWith(std::string const &str, std::string const &end) {
|
|
@@ -363,12 +363,13 @@ namespace sharp {
|
|
|
363
363
|
if (descriptor->isBuffer) {
|
|
364
364
|
if (descriptor->rawChannels > 0) {
|
|
365
365
|
// Raw, uncompressed pixel data
|
|
366
|
+
bool const is8bit = vips_band_format_is8bit(descriptor->rawDepth);
|
|
366
367
|
image = VImage::new_from_memory(descriptor->buffer, descriptor->bufferLength,
|
|
367
368
|
descriptor->rawWidth, descriptor->rawHeight, descriptor->rawChannels, descriptor->rawDepth);
|
|
368
369
|
if (descriptor->rawChannels < 3) {
|
|
369
|
-
image.get_image()->Type = VIPS_INTERPRETATION_B_W;
|
|
370
|
+
image.get_image()->Type = is8bit ? VIPS_INTERPRETATION_B_W : VIPS_INTERPRETATION_GREY16;
|
|
370
371
|
} else {
|
|
371
|
-
image.get_image()->Type = VIPS_INTERPRETATION_sRGB;
|
|
372
|
+
image.get_image()->Type = is8bit ? VIPS_INTERPRETATION_sRGB : VIPS_INTERPRETATION_RGB16;
|
|
372
373
|
}
|
|
373
374
|
if (descriptor->rawPremultiplied) {
|
|
374
375
|
image = image.unpremultiply();
|
package/src/common.h
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
#include <string>
|
|
8
8
|
#include <tuple>
|
|
9
9
|
#include <vector>
|
|
10
|
+
#include <atomic>
|
|
10
11
|
|
|
11
12
|
#include <napi.h>
|
|
12
13
|
#include <vips/vips8>
|
|
@@ -14,9 +15,9 @@
|
|
|
14
15
|
// Verify platform and compiler compatibility
|
|
15
16
|
|
|
16
17
|
#if (VIPS_MAJOR_VERSION < 8) || \
|
|
17
|
-
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION <
|
|
18
|
-
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION ==
|
|
19
|
-
#error "libvips version 8.
|
|
18
|
+
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 15) || \
|
|
19
|
+
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 15 && VIPS_MICRO_VERSION < 0)
|
|
20
|
+
#error "libvips version 8.15.0+ is required - please see https://sharp.pixelplumbing.com/install"
|
|
20
21
|
#endif
|
|
21
22
|
|
|
22
23
|
#if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))
|
|
@@ -161,10 +162,10 @@ namespace sharp {
|
|
|
161
162
|
};
|
|
162
163
|
|
|
163
164
|
// How many tasks are in the queue?
|
|
164
|
-
extern
|
|
165
|
+
extern std::atomic<int> counterQueue;
|
|
165
166
|
|
|
166
167
|
// How many tasks are being processed?
|
|
167
|
-
extern
|
|
168
|
+
extern std::atomic<int> counterProcess;
|
|
168
169
|
|
|
169
170
|
// Filename extension checkers
|
|
170
171
|
bool IsJpeg(std::string const &str);
|
package/src/metadata.cc
CHANGED
|
@@ -18,7 +18,7 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|
|
18
18
|
|
|
19
19
|
void Execute() {
|
|
20
20
|
// Decrement queued task counter
|
|
21
|
-
|
|
21
|
+
sharp::counterQueue--;
|
|
22
22
|
|
|
23
23
|
vips::VImage image;
|
|
24
24
|
sharp::ImageType imageType = sharp::ImageType::UNKNOWN;
|
|
@@ -145,7 +145,7 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|
|
145
145
|
// Handle warnings
|
|
146
146
|
std::string warning = sharp::VipsWarningPop();
|
|
147
147
|
while (!warning.empty()) {
|
|
148
|
-
debuglog.
|
|
148
|
+
debuglog.Call(Receiver().Value(), { Napi::String::New(env, warning) });
|
|
149
149
|
warning = sharp::VipsWarningPop();
|
|
150
150
|
}
|
|
151
151
|
|
|
@@ -246,9 +246,9 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|
|
246
246
|
Napi::Buffer<char>::NewOrCopy(env, baton->tifftagPhotoshop,
|
|
247
247
|
baton->tifftagPhotoshopLength, sharp::FreeCallback));
|
|
248
248
|
}
|
|
249
|
-
Callback().
|
|
249
|
+
Callback().Call(Receiver().Value(), { env.Null(), info });
|
|
250
250
|
} else {
|
|
251
|
-
Callback().
|
|
251
|
+
Callback().Call(Receiver().Value(), { Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
|
|
252
252
|
}
|
|
253
253
|
|
|
254
254
|
delete baton->input;
|
|
@@ -281,7 +281,7 @@ Napi::Value metadata(const Napi::CallbackInfo& info) {
|
|
|
281
281
|
worker->Queue();
|
|
282
282
|
|
|
283
283
|
// Increment queued task counter
|
|
284
|
-
|
|
284
|
+
sharp::counterQueue++;
|
|
285
285
|
|
|
286
286
|
return info.Env().Undefined();
|
|
287
287
|
}
|
package/src/operations.cc
CHANGED
|
@@ -141,7 +141,7 @@ namespace sharp {
|
|
|
141
141
|
return image.conv(blur);
|
|
142
142
|
} else {
|
|
143
143
|
// Slower, accurate Gaussian blur
|
|
144
|
-
return image.gaussblur(sigma);
|
|
144
|
+
return StaySequential(image, VIPS_ACCESS_SEQUENTIAL).gaussblur(sigma);
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
|
|
@@ -265,7 +265,7 @@ namespace sharp {
|
|
|
265
265
|
/*
|
|
266
266
|
Trim an image
|
|
267
267
|
*/
|
|
268
|
-
VImage Trim(VImage image, std::vector<double> background, double threshold) {
|
|
268
|
+
VImage Trim(VImage image, std::vector<double> background, double threshold, bool const lineArt) {
|
|
269
269
|
if (image.width() < 3 && image.height() < 3) {
|
|
270
270
|
throw VError("Image to trim must be at least 3x3 pixels");
|
|
271
271
|
}
|
|
@@ -287,6 +287,7 @@ namespace sharp {
|
|
|
287
287
|
int left, top, width, height;
|
|
288
288
|
left = image.find_trim(&top, &width, &height, VImage::option()
|
|
289
289
|
->set("background", background)
|
|
290
|
+
->set("line_art", lineArt)
|
|
290
291
|
->set("threshold", threshold));
|
|
291
292
|
if (HasAlpha(image)) {
|
|
292
293
|
// Search alpha channel (A)
|
|
@@ -294,6 +295,7 @@ namespace sharp {
|
|
|
294
295
|
VImage alpha = image[image.bands() - 1];
|
|
295
296
|
leftA = alpha.find_trim(&topA, &widthA, &heightA, VImage::option()
|
|
296
297
|
->set("background", backgroundAlpha)
|
|
298
|
+
->set("line_art", lineArt)
|
|
297
299
|
->set("threshold", threshold));
|
|
298
300
|
if (widthA > 0 && heightA > 0) {
|
|
299
301
|
if (width > 0 && height > 0) {
|
|
@@ -370,6 +372,7 @@ namespace sharp {
|
|
|
370
372
|
pages.reserve(nPages);
|
|
371
373
|
|
|
372
374
|
// Split the image into cropped frames
|
|
375
|
+
image = StaySequential(image, VIPS_ACCESS_SEQUENTIAL);
|
|
373
376
|
for (int i = 0; i < nPages; i++) {
|
|
374
377
|
pages.push_back(
|
|
375
378
|
image.extract_area(left, *pageHeight * i + top, width, height));
|
package/src/operations.h
CHANGED
|
@@ -79,7 +79,7 @@ namespace sharp {
|
|
|
79
79
|
/*
|
|
80
80
|
Trim an image
|
|
81
81
|
*/
|
|
82
|
-
VImage Trim(VImage image, std::vector<double> background, double const
|
|
82
|
+
VImage Trim(VImage image, std::vector<double> background, double threshold, bool const lineArt);
|
|
83
83
|
|
|
84
84
|
/*
|
|
85
85
|
* Linear adjustment (a * in + b)
|
package/src/pipeline.cc
CHANGED
|
@@ -44,9 +44,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
44
44
|
// libuv worker
|
|
45
45
|
void Execute() {
|
|
46
46
|
// Decrement queued task counter
|
|
47
|
-
|
|
47
|
+
sharp::counterQueue--;
|
|
48
48
|
// Increment processing task counter
|
|
49
|
-
|
|
49
|
+
sharp::counterProcess++;
|
|
50
50
|
|
|
51
51
|
try {
|
|
52
52
|
// Open input
|
|
@@ -126,10 +126,10 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
// Trim
|
|
129
|
-
if (baton->trimThreshold
|
|
129
|
+
if (baton->trimThreshold >= 0.0) {
|
|
130
130
|
MultiPageUnsupported(nPages, "Trim");
|
|
131
131
|
image = sharp::StaySequential(image, access);
|
|
132
|
-
image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold);
|
|
132
|
+
image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold, baton->trimLineArt);
|
|
133
133
|
baton->trimOffsetLeft = image.xoffset();
|
|
134
134
|
baton->trimOffsetTop = image.yoffset();
|
|
135
135
|
}
|
|
@@ -182,7 +182,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
182
182
|
// - trimming or pre-resize extract isn't required;
|
|
183
183
|
// - input colourspace is not specified;
|
|
184
184
|
bool const shouldPreShrink = (targetResizeWidth > 0 || targetResizeHeight > 0) &&
|
|
185
|
-
baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold
|
|
185
|
+
baton->gamma == 0 && baton->topOffsetPre == -1 && baton->trimThreshold < 0.0 &&
|
|
186
186
|
baton->colourspaceInput == VIPS_INTERPRETATION_LAST && !shouldRotateBefore;
|
|
187
187
|
|
|
188
188
|
if (shouldPreShrink) {
|
|
@@ -326,7 +326,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
326
326
|
try {
|
|
327
327
|
image = image.icc_transform(processingProfile, VImage::option()
|
|
328
328
|
->set("embedded", TRUE)
|
|
329
|
-
->set("depth", image.interpretation()
|
|
329
|
+
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
|
330
330
|
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
|
331
331
|
} catch(...) {
|
|
332
332
|
sharp::VipsWarningCallback(nullptr, G_LOG_LEVEL_WARNING, "Invalid embedded profile", nullptr);
|
|
@@ -485,9 +485,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
485
485
|
image = sharp::StaySequential(image, access);
|
|
486
486
|
image = image.smartcrop(baton->width, baton->height, VImage::option()
|
|
487
487
|
->set("interesting", baton->position == 16 ? VIPS_INTERESTING_ENTROPY : VIPS_INTERESTING_ATTENTION)
|
|
488
|
-
#if (VIPS_MAJOR_VERSION >= 8 && VIPS_MINOR_VERSION >= 15)
|
|
489
488
|
->set("premultiplied", shouldPremultiplyAlpha)
|
|
490
|
-
#endif
|
|
491
489
|
->set("attention_x", &attention_x)
|
|
492
490
|
->set("attention_y", &attention_y));
|
|
493
491
|
baton->hasCropOffset = true;
|
|
@@ -653,7 +651,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
653
651
|
if (across != 0 || down != 0) {
|
|
654
652
|
int left;
|
|
655
653
|
int top;
|
|
656
|
-
compositeImage = compositeImage.replicate(across, down);
|
|
654
|
+
compositeImage = sharp::StaySequential(compositeImage, access).replicate(across, down);
|
|
657
655
|
if (composite->hasOffset) {
|
|
658
656
|
std::tie(left, top) = sharp::CalculateCrop(
|
|
659
657
|
compositeImage.width(), compositeImage.height(), image.width(), image.height(),
|
|
@@ -763,6 +761,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
763
761
|
if (baton->withMetadata && sharp::HasProfile(image) && baton->withMetadataIcc.empty()) {
|
|
764
762
|
image = image.icc_transform("srgb", VImage::option()
|
|
765
763
|
->set("embedded", TRUE)
|
|
764
|
+
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
|
766
765
|
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
|
767
766
|
}
|
|
768
767
|
}
|
|
@@ -794,6 +793,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
794
793
|
VImage::option()
|
|
795
794
|
->set("input_profile", processingProfile)
|
|
796
795
|
->set("embedded", TRUE)
|
|
796
|
+
->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
|
|
797
797
|
->set("intent", VIPS_INTENT_PERCEPTUAL));
|
|
798
798
|
}
|
|
799
799
|
// Override EXIF Orientation tag
|
|
@@ -938,6 +938,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
938
938
|
->set("Q", baton->tiffQuality)
|
|
939
939
|
->set("bitdepth", baton->tiffBitdepth)
|
|
940
940
|
->set("compression", baton->tiffCompression)
|
|
941
|
+
->set("miniswhite", baton->tiffMiniswhite)
|
|
941
942
|
->set("predictor", baton->tiffPredictor)
|
|
942
943
|
->set("pyramid", baton->tiffPyramid)
|
|
943
944
|
->set("tile", baton->tiffTile)
|
|
@@ -1134,6 +1135,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1134
1135
|
->set("Q", baton->tiffQuality)
|
|
1135
1136
|
->set("bitdepth", baton->tiffBitdepth)
|
|
1136
1137
|
->set("compression", baton->tiffCompression)
|
|
1138
|
+
->set("miniswhite", baton->tiffMiniswhite)
|
|
1137
1139
|
->set("predictor", baton->tiffPredictor)
|
|
1138
1140
|
->set("pyramid", baton->tiffPyramid)
|
|
1139
1141
|
->set("tile", baton->tiffTile)
|
|
@@ -1213,7 +1215,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1213
1215
|
// Handle warnings
|
|
1214
1216
|
std::string warning = sharp::VipsWarningPop();
|
|
1215
1217
|
while (!warning.empty()) {
|
|
1216
|
-
debuglog.
|
|
1218
|
+
debuglog.Call(Receiver().Value(), { Napi::String::New(env, warning) });
|
|
1217
1219
|
warning = sharp::VipsWarningPop();
|
|
1218
1220
|
}
|
|
1219
1221
|
|
|
@@ -1246,11 +1248,10 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1246
1248
|
info.Set("attentionX", static_cast<int32_t>(baton->attentionX));
|
|
1247
1249
|
info.Set("attentionY", static_cast<int32_t>(baton->attentionY));
|
|
1248
1250
|
}
|
|
1249
|
-
if (baton->trimThreshold
|
|
1251
|
+
if (baton->trimThreshold >= 0.0) {
|
|
1250
1252
|
info.Set("trimOffsetLeft", static_cast<int32_t>(baton->trimOffsetLeft));
|
|
1251
1253
|
info.Set("trimOffsetTop", static_cast<int32_t>(baton->trimOffsetTop));
|
|
1252
1254
|
}
|
|
1253
|
-
|
|
1254
1255
|
if (baton->input->textAutofitDpi) {
|
|
1255
1256
|
info.Set("textAutofitDpi", static_cast<uint32_t>(baton->input->textAutofitDpi));
|
|
1256
1257
|
}
|
|
@@ -1261,17 +1262,17 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1261
1262
|
// Pass ownership of output data to Buffer instance
|
|
1262
1263
|
Napi::Buffer<char> data = Napi::Buffer<char>::NewOrCopy(env, static_cast<char*>(baton->bufferOut),
|
|
1263
1264
|
baton->bufferOutLength, sharp::FreeCallback);
|
|
1264
|
-
Callback().
|
|
1265
|
+
Callback().Call(Receiver().Value(), { env.Null(), data, info });
|
|
1265
1266
|
} else {
|
|
1266
1267
|
// Add file size to info
|
|
1267
1268
|
struct STAT64_STRUCT st;
|
|
1268
1269
|
if (STAT64_FUNCTION(baton->fileOut.data(), &st) == 0) {
|
|
1269
1270
|
info.Set("size", static_cast<uint32_t>(st.st_size));
|
|
1270
1271
|
}
|
|
1271
|
-
Callback().
|
|
1272
|
+
Callback().Call(Receiver().Value(), { env.Null(), info });
|
|
1272
1273
|
}
|
|
1273
1274
|
} else {
|
|
1274
|
-
Callback().
|
|
1275
|
+
Callback().Call(Receiver().Value(), { Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
|
|
1275
1276
|
}
|
|
1276
1277
|
|
|
1277
1278
|
// Delete baton
|
|
@@ -1287,9 +1288,9 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1287
1288
|
delete baton;
|
|
1288
1289
|
|
|
1289
1290
|
// Decrement processing task counter
|
|
1290
|
-
|
|
1291
|
-
Napi::Number queueLength = Napi::Number::New(env, static_cast<
|
|
1292
|
-
queueListener.
|
|
1291
|
+
sharp::counterProcess--;
|
|
1292
|
+
Napi::Number queueLength = Napi::Number::New(env, static_cast<int>(sharp::counterQueue));
|
|
1293
|
+
queueListener.Call(Receiver().Value(), { queueLength });
|
|
1293
1294
|
}
|
|
1294
1295
|
|
|
1295
1296
|
private:
|
|
@@ -1517,6 +1518,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1517
1518
|
baton->thresholdGrayscale = sharp::AttrAsBool(options, "thresholdGrayscale");
|
|
1518
1519
|
baton->trimBackground = sharp::AttrAsVectorOfDouble(options, "trimBackground");
|
|
1519
1520
|
baton->trimThreshold = sharp::AttrAsDouble(options, "trimThreshold");
|
|
1521
|
+
baton->trimLineArt = sharp::AttrAsBool(options, "trimLineArt");
|
|
1520
1522
|
baton->gamma = sharp::AttrAsDouble(options, "gamma");
|
|
1521
1523
|
baton->gammaOut = sharp::AttrAsDouble(options, "gammaOut");
|
|
1522
1524
|
baton->linearA = sharp::AttrAsVectorOfDouble(options, "linearA");
|
|
@@ -1645,6 +1647,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1645
1647
|
baton->gifProgressive = sharp::AttrAsBool(options, "gifProgressive");
|
|
1646
1648
|
baton->tiffQuality = sharp::AttrAsUint32(options, "tiffQuality");
|
|
1647
1649
|
baton->tiffPyramid = sharp::AttrAsBool(options, "tiffPyramid");
|
|
1650
|
+
baton->tiffMiniswhite = sharp::AttrAsBool(options, "tiffMiniswhite");
|
|
1648
1651
|
baton->tiffBitdepth = sharp::AttrAsUint32(options, "tiffBitdepth");
|
|
1649
1652
|
baton->tiffTile = sharp::AttrAsBool(options, "tiffTile");
|
|
1650
1653
|
baton->tiffTileWidth = sharp::AttrAsUint32(options, "tiffTileWidth");
|
|
@@ -1705,9 +1708,8 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1705
1708
|
worker->Queue();
|
|
1706
1709
|
|
|
1707
1710
|
// Increment queued task counter
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
queueListener.MakeCallback(info.This(), { queueLength });
|
|
1711
|
+
Napi::Number queueLength = Napi::Number::New(info.Env(), static_cast<int>(++sharp::counterQueue));
|
|
1712
|
+
queueListener.Call(info.This(), { queueLength });
|
|
1711
1713
|
|
|
1712
1714
|
return info.Env().Undefined();
|
|
1713
1715
|
}
|
package/src/pipeline.h
CHANGED
|
@@ -92,6 +92,7 @@ struct PipelineBaton {
|
|
|
92
92
|
bool thresholdGrayscale;
|
|
93
93
|
std::vector<double> trimBackground;
|
|
94
94
|
double trimThreshold;
|
|
95
|
+
bool trimLineArt;
|
|
95
96
|
int trimOffsetLeft;
|
|
96
97
|
int trimOffsetTop;
|
|
97
98
|
std::vector<double> linearA;
|
|
@@ -169,6 +170,7 @@ struct PipelineBaton {
|
|
|
169
170
|
VipsForeignTiffPredictor tiffPredictor;
|
|
170
171
|
bool tiffPyramid;
|
|
171
172
|
int tiffBitdepth;
|
|
173
|
+
bool tiffMiniswhite;
|
|
172
174
|
bool tiffTile;
|
|
173
175
|
int tiffTileHeight;
|
|
174
176
|
int tiffTileWidth;
|
|
@@ -259,7 +261,8 @@ struct PipelineBaton {
|
|
|
259
261
|
threshold(0),
|
|
260
262
|
thresholdGrayscale(true),
|
|
261
263
|
trimBackground{},
|
|
262
|
-
trimThreshold(
|
|
264
|
+
trimThreshold(-1.0),
|
|
265
|
+
trimLineArt(false),
|
|
263
266
|
trimOffsetLeft(0),
|
|
264
267
|
trimOffsetTop(0),
|
|
265
268
|
linearA{},
|
|
@@ -335,6 +338,7 @@ struct PipelineBaton {
|
|
|
335
338
|
tiffPredictor(VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL),
|
|
336
339
|
tiffPyramid(false),
|
|
337
340
|
tiffBitdepth(8),
|
|
341
|
+
tiffMiniswhite(false),
|
|
338
342
|
tiffTile(false),
|
|
339
343
|
tiffTileHeight(256),
|
|
340
344
|
tiffTileWidth(256),
|
package/src/sharp.cc
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// Copyright 2013 Lovell Fuller and others.
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
|
|
4
|
+
#include <mutex> // NOLINT(build/c++11)
|
|
5
|
+
|
|
4
6
|
#include <napi.h>
|
|
5
7
|
#include <vips/vips8>
|
|
6
8
|
|
|
@@ -10,14 +12,11 @@
|
|
|
10
12
|
#include "utilities.h"
|
|
11
13
|
#include "stats.h"
|
|
12
14
|
|
|
13
|
-
static void* sharp_vips_init(void*) {
|
|
14
|
-
vips_init("sharp");
|
|
15
|
-
return nullptr;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
15
|
Napi::Object init(Napi::Env env, Napi::Object exports) {
|
|
19
|
-
static
|
|
20
|
-
|
|
16
|
+
static std::once_flag sharp_vips_init_once;
|
|
17
|
+
std::call_once(sharp_vips_init_once, []() {
|
|
18
|
+
vips_init("sharp");
|
|
19
|
+
});
|
|
21
20
|
|
|
22
21
|
g_log_set_handler("VIPS", static_cast<GLogLevelFlags>(G_LOG_LEVEL_WARNING),
|
|
23
22
|
static_cast<GLogFunc>(sharp::VipsWarningCallback), nullptr);
|
package/src/stats.cc
CHANGED
|
@@ -30,7 +30,7 @@ class StatsWorker : public Napi::AsyncWorker {
|
|
|
30
30
|
|
|
31
31
|
void Execute() {
|
|
32
32
|
// Decrement queued task counter
|
|
33
|
-
|
|
33
|
+
sharp::counterQueue--;
|
|
34
34
|
|
|
35
35
|
vips::VImage image;
|
|
36
36
|
sharp::ImageType imageType = sharp::ImageType::UNKNOWN;
|
|
@@ -106,7 +106,7 @@ class StatsWorker : public Napi::AsyncWorker {
|
|
|
106
106
|
// Handle warnings
|
|
107
107
|
std::string warning = sharp::VipsWarningPop();
|
|
108
108
|
while (!warning.empty()) {
|
|
109
|
-
debuglog.
|
|
109
|
+
debuglog.Call(Receiver().Value(), { Napi::String::New(env, warning) });
|
|
110
110
|
warning = sharp::VipsWarningPop();
|
|
111
111
|
}
|
|
112
112
|
|
|
@@ -141,9 +141,9 @@ class StatsWorker : public Napi::AsyncWorker {
|
|
|
141
141
|
dominant.Set("g", baton->dominantGreen);
|
|
142
142
|
dominant.Set("b", baton->dominantBlue);
|
|
143
143
|
info.Set("dominant", dominant);
|
|
144
|
-
Callback().
|
|
144
|
+
Callback().Call(Receiver().Value(), { env.Null(), info });
|
|
145
145
|
} else {
|
|
146
|
-
Callback().
|
|
146
|
+
Callback().Call(Receiver().Value(), { Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
delete baton->input;
|
|
@@ -177,7 +177,7 @@ Napi::Value stats(const Napi::CallbackInfo& info) {
|
|
|
177
177
|
worker->Queue();
|
|
178
178
|
|
|
179
179
|
// Increment queued task counter
|
|
180
|
-
|
|
180
|
+
sharp::counterQueue++;
|
|
181
181
|
|
|
182
182
|
return info.Env().Undefined();
|
|
183
183
|
}
|