sharp 0.32.6 → 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.
@@ -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(\'./lib/libvips\').minimumLibvipsVersion")',
4
- 'platform_and_arch': '<!(node -p "require(\'./lib/platform\')()")',
5
- 'sharp_vendor_dir': './vendor/<(vips_version)/<(platform_and_arch)'
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
- 'src/libvips/cplusplus/VConnection.cpp',
19
- 'src/libvips/cplusplus/VError.cpp',
20
- 'src/libvips/cplusplus/VImage.cpp',
21
- 'src/libvips/cplusplus/VInterpolate.cpp',
22
- 'src/libvips/cplusplus/VRegion.cpp'
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
- '<(sharp_vendor_dir)/include',
26
- '<(sharp_vendor_dir)/include/glib-2.0',
27
- '<(sharp_vendor_dir)/lib/glib-2.0/include'
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': ['<(sharp_vendor_dir)/lib'],
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=7',
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(\'./lib/libvips\').pkgConfigPath()")',
86
- 'use_global_libvips': '<!(node -p "Boolean(require(\'./lib/libvips\').useGlobalLibvips()).toString()")'
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
- 'src/common.cc',
95
- 'src/metadata.cc',
96
- 'src/stats.cc',
97
- 'src/operations.cc',
98
- 'src/pipeline.cc',
99
- 'src/utilities.cc',
100
- 'src/sharp.cc'
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
- '<(sharp_vendor_dir)/include',
126
- '<(sharp_vendor_dir)/include/glib-2.0',
127
- '<(sharp_vendor_dir)/lib/glib-2.0/include'
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/../../<(sharp_vendor_dir)/lib\''
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 -Wl,--disable-new-dtags -Wl,-rpath=\'$$ORIGIN/../../<(sharp_vendor_dir)/lib\''
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
- volatile int counterQueue = 0;
169
+ std::atomic<int> counterQueue{0};
170
170
 
171
171
  // How many tasks are being processed?
172
- volatile int counterProcess = 0;
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 < 14) || \
18
- (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 14 && VIPS_MICRO_VERSION < 5)
19
- #error "libvips version 8.14.5+ is required - please see https://sharp.pixelplumbing.com/install"
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 volatile int counterQueue;
165
+ extern std::atomic<int> counterQueue;
165
166
 
166
167
  // How many tasks are being processed?
167
- extern volatile int counterProcess;
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
- g_atomic_int_dec_and_test(&sharp::counterQueue);
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.MakeCallback(Receiver().Value(), { Napi::String::New(env, warning) });
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().MakeCallback(Receiver().Value(), { env.Null(), info });
249
+ Callback().Call(Receiver().Value(), { env.Null(), info });
250
250
  } else {
251
- Callback().MakeCallback(Receiver().Value(), { Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
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
- g_atomic_int_inc(&sharp::counterQueue);
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 threshold);
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
- g_atomic_int_dec_and_test(&sharp::counterQueue);
47
+ sharp::counterQueue--;
48
48
  // Increment processing task counter
49
- g_atomic_int_inc(&sharp::counterProcess);
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 > 0.0) {
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 == 0.0 &&
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) {
@@ -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;
@@ -940,6 +938,7 @@ class PipelineWorker : public Napi::AsyncWorker {
940
938
  ->set("Q", baton->tiffQuality)
941
939
  ->set("bitdepth", baton->tiffBitdepth)
942
940
  ->set("compression", baton->tiffCompression)
941
+ ->set("miniswhite", baton->tiffMiniswhite)
943
942
  ->set("predictor", baton->tiffPredictor)
944
943
  ->set("pyramid", baton->tiffPyramid)
945
944
  ->set("tile", baton->tiffTile)
@@ -1136,6 +1135,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1136
1135
  ->set("Q", baton->tiffQuality)
1137
1136
  ->set("bitdepth", baton->tiffBitdepth)
1138
1137
  ->set("compression", baton->tiffCompression)
1138
+ ->set("miniswhite", baton->tiffMiniswhite)
1139
1139
  ->set("predictor", baton->tiffPredictor)
1140
1140
  ->set("pyramid", baton->tiffPyramid)
1141
1141
  ->set("tile", baton->tiffTile)
@@ -1215,7 +1215,7 @@ class PipelineWorker : public Napi::AsyncWorker {
1215
1215
  // Handle warnings
1216
1216
  std::string warning = sharp::VipsWarningPop();
1217
1217
  while (!warning.empty()) {
1218
- debuglog.MakeCallback(Receiver().Value(), { Napi::String::New(env, warning) });
1218
+ debuglog.Call(Receiver().Value(), { Napi::String::New(env, warning) });
1219
1219
  warning = sharp::VipsWarningPop();
1220
1220
  }
1221
1221
 
@@ -1248,11 +1248,10 @@ class PipelineWorker : public Napi::AsyncWorker {
1248
1248
  info.Set("attentionX", static_cast<int32_t>(baton->attentionX));
1249
1249
  info.Set("attentionY", static_cast<int32_t>(baton->attentionY));
1250
1250
  }
1251
- if (baton->trimThreshold > 0.0) {
1251
+ if (baton->trimThreshold >= 0.0) {
1252
1252
  info.Set("trimOffsetLeft", static_cast<int32_t>(baton->trimOffsetLeft));
1253
1253
  info.Set("trimOffsetTop", static_cast<int32_t>(baton->trimOffsetTop));
1254
1254
  }
1255
-
1256
1255
  if (baton->input->textAutofitDpi) {
1257
1256
  info.Set("textAutofitDpi", static_cast<uint32_t>(baton->input->textAutofitDpi));
1258
1257
  }
@@ -1263,17 +1262,17 @@ class PipelineWorker : public Napi::AsyncWorker {
1263
1262
  // Pass ownership of output data to Buffer instance
1264
1263
  Napi::Buffer<char> data = Napi::Buffer<char>::NewOrCopy(env, static_cast<char*>(baton->bufferOut),
1265
1264
  baton->bufferOutLength, sharp::FreeCallback);
1266
- Callback().MakeCallback(Receiver().Value(), { env.Null(), data, info });
1265
+ Callback().Call(Receiver().Value(), { env.Null(), data, info });
1267
1266
  } else {
1268
1267
  // Add file size to info
1269
1268
  struct STAT64_STRUCT st;
1270
1269
  if (STAT64_FUNCTION(baton->fileOut.data(), &st) == 0) {
1271
1270
  info.Set("size", static_cast<uint32_t>(st.st_size));
1272
1271
  }
1273
- Callback().MakeCallback(Receiver().Value(), { env.Null(), info });
1272
+ Callback().Call(Receiver().Value(), { env.Null(), info });
1274
1273
  }
1275
1274
  } else {
1276
- Callback().MakeCallback(Receiver().Value(), { Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
1275
+ Callback().Call(Receiver().Value(), { Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
1277
1276
  }
1278
1277
 
1279
1278
  // Delete baton
@@ -1289,9 +1288,9 @@ class PipelineWorker : public Napi::AsyncWorker {
1289
1288
  delete baton;
1290
1289
 
1291
1290
  // Decrement processing task counter
1292
- g_atomic_int_dec_and_test(&sharp::counterProcess);
1293
- Napi::Number queueLength = Napi::Number::New(env, static_cast<double>(sharp::counterQueue));
1294
- queueListener.MakeCallback(Receiver().Value(), { queueLength });
1291
+ sharp::counterProcess--;
1292
+ Napi::Number queueLength = Napi::Number::New(env, static_cast<int>(sharp::counterQueue));
1293
+ queueListener.Call(Receiver().Value(), { queueLength });
1295
1294
  }
1296
1295
 
1297
1296
  private:
@@ -1519,6 +1518,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1519
1518
  baton->thresholdGrayscale = sharp::AttrAsBool(options, "thresholdGrayscale");
1520
1519
  baton->trimBackground = sharp::AttrAsVectorOfDouble(options, "trimBackground");
1521
1520
  baton->trimThreshold = sharp::AttrAsDouble(options, "trimThreshold");
1521
+ baton->trimLineArt = sharp::AttrAsBool(options, "trimLineArt");
1522
1522
  baton->gamma = sharp::AttrAsDouble(options, "gamma");
1523
1523
  baton->gammaOut = sharp::AttrAsDouble(options, "gammaOut");
1524
1524
  baton->linearA = sharp::AttrAsVectorOfDouble(options, "linearA");
@@ -1647,6 +1647,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1647
1647
  baton->gifProgressive = sharp::AttrAsBool(options, "gifProgressive");
1648
1648
  baton->tiffQuality = sharp::AttrAsUint32(options, "tiffQuality");
1649
1649
  baton->tiffPyramid = sharp::AttrAsBool(options, "tiffPyramid");
1650
+ baton->tiffMiniswhite = sharp::AttrAsBool(options, "tiffMiniswhite");
1650
1651
  baton->tiffBitdepth = sharp::AttrAsUint32(options, "tiffBitdepth");
1651
1652
  baton->tiffTile = sharp::AttrAsBool(options, "tiffTile");
1652
1653
  baton->tiffTileWidth = sharp::AttrAsUint32(options, "tiffTileWidth");
@@ -1707,9 +1708,8 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
1707
1708
  worker->Queue();
1708
1709
 
1709
1710
  // Increment queued task counter
1710
- g_atomic_int_inc(&sharp::counterQueue);
1711
- Napi::Number queueLength = Napi::Number::New(info.Env(), static_cast<double>(sharp::counterQueue));
1712
- 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 });
1713
1713
 
1714
1714
  return info.Env().Undefined();
1715
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(0.0),
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 GOnce sharp_vips_init_once = G_ONCE_INIT;
20
- g_once(&sharp_vips_init_once, static_cast<GThreadFunc>(sharp_vips_init), nullptr);
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
- g_atomic_int_dec_and_test(&sharp::counterQueue);
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.MakeCallback(Receiver().Value(), { Napi::String::New(env, warning) });
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().MakeCallback(Receiver().Value(), { env.Null(), info });
144
+ Callback().Call(Receiver().Value(), { env.Null(), info });
145
145
  } else {
146
- Callback().MakeCallback(Receiver().Value(), { Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
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
- g_atomic_int_inc(&sharp::counterQueue);
180
+ sharp::counterQueue++;
181
181
 
182
182
  return info.Env().Undefined();
183
183
  }
package/src/utilities.cc CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  #include <cmath>
5
5
  #include <string>
6
+ #include <cstdio>
6
7
 
7
8
  #include <napi.h>
8
9
  #include <vips/vips8>
@@ -70,8 +71,8 @@ Napi::Value concurrency(const Napi::CallbackInfo& info) {
70
71
  */
71
72
  Napi::Value counters(const Napi::CallbackInfo& info) {
72
73
  Napi::Object counters = Napi::Object::New(info.Env());
73
- counters.Set("queue", sharp::counterQueue);
74
- counters.Set("process", sharp::counterProcess);
74
+ counters.Set("queue", static_cast<int>(sharp::counterQueue));
75
+ counters.Set("process", static_cast<int>(sharp::counterProcess));
75
76
  return counters;
76
77
  }
77
78
 
@@ -91,9 +92,18 @@ Napi::Value simd(const Napi::CallbackInfo& info) {
91
92
  Get libvips version
92
93
  */
93
94
  Napi::Value libvipsVersion(const Napi::CallbackInfo& info) {
94
- char version[9];
95
- g_snprintf(version, sizeof(version), "%d.%d.%d", vips_version(0), vips_version(1), vips_version(2));
96
- return Napi::String::New(info.Env(), version);
95
+ Napi::Env env = info.Env();
96
+ Napi::Object version = Napi::Object::New(env);
97
+
98
+ char semver[9];
99
+ std::snprintf(semver, sizeof(semver), "%d.%d.%d", vips_version(0), vips_version(1), vips_version(2));
100
+ version.Set("semver", Napi::String::New(env, semver));
101
+ #ifdef SHARP_USE_GLOBAL_LIBVIPS
102
+ version.Set("isGlobal", Napi::Boolean::New(env, true));
103
+ #else
104
+ version.Set("isGlobal", Napi::Boolean::New(env, false));
105
+ #endif
106
+ return version;
97
107
  }
98
108
 
99
109
  /*
@@ -1,14 +0,0 @@
1
- // Copyright 2013 Lovell Fuller and others.
2
- // SPDX-License-Identifier: Apache-2.0
3
-
4
- 'use strict';
5
-
6
- const libvips = require('../lib/libvips');
7
-
8
- try {
9
- if (!(libvips.useGlobalLibvips() || libvips.hasVendoredLibvips())) {
10
- process.exitCode = 1;
11
- }
12
- } catch (err) {
13
- process.exitCode = 1;
14
- }