sharp 0.35.0-rc.0 → 0.35.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.35.0-rc.0",
4
+ "version": "0.35.0-rc.2",
5
5
  "author": "Lovell Fuller <npm@lovell.info>",
6
6
  "homepage": "https://sharp.pixelplumbing.com",
7
7
  "contributors": [
@@ -103,6 +103,7 @@
103
103
  "test-leak": "./test/leak/leak.sh",
104
104
  "test-unit": "node --experimental-test-coverage test/unit.mjs",
105
105
  "package-from-local-build": "node npm/from-local-build.js",
106
+ "package-wasm-wrappers": "node npm/wasm-wrappers.js",
106
107
  "package-release-notes": "node npm/release-notes.js",
107
108
  "docs-build": "node docs/build.mjs",
108
109
  "docs-serve": "cd docs && npm start",
@@ -139,53 +140,54 @@
139
140
  "vips"
140
141
  ],
141
142
  "dependencies": {
142
- "@img/colour": "^1.0.0",
143
+ "@img/colour": "^1.1.0",
143
144
  "detect-libc": "^2.1.2",
144
- "semver": "^7.7.3"
145
+ "semver": "^7.7.4"
145
146
  },
146
147
  "optionalDependencies": {
147
- "@img/sharp-darwin-arm64": "0.35.0-rc.0",
148
- "@img/sharp-darwin-x64": "0.35.0-rc.0",
149
- "@img/sharp-libvips-darwin-arm64": "1.3.0-rc.2",
150
- "@img/sharp-libvips-darwin-x64": "1.3.0-rc.2",
151
- "@img/sharp-libvips-linux-arm": "1.3.0-rc.2",
152
- "@img/sharp-libvips-linux-arm64": "1.3.0-rc.2",
153
- "@img/sharp-libvips-linux-ppc64": "1.3.0-rc.2",
154
- "@img/sharp-libvips-linux-riscv64": "1.3.0-rc.2",
155
- "@img/sharp-libvips-linux-s390x": "1.3.0-rc.2",
156
- "@img/sharp-libvips-linux-x64": "1.3.0-rc.2",
157
- "@img/sharp-libvips-linuxmusl-arm64": "1.3.0-rc.2",
158
- "@img/sharp-libvips-linuxmusl-x64": "1.3.0-rc.2",
159
- "@img/sharp-linux-arm": "0.35.0-rc.0",
160
- "@img/sharp-linux-arm64": "0.35.0-rc.0",
161
- "@img/sharp-linux-ppc64": "0.35.0-rc.0",
162
- "@img/sharp-linux-riscv64": "0.35.0-rc.0",
163
- "@img/sharp-linux-s390x": "0.35.0-rc.0",
164
- "@img/sharp-linux-x64": "0.35.0-rc.0",
165
- "@img/sharp-linuxmusl-arm64": "0.35.0-rc.0",
166
- "@img/sharp-linuxmusl-x64": "0.35.0-rc.0",
167
- "@img/sharp-wasm32": "0.35.0-rc.0",
168
- "@img/sharp-win32-arm64": "0.35.0-rc.0",
169
- "@img/sharp-win32-ia32": "0.35.0-rc.0",
170
- "@img/sharp-win32-x64": "0.35.0-rc.0"
148
+ "@img/sharp-darwin-arm64": "0.35.0-rc.2",
149
+ "@img/sharp-darwin-x64": "0.35.0-rc.2",
150
+ "@img/sharp-freebsd-wasm32": "0.35.0-rc.2",
151
+ "@img/sharp-libvips-darwin-arm64": "1.3.0-rc.4",
152
+ "@img/sharp-libvips-darwin-x64": "1.3.0-rc.4",
153
+ "@img/sharp-libvips-linux-arm": "1.3.0-rc.4",
154
+ "@img/sharp-libvips-linux-arm64": "1.3.0-rc.4",
155
+ "@img/sharp-libvips-linux-ppc64": "1.3.0-rc.4",
156
+ "@img/sharp-libvips-linux-riscv64": "1.3.0-rc.4",
157
+ "@img/sharp-libvips-linux-s390x": "1.3.0-rc.4",
158
+ "@img/sharp-libvips-linux-x64": "1.3.0-rc.4",
159
+ "@img/sharp-libvips-linuxmusl-arm64": "1.3.0-rc.4",
160
+ "@img/sharp-libvips-linuxmusl-x64": "1.3.0-rc.4",
161
+ "@img/sharp-linux-arm": "0.35.0-rc.2",
162
+ "@img/sharp-linux-arm64": "0.35.0-rc.2",
163
+ "@img/sharp-linux-ppc64": "0.35.0-rc.2",
164
+ "@img/sharp-linux-riscv64": "0.35.0-rc.2",
165
+ "@img/sharp-linux-s390x": "0.35.0-rc.2",
166
+ "@img/sharp-linux-x64": "0.35.0-rc.2",
167
+ "@img/sharp-linuxmusl-arm64": "0.35.0-rc.2",
168
+ "@img/sharp-linuxmusl-x64": "0.35.0-rc.2",
169
+ "@img/sharp-webcontainers-wasm32": "0.35.0-rc.2",
170
+ "@img/sharp-win32-arm64": "0.35.0-rc.2",
171
+ "@img/sharp-win32-ia32": "0.35.0-rc.2",
172
+ "@img/sharp-win32-x64": "0.35.0-rc.2"
171
173
  },
