sharp 0.33.0-alpha.8 → 0.33.0-rc.2

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sharp",
3
3
  "description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images",
4
- "version": "0.33.0-alpha.8",
4
+ "version": "0.33.0-rc.2",
5
5
  "author": "Lovell Fuller <npm@lovell.info>",
6
6
  "homepage": "https://github.com/lovell/sharp",
7
7
  "contributors": [
@@ -86,7 +86,9 @@
86
86
  "Ankur Parihar <ankur.github@gmail.com>",
87
87
  "Brahim Ait elhaj <brahima@gmail.com>",
88
88
  "Mart Jansink <m.jansink@gmail.com>",
89
- "Lachlan Newman <lachnewman007@gmail.com>"
89
+ "Lachlan Newman <lachnewman007@gmail.com>",
90
+ "Dennis Beatty <dennis@dcbeatty.com>",
91
+ "Ingvar Stepanyan <me@rreverser.com>"
90
92
  ],
91
93
  "scripts": {
92
94
  "install": "node install/check",
@@ -139,30 +141,36 @@
139
141
  "semver": "^7.5.4"
140
142
  },
141
143
  "optionalDependencies": {
142
- "@sharpen/sharp-darwin-arm64": "0.0.1-alpha.8",
143
- "@sharpen/sharp-darwin-x64": "0.0.1-alpha.8",
144
- "@sharpen/sharp-libvips-darwin-arm64": "0.0.1-alpha.2",
145
- "@sharpen/sharp-libvips-darwin-x64": "0.0.1-alpha.2",
146
- "@sharpen/sharp-libvips-linux-arm": "0.0.1-alpha.2",
147
- "@sharpen/sharp-libvips-linux-arm64": "0.0.1-alpha.2",
148
- "@sharpen/sharp-libvips-linux-x64": "0.0.1-alpha.2",
149
- "@sharpen/sharp-libvips-linuxmusl-arm64": "0.0.1-alpha.2",
150
- "@sharpen/sharp-libvips-linuxmusl-x64": "0.0.1-alpha.2",
151
- "@sharpen/sharp-linux-arm": "0.0.1-alpha.8",
152
- "@sharpen/sharp-linux-arm64": "0.0.1-alpha.8",
153
- "@sharpen/sharp-linux-x64": "0.0.1-alpha.8",
154
- "@sharpen/sharp-linuxmusl-arm64": "0.0.1-alpha.8",
155
- "@sharpen/sharp-linuxmusl-x64": "0.0.1-alpha.8",
156
- "@sharpen/sharp-win32-ia32": "0.0.1-alpha.8",
157
- "@sharpen/sharp-win32-x64": "0.0.1-alpha.8"
144
+ "@img/sharp-darwin-arm64": "0.33.0-rc.2",
145
+ "@img/sharp-darwin-x64": "0.33.0-rc.2",
146
+ "@img/sharp-libvips-darwin-arm64": "1.0.0",
147
+ "@img/sharp-libvips-darwin-x64": "1.0.0",
148
+ "@img/sharp-libvips-linux-arm": "1.0.0",
149
+ "@img/sharp-libvips-linux-arm64": "1.0.0",
150
+ "@img/sharp-libvips-linux-s390x": "1.0.0",
151
+ "@img/sharp-libvips-linux-x64": "1.0.0",
152
+ "@img/sharp-libvips-linuxmusl-arm64": "1.0.0",
153
+ "@img/sharp-libvips-linuxmusl-x64": "1.0.0",
154
+ "@img/sharp-linux-arm": "0.33.0-rc.2",
155
+ "@img/sharp-linux-arm64": "0.33.0-rc.2",
156
+ "@img/sharp-linux-s390x": "0.33.0-rc.2",
157
+ "@img/sharp-linux-x64": "0.33.0-rc.2",
158
+ "@img/sharp-linuxmusl-arm64": "0.33.0-rc.2",
159
+ "@img/sharp-linuxmusl-x64": "0.33.0-rc.2",
160
+ "@img/sharp-wasm32": "0.33.0-rc.2",
161
+ "@img/sharp-win32-ia32": "0.33.0-rc.2",
162
+ "@img/sharp-win32-x64": "0.33.0-rc.2"
158
163
  },
