@revizly/sharp 0.35.0-revizly54 → 0.35.0-revizly55

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/dist/index.d.cts CHANGED
@@ -1462,8 +1462,8 @@ declare namespace sharp {
1462
1462
  interface HeifOptions extends OutputOptions {
1463
1463
  /** quality, integer 1-100 (optional, default 50) */
1464
1464
  quality?: number | undefined;
1465
- /** compression format: av1, hevc (optional, default 'av1') */
1466
- compression?: HeifCompression | undefined;
1465
+ /** compression format: av1, hevc */
1466
+ compression: HeifCompression;
1467
1467
  /** use lossless compression (optional, default false) */
1468
1468
  lossless?: boolean | undefined;
1469
1469
  /** Level of CPU effort to reduce file size, between 0 (fastest) and 9 (slowest) (optional, default 4) */
@@ -1472,7 +1472,7 @@ declare namespace sharp {
1472
1472
  chromaSubsampling?: string | undefined;
1473
1473
  /** Set bitdepth to 8, 10 or 12 bit (optional, default 8) */
1474
1474
  bitdepth?: 8 | 10 | 12 | undefined;
1475
- /** Tune output for a quality metric, one of 'auto', 'iq', 'psnr' or 'ssim' (optional, default 'auto') */
1475
+ /** Tune output for a quality metric, one of 'auto' (av1 default), 'iq' (av1 only), 'psnr' or 'ssim' (hevc default) */
1476
1476
  tune?: HeifTune | undefined;
1477
1477
  /** Which encoder libheif uses (must be compiled in) (optional, default 'auto') */
1478
1478
  encoder?: 'auto' | 'aom' | 'rav1e' | 'svt' | 'x265' | undefined;
package/dist/index.d.mts CHANGED
@@ -1456,8 +1456,8 @@ export interface AvifOptions extends OutputOptions {
1456
1456
  export interface HeifOptions extends OutputOptions {
1457
1457
  /** quality, integer 1-100 (optional, default 50) */
1458
1458
  quality?: number | undefined;
1459
- /** compression format: av1, hevc (optional, default 'av1') */
1460
- compression?: HeifCompression | undefined;
1459
+ /** compression format: av1, hevc */
1460
+ compression: HeifCompression;
1461
1461
  /** use lossless compression (optional, default false) */
1462
1462
  lossless?: boolean | undefined;
1463
1463
  /** Level of CPU effort to reduce file size, between 0 (fastest) and 9 (slowest) (optional, default 4) */
@@ -1466,7 +1466,7 @@ export interface HeifOptions extends OutputOptions {
1466
1466
  chromaSubsampling?: string | undefined;
1467
1467
  /** Set bitdepth to 8, 10 or 12 bit (optional, default 8) */
1468
1468
  bitdepth?: 8 | 10 | 12 | undefined;
1469
- /** Tune output for a quality metric, one of 'auto', 'iq', 'psnr' or 'ssim' (optional, default 'auto') */
1469
+ /** Tune output for a quality metric, one of 'auto' (av1 default), 'iq' (av1 only), 'psnr' or 'ssim' (hevc default) */
1470
1470
  tune?: HeifTune | undefined;
1471
1471
  /** Which encoder libheif uses (must be compiled in) (optional, default 'auto') */
1472
1472
  encoder?: 'auto' | 'aom' | 'rav1e' | 'svt' | 'x265' | undefined;
package/dist/is.cjs CHANGED
@@ -13,7 +13,7 @@ const defined = (val) => typeof val !== 'undefined' && val !== null;
13
13
  * Is this value an object?
14
14
  * @private
15
15
  */
16
- const object = (val) => typeof val === 'object';
16
+ const object = (val) => typeof val === 'object' && val !== null;
17
17
 
18
18
  /**
19
19
  * Is this value a plain object?
package/dist/is.mjs CHANGED
@@ -13,7 +13,7 @@ const defined = (val) => typeof val !== 'undefined' && val !== null;
13
13
  * Is this value an object?
14
14
  * @private
15
15
  */
16
- const object = (val) => typeof val === 'object';
16
+ const object = (val) => typeof val === 'object' && val !== null;
17
17
 
18
18
  /**
19
19
  * Is this value a plain object?
package/dist/output.cjs CHANGED
@@ -205,15 +205,15 @@ function toUint8Array () {
205
205
  * .withDensity(96)
206
206
  * .toBuffer();
207
207
  *
208
- * @param {number} density Number of pixels per inch (DPI).
208
+ * @param {number} density Number of pixels per inch (DPI), between 1 and 100000.
209
209
  * @returns {Sharp}
210
210
  * @throws {Error} Invalid parameters
211
211
  */
212
212
  function withDensity (density) {
213
- if (is.number(density) && density > 0) {
213
+ if (is.number(density) && is.inRange(density, 1, 100000)) {
214
214
  this.options.withMetadataDensity = density;
215
215
  } else {
216
- throw is.invalidParameterError('density', 'positive number', density);
216
+ throw is.invalidParameterError('density', 'number between 1 and 100000', density);
217
217
  }
218
218
  return this.keepExif();
219
219
  }
@@ -520,7 +520,7 @@ function keepMetadata () {
520
520
  *
521
521
  * @param {Object} [options]
522
522
  * @param {number} [options.orientation] Used to update the EXIF `Orientation` tag, integer between 1 and 8.
523
- * @param {number} [options.density] Number of pixels per inch (DPI).
523
+ * @param {number} [options.density] Number of pixels per inch (DPI), between 1 and 100000.
524
524
  * @returns {Sharp}
525
525
  * @throws {Error} Invalid parameters
526
526
  */
@@ -536,10 +536,10 @@ function withMetadata (options) {
536
536
  }
537
537
  }
538
538
  if (is.defined(options.density)) {
539
- if (is.number(options.density) && options.density > 0) {
539
+ if (is.number(options.density) && is.inRange(options.density, 1, 100000)) {
540
540
  this.options.withMetadataDensity = options.density;
541
541
  } else {
542
- throw is.invalidParameterError('density', 'positive number', options.density);
542
+ throw is.invalidParameterError('density', 'number between 1 and 100000', options.density);
543
543
  }
544
544
  }
545
545
  if (is.defined(options.icc)) {
@@ -1250,7 +1250,7 @@ function avif (options) {
1250
1250
  * @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
1251
1251
  * @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
1252
1252
  * @param {number} [options.bitdepth=8] - set bitdepth to 8, 10 or 12 bit
1253
- * @param {string} [options.tune='auto'] - tune output for a quality metric, one of 'auto' (default), 'iq', 'psnr' or 'ssim'
1253
+ * @param {string} [options.tune='auto'] - tune output for a quality metric, one of 'auto' (av1 default), 'iq' (av1 only), 'psnr' or 'ssim' (hevc default)
1254
1254
  * @returns {Sharp}
1255
1255
  * @throws {Error} Invalid options
1256
1256
  */
@@ -1258,6 +1258,9 @@ function heif (options) {
1258
1258
  if (is.object(options)) {
1259
1259
  if (is.string(options.compression) && is.inArray(options.compression, ['av1', 'hevc'])) {
1260
1260
  this.options.heifCompression = options.compression;
1261
+ if (options.compression === 'hevc' && this.options.heifTune === 'auto') {
1262
+ this.options.heifTune = 'ssim';
1263
+ }
1261
1264
  } else {
1262
1265
  throw is.invalidParameterError('compression', 'one of: av1, hevc', options.compression);
1263
1266
  }
@@ -1297,14 +1300,24 @@ function heif (options) {
1297
1300
  }
1298
1301
  }
1299
1302
  if (is.defined(options.tune)) {
1300
- if (is.string(options.tune) && is.inArray(options.tune, ['auto', 'iq', 'psnr', 'ssim'])) {
1301
- if (this.options.heifLossless && options.tune === 'iq') {
1302
- this.options.heifTune = 'ssim';
1303
- } else {
1303
+ if (is.string(options.tune)) {
1304
+ if (this.options.heifCompression === 'av1') {
1305
+ if (is.inArray(options.tune, ['auto', 'iq', 'psnr', 'ssim'])) {
1306
+ if (this.options.heifLossless && options.tune === 'iq') {
1307
+ this.options.heifTune = 'ssim';
1308
+ } else {
1309
+ this.options.heifTune = options.tune;
1310
+ }
1311
+ } else {
1312
+ throw is.invalidParameterError('tune', 'one of: auto, iq, psnr, ssim', options.tune);
1313
+ }
1314
+ } else if (is.inArray(options.tune, ['psnr', 'ssim'])) {
1304
1315
  this.options.heifTune = options.tune;
1316
+ } else {
1317
+ throw is.invalidParameterError('tune', 'one of: psnr, ssim', options.tune);
1305
1318
  }
1306
1319
  } else {
1307
- throw is.invalidParameterError('tune', 'one of: auto, iq, psnr, ssim', options.tune);
1320
+ throw is.invalidParameterError('tune', 'string', options.tune);
1308
1321
  }
1309
1322
  }
1310
1323
  if (is.defined(options.encoder)) {
package/dist/output.mjs CHANGED
@@ -205,15 +205,15 @@ function toUint8Array () {
205
205
  * .withDensity(96)
206
206
  * .toBuffer();
207
207
  *
208
- * @param {number} density Number of pixels per inch (DPI).
208
+ * @param {number} density Number of pixels per inch (DPI), between 1 and 100000.
209
209
  * @returns {Sharp}
210
210
  * @throws {Error} Invalid parameters
211
211
  */
212
212
  function withDensity (density) {
213
- if (is.number(density) && density > 0) {
213
+ if (is.number(density) && is.inRange(density, 1, 100000)) {
214
214
  this.options.withMetadataDensity = density;
215
215
  } else {
216
- throw is.invalidParameterError('density', 'positive number', density);
216
+ throw is.invalidParameterError('density', 'number between 1 and 100000', density);
217
217
  }
218
218
  return this.keepExif();
219
219
  }
@@ -520,7 +520,7 @@ function keepMetadata () {
520
520
  *
521
521
  * @param {Object} [options]
522
522
  * @param {number} [options.orientation] Used to update the EXIF `Orientation` tag, integer between 1 and 8.
523
- * @param {number} [options.density] Number of pixels per inch (DPI).
523
+ * @param {number} [options.density] Number of pixels per inch (DPI), between 1 and 100000.
524
524
  * @returns {Sharp}
525
525
  * @throws {Error} Invalid parameters
526
526
  */
@@ -536,10 +536,10 @@ function withMetadata (options) {
536
536
  }
537
537
  }
538
538
  if (is.defined(options.density)) {
539
- if (is.number(options.density) && options.density > 0) {
539
+ if (is.number(options.density) && is.inRange(options.density, 1, 100000)) {
540
540
  this.options.withMetadataDensity = options.density;
541
541
  } else {
542
- throw is.invalidParameterError('density', 'positive number', options.density);
542
+ throw is.invalidParameterError('density', 'number between 1 and 100000', options.density);
543
543
  }
544
544
  }
545
545
  if (is.defined(options.icc)) {
@@ -1250,7 +1250,7 @@ function avif (options) {
1250
1250
  * @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
1251
1251
  * @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
1252
1252
  * @param {number} [options.bitdepth=8] - set bitdepth to 8, 10 or 12 bit
1253
- * @param {string} [options.tune='auto'] - tune output for a quality metric, one of 'auto' (default), 'iq', 'psnr' or 'ssim'
1253
+ * @param {string} [options.tune='auto'] - tune output for a quality metric, one of 'auto' (av1 default), 'iq' (av1 only), 'psnr' or 'ssim' (hevc default)
1254
1254
  * @returns {Sharp}
1255
1255
  * @throws {Error} Invalid options
1256
1256
  */
@@ -1258,6 +1258,9 @@ function heif (options) {
1258
1258
  if (is.object(options)) {
1259
1259
  if (is.string(options.compression) && is.inArray(options.compression, ['av1', 'hevc'])) {
1260
1260
  this.options.heifCompression = options.compression;
1261
+ if (options.compression === 'hevc' && this.options.heifTune === 'auto') {
1262
+ this.options.heifTune = 'ssim';
1263
+ }
1261
1264
  } else {
1262
1265
  throw is.invalidParameterError('compression', 'one of: av1, hevc', options.compression);
1263
1266
  }
@@ -1297,14 +1300,24 @@ function heif (options) {
1297
1300
  }
1298
1301
  }
1299
1302
  if (is.defined(options.tune)) {
1300
- if (is.string(options.tune) && is.inArray(options.tune, ['auto', 'iq', 'psnr', 'ssim'])) {
1301
- if (this.options.heifLossless && options.tune === 'iq') {
1302
- this.options.heifTune = 'ssim';
1303
- } else {
1303
+ if (is.string(options.tune)) {
1304
+ if (this.options.heifCompression === 'av1') {
1305
+ if (is.inArray(options.tune, ['auto', 'iq', 'psnr', 'ssim'])) {
1306
+ if (this.options.heifLossless && options.tune === 'iq') {
1307
+ this.options.heifTune = 'ssim';
1308
+ } else {
1309
+ this.options.heifTune = options.tune;
1310
+ }
1311
+ } else {
1312
+ throw is.invalidParameterError('tune', 'one of: auto, iq, psnr, ssim', options.tune);
1313
+ }
1314
+ } else if (is.inArray(options.tune, ['psnr', 'ssim'])) {
1304
1315
  this.options.heifTune = options.tune;
1316
+ } else {
1317
+ throw is.invalidParameterError('tune', 'one of: psnr, ssim', options.tune);
1305
1318
  }
1306
1319
  } else {
1307
- throw is.invalidParameterError('tune', 'one of: auto, iq, psnr, ssim', options.tune);
1320
+ throw is.invalidParameterError('tune', 'string', options.tune);
1308
1321
  }
1309
1322
  }
1310
1323
  if (is.defined(options.encoder)) {
package/lib/index.d.ts CHANGED
@@ -1462,8 +1462,8 @@ declare namespace sharp {
1462
1462
  interface HeifOptions extends OutputOptions {
1463
1463
  /** quality, integer 1-100 (optional, default 50) */
1464
1464
  quality?: number | undefined;
1465
- /** compression format: av1, hevc (optional, default 'av1') */
1466
- compression?: HeifCompression | undefined;
1465
+ /** compression format: av1, hevc */
1466
+ compression: HeifCompression;
1467
1467
  /** use lossless compression (optional, default false) */
1468
1468
  lossless?: boolean | undefined;
1469
1469
  /** Level of CPU effort to reduce file size, between 0 (fastest) and 9 (slowest) (optional, default 4) */
@@ -1472,7 +1472,7 @@ declare namespace sharp {
1472
1472
  chromaSubsampling?: string | undefined;
1473
1473
  /** Set bitdepth to 8, 10 or 12 bit (optional, default 8) */
1474
1474
  bitdepth?: 8 | 10 | 12 | undefined;
1475
- /** Tune output for a quality metric, one of 'auto', 'iq', 'psnr' or 'ssim' (optional, default 'auto') */
1475
+ /** Tune output for a quality metric, one of 'auto' (av1 default), 'iq' (av1 only), 'psnr' or 'ssim' (hevc default) */
1476
1476
  tune?: HeifTune | undefined;
1477
1477
  /** Which encoder libheif uses (must be compiled in) (optional, default 'auto') */
1478
1478
  encoder?: 'auto' | 'aom' | 'rav1e' | 'svt' | 'x265' | undefined;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@revizly/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-revizly54",
4
+ "version": "0.35.0-revizly55",
5
5
  "author": "Lovell Fuller <npm@lovell.info>",
6
6
  "homepage": "https://sharp.pixelplumbing.com",
7
7
  "contributors": [
@@ -163,10 +163,10 @@
163
163
  "semver": "^7.8.5"
164
164
  },
165
165
  "optionalDependencies": {
166
- "@revizly/sharp-libvips-linux-arm64": "1.0.54",
167
- "@revizly/sharp-libvips-linux-x64": "1.0.54",
168
- "@revizly/sharp-linux-arm64": "0.35.0-revizly54",
169
- "@revizly/sharp-linux-x64": "0.35.0-revizly54"
166
+ "@revizly/sharp-libvips-linux-arm64": "1.0.55",
167
+ "@revizly/sharp-libvips-linux-x64": "1.0.55",
168
+ "@revizly/sharp-linux-arm64": "0.35.0-revizly55",
169
+ "@revizly/sharp-linux-x64": "0.35.0-revizly55"
170
170
  },
171
171
  "peerDependenciesMeta": {
172
172
  "@types/node": {
@@ -177,7 +177,7 @@
177
177
  "@biomejs/biome": "^2.5.14",
178
178
  "@cpplint/cli": "^0.1.0",
179
179
  "@emnapi/runtime": "^1.11.3",
180
- "@revizly/sharp-libvips-dev": "1.0.54",
180
+ "@revizly/sharp-libvips-dev": "1.0.55",
181
181
  "@types/node": "*",
182
182
  "emnapi": "^1.11.3",
183
183
  "exif-reader": "^2.0.3",
package/src/pipeline.cc CHANGED
@@ -40,6 +40,7 @@ class PipelineWorker : public Napi::AsyncWorker {
40
40
  // Increment processing task counter
41
41
  sharp::counterProcess++;
42
42
 
43
+ std::pair<char*, size_t> inputProfile(nullptr, 0);
43
44
  try {
44
45
  // Open input
45
46
  vips::VImage image;
@@ -325,7 +326,7 @@ class PipelineWorker : public Napi::AsyncWorker {
325
326
  int gainMapScaleFactor = 1;
326
327
  if (sharp::HasGainMap(image)) {
327
328
  if (baton->keepGainMap) {
328
- gainMap = image.gainmap();
329
+ gainMap = image.gainmap().copy_memory();
329
330
  if (image.get_typeof("gainmap-scale-factor") == G_TYPE_INT) {
330
331
  gainMapScaleFactor = image.get_int("gainmap-scale-factor");
331
332
  }
@@ -378,7 +379,6 @@ class PipelineWorker : public Napi::AsyncWorker {
378
379
  }
379
380
 
380
381
  // Ensure we're using a device-independent colour space
381
- std::pair<char*, size_t> inputProfile(nullptr, 0);
382
382
  if ((baton->keepMetadata & VIPS_FOREIGN_KEEP_ICC) && baton->withIccProfile.empty()) {
383
383
  // Cache input profile for use with output
384
384
  inputProfile = sharp::GetProfile(image);
@@ -481,14 +481,14 @@ class PipelineWorker : public Napi::AsyncWorker {
481
481
  }
482
482
  image = image.rot(autoRotation);
483
483
  if (baton->keepGainMap) {
484
- gainMap = sharp::StaySequential(gainMap).rot(autoRotation);
484
+ gainMap = gainMap.rot(autoRotation);
485
485
  }
486
486
  }
487
487
  // Mirror vertically (up-down) about the x-axis
488
488
  if (baton->flip) {
489
489
  image = image.flip(VIPS_DIRECTION_VERTICAL);
490
490
  if (baton->keepGainMap) {
491
- gainMap = sharp::StaySequential(gainMap).flip(VIPS_DIRECTION_VERTICAL);
491
+ gainMap = gainMap.flip(VIPS_DIRECTION_VERTICAL);
492
492
  }
493
493
  }
494
494
  // Mirror horizontally (left-right) about the y-axis
@@ -505,7 +505,7 @@ class PipelineWorker : public Napi::AsyncWorker {
505
505
  }
506
506
  image = image.rot(rotation);
507
507
  if (baton->keepGainMap) {
508
- gainMap = sharp::StaySequential(gainMap).rot(rotation);
508
+ gainMap = gainMap.rot(rotation);
509
509
  }
510
510
  }
511
511
 
@@ -931,11 +931,8 @@ class PipelineWorker : public Napi::AsyncWorker {
931
931
  image = image.colourspace(baton->colourspace, VImage::option()->set("source_space", image.interpretation()));
932
932
  if (inputProfile.first != nullptr && baton->withIccProfile.empty()) {
933
933
  image = sharp::SetProfile(image, inputProfile);
934
- } else {
935
- g_free(inputProfile.first);
934
+ inputProfile.first = nullptr;
936
935
  }
937
- } else {
938
- g_free(inputProfile.first);
939
936
  }
940
937
 
941
938
  // Extract channel
@@ -945,10 +942,9 @@ class PipelineWorker : public Napi::AsyncWorker {
945
942
  if (baton->extractChannel == 3 && image.has_alpha()) {
946
943
  baton->extractChannel = image.bands() - 1;
947
944
  } else {
948
- (baton->err)
949
- .append("Cannot extract channel ").append(std::to_string(baton->extractChannel))
950
- .append(" from image with channels 0-").append(std::to_string(image.bands() - 1));
951
- return Error();
945
+ throw std::runtime_error(
946
+ std::string("Cannot extract channel ").append(std::to_string(baton->extractChannel))
947
+ .append(" from image with channels 0-").append(std::to_string(image.bands() - 1)));
952
948
  }
953
949
  }
954
950
  VipsInterpretation colourspace = sharp::Is16Bit(image.interpretation())
@@ -1444,6 +1440,8 @@ class PipelineWorker : public Napi::AsyncWorker {
1444
1440
  }
1445
1441
  }
1446
1442
  }
1443
+ g_free(inputProfile.first);
1444
+
1447
1445
  // Clean up libvips' per-request data and threads
1448
1446
  vips_error_clear();
1449
1447
  vips_thread_shutdown();