172
174
  "devDependencies": {
173
- "@biomejs/biome": "^2.3.10",
175
+ "@biomejs/biome": "^2.4.10",
174
176
  "@cpplint/cli": "^0.1.0",
175
- "@emnapi/runtime": "^1.7.1",
176
- "@img/sharp-libvips-dev": "1.3.0-rc.2",
177
- "@img/sharp-libvips-dev-wasm32": "1.3.0-rc.2",
178
- "@img/sharp-libvips-win32-arm64": "1.3.0-rc.2",
179
- "@img/sharp-libvips-win32-ia32": "1.3.0-rc.2",
180
- "@img/sharp-libvips-win32-x64": "1.3.0-rc.2",
177
+ "@emnapi/runtime": "^1.9.2",
178
+ "@img/sharp-libvips-dev": "1.3.0-rc.4",
179
+ "@img/sharp-libvips-dev-wasm32": "1.3.0-rc.4",
180
+ "@img/sharp-libvips-win32-arm64": "1.3.0-rc.4",
181
+ "@img/sharp-libvips-win32-ia32": "1.3.0-rc.4",
182
+ "@img/sharp-libvips-win32-x64": "1.3.0-rc.4",
181
183
  "@types/node": "*",
182
- "emnapi": "^1.7.1",
184
+ "emnapi": "^1.9.2",
183
185
  "exif-reader": "^2.0.3",
184
186
  "extract-zip": "^2.0.1",
185
187
  "icc": "^3.0.0",
186
- "node-addon-api": "^8.5.0",
187
- "node-gyp": "^12.1.0",
188
- "tar-fs": "^3.1.1",
188
+ "node-addon-api": "^8.7.0",
189
+ "node-gyp": "^12.2.0",
190
+ "tar-fs": "^3.1.2",
189
191
  "tsd": "^0.33.0"
190
192
  },
191
193
  "license": "Apache-2.0",
@@ -193,7 +195,7 @@
193
195
  "node": ">=20.9.0"
194
196
  },
195
197
  "config": {
196
- "libvips": ">=8.18.0"
198
+ "libvips": ">=8.18.2"
197
199
  },