159
164
  "devDependencies": {
160
- "@sharpen/sharp-libvips-dev": "0.0.1-alpha.2",
161
- "@sharpen/sharp-libvips-win32-ia32": "0.0.1-alpha.2",
162
- "@sharpen/sharp-libvips-win32-x64": "0.0.1-alpha.2",
165
+ "@emnapi/runtime": "^0.44.0",
166
+ "@img/sharp-libvips-dev": "1.0.0",
167
+ "@img/sharp-libvips-dev-wasm32": "1.0.0",
168
+ "@img/sharp-libvips-win32-ia32": "1.0.0",
169
+ "@img/sharp-libvips-win32-x64": "1.0.0",
163
170
  "@types/node": "*",
164
- "async": "^3.2.4",
171
+ "async": "^3.2.5",
165
172
  "cc": "^3.0.1",
173
+ "emnapi": "^0.44.0",
166
174
  "exif-reader": "^2.0.0",
167
175
  "extract-zip": "^2.0.1",
168
176
  "icc": "^3.0.0",
@@ -179,7 +187,7 @@
179
187
  "license": "Apache-2.0",
180
188
  "engines": {
181
189
  "node": "^18.17.0 || ^20.3.0 || >=21.0.0",
182
- "libvips": ">=8.14.5"
190
+ "libvips": ">=8.15.0"
183
191
  },
184
192
  "funding": {
185
193
  "url": "https://opencollective.com/libvips"
@@ -200,6 +208,11 @@
200
208
  "build/include"
201
209
  ]
202
210
  },
211
+ "nyc": {
212
+ "include": [
213
+ "lib"
214
+ ]
215
+ },
203
216
  "tsd": {
204
217
  "directory": "test/types/"
205
218
  }
package/src/binding.gyp CHANGED
@@ -5,6 +5,7 @@
5
5
  'variables': {
6
6
  'vips_version': '<!(node -p "require(\'../lib/libvips\').minimumLibvipsVersion")',
7
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)\']")',
8
9
  'sharp_libvips_include_dir': '<!(node -p "require(\'../lib/libvips\').buildSharpLibvipsIncludeDir()")',
9
10
  'sharp_libvips_cplusplus_dir': '<!(node -p "require(\'../lib/libvips\').buildSharpLibvipsCPlusPlusDir()")',
10
11
  'sharp_libvips_lib_dir': '<!(node -p "require(\'../lib/libvips\').buildSharpLibvipsLibDir()")'
@@ -32,11 +33,11 @@
32
33
  '<(sharp_libvips_lib_dir)/glib-2.0/include'
33
34
  ],
34
35
  'link_settings': {
35
- 'library_dirs': ['<(sharp_libvips_lib_dir)'],
36
+ 'library_dirs': [
37
+ '<(sharp_libvips_lib_dir)'
38
+ ],
36
39
  'libraries': [
37
- 'libvips.lib',
38
- 'libglib-2.0.lib',
39
- 'libgobject-2.0.lib'
40
+ 'libvips.lib'
40
41
  ],
41
42
  },
42
43
  'configurations': {
@@ -129,6 +130,9 @@
129
130
  '<(sharp_libvips_include_dir)/glib-2.0',
130
131
  '<(sharp_libvips_lib_dir)/glib-2.0/include'
131
132
  ],
133
+ 'library_dirs': [
134
+ '<(sharp_libvips_lib_dir)'
135
+ ],
132
136
  'conditions': [
133
137
  ['OS == "win"', {
134
138
  'defines': [
@@ -136,19 +140,13 @@
136
140
  '_FILE_OFFSET_BITS=64'
137
141
  ],
138
142
  'link_settings': {
139
- 'library_dirs': ['<(sharp_libvips_lib_dir)'],
140
143
  'libraries': [
141
- 'libvips.lib',
142
- 'libglib-2.0.lib',
143
- 'libgobject-2.0.lib'
144
+ 'libvips.lib'
144
145
  ]
145
146
  }
146
147
  }],
147
148
  ['OS == "mac"', {
148
149
  'link_settings': {
149
- 'library_dirs': [
150
- '<(sharp_libvips_lib_dir)'
151
- ],
152
150
  'libraries': [
153
151
  'libvips-cpp.42.dylib'
154
152
  ]
@@ -157,8 +155,9 @@
157
155
  'OTHER_LDFLAGS': [
158
156
  # Ensure runtime linking is relative to sharp.node
159
157
  '-Wl,-rpath,\'@loader_path/../../sharp-libvips-<(platform_and_arch)/lib\'',
160
- '-Wl,-rpath,\'@loader_path/../../node_modules/@sharpen/sharp-libvips-<(platform_and_arch)/lib\'',
161
- '-Wl,-rpath,\'@loader_path/../../../node_modules/@sharpen/sharp-libvips-<(platform_and_arch)/lib\''
158
+ '-Wl,-rpath,\'@loader_path/../../../sharp-libvips-<(platform_and_arch)/<(sharp_libvips_version)/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\''
162
161
  ]
163
162
  }
164
163
  }],
@@ -167,21 +166,39 @@
167
166
  '_GLIBCXX_USE_CXX11_ABI=1'
168
167
  ],
