sharp 0.32.4 → 0.32.6

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/lib/index.d.ts CHANGED
@@ -139,6 +139,52 @@ declare namespace sharp {
139
139
  */
140
140
  function simd(enable?: boolean): boolean;
141
141
 
142
+ /**
143
+ * Block libvips operations at runtime.
144
+ *
145
+ * This is in addition to the `VIPS_BLOCK_UNTRUSTED` environment variable,
146
+ * which when set will block all "untrusted" operations.
147
+ *
148
+ * @since 0.32.4
149
+ *
150
+ * @example <caption>Block all TIFF input.</caption>
151
+ * sharp.block({
152
+ * operation: ['VipsForeignLoadTiff']
153
+ * });
154
+ *
155
+ * @param {Object} options
156
+ * @param {Array<string>} options.operation - List of libvips low-level operation names to block.
157
+ */
158
+ function block(options: { operation: string[] }): void;
159
+
160
+ /**
161
+ * Unblock libvips operations at runtime.
162
+ *
163
+ * This is useful for defining a list of allowed operations.
164
+ *
165
+ * @since 0.32.4
166
+ *
167
+ * @example <caption>Block all input except WebP from the filesystem.</caption>
168
+ * sharp.block({
169
+ * operation: ['VipsForeignLoad']
170
+ * });
171
+ * sharp.unblock({
172
+ * operation: ['VipsForeignLoadWebpFile']
173
+ * });
174
+ *
175
+ * @example <caption>Block all input except JPEG and PNG from a Buffer or Stream.</caption>
176
+ * sharp.block({
177
+ * operation: ['VipsForeignLoad']
178
+ * });
179
+ * sharp.unblock({
180
+ * operation: ['VipsForeignLoadJpegBuffer', 'VipsForeignLoadPngBuffer']
181
+ * });
182
+ *
183
+ * @param {Object} options
184
+ * @param {Array<string>} options.operation - List of libvips low-level operation names to unblock.
185
+ */
186
+ function unblock(options: { operation: string[] }): void;
187
+
142
188
  //#endregion
143
189
 
144
190
  const gravity: GravityEnum;
@@ -1124,9 +1170,11 @@ declare namespace sharp {
1124
1170
  /** Level of CPU effort to reduce file size, integer 0-6 (optional, default 4) */
1125
1171
  effort?: number | undefined;
1126
1172
  /** Prevent use of animation key frames to minimise file size (slow) (optional, default false) */
1127
- minSize?: number;
1173
+ minSize?: boolean;
1128
1174
  /** Allow mixture of lossy and lossless animation frames (slow) (optional, default false) */
1129
1175
  mixed?: boolean;
1176
+ /** Preset options: one of default, photo, picture, drawing, icon, text (optional, default 'default') */
1177
+ preset?: keyof PresetEnum | undefined;
1130
1178
  }
1131
1179
 
1132
1180
  interface AvifOptions extends OutputOptions {
@@ -1476,6 +1524,15 @@ declare namespace sharp {
1476
1524
  lanczos3: 'lanczos3';
1477
1525
  }
1478
1526
 
1527
+ interface PresetEnum {
1528
+ default: 'default';
1529
+ picture: 'picture';
1530
+ photo: 'photo';
1531
+ drawing: 'drawing';
1532
+ icon: 'icon';
1533
+ text: 'text';
1534
+ }
1535
+
1479
1536
  interface BoolEnum {
1480
1537
  and: 'and';
1481
1538
  or: 'or';
package/lib/input.js CHANGED
@@ -432,6 +432,7 @@ function _isStreamInput () {
432
432
  * - `isProgressive`: Boolean indicating whether the image is interlaced using a progressive scan
433
433
  * - `pages`: Number of pages/frames contained within the image, with support for TIFF, HEIF, PDF, animated GIF and animated WebP
434
434
  * - `pageHeight`: Number of pixels high each page in a multi-page image will be.
435
+ * - `paletteBitDepth`: Bit depth of palette-based image (GIF, PNG).
435
436
  * - `loop`: Number of times to loop an animated image, zero refers to a continuous loop.
436
437
  * - `delay`: Delay in ms between each page in an animated image, provided as an array of integers.
437
438
  * - `pagePrimary`: Number of the primary page in a HEIF image
package/lib/operation.js CHANGED
@@ -19,7 +19,7 @@ const is = require('./is');
19
19
  * If no angle is provided, it is determined from the EXIF data.
20
20
  * Mirroring is supported and may infer the use of a flip operation.
21
21
  *
22
- * The use of `rotate` implies the removal of the EXIF `Orientation` tag, if any.
22
+ * The use of `rotate` without an angle will remove the EXIF `Orientation` tag, if any.
23
23
  *
24
24
  * Only one rotation can occur per pipeline.
25
25
  * Previous calls to `rotate` in the same pipeline will be ignored.
@@ -83,8 +83,6 @@ function rotate (angle, options) {
83
83
  * Mirror the image vertically (up-down) about the x-axis.
84
84
  * This always occurs before rotation, if any.
85
85
  *
86
- * The use of `flip` implies the removal of the EXIF `Orientation` tag, if any.
87
- *
88
86
  * This operation does not work correctly with multi-page images.
89
87
  *
90
88
  * @example
@@ -102,8 +100,6 @@ function flip (flip) {
102
100
  * Mirror the image horizontally (left-right) about the y-axis.
103
101
  * This always occurs before rotation, if any.
104
102
  *
105
- * The use of `flop` implies the removal of the EXIF `Orientation` tag, if any.
106
- *
107
103
  * @example
108
104
  * const output = await sharp(input).flop().toBuffer();
109
105
  *
package/lib/output.js CHANGED
@@ -162,8 +162,8 @@ function toBuffer (options, callback) {
162
162
 
163
163
  /**
164
164
  * Include all metadata (EXIF, XMP, IPTC) from the input image in the output image.
165
- * This will also convert to and add a web-friendly sRGB ICC profile unless a custom
166
- * output profile is provided.
165
+ * This will also convert to and add a web-friendly sRGB ICC profile if appropriate,
166
+ * unless a custom output profile is provided.
167
167
  *
168
168
  * The default behaviour, when `withMetadata` is not used, is to convert to the device-independent
169
169
  * sRGB colour space and strip all metadata, including the removal of any ICC profile.
@@ -1046,6 +1046,7 @@ function jxl (options) {
1046
1046
  *
1047
1047
  * @param {Object} [options] - output options
1048
1048
  * @param {string} [options.depth='uchar'] - bit depth, one of: char, uchar (default), short, ushort, int, uint, float, complex, double, dpcomplex
1049
+ * @returns {Sharp}
1049
1050
  * @throws {Error} Invalid options
1050
1051
  */
1051
1052
  function raw (options) {
package/lib/resize.js CHANGED
@@ -126,7 +126,7 @@ function isResizeExpected (options) {
126
126
  *
127
127
  * Some of these values are based on the [object-fit](https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit) CSS property.
128
128
  *
129
- * <img alt="Examples of various values for the fit property when resizing" width="100%" style="aspect-ratio: 998/243" src="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/image/api-resize-fit.png">
129
+ * <img alt="Examples of various values for the fit property when resizing" width="100%" style="aspect-ratio: 998/243" src="https://cdn.jsdelivr.net/gh/lovell/sharp@main/docs/image/api-resize-fit.svg">
130
130
  *
131
131
  * When using a **fit** of `cover` or `contain`, the default **position** is `centre`. Other options are:
132
132
  * - `sharp.position`: `top`, `right top`, `right`, `right bottom`, `bottom`, `left bottom`, `left`, `left top`.
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.32.4",
4
+ "version": "0.32.6",
5
5
  "author": "Lovell Fuller <npm@lovell.info>",
6
6
  "homepage": "https://github.com/lovell/sharp",
7
7
  "contributors": [
@@ -153,25 +153,25 @@
153
153
  "mocha": "^10.2.0",
154
154
  "mock-fs": "^5.2.0",
155
155
  "nyc": "^15.1.0",
156
- "prebuild": "lovell/prebuild#add-nodejs-20-drop-nodejs-10-and-12",
156
+ "prebuild": "^12.0.0",
157
157
  "semistandard": "^16.0.1",
158
- "tsd": "^0.28.1"
158
+ "tsd": "^0.29.0"
159
159
  },
160
160
  "license": "Apache-2.0",
161
161
  "config": {
162
- "libvips": "8.14.3",
162
+ "libvips": "8.14.5",
163
163
  "integrity": {
164
- "darwin-arm64v8": "sha512-zeb7jQ/5ARZfBH9Uy5wlpN05bFpiIN0qN3gIIpfJhpN0rhGDnjJZQgK0W+pOmG1YiLL42BMCS0SHldb0xE33rA==",
165
- "darwin-x64": "sha512-C3N6smxdfprfz58cjojv0aekYXDl6+f9SwpGpxPG5RrZnrDMn5NOXtUQOEQ8PZ3Hd9VzfkJTnW/s36EvcMPfYg==",
166
- "linux-arm64v8": "sha512-hT6B+OswqVQH10Fggq3jpOdn+GhxNx+5bk+EMr3lY3RZy72PZ+n4ZHJDfYSxAymdiz5rCdzGxsRLMb9GgD4OSw==",
167
- "linux-armv6": "sha512-cW9giVrBssHXFt07l+PgqGu7P7XRDv7oW8jC6iXGBcjG75N7rXz2CK0DyPclfnyoWH4IQ78dh5SkQWmb6X4tig==",
168
- "linux-armv7": "sha512-hgqFt3UkZHK6D91JtYrYmT1niznh+N93Zxj2EWXgTLAdcS1D3QqaDPEg2EhInHbXqYvfOuQYAAXPxt7zVtKqcw==",
169
- "linux-x64": "sha512-FKbMBbCcFcSugRtuiTsA6Cov+M2WQ8nzvmmJ5xYYpRg/rsrWvObFT+6x/YBpblur9uXGjGIehjXVZtB3VXc+pg==",
170
- "linuxmusl-arm64v8": "sha512-RTf6mrFyLGWnyt0DH4nHeXv5oSZMSJWxTdTt4cjvJsgp2Husz3mNJLQJGeehCuqPCYj/liJ9NIczw8u71eHFng==",
171
- "linuxmusl-x64": "sha512-y/8UOkHzKhi/5UM1/ONyPvpuhO11nPQmuJWfzqUKj8kSKnDasmxv3FN46yI0XY3xA2oFC8lQNFBnLudQsi3Nvw==",
172
- "win32-arm64v8": "sha512-D3PiVL981S7V0bSUwW3OqDS48H9QRw2vqQhYIY3JcIEssOnjWxmJGaz0Y9Zb8TYF5DHnnD6g5kEhob5Y2PIVEw==",
173
- "win32-ia32": "sha512-FuLIaSIYJGJAcxyKkG/3/uuTzputekKSCcRCpRHkQS9J8IwM+yHzQeJ5W2PyAvNdeGIEwlYq3wnCNcXe1UGXWA==",
174
- "win32-x64": "sha512-VQg4aBqpEfybgV8bjnrjfvnosxQDII/23mouFUfKHCsH5kvvHV5tTuPsxm6qbl+SCVploDK/zK1qpjop8YEvtg=="
164
+ "darwin-arm64v8": "sha512-1QZzICfCJd4wAO0P6qmYI5e5VFMt9iCE4QgefI8VMMbdSzjIXA9L/ARN6pkMQPZ3h20Y9RtJ2W1skgCsvCIccw==",
165
+ "darwin-x64": "sha512-sMIKMYXsdU9FlIfztj6Kt/SfHlhlDpP0Ups7ftVFqwjaszmYmpI9y/d/q3mLb4jrzuSiSUEislSWCwBnW7MPTw==",
166
+ "linux-arm64v8": "sha512-CD8owELzkDumaom+O3jJ8fKamILAQdj+//KK/VNcHK3sngUcFpdjx36C8okwbux9sml/T7GTB/gzpvReDrAejQ==",
167
+ "linux-armv6": "sha512-wk6IPHatDFVWKJy7lI1TJezHGHPQut1wF2bwx256KlZwXUQU3fcVcMpV1zxXjgLFewHq2+uhyMkoSGBPahWzlA==",
168
+ "linux-armv7": "sha512-HEZC9KYtkmBK5rUR2MqBhrVarnQVZ/TwLUeLkKq0XuoM2pc/eXI6N0Fh5NGEFwdXI2XE8g1ySf+OYS6DDi+xCQ==",
169
+ "linux-x64": "sha512-SlFWrITSW5XVUkaFPQOySAaSGXnhkGJCj8X2wGYYta9hk5piZldQyMp4zwy0z6UeRu1qKTKtZvmq28W3Gnh9xA==",
170
+ "linuxmusl-arm64v8": "sha512-ga9iX7WUva3sG/VsKkOD318InLlCfPIztvzCZKZ2/+izQXRbQi8VoXWMHgEN4KHACv45FTl7mJ/8CRqUzhS8wQ==",
171
+ "linuxmusl-x64": "sha512-yeaHnpfee1hrZLok2l4eFceHzlfq8gN3QOu0R4Mh8iMK5O5vAUu97bdtxeZZeJJvHw8tfh2/msGi0qysxKN8bw==",
172
+ "win32-arm64v8": "sha512-kR91hy9w1+GEXK56hLh51+hBCBo7T+ijM4Slkmvb/2PsYZySq5H7s61n99iDYl6kTJP2y9sW5Xcvm3uuXDaDgg==",
173
+ "win32-ia32": "sha512-HrnofEbzHNpHJ0vVnjsTj5yfgVdcqdWshXuwFO2zc8xlEjA83BvXZ0lVj9MxPxkxJ2ta+/UlLr+CFzc5bOceMw==",
174
+ "win32-x64": "sha512-BwKckinJZ0Fu/EcunqiLPwOLEBWp4xf8GV7nvmVuKKz5f6B+GxoA2k9aa2wueqv4r4RJVgV/aWXZWFKOIjre/Q=="
175
175
  },
176
176
  "runtime": "napi",
177
177
  "target": 7
package/src/common.cc CHANGED
@@ -964,12 +964,7 @@ namespace sharp {
964
964
  }
965
965
 
966
966
  std::pair<double, double> ResolveShrink(int width, int height, int targetWidth, int targetHeight,
967
- Canvas canvas, bool swap, bool withoutEnlargement, bool withoutReduction) {
968
- if (swap && canvas != Canvas::IGNORE_ASPECT) {
969
- // Swap input width and height when requested.
970
- std::swap(width, height);
971
- }
972
-
967
+ Canvas canvas, bool withoutEnlargement, bool withoutReduction) {
973
968
  double hshrink = 1.0;
974
969
  double vshrink = 1.0;
975
970
 
package/src/common.h CHANGED
@@ -15,8 +15,8 @@
15
15
 
16
16
  #if (VIPS_MAJOR_VERSION < 8) || \
17
17
  (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION < 14) || \
18
- (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION == 14 && VIPS_MICRO_VERSION < 3)
19
- #error "libvips version 8.14.3+ is required - please see https://sharp.pixelplumbing.com/install"
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"
20
20
  #endif
21
21
 
22
22
  #if ((!defined(__clang__)) && defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)))
@@ -362,13 +362,10 @@ namespace sharp {
362
362
  VImage EnsureAlpha(VImage image, double const value);
363
363
 
364
364
  /*
365
- Calculate the shrink factor, taking into account auto-rotate, the canvas
366
- mode, and so on. The hshrink/vshrink are the amount to shrink the input
367
- image axes by in order for the output axes (ie. after rotation) to match
368
- the required thumbnail width/height and canvas mode.
365
+ Calculate the horizontal and vertical shrink factors, taking the canvas mode into account.
369
366
  */
370
367
  std::pair<double, double> ResolveShrink(int width, int height, int targetWidth, int targetHeight,
371
- Canvas canvas, bool swap, bool withoutEnlargement, bool withoutReduction);
368
+ Canvas canvas, bool withoutEnlargement, bool withoutReduction);
372
369
 
373
370
  /*
374
371
  Ensure decoding remains sequential.
package/src/pipeline.cc CHANGED
@@ -20,18 +20,15 @@
20
20
  #include "operations.h"
21
21
  #include "pipeline.h"
22
22
 
23
- #if defined(WIN32)
23
+ #ifdef _WIN32
24
24
  #define STAT64_STRUCT __stat64
25
25
  #define STAT64_FUNCTION _stat64
26
- #elif defined(__APPLE__)
27
- #define STAT64_STRUCT stat
28
- #define STAT64_FUNCTION stat
29
- #elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
30
- #define STAT64_STRUCT stat
31
- #define STAT64_FUNCTION stat
32
- #else
26
+ #elif defined(_LARGEFILE64_SOURCE)
33
27
  #define STAT64_STRUCT stat64
34
28
  #define STAT64_FUNCTION stat64
29
+ #else
30
+ #define STAT64_STRUCT stat
31
+ #define STAT64_FUNCTION stat
35
32
  #endif
36
33
 
37
34
  class PipelineWorker : public Napi::AsyncWorker {
@@ -160,15 +157,18 @@ class PipelineWorker : public Napi::AsyncWorker {
160
157
  int targetResizeWidth = baton->width;
161
158
  int targetResizeHeight = baton->height;
162
159
 
163
- // Swap input output width and height when rotating by 90 or 270 degrees
164
- bool swap = !baton->rotateBeforePreExtract &&
165
- (rotation == VIPS_ANGLE_D90 || rotation == VIPS_ANGLE_D270 ||
166
- autoRotation == VIPS_ANGLE_D90 || autoRotation == VIPS_ANGLE_D270);
160
+ // When auto-rotating by 90 or 270 degrees, swap the target width and
161
+ // height to ensure the behavior aligns with how it would have been if
162
+ // the rotation had taken place *before* resizing.
163
+ if (!baton->rotateBeforePreExtract &&
164
+ (autoRotation == VIPS_ANGLE_D90 || autoRotation == VIPS_ANGLE_D270)) {
165
+ std::swap(targetResizeWidth, targetResizeHeight);
166
+ }
167
167
 
168
168
  // Shrink to pageHeight, so we work for multi-page images
169
169
  std::tie(hshrink, vshrink) = sharp::ResolveShrink(
170
170
  inputWidth, pageHeight, targetResizeWidth, targetResizeHeight,
171
- baton->canvas, swap, baton->withoutEnlargement, baton->withoutReduction);
171
+ baton->canvas, baton->withoutEnlargement, baton->withoutReduction);
172
172
 
173
173
  // The jpeg preload shrink.
174
174
  int jpegShrinkOnLoad = 1;
@@ -302,7 +302,7 @@ class PipelineWorker : public Napi::AsyncWorker {
302
302
  // Shrink to pageHeight, so we work for multi-page images
303
303
  std::tie(hshrink, vshrink) = sharp::ResolveShrink(
304
304
  inputWidth, pageHeight, targetResizeWidth, targetResizeHeight,
305
- baton->canvas, swap, baton->withoutEnlargement, baton->withoutReduction);
305
+ baton->canvas, baton->withoutEnlargement, baton->withoutReduction);
306
306
 
307
307
  int targetHeight = static_cast<int>(std::rint(static_cast<double>(pageHeight) / vshrink));
308
308
  int targetPageHeight = targetHeight;
@@ -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);
@@ -653,7 +653,7 @@ class PipelineWorker : public Napi::AsyncWorker {
653
653
  if (across != 0 || down != 0) {
654
654
  int left;
655
655
  int top;
656
- compositeImage = compositeImage.replicate(across, down);
656
+ compositeImage = sharp::StaySequential(compositeImage, access).replicate(across, down);
657
657
  if (composite->hasOffset) {
658
658
  std::tie(left, top) = sharp::CalculateCrop(
659
659
  compositeImage.width(), compositeImage.height(), image.width(), image.height(),
@@ -763,6 +763,7 @@ class PipelineWorker : public Napi::AsyncWorker {
763
763
  if (baton->withMetadata && sharp::HasProfile(image) && baton->withMetadataIcc.empty()) {
764
764
  image = image.icc_transform("srgb", VImage::option()
765
765
  ->set("embedded", TRUE)
766
+ ->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
766
767
  ->set("intent", VIPS_INTENT_PERCEPTUAL));
767
768
  }
768
769
  }
@@ -788,12 +789,13 @@ class PipelineWorker : public Napi::AsyncWorker {
788
789
  }
789
790
 
790
791
  // Apply output ICC profile
791
- if (!baton->withMetadataIcc.empty()) {
792
+ if (baton->withMetadata) {
792
793
  image = image.icc_transform(
793
- const_cast<char*>(baton->withMetadataIcc.data()),
794
+ baton->withMetadataIcc.empty() ? "srgb" : const_cast<char*>(baton->withMetadataIcc.data()),
794
795
  VImage::option()
795
796
  ->set("input_profile", processingProfile)
796
797
  ->set("embedded", TRUE)
798
+ ->set("depth", sharp::Is16Bit(image.interpretation()) ? 16 : 8)
797
799
  ->set("intent", VIPS_INTENT_PERCEPTUAL));
798
800
  }
799
801
  // Override EXIF Orientation tag