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.
@@ -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 < 4)
19
- #error "libvips version 8.14.4+ 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) {
@@ -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() == VIPS_INTERPRETATION_RGB16 ? 16 : 8)
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.MakeCallback(Receiver().Value(), { Napi::String::New(env, warning) });
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 > 0.0) {
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().MakeCallback(Receiver().Value(), { env.Null(), data, info });
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().MakeCallback(Receiver().Value(), { env.Null(), info });
1272
+ Callback().Call(Receiver().Value(), { env.Null(), info });
1272
1273
  }
1273
1274
  } else {
1274
- 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() });
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
- g_atomic_int_dec_and_test(&sharp::counterProcess);
1291
- Napi::Number queueLength = Napi::Number::New(env, static_cast<double>(sharp::counterQueue));
1292
- 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 });
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
- g_atomic_int_inc(&sharp::counterQueue);
1709
- Napi::Number queueLength = Napi::Number::New(info.Env(), static_cast<double>(sharp::counterQueue));
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(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
  }