169
168
  'link_settings': {
170
- 'library_dirs': [
171
- '<(sharp_libvips_lib_dir)'
172
- ],
173
169
  'libraries': [
174
170
  '-l:libvips-cpp.so.42'
175
171
  ],
176
172
  'ldflags': [
177
- # Ensure runtime linking is relative to sharp.node
178
173
  '-Wl,-s',
179
174
  '-Wl,--disable-new-dtags',
175
+ '-Wl,-z,nodelete',
180
176
  '-Wl,-rpath=\'$$ORIGIN/../../sharp-libvips-<(platform_and_arch)/lib\'',
181
- '-Wl,-rpath=\'$$ORIGIN/../../node_modules/@sharpen/sharp-libvips-<(platform_and_arch)/lib\'',
182
- '-Wl,-rpath=\'$$ORIGIN/../../../node_modules/@sharpen/sharp-libvips-<(platform_and_arch)/lib\''
177
+ '-Wl,-rpath=\'$$ORIGIN/../../../sharp-libvips-<(platform_and_arch)/<(sharp_libvips_version)/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\''
183
180
  ]
184
181
  }
182
+ }],
183
+ ['OS == "emscripten"', {
184
+ 'product_extension': 'node.js',
185
+ 'link_settings': {
186
+ 'ldflags': [
187
+ '-fexceptions',
188
+ '--pre-js=<!(node -p "require.resolve(\'./emscripten/pre.js\')")',
189
+ '-Oz',
190
+ '-sALLOW_MEMORY_GROWTH',
191
+ '-sENVIRONMENT=node',
192
+ '-sEXPORTED_FUNCTIONS=["_vips_shutdown", "_uv_library_shutdown"]',
193
+ '-sNODERAWFS',
194
+ '-sTEXTDECODER=0',
195
+ '-sWASM_ASYNC_COMPILATION=0',
196
+ '-sWASM_BIGINT'
197
+ ],
198
+ 'libraries': [
199
+ '<!@(PKG_CONFIG_PATH="<!(node -p "require(\'@img/sharp-libvips-dev-wasm32/lib\')")/pkgconfig" pkg-config --static --libs vips-cpp)'
200
+ ],
201
+ }
185
202
  }]
186
203
  ]
187
204
  }]