198
200
  "funding": {
199
201
  "url": "https://opencollective.com/libvips"
package/src/binding.gyp CHANGED
@@ -21,6 +21,7 @@
21
21
  'defines': [
22
22
  '_VIPS_PUBLIC=__declspec(dllexport)',
23
23
  '_ALLOW_KEYWORD_MACROS',
24
+ '_HAS_EXCEPTIONS=1',
24
25
  'G_DISABLE_ASSERT',
25
26
  'G_DISABLE_CAST_CHECKS',
26
27
  'G_DISABLE_CHECKS'
@@ -148,7 +149,8 @@
148
149
  ['OS == "win"', {
149
150
  'defines': [
150
151
  '_ALLOW_KEYWORD_MACROS',
151
- '_FILE_OFFSET_BITS=64'
152
+ '_FILE_OFFSET_BITS=64',
153
+ '_HAS_EXCEPTIONS=1'
152
154
  ],
153
155
  'link_settings': {
154
156
  'libraries': [
@@ -203,14 +205,16 @@
203
205
  }],
204
206
  ['OS == "emscripten"', {
205
207
  'product_extension': 'node.js',
208
+ 'cflags_cc': [
209
+ '-fwasm-exceptions'
210
+ ],
206
211
  'link_settings': {
207
212
  'ldflags': [
208
- '-fexceptions',
213
+ '-fwasm-exceptions',
209
214
  '--pre-js=<!(node -p "require.resolve(\'./emscripten/pre.js\')")',
210
215
  '-Oz',
211
216
  '-sALLOW_MEMORY_GROWTH',
212
217
  '-sENVIRONMENT=node',
213
- '-sEXPORTED_FUNCTIONS=emnapiInit,_vips_shutdown,_uv_library_shutdown',
214
218
  '-sNODERAWFS',
215
219
  '-sWASM_ASYNC_COMPILATION=0'
216
220
  ],
package/src/common.cc CHANGED
@@ -426,7 +426,7 @@ namespace sharp {
426
426
  }
427
427
  if (ImageTypeSupportsPage(imageType)) {
428
428
  option->set("n", descriptor->pages);
429
- option->set("page", descriptor->page);
429
+ option->set("page", std::max(0, descriptor->page));
430
430
  }
431
431
  switch (imageType) {
432
432
  case ImageType::SVG:
@@ -456,6 +456,22 @@ namespace sharp {
456
456
  return option;
457
457
  }
458
458
 
459
+ /*
460
+ Should HEIF image be re-opened using the primary item?
461
+ */
462
+ static bool HeifPrimaryPageReopen(VImage image, InputDescriptor *descriptor) {
463
+ if (image.get_typeof(VIPS_META_N_PAGES) == G_TYPE_INT && image.get_typeof("heif-primary") == G_TYPE_INT) {
464
+ if (image.get_int(VIPS_META_N_PAGES) > 1 && descriptor->pages == 1 && descriptor->page == -1) {
465
+ int const pagePrimary = image.get_int("heif-primary");
466
+ if (pagePrimary != 0) {
467
+ descriptor->page = pagePrimary;
468
+ return true;
469
+ }
470
+ }
471
+ }
472
+ return false;
473
+ }
474
+
459
475
  /*
460
476
  Open an image from the given InputDescriptor (filesystem, compressed buffer, raw pixel data)
461
477
  */
@@ -490,12 +506,15 @@ namespace sharp {
490
506
  image = VImage::new_from_buffer(descriptor->buffer, descriptor->bufferLength, nullptr, option);
491
507
  if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
492
508
  image = SetDensity(image, descriptor->density);
509
+ } else if (imageType == ImageType::HEIF && HeifPrimaryPageReopen(image, descriptor)) {
510
+ option = GetOptionsForImageType(imageType, descriptor);
511
+ image = VImage::new_from_buffer(descriptor->buffer, descriptor->bufferLength, nullptr, option);
493
512
  }
494
- } catch (vips::VError const &err) {
495
- throw vips::VError(std::string("Input buffer has corrupt header: ") + err.what());
513
+ } catch (std::runtime_error const &err) {
514
+ throw std::runtime_error(std::string("Input buffer has corrupt header: ") + err.what());
496
515
  }
497
516
  } else {
498
- throw vips::VError("Input buffer contains unsupported image format");
517
+ throw std::runtime_error("Input buffer contains unsupported image format");
499
518
  }
500
519
  }
501
520
  } else {
@@ -566,10 +585,10 @@ namespace sharp {
566
585
  imageType = DetermineImageType(descriptor->file.data());
567
586
  if (imageType == ImageType::MISSING) {
568
587
  if (descriptor->file.find("<svg") != std::string::npos) {
569
- throw vips::VError("Input file is missing, did you mean "
588
+ throw std::runtime_error("Input file is missing, did you mean "
570
589
  "sharp(Buffer.from('" + descriptor->file.substr(0, 8) + "...')?");
571
590
  }
572
- throw vips::VError("Input file is missing: " + descriptor->file);
591
+ throw std::runtime_error("Input file is missing: " + descriptor->file);
573
592
  }
574
593
  if (imageType != ImageType::UNKNOWN) {
575
594
  try {
@@ -577,12 +596,15 @@ namespace sharp {
577
596
  image = VImage::new_from_file(descriptor->file.data(), option);
578
597
  if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
579
598
  image = SetDensity(image, descriptor->density);
599
+ } else if (imageType == ImageType::HEIF && HeifPrimaryPageReopen(image, descriptor)) {
600
+ option = GetOptionsForImageType(imageType, descriptor);
601
+ image = VImage::new_from_file(descriptor->file.data(), option);
580
602
  }
581
- } catch (vips::VError const &err) {
582
- throw vips::VError(std::string("Input file has corrupt header: ") + err.what());
603
+ } catch (std::runtime_error const &err) {
604
+ throw std::runtime_error(std::string("Input file has corrupt header: ") + err.what());
583
605
  }
584
606
  } else {
585
- throw vips::VError("Input file contains unsupported image format");
607
+ throw std::runtime_error("Input file contains unsupported image format");
586
608
  }
587
609
  }
588
610
  }
@@ -590,7 +612,7 @@ namespace sharp {
590
612
  // Limit input images to a given number of pixels, where pixels = width * height
591
613
  if (descriptor->limitInputPixels > 0 &&
592
614
  static_cast<uint64_t>(image.width()) * image.height() > descriptor->limitInputPixels) {
593
- throw vips::VError("Input image exceeds pixel limit");
615
+ throw std::runtime_error("Input image exceeds pixel limit");
594
616
  }
595
617
  return std::make_tuple(image, imageType);
596
618
  }
@@ -766,19 +788,19 @@ namespace sharp {
766
788
  : image.height();
767
789
  if (imageType == ImageType::JPEG) {
768
790
  if (image.width() > 65535 || height > 65535) {
769
- throw vips::VError("Processed image is too large for the JPEG format");
791
+ throw std::runtime_error("Processed image is too large for the JPEG format");
770
792
  }
771
793
  } else if (imageType == ImageType::WEBP) {
772
794
  if (image.width() > 16383 || height > 16383) {
773
- throw vips::VError("Processed image is too large for the WebP format");
795
+ throw std::runtime_error("Processed image is too large for the WebP format");
774
796
  }
775
797
  } else if (imageType == ImageType::GIF) {
776
798
  if (image.width() > 65535 || height > 65535) {
777
- throw vips::VError("Processed image is too large for the GIF format");
799
+ throw std::runtime_error("Processed image is too large for the GIF format");
778
800
  }
779
801
  } else if (imageType == ImageType::HEIF) {
780
802
  if (image.width() > 16384 || height > 16384) {
781
- throw vips::VError("Processed image is too large for the HEIF format");
803
+ throw std::runtime_error("Processed image is too large for the HEIF format");
782
804
  }
783
805
  }
784
806
  }
@@ -1142,7 +1164,8 @@ namespace sharp {
1142
1164
  Does this image have a gain map?
1143
1165
  */
1144
1166
  bool HasGainMap(VImage image) {
1145
- return image.get_typeof("gainmap-data") == VIPS_TYPE_BLOB;
1167
+ return image.get_typeof("gainmap") == VIPS_TYPE_BLOB ||
1168
+ image.get_typeof("gainmap-data") == VIPS_TYPE_BLOB;
1146
1169
  }
1147
1170
 
1148
1171
  /*
@@ -1150,6 +1173,7 @@ namespace sharp {
1150
1173
  */
1151
1174
  VImage RemoveGainMap(VImage image) {
1152
1175
  VImage copy = image.copy();
1176
+ copy.remove("gainmap");
1153
1177
  copy.remove("gainmap-data");
1154
1178
  return copy;
1155
1179
  }
package/src/common.h CHANGED
@@ -19,8 +19,8 @@
19
19
 
20
20
  #if (VIPS_MAJOR_VERSION < 8) || \
21
21
  (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 18) || \
22
- (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 18 && VIPS_MICRO_VERSION < 0)
23
- #error "libvips version 8.18.0+ is required - please see https://sharp.pixelplumbing.com/install"
22
+ (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 18 && VIPS_MICRO_VERSION < 2)
23
+ #error "libvips version 8.18.2+ is required - please see https://sharp.pixelplumbing.com/install"
24
24
  #endif
25
25
 
26
26
  #if defined(__has_include)
@@ -29,6 +29,12 @@
29
29
  #endif
30
30
  #endif
31
31
 
32
+ #ifdef __EMSCRIPTEN__
33
+ #define SHARP_CALLBACK_FN_NAME Call
34
+ #else
35
+ #define SHARP_CALLBACK_FN_NAME MakeCallback
36
+ #endif
37
+
32
38
  using vips::VImage;
33
39
 
34
40
  namespace sharp {
@@ -105,7 +111,7 @@ namespace sharp {
105
111
  rawPremultiplied(false),
106
112
  rawPageHeight(0),
107
113
  pages(1),
108
- page(0),
114
+ page(-1),
109
115
  createChannels(0),
110
116
  createWidth(0),
111
117
  createHeight(0),
package/src/metadata.cc CHANGED
@@ -31,7 +31,7 @@ class MetadataWorker : public Napi::AsyncWorker {
31
31
  sharp::ImageType imageType = sharp::ImageType::UNKNOWN;
32
32
  try {
33
33
  std::tie(image, imageType) = OpenInput(baton->input);
34
- } catch (vips::VError const &err) {
34
+ } catch (std::runtime_error const &err) {
35
35
  (baton->err).append(err.what());
36
36
  }
37
37
  if (imageType != sharp::ImageType::UNKNOWN) {
@@ -151,6 +151,50 @@ class MetadataWorker : public Napi::AsyncWorker {
151
151
  }
152
152
  // PNG comments
153
153
  vips_image_map(image.get_image(), readPNGComment, &baton->comments);
154
+ // Media type
155
+ std::string mediaType;
156
+ switch (imageType) {
157
+ case sharp::ImageType::JPEG:
158
+ case sharp::ImageType::PNG:
159
+ case sharp::ImageType::WEBP:
160
+ case sharp::ImageType::JP2:
161
+ case sharp::ImageType::TIFF:
162
+ case sharp::ImageType::GIF:
163
+ case sharp::ImageType::FITS:
164
+ case sharp::ImageType::JXL:
165
+ baton->mediaType = "image/" + baton->format;
166
+ break;
167
+ case sharp::ImageType::SVG:
168
+ baton->mediaType = "image/svg+xml";
169
+ break;
170
+ case sharp::ImageType::HEIF:
171
+ if (baton->compression == "av1") {
172
+ baton->mediaType = "image/avif";
173
+ } else if (baton->compression == "hevc") {
174
+ baton->mediaType = "image/heic";
175
+ }
176
+ break;
177
+ case sharp::ImageType::PDF:
178
+ baton->mediaType = "application/pdf";
179
+ break;
180
+ case sharp::ImageType::OPENSLIDE:
181
+ baton->mediaType = "image/tiff";
182
+ break;
183
+ case sharp::ImageType::PPM:
184
+ baton->mediaType = "image/x-portable-pixmap";
185
+ break;
186
+ case sharp::ImageType::EXR:
187
+ baton->mediaType = "image/x-exr";
188
+ break;
189
+ case sharp::ImageType::RAD:
190
+ baton->mediaType = "image/vnd.radiance";
191
+ break;
192
+ case sharp::ImageType::UHDR:
193
+ baton->mediaType = "image/jpeg";
194
+ break;
195
+ default:
196
+ break;
197
+ }
154
198
  }
155
199
 
156
200
  // Clean up
@@ -165,13 +209,16 @@ class MetadataWorker : public Napi::AsyncWorker {
165
209
  // Handle warnings
166
210
  std::string warning = sharp::VipsWarningPop();
167
211
  while (!warning.empty()) {
168
- debuglog.Call(Receiver().Value(), { Napi::String::New(env, warning) });
212
+ debuglog.SHARP_CALLBACK_FN_NAME(Receiver().Value(), { Napi::String::New(env, warning) });
169
213
  warning = sharp::VipsWarningPop();
170
214
  }
171
215
 
172
216
  if (baton->err.empty()) {
173
217
  Napi::Object info = Napi::Object::New(env);
174
218
  info.Set("format", baton->format);
219
+ if (!baton->mediaType.empty()) {
220
+ info.Set("mediaType", baton->mediaType);
221
+ }
175
222
  if (baton->input->bufferLength > 0) {
176
223
  info.Set("size", baton->input->bufferLength);
177
224
  }
@@ -297,9 +344,10 @@ class MetadataWorker : public Napi::AsyncWorker {
297
344
  }
298
345
  info.Set("comments", comments);
299
346
  }
300
- Callback().Call(Receiver().Value(), { env.Null(), info });
347
+ Callback().SHARP_CALLBACK_FN_NAME(Receiver().Value(), { env.Null(), info });
301
348
  } else {
302
- Callback().Call(Receiver().Value(), { Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
349
+ Callback().SHARP_CALLBACK_FN_NAME(Receiver().Value(),
350
+ { Napi::Error::New(env, sharp::TrimEnd(baton->err)).Value() });
303
351
  }
304
352
 
305
353
  delete baton->input;
package/src/metadata.h CHANGED
@@ -19,6 +19,7 @@ struct MetadataBaton {
19
19
  sharp::InputDescriptor *input;
20
20
  // Output
21
21
  std::string format;
22
+ std::string mediaType;
22
23
  int width;
23
24
  int height;
24
25
  std::string space;
package/src/operations.cc CHANGED
@@ -14,7 +14,6 @@
14
14
  #include "./operations.h"
15
15
 
16
16
  using vips::VImage;
17
- using vips::VError;
18
17
 
19
18
  namespace sharp {
20
19
  /*
@@ -287,7 +286,7 @@ namespace sharp {
287
286
  */
288
287
  VImage Trim(VImage image, std::vector<double> background, double threshold, bool const lineArt, int const margin) {
289
288
  if (image.width() < 3 && image.height() < 3) {
290
- throw VError("Image to trim must be at least 3x3 pixels");
289
+ throw std::runtime_error("Image to trim must be at least 3x3 pixels");
291
290
  }
292
291
  if (background.size() == 0) {
293
292
  // Top-left pixel provides the default background colour if none is given
@@ -361,7 +360,7 @@ namespace sharp {
361
360
  VImage Linear(VImage image, std::vector<double> const a, std::vector<double> const b) {
362
361
  size_t const bands = static_cast<size_t>(image.bands());
363
362
  if (a.size() > bands) {
364
- throw VError("Band expansion using linear is unsupported");
363
+ throw std::runtime_error("Band expansion using linear is unsupported");
365
364
  }
366
365
  bool const uchar = !Is16Bit(image.interpretation());
367
366
  if (image.has_alpha() && a.size() != bands && (a.size() == 1 || a.size() == bands - 1 || bands - 1 == 1)) {