@@ -206,11 +223,6 @@
206
223
  'configurations': {
207
224
  'Release': {
208
225
  'conditions': [
209
- ['OS == "linux"', {
210
- 'cflags_cc': [
211
- '-Wno-cast-function-type'
212
- ]
213
- }],
214
226
  ['target_arch == "arm"', {
215
227
  'cflags_cc': [
216
228
  '-Wno-psabi'
@@ -256,9 +268,7 @@
256
268
  'copies': [{
257
269
  'destination': 'build/Release',
258
270
  'files': [
259
- '<(sharp_libvips_lib_dir)/libvips-42.dll',
260
- '<(sharp_libvips_lib_dir)/libglib-2.0-0.dll',
261
- '<(sharp_libvips_lib_dir)/libgobject-2.0-0.dll'
271
+ '<(sharp_libvips_lib_dir)/libvips-42.dll'
262
272
  ]
263
273
  }]
264
274
  }]
package/src/common.cc CHANGED
@@ -531,7 +531,33 @@ namespace sharp {
531
531
  Does this image have an embedded profile?
532
532
  */
533
533
  bool HasProfile(VImage image) {
534
- return (image.get_typeof(VIPS_META_ICC_NAME) != 0) ? TRUE : FALSE;
534
+ return image.get_typeof(VIPS_META_ICC_NAME) == VIPS_TYPE_BLOB;
535
+ }
536
+
537
+ /*
538
+ Get copy of embedded profile.
539
+ */
540
+ std::pair<char*, size_t> GetProfile(VImage image) {
541
+ std::pair<char*, size_t> icc(nullptr, 0);
542
+ if (HasProfile(image)) {
543
+ size_t length;
544
+ const void *data = image.get_blob(VIPS_META_ICC_NAME, &length);
545
+ icc.first = static_cast<char*>(g_malloc(length));
546
+ icc.second = length;
547
+ memcpy(icc.first, data, length);
548
+ }
549
+ return icc;
550
+ }
551
+
552
+ /*
553
+ Set embedded profile.
554
+ */
555
+ VImage SetProfile(VImage image, std::pair<char*, size_t> icc) {
556
+ if (icc.first != nullptr) {
557
+ image = image.copy();
558
+ image.set(VIPS_META_ICC_NAME, reinterpret_cast<VipsCallbackFn>(vips_area_free_cb), icc.first, icc.second);
559
+ }
560
+ return image;
535
561
  }
536
562
 
537
563
  /*
@@ -542,6 +568,27 @@ namespace sharp {
542
568
  return image.has_alpha();
543
569
  }
544
570
 
571
+ static void* RemoveExifCallback(VipsImage *image, char const *field, GValue *value, void *data) {
572
+ std::vector<std::string> *fieldNames = static_cast<std::vector<std::string> *>(data);
573
+ std::string fieldName(field);
574
+ if (fieldName.substr(0, 8) == ("exif-ifd")) {
575
+ fieldNames->push_back(fieldName);
576
+ }
577
+ return nullptr;
578
+ }
579
+
580
+ /*
581
+ Remove all EXIF-related image fields.
582
+ */
583
+ VImage RemoveExif(VImage image) {
584
+ std::vector<std::string> fieldNames;
585
+ vips_image_map(image.get_image(), static_cast<VipsImageMapFn>(RemoveExifCallback), &fieldNames);
586
+ for (const auto& f : fieldNames) {
587
+ image.remove(f.data());
588
+ }
589
+ return image;
590
+ }
591
+
545
592
  /*
546
593
  Get EXIF Orientation of image, if any.
547
594
  */
package/src/common.h CHANGED
@@ -15,9 +15,9 @@
15
15
  // Verify platform and compiler compatibility
16
16
 
17
17
  #if (VIPS_MAJOR_VERSION < 8) || \
18
- (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 14) || \
19
- (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 14 && VIPS_MICRO_VERSION < 5)
20
- #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"
21
21
  #endif
22
22
 
23
23
  #if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))
@@ -222,12 +222,27 @@ namespace sharp {
222
222
  */
223
223
  bool HasProfile(VImage image);
224
224
 
225
+ /*
226
+ Get copy of embedded profile.
227
+ */
228
+ std::pair<char*, size_t> GetProfile(VImage image);
229
+
230
+ /*
231
+ Set embedded profile.
232
+ */
233
+ VImage SetProfile(VImage image, std::pair<char*, size_t> icc);
234
+
225
235
  /*
226
236
  Does this image have an alpha channel?
227
237
  Uses colour space interpretation with number of channels to guess this.
228
238
  */
229
239
  bool HasAlpha(VImage image);
230
240
 
241
+ /*
242
+ Remove all EXIF-related image fields.
243
+ */
244
+ VImage RemoveExif(VImage image);
245
+
231
246
  /*
232
247
  Get EXIF Orientation of image, if any.
233
248
  */
package/src/metadata.cc CHANGED
@@ -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;
package/src/operations.cc CHANGED
@@ -16,30 +16,44 @@ using vips::VError;
16
16
 
17
17
  namespace sharp {
18
18
  /*
19
- * Tint an image using the specified chroma, preserving the original image luminance
19
+ * Tint an image using the provided RGB.
20
20
  */
21
- VImage Tint(VImage image, double const a, double const b) {
22
- // Get original colourspace
21
+ VImage Tint(VImage image, std::vector<double> const tint) {
22
+ std::vector<double> const tintLab = (VImage::black(1, 1) + tint)
23
+ .colourspace(VIPS_INTERPRETATION_LAB, VImage::option()->set("source_space", VIPS_INTERPRETATION_sRGB))
24
+ .getpoint(0, 0);
25
+ // LAB identity function
26
+ VImage identityLab = VImage::identity(VImage::option()->set("bands", 3))
27
+ .colourspace(VIPS_INTERPRETATION_LAB, VImage::option()->set("source_space", VIPS_INTERPRETATION_sRGB));
28
+ // Scale luminance range, 0.0 to 1.0
29
+ VImage l = identityLab[0] / 100;
30
+ // Weighting functions
31
+ VImage weightL = 1.0 - 4.0 * ((l - 0.5) * (l - 0.5));
32
+ VImage weightAB = (weightL * tintLab).extract_band(1, VImage::option()->set("n", 2));
33
+ identityLab = identityLab[0].bandjoin(weightAB);
34
+ // Convert lookup table to sRGB
35
+ VImage lut = identityLab.colourspace(VIPS_INTERPRETATION_sRGB,
36
+ VImage::option()->set("source_space", VIPS_INTERPRETATION_LAB));
37
+ // Original colourspace
23
38
  VipsInterpretation typeBeforeTint = image.interpretation();
24
39
  if (typeBeforeTint == VIPS_INTERPRETATION_RGB) {
25
40
  typeBeforeTint = VIPS_INTERPRETATION_sRGB;
26
41
  }
27
- // Extract luminance
28
- VImage luminance = image.colourspace(VIPS_INTERPRETATION_LAB)[0];
29
- // Create the tinted version by combining the L from the original and the chroma from the tint
30
- std::vector<double> chroma {a, b};
31
- VImage tinted = luminance
32
- .bandjoin(chroma)
33
- .copy(VImage::option()->set("interpretation", VIPS_INTERPRETATION_LAB))
34
- .colourspace(typeBeforeTint);
35
- // Attach original alpha channel, if any
42
+ // Apply lookup table
36
43
  if (HasAlpha(image)) {
37
- // Extract original alpha channel
38
44
  VImage alpha = image[image.bands() - 1];
39
- // Join alpha channel to normalised image
40
- tinted = tinted.bandjoin(alpha);
45
+ image = RemoveAlpha(image)
46
+ .colourspace(VIPS_INTERPRETATION_B_W)
47
+ .maplut(lut)
48
+ .colourspace(typeBeforeTint)
49
+ .bandjoin(alpha);
50
+ } else {
51
+ image = image
52
+ .colourspace(VIPS_INTERPRETATION_B_W)
53
+ .maplut(lut)
54
+ .colourspace(typeBeforeTint);
41
55
  }
42
- return tinted;
56
+ return image;
43
57
  }
44
58
 
45
59
  /*
@@ -141,7 +155,7 @@ namespace sharp {
141
155
  return image.conv(blur);
142
156
  } else {
143
157
  // Slower, accurate Gaussian blur
144
- return image.gaussblur(sigma);
158
+ return StaySequential(image, VIPS_ACCESS_SEQUENTIAL).gaussblur(sigma);
145
159
  }
146
160
  }
147
161
 
@@ -265,7 +279,7 @@ namespace sharp {
265
279
  /*
266
280
  Trim an image
267
281
  */
268
- VImage Trim(VImage image, std::vector<double> background, double threshold) {
282
+ VImage Trim(VImage image, std::vector<double> background, double threshold, bool const lineArt) {
269
283
  if (image.width() < 3 && image.height() < 3) {
270
284
  throw VError("Image to trim must be at least 3x3 pixels");
271
285
  }
@@ -287,6 +301,7 @@ namespace sharp {
287
301
  int left, top, width, height;
288
302
  left = image.find_trim(&top, &width, &height, VImage::option()
289
303
  ->set("background", background)
304
+ ->set("line_art", lineArt)
290
305
  ->set("threshold", threshold));
291
306
  if (HasAlpha(image)) {
292
307
  // Search alpha channel (A)
@@ -294,6 +309,7 @@ namespace sharp {
294
309
  VImage alpha = image[image.bands() - 1];
295
310
  leftA = alpha.find_trim(&topA, &widthA, &heightA, VImage::option()
296
311
  ->set("background", backgroundAlpha)
312
+ ->set("line_art", lineArt)
297
313
  ->set("threshold", threshold));
298
314
  if (widthA > 0 && heightA > 0) {
299
315
  if (width > 0 && height > 0) {
@@ -370,6 +386,7 @@ namespace sharp {
370
386
  pages.reserve(nPages);
371
387
 
372
388
  // Split the image into cropped frames
389
+ image = StaySequential(image, VIPS_ACCESS_SEQUENTIAL);
373
390
  for (int i = 0; i < nPages; i++) {
374
391
  pages.push_back(
375
392
  image.extract_area(left, *pageHeight * i + top, width, height));
package/src/operations.h CHANGED
@@ -15,9 +15,9 @@ using vips::VImage;
15
15
  namespace sharp {
16
16
 
17
17
  /*
18
- * Tint an image using the specified chroma, preserving the original image luminance
18
+ * Tint an image using the provided RGB.
19
19
  */
20
- VImage Tint(VImage image, double const a, double const b);
20
+ VImage Tint(VImage image, std::vector<double> const tint);
21
21
 
22
22
  /*
23
23
  * Stretch luminance to cover full dynamic range.
@@ -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)