sharp 0.34.5-rc.1 → 0.35.0-rc.0
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/README.md +1 -1
- package/install/build.js +2 -2
- package/lib/constructor.js +5 -0
- package/lib/index.d.ts +35 -39
- package/lib/input.js +3 -10
- package/lib/operation.js +4 -33
- package/lib/output.js +79 -5
- package/lib/resize.js +16 -0
- package/lib/sharp.js +4 -2
- package/lib/utility.js +1 -1
- package/package.json +40 -47
- package/src/binding.gyp +4 -3
- package/src/common.cc +26 -0
- package/src/common.h +14 -3
- package/src/metadata.cc +14 -4
- package/src/metadata.h +5 -1
- package/src/operations.cc +23 -5
- package/src/operations.h +1 -1
- package/src/pipeline.cc +34 -7
- package/src/pipeline.h +10 -0
- package/src/utilities.cc +3 -2
- package/install/check.js +0 -14
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ smaller, web-friendly JPEG, PNG, WebP, GIF and AVIF images of varying dimensions
|
|
|
8
8
|
|
|
9
9
|
It can be used with all JavaScript runtimes
|
|
10
10
|
that provide support for Node-API v9, including
|
|
11
|
-
Node.js (
|
|
11
|
+
Node.js (>= 20.9.0), Deno and Bun.
|
|
12
12
|
|
|
13
13
|
Resizing an image is typically 4x-5x faster than using the
|
|
14
14
|
quickest ImageMagick and GraphicsMagick settings
|
package/install/build.js
CHANGED
|
@@ -10,7 +10,7 @@ const {
|
|
|
10
10
|
spawnRebuild,
|
|
11
11
|
} = require('../lib/libvips');
|
|
12
12
|
|
|
13
|
-
log('
|
|
13
|
+
log('Building from source');
|
|
14
14
|
log('See https://sharp.pixelplumbing.com/install#building-from-source');
|
|
15
15
|
|
|
16
16
|
try {
|
|
@@ -29,7 +29,7 @@ try {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
if (useGlobalLibvips(log)) {
|
|
32
|
-
log(`
|
|
32
|
+
log(`Found globally-installed libvips v${globalLibvipsVersion()}`);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
const status = spawnRebuild();
|
package/lib/constructor.js
CHANGED
|
@@ -278,6 +278,7 @@ const Sharp = function (input, options) {
|
|
|
278
278
|
trimBackground: [],
|
|
279
279
|
trimThreshold: -1,
|
|
280
280
|
trimLineArt: false,
|
|
281
|
+
trimMargin: 0,
|
|
281
282
|
dilateWidth: 0,
|
|
282
283
|
erodeWidth: 0,
|
|
283
284
|
gamma: 0,
|
|
@@ -306,6 +307,7 @@ const Sharp = function (input, options) {
|
|
|
306
307
|
fileOut: '',
|
|
307
308
|
formatOut: 'input',
|
|
308
309
|
streamOut: false,
|
|
310
|
+
typedArrayOut: false,
|
|
309
311
|
keepMetadata: 0,
|
|
310
312
|
withMetadataOrientation: -1,
|
|
311
313
|
withMetadataDensity: 0,
|
|
@@ -313,6 +315,7 @@ const Sharp = function (input, options) {
|
|
|
313
315
|
withExif: {},
|
|
314
316
|
withExifMerge: true,
|
|
315
317
|
withXmp: '',
|
|
318
|
+
withGainMap: false,
|
|
316
319
|
resolveWithObject: false,
|
|
317
320
|
loop: -1,
|
|
318
321
|
delay: [],
|
|
@@ -348,6 +351,7 @@ const Sharp = function (input, options) {
|
|
|
348
351
|
webpEffort: 4,
|
|
349
352
|
webpMinSize: false,
|
|
350
353
|
webpMixed: false,
|
|
354
|
+
webpExact: false,
|
|
351
355
|
gifBitdepth: 8,
|
|
352
356
|
gifEffort: 7,
|
|
353
357
|
gifDither: 1,
|
|
@@ -375,6 +379,7 @@ const Sharp = function (input, options) {
|
|
|
375
379
|
heifEffort: 4,
|
|
376
380
|
heifChromaSubsampling: '4:4:4',
|
|
377
381
|
heifBitdepth: 8,
|
|
382
|
+
heifTune: 'ssim',
|
|
378
383
|
jxlDistance: 1,
|
|
379
384
|
jxlDecodingTier: 0,
|
|
380
385
|
jxlEffort: 7,
|
package/lib/index.d.ts
CHANGED
|
@@ -259,7 +259,6 @@ declare namespace sharp {
|
|
|
259
259
|
* Set the pipeline colourspace.
|
|
260
260
|
* The input image will be converted to the provided colourspace at the start of the pipeline.
|
|
261
261
|
* All operations will use this colourspace before converting to the output colourspace, as defined by toColourspace.
|
|
262
|
-
* This feature is experimental and has not yet been fully-tested with all operations.
|
|
263
262
|
*
|
|
264
263
|
* @param colourspace pipeline colourspace e.g. rgb16, scrgb, lab, grey16 ...
|
|
265
264
|
* @throws {Error} Invalid parameters
|
|
@@ -470,21 +469,6 @@ declare namespace sharp {
|
|
|
470
469
|
*/
|
|
471
470
|
sharpen(options?: SharpenOptions): Sharp;
|
|
472
471
|
|
|
473
|
-
/**
|
|
474
|
-
* Sharpen the image.
|
|
475
|
-
* When used without parameters, performs a fast, mild sharpen of the output image.
|
|
476
|
-
* When a sigma is provided, performs a slower, more accurate sharpen of the L channel in the LAB colour space.
|
|
477
|
-
* Fine-grained control over the level of sharpening in "flat" (m1) and "jagged" (m2) areas is available.
|
|
478
|
-
* @param sigma the sigma of the Gaussian mask, where sigma = 1 + radius / 2.
|
|
479
|
-
* @param flat the level of sharpening to apply to "flat" areas. (optional, default 1.0)
|
|
480
|
-
* @param jagged the level of sharpening to apply to "jagged" areas. (optional, default 2.0)
|
|
481
|
-
* @throws {Error} Invalid parameters
|
|
482
|
-
* @returns A sharp instance that can be used to chain operations
|
|
483
|
-
*
|
|
484
|
-
* @deprecated Use the object parameter `sharpen({sigma, m1, m2, x1, y2, y3})` instead
|
|
485
|
-
*/
|
|
486
|
-
sharpen(sigma?: number, flat?: number, jagged?: number): Sharp;
|
|
487
|
-
|
|
488
472
|
/**
|
|
489
473
|
* Apply median filter. When used without parameters the default window is 3x3.
|
|
490
474
|
* @param size square mask size: size x size (optional, default 3)
|
|
@@ -693,6 +677,13 @@ declare namespace sharp {
|
|
|
693
677
|
*/
|
|
694
678
|
toBuffer(options: { resolveWithObject: true }): Promise<{ data: Buffer; info: OutputInfo }>;
|
|
695
679
|
|
|
680
|
+
/**
|
|
681
|
+
* Write output to a Uint8Array backed by a transferable ArrayBuffer. JPEG, PNG, WebP, AVIF, TIFF, GIF and RAW output are supported.
|
|
682
|
+
* By default, the format will match the input image, except SVG input which becomes PNG output.
|
|
683
|
+
* @returns A promise that resolves with an object containing the Uint8Array data and an info object containing the output image format, size (bytes), width, height and channels
|
|
684
|
+
*/
|
|
685
|
+
toUint8Array(): Promise<{ data: Uint8Array; info: OutputInfo }>;
|
|
686
|
+
|
|
696
687
|
/**
|
|
697
688
|
* Keep all EXIF metadata from the input image in the output image.
|
|
698
689
|
* EXIF metadata is unsupported for TIFF output.
|
|
@@ -849,7 +840,7 @@ declare namespace sharp {
|
|
|
849
840
|
* @returns A sharp instance that can be used to chain operations
|
|
850
841
|
*/
|
|
851
842
|
toFormat(
|
|
852
|
-
format: keyof FormatEnum | AvailableFormatInfo,
|
|
843
|
+
format: keyof FormatEnum | AvailableFormatInfo | "avif",
|
|
853
844
|
options?:
|
|
854
845
|
| OutputOptions
|
|
855
846
|
| JpegOptions
|
|
@@ -903,7 +894,7 @@ declare namespace sharp {
|
|
|
903
894
|
* - sharp.gravity: north, northeast, east, southeast, south, southwest, west, northwest, center or centre.
|
|
904
895
|
* - sharp.strategy: cover only, dynamically crop using either the entropy or attention strategy. Some of these values are based on the object-position CSS property.
|
|
905
896
|
*
|
|
906
|
-
* The
|
|
897
|
+
* The strategy-based approach resizes so one dimension is at its target length then repeatedly ranks edge regions,
|
|
907
898
|
* discarding the edge with the lowest score based on the selected strategy.
|
|
908
899
|
* - entropy: focus on the region with the highest Shannon entropy.
|
|
909
900
|
* - attention: focus on the region with the highest luminance frequency, colour saturation and presence of skin tones.
|
|
@@ -992,14 +983,6 @@ declare namespace sharp {
|
|
|
992
983
|
* 'none' (least), 'truncated', 'error' or 'warning' (most), highers level imply lower levels, invalid metadata will always abort. (optional, default 'warning')
|
|
993
984
|
*/
|
|
994
985
|
failOn?: FailOnOptions | undefined;
|
|
995
|
-
/**
|
|
996
|
-
* By default halt processing and raise an error when loading invalid images.
|
|
997
|
-
* Set this flag to false if you'd rather apply a "best effort" to decode images,
|
|
998
|
-
* even if the data is corrupt or invalid. (optional, default true)
|
|
999
|
-
*
|
|
1000
|
-
* @deprecated Use `failOn` instead
|
|
1001
|
-
*/
|
|
1002
|
-
failOnError?: boolean | undefined;
|
|
1003
986
|
/**
|
|
1004
987
|
* Do not process input images where the number of pixels (width x height) exceeds this limit.
|
|
1005
988
|
* Assumes image dimensions contained in the input metadata can be trusted.
|
|
@@ -1028,11 +1011,11 @@ declare namespace sharp {
|
|
|
1028
1011
|
openSlide?: OpenSlideInputOptions | undefined;
|
|
1029
1012
|
/** JPEG 2000 specific input options */
|
|
1030
1013
|
jp2?: Jp2InputOptions | undefined;
|
|
1031
|
-
/**
|
|
1014
|
+
/** @deprecated Use {@link SharpOptions.tiff} instead */
|
|
1032
1015
|
subifd?: number | undefined;
|
|
1033
|
-
/**
|
|
1016
|
+
/** @deprecated Use {@link SharpOptions.pdf} instead */
|
|
1034
1017
|
pdfBackground?: Colour | Color | undefined;
|
|
1035
|
-
/**
|
|
1018
|
+
/** @deprecated Use {@link SharpOptions.openSlide} instead */
|
|
1036
1019
|
level?: number | undefined;
|
|
1037
1020
|
/** Set to `true` to read all frames/pages of an animated image (equivalent of setting `pages` to `-1`). (optional, default false) */
|
|
1038
1021
|
animated?: boolean | undefined;
|
|
@@ -1184,6 +1167,8 @@ declare namespace sharp {
|
|
|
1184
1167
|
|
|
1185
1168
|
type HeifCompression = 'av1' | 'hevc';
|
|
1186
1169
|
|
|
1170
|
+
type HeifTune = 'iq' | 'ssim' | 'psnr';
|
|
1171
|
+
|
|
1187
1172
|
type Unit = 'inch' | 'cm';
|
|
1188
1173
|
|
|
1189
1174
|
interface WriteableMetadata {
|
|
@@ -1277,6 +1262,8 @@ declare namespace sharp {
|
|
|
1277
1262
|
formatMagick?: string | undefined;
|
|
1278
1263
|
/** Array of keyword/text pairs representing PNG text blocks, if present. */
|
|
1279
1264
|
comments?: CommentsMetadata[] | undefined;
|
|
1265
|
+
/** HDR gain map, if present */
|
|
1266
|
+
gainMap?: GainMapMetadata | undefined;
|
|
1280
1267
|
}
|
|
1281
1268
|
|
|
1282
1269
|
interface LevelMetadata {
|
|
@@ -1289,16 +1276,21 @@ declare namespace sharp {
|
|
|
1289
1276
|
text: string;
|
|
1290
1277
|
}
|
|
1291
1278
|
|
|
1279
|
+
interface GainMapMetadata {
|
|
1280
|
+
/** JPEG image */
|
|
1281
|
+
image: Buffer;
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1292
1284
|
interface Stats {
|
|
1293
1285
|
/** Array of channel statistics for each channel in the image. */
|
|
1294
1286
|
channels: ChannelStats[];
|
|
1295
1287
|
/** Value to identify if the image is opaque or transparent, based on the presence and use of alpha channel */
|
|
1296
1288
|
isOpaque: boolean;
|
|
1297
|
-
/** Histogram-based estimation of greyscale entropy, discarding alpha channel if any
|
|
1289
|
+
/** Histogram-based estimation of greyscale entropy, discarding alpha channel if any */
|
|
1298
1290
|
entropy: number;
|
|
1299
|
-
/** Estimation of greyscale sharpness based on the standard deviation of a Laplacian convolution, discarding alpha channel if any
|
|
1291
|
+
/** Estimation of greyscale sharpness based on the standard deviation of a Laplacian convolution, discarding alpha channel if any */
|
|
1300
1292
|
sharpness: number;
|
|
1301
|
-
/** Object containing most dominant sRGB colour based on a 4096-bin 3D histogram
|
|
1293
|
+
/** Object containing most dominant sRGB colour based on a 4096-bin 3D histogram */
|
|
1302
1294
|
dominant: { r: number; g: number; b: number };
|
|
1303
1295
|
}
|
|
1304
1296
|
|
|
@@ -1404,11 +1396,13 @@ declare namespace sharp {
|
|
|
1404
1396
|
/** Level of CPU effort to reduce file size, integer 0-6 (optional, default 4) */
|
|
1405
1397
|
effort?: number | undefined;
|
|
1406
1398
|
/** Prevent use of animation key frames to minimise file size (slow) (optional, default false) */
|
|
1407
|
-
minSize?: boolean;
|
|
1399
|
+
minSize?: boolean | undefined;
|
|
1408
1400
|
/** Allow mixture of lossy and lossless animation frames (slow) (optional, default false) */
|
|
1409
|
-
mixed?: boolean;
|
|
1401
|
+
mixed?: boolean | undefined;
|
|
1410
1402
|
/** Preset options: one of default, photo, picture, drawing, icon, text (optional, default 'default') */
|
|
1411
1403
|
preset?: keyof PresetEnum | undefined;
|
|
1404
|
+
/** Preserve the colour data in transparent pixels (optional, default false) */
|
|
1405
|
+
exact?: boolean | undefined;
|
|
1412
1406
|
}
|
|
1413
1407
|
|
|
1414
1408
|
interface AvifOptions extends OutputOptions {
|
|
@@ -1422,6 +1416,8 @@ declare namespace sharp {
|
|
|
1422
1416
|
chromaSubsampling?: string | undefined;
|
|
1423
1417
|
/** Set bitdepth to 8, 10 or 12 bit (optional, default 8) */
|
|
1424
1418
|
bitdepth?: 8 | 10 | 12 | undefined;
|
|
1419
|
+
/** Tune output for a quality metric, one of 'iq', 'ssim' or 'psnr' (optional, default 'iq') */
|
|
1420
|
+
tune?: HeifTune | undefined;
|
|
1425
1421
|
}
|
|
1426
1422
|
|
|
1427
1423
|
interface HeifOptions extends OutputOptions {
|
|
@@ -1437,6 +1433,8 @@ declare namespace sharp {
|
|
|
1437
1433
|
chromaSubsampling?: string | undefined;
|
|
1438
1434
|
/** Set bitdepth to 8, 10 or 12 bit (optional, default 8) */
|
|
1439
1435
|
bitdepth?: 8 | 10 | 12 | undefined;
|
|
1436
|
+
/** Tune output for a quality metric, one of 'ssim', 'psnr' or 'iq' (optional, default 'ssim') */
|
|
1437
|
+
tune?: HeifTune | undefined;
|
|
1440
1438
|
}
|
|
1441
1439
|
|
|
1442
1440
|
interface GifOptions extends OutputOptions, AnimationOptions {
|
|
@@ -1608,6 +1606,8 @@ declare namespace sharp {
|
|
|
1608
1606
|
threshold?: number | undefined;
|
|
1609
1607
|
/** Does the input more closely resemble line art (e.g. vector) rather than being photographic? (optional, default false) */
|
|
1610
1608
|
lineArt?: boolean | undefined;
|
|
1609
|
+
/** Leave a margin around trimmed content, value is in pixels. (optional, default 0) */
|
|
1610
|
+
margin?: number | undefined;
|
|
1611
1611
|
}
|
|
1612
1612
|
|
|
1613
1613
|
interface RawOptions {
|
|
@@ -1913,16 +1913,13 @@ declare namespace sharp {
|
|
|
1913
1913
|
}
|
|
1914
1914
|
|
|
1915
1915
|
interface FormatEnum {
|
|
1916
|
-
avif: AvailableFormatInfo;
|
|
1917
1916
|
dcraw: AvailableFormatInfo;
|
|
1918
1917
|
dz: AvailableFormatInfo;
|
|
1919
1918
|
exr: AvailableFormatInfo;
|
|
1920
1919
|
fits: AvailableFormatInfo;
|
|
1921
1920
|
gif: AvailableFormatInfo;
|
|
1922
1921
|
heif: AvailableFormatInfo;
|
|
1923
|
-
input: AvailableFormatInfo;
|
|
1924
1922
|
jpeg: AvailableFormatInfo;
|
|
1925
|
-
jpg: AvailableFormatInfo;
|
|
1926
1923
|
jp2: AvailableFormatInfo;
|
|
1927
1924
|
jxl: AvailableFormatInfo;
|
|
1928
1925
|
magick: AvailableFormatInfo;
|
|
@@ -1934,8 +1931,7 @@ declare namespace sharp {
|
|
|
1934
1931
|
raw: AvailableFormatInfo;
|
|
1935
1932
|
svg: AvailableFormatInfo;
|
|
1936
1933
|
tiff: AvailableFormatInfo;
|
|
1937
|
-
|
|
1938
|
-
v: AvailableFormatInfo;
|
|
1934
|
+
vips: AvailableFormatInfo;
|
|
1939
1935
|
webp: AvailableFormatInfo;
|
|
1940
1936
|
}
|
|
1941
1937
|
|
package/lib/input.js
CHANGED
|
@@ -30,7 +30,7 @@ const inputStreamParameters = [
|
|
|
30
30
|
// Format-specific
|
|
31
31
|
'jp2', 'openSlide', 'pdf', 'raw', 'svg', 'tiff',
|
|
32
32
|
// Deprecated
|
|
33
|
-
'
|
|
33
|
+
'openSlideLevel', 'pdfBackground', 'tiffSubifd'
|
|
34
34
|
];
|
|
35
35
|
|
|
36
36
|
/**
|
|
@@ -106,14 +106,6 @@ function _createInputDescriptor (input, inputOptions, containerOptions) {
|
|
|
106
106
|
}`);
|
|
107
107
|
}
|
|
108
108
|
if (is.object(inputOptions)) {
|
|
109
|
-
// Deprecated: failOnError
|
|
110
|
-
if (is.defined(inputOptions.failOnError)) {
|
|
111
|
-
if (is.bool(inputOptions.failOnError)) {
|
|
112
|
-
inputDescriptor.failOn = inputOptions.failOnError ? 'warning' : 'none';
|
|
113
|
-
} else {
|
|
114
|
-
throw is.invalidParameterError('failOnError', 'boolean', inputOptions.failOnError);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
109
|
// failOn
|
|
118
110
|
if (is.defined(inputOptions.failOn)) {
|
|
119
111
|
if (is.string(inputOptions.failOn) && is.inArray(inputOptions.failOn, ['none', 'truncated', 'error', 'warning'])) {
|
|
@@ -574,7 +566,7 @@ function _isStreamInput () {
|
|
|
574
566
|
*
|
|
575
567
|
* A `Promise` is returned when `callback` is not provided.
|
|
576
568
|
*
|
|
577
|
-
* - `format`: Name of decoder used to
|
|
569
|
+
* - `format`: Name of decoder used to parse image e.g. `jpeg`, `png`, `webp`, `gif`, `svg`, `heif`, `tiff`
|
|
578
570
|
* - `size`: Total size of image in bytes, for Stream and Buffer input only
|
|
579
571
|
* - `width`: Number of pixels wide (EXIF orientation is not taken into consideration, see example below)
|
|
580
572
|
* - `height`: Number of pixels high (EXIF orientation is not taken into consideration, see example below)
|
|
@@ -607,6 +599,7 @@ function _isStreamInput () {
|
|
|
607
599
|
* - `tifftagPhotoshop`: Buffer containing raw TIFFTAG_PHOTOSHOP data, if present
|
|
608
600
|
* - `formatMagick`: String containing format for images loaded via *magick
|
|
609
601
|
* - `comments`: Array of keyword/text pairs representing PNG text blocks, if present.
|
|
602
|
+
* - `gainMap.image`: HDR gain map, if present, as compressed JPEG image.
|
|
610
603
|
*
|
|
611
604
|
* @example
|
|
612
605
|
* const metadata = await sharp(input).metadata();
|
package/lib/operation.js
CHANGED
|
@@ -259,45 +259,18 @@ function affine (matrix, options) {
|
|
|
259
259
|
* })
|
|
260
260
|
* .toBuffer();
|
|
261
261
|
*
|
|
262
|
-
* @param {Object
|
|
262
|
+
* @param {Object} [options] - if present, is an Object with attributes
|
|
263
263
|
* @param {number} [options.sigma] - the sigma of the Gaussian mask, where `sigma = 1 + radius / 2`, between 0.000001 and 10
|
|
264
264
|
* @param {number} [options.m1=1.0] - the level of sharpening to apply to "flat" areas, between 0 and 1000000
|
|
265
265
|
* @param {number} [options.m2=2.0] - the level of sharpening to apply to "jagged" areas, between 0 and 1000000
|
|
266
266
|
* @param {number} [options.x1=2.0] - threshold between "flat" and "jagged", between 0 and 1000000
|
|
267
267
|
* @param {number} [options.y2=10.0] - maximum amount of brightening, between 0 and 1000000
|
|
268
268
|
* @param {number} [options.y3=20.0] - maximum amount of darkening, between 0 and 1000000
|
|
269
|
-
* @param {number} [flat] - (deprecated) see `options.m1`.
|
|
270
|
-
* @param {number} [jagged] - (deprecated) see `options.m2`.
|
|
271
269
|
* @returns {Sharp}
|
|
272
270
|
* @throws {Error} Invalid parameters
|
|
273
271
|
*/
|
|
274
|
-
function sharpen (options
|
|
275
|
-
if (
|
|
276
|
-
// No arguments: default to mild sharpen
|
|
277
|
-
this.options.sharpenSigma = -1;
|
|
278
|
-
} else if (is.bool(options)) {
|
|
279
|
-
// Deprecated boolean argument: apply mild sharpen?
|
|
280
|
-
this.options.sharpenSigma = options ? -1 : 0;
|
|
281
|
-
} else if (is.number(options) && is.inRange(options, 0.01, 10000)) {
|
|
282
|
-
// Deprecated numeric argument: specific sigma
|
|
283
|
-
this.options.sharpenSigma = options;
|
|
284
|
-
// Deprecated control over flat areas
|
|
285
|
-
if (is.defined(flat)) {
|
|
286
|
-
if (is.number(flat) && is.inRange(flat, 0, 10000)) {
|
|
287
|
-
this.options.sharpenM1 = flat;
|
|
288
|
-
} else {
|
|
289
|
-
throw is.invalidParameterError('flat', 'number between 0 and 10000', flat);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
// Deprecated control over jagged areas
|
|
293
|
-
if (is.defined(jagged)) {
|
|
294
|
-
if (is.number(jagged) && is.inRange(jagged, 0, 10000)) {
|
|
295
|
-
this.options.sharpenM2 = jagged;
|
|
296
|
-
} else {
|
|
297
|
-
throw is.invalidParameterError('jagged', 'number between 0 and 10000', jagged);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
} else if (is.plainObject(options)) {
|
|
272
|
+
function sharpen (options) {
|
|
273
|
+
if (is.plainObject(options)) {
|
|
301
274
|
if (is.number(options.sigma) && is.inRange(options.sigma, 0.000001, 10)) {
|
|
302
275
|
this.options.sharpenSigma = options.sigma;
|
|
303
276
|
} else {
|
|
@@ -339,7 +312,7 @@ function sharpen (options, flat, jagged) {
|
|
|
339
312
|
}
|
|
340
313
|
}
|
|
341
314
|
} else {
|
|
342
|
-
|
|
315
|
+
this.options.sharpenSigma = -1;
|
|
343
316
|
}
|
|
344
317
|
return this;
|
|
345
318
|
}
|
|
@@ -510,8 +483,6 @@ function flatten (options) {
|
|
|
510
483
|
*
|
|
511
484
|
* Existing alpha channel values for non-white pixels remain unchanged.
|
|
512
485
|
*
|
|
513
|
-
* This feature is experimental and the API may change.
|
|
514
|
-
*
|
|
515
486
|
* @since 0.32.1
|
|
516
487
|
*
|
|
517
488
|
* @example
|
package/lib/output.js
CHANGED
|
@@ -76,7 +76,7 @@ function toFile (fileOut, callback) {
|
|
|
76
76
|
err = new Error('Missing output file path');
|
|
77
77
|
} else if (is.string(this.options.input.file) && path.resolve(this.options.input.file) === path.resolve(fileOut)) {
|
|
78
78
|
err = new Error('Cannot use same file for input and output');
|
|
79
|
-
} else if (jp2Regex.test(path.extname(fileOut)) && !this.constructor.format.
|
|
79
|
+
} else if (jp2Regex.test(path.extname(fileOut)) && !this.constructor.format.jp2.output.file) {
|
|
80
80
|
err = errJp2Save();
|
|
81
81
|
}
|
|
82
82
|
if (err) {
|
|
@@ -164,6 +164,41 @@ function toBuffer (options, callback) {
|
|
|
164
164
|
return this._pipeline(is.fn(options) ? options : callback, stack);
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
+
/**
|
|
168
|
+
* Write output to a `Uint8Array` backed by a transferable `ArrayBuffer`.
|
|
169
|
+
* JPEG, PNG, WebP, AVIF, TIFF, GIF and raw pixel data output are supported.
|
|
170
|
+
*
|
|
171
|
+
* Use {@link #toformat toFormat} or one of the format-specific functions such as {@link #jpeg jpeg}, {@link #png png} etc. to set the output format.
|
|
172
|
+
*
|
|
173
|
+
* If no explicit format is set, the output format will match the input image, except SVG input which becomes PNG output.
|
|
174
|
+
*
|
|
175
|
+
* By default all metadata will be removed, which includes EXIF-based orientation.
|
|
176
|
+
* See {@link #keepexif keepExif} and similar methods for control over this.
|
|
177
|
+
*
|
|
178
|
+
* Resolves with an `Object` containing:
|
|
179
|
+
* - `data` is the output image as a `Uint8Array` backed by a transferable `ArrayBuffer`.
|
|
180
|
+
* - `info` contains properties relating to the output image such as `width` and `height`.
|
|
181
|
+
*
|
|
182
|
+
* @since v0.35.0
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* const { data, info } = await sharp(input).toUint8Array();
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* const { data } = await sharp(input)
|
|
189
|
+
* .avif()
|
|
190
|
+
* .toUint8Array();
|
|
191
|
+
* const base64String = data.toBase64();
|
|
192
|
+
*
|
|
193
|
+
* @returns {Promise<{ data: Uint8Array, info: Object }>}
|
|
194
|
+
*/
|
|
195
|
+
function toUint8Array () {
|
|
196
|
+
this.options.resolveWithObject = true;
|
|
197
|
+
this.options.typedArrayOut = true;
|
|
198
|
+
const stack = Error();
|
|
199
|
+
return this._pipeline(null, stack);
|
|
200
|
+
}
|
|
201
|
+
|
|
167
202
|
/**
|
|
168
203
|
* Keep all EXIF metadata from the input image in the output image.
|
|
169
204
|
*
|
|
@@ -319,6 +354,30 @@ function withIccProfile (icc, options) {
|
|
|
319
354
|
return this;
|
|
320
355
|
}
|
|
321
356
|
|
|
357
|
+
/**
|
|
358
|
+
* If the input contains gain map metadata, use it to convert the main image to HDR (High Dynamic Range) before further processing.
|
|
359
|
+
* The input gain map is discarded.
|
|
360
|
+
*
|
|
361
|
+
* If the output is JPEG, generate and attach a new ISO 21496-1 gain map.
|
|
362
|
+
* JPEG output options other than `quality` are ignored.
|
|
363
|
+
*
|
|
364
|
+
* This feature is experimental and the API may change.
|
|
365
|
+
*
|
|
366
|
+
* @since 0.35.0
|
|
367
|
+
*
|
|
368
|
+
* @example
|
|
369
|
+
* const outputWithGainMap = await sharp(inputWithGainMap)
|
|
370
|
+
* .withGainMap()
|
|
371
|
+
* .toBuffer();
|
|
372
|
+
*
|
|
373
|
+
* @returns {Sharp}
|
|
374
|
+
*/
|
|
375
|
+
function withGainMap() {
|
|
376
|
+
this.options.withGainMap = true;
|
|
377
|
+
this.options.colourspace = 'scrgb';
|
|
378
|
+
return this;
|
|
379
|
+
}
|
|
380
|
+
|
|
322
381
|
/**
|
|
323
382
|
* Keep XMP metadata from the input image in the output image.
|
|
324
383
|
*
|
|
@@ -690,6 +749,7 @@ function png (options) {
|
|
|
690
749
|
* @param {number|number[]} [options.delay] - delay(s) between animation frames (in milliseconds)
|
|
691
750
|
* @param {boolean} [options.minSize=false] - prevent use of animation key frames to minimise file size (slow)
|
|
692
751
|
* @param {boolean} [options.mixed=false] - allow mixture of lossy and lossless animation frames (slow)
|
|
752
|
+
* @param {boolean} [options.exact=false] - preserve the colour data in transparent pixels
|
|
693
753
|
* @param {boolean} [options.force=true] - force WebP output, otherwise attempt to use input format
|
|
694
754
|
* @returns {Sharp}
|
|
695
755
|
* @throws {Error} Invalid options
|
|
@@ -742,6 +802,9 @@ function webp (options) {
|
|
|
742
802
|
if (is.defined(options.mixed)) {
|
|
743
803
|
this._setBooleanOption('webpMixed', options.mixed);
|
|
744
804
|
}
|
|
805
|
+
if (is.defined(options.exact)) {
|
|
806
|
+
this._setBooleanOption('webpExact', options.exact);
|
|
807
|
+
}
|
|
745
808
|
}
|
|
746
809
|
trySetAnimationOptions(options, this.options);
|
|
747
810
|
return this._updateFormatOut('webp', options);
|
|
@@ -887,7 +950,7 @@ function gif (options) {
|
|
|
887
950
|
*/
|
|
888
951
|
function jp2 (options) {
|
|
889
952
|
/* node:coverage ignore next 41 */
|
|
890
|
-
if (!this.constructor.format.
|
|
953
|
+
if (!this.constructor.format.jp2.output.buffer) {
|
|
891
954
|
throw errJp2Save();
|
|
892
955
|
}
|
|
893
956
|
if (is.object(options)) {
|
|
@@ -1092,8 +1155,7 @@ function tiff (options) {
|
|
|
1092
1155
|
* AVIF image sequences are not supported.
|
|
1093
1156
|
* Prebuilt binaries support a bitdepth of 8 only.
|
|
1094
1157
|
*
|
|
1095
|
-
*
|
|
1096
|
-
* and requires a CPU with ARM64v8.4 or later.
|
|
1158
|
+
* When using Windows ARM64, this feature requires a CPU with ARM64v8.4 or later.
|
|
1097
1159
|
*
|
|
1098
1160
|
* @example
|
|
1099
1161
|
* const data = await sharp(input)
|
|
@@ -1113,11 +1175,13 @@ function tiff (options) {
|
|
|
1113
1175
|
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
|
|
1114
1176
|
* @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
|
|
1115
1177
|
* @param {number} [options.bitdepth=8] - set bitdepth to 8, 10 or 12 bit
|
|
1178
|
+
* @param {string} [options.tune='iq'] - tune output for a quality metric, one of 'iq' (default), 'ssim' or 'psnr'
|
|
1116
1179
|
* @returns {Sharp}
|
|
1117
1180
|
* @throws {Error} Invalid options
|
|
1118
1181
|
*/
|
|
1119
1182
|
function avif (options) {
|
|
1120
|
-
|
|
1183
|
+
const tune = is.object(options) && is.defined(options.tune) ? options.tune : 'iq';
|
|
1184
|
+
return this.heif({ ...options, compression: 'av1', tune });
|
|
1121
1185
|
}
|
|
1122
1186
|
|
|
1123
1187
|
/**
|
|
@@ -1140,6 +1204,7 @@ function avif (options) {
|
|
|
1140
1204
|
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
|
|
1141
1205
|
* @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
|
|
1142
1206
|
* @param {number} [options.bitdepth=8] - set bitdepth to 8, 10 or 12 bit
|
|
1207
|
+
* @param {string} [options.tune='ssim'] - tune output for a quality metric, one of 'ssim' (default), 'psnr' or 'iq'
|
|
1143
1208
|
* @returns {Sharp}
|
|
1144
1209
|
* @throws {Error} Invalid options
|
|
1145
1210
|
*/
|
|
@@ -1188,6 +1253,13 @@ function heif (options) {
|
|
|
1188
1253
|
throw is.invalidParameterError('bitdepth', '8, 10 or 12', options.bitdepth);
|
|
1189
1254
|
}
|
|
1190
1255
|
}
|
|
1256
|
+
if (is.defined(options.tune)) {
|
|
1257
|
+
if (is.string(options.tune) && is.inArray(options.tune, ['iq', 'ssim', 'psnr'])) {
|
|
1258
|
+
this.options.heifTune = options.tune;
|
|
1259
|
+
} else {
|
|
1260
|
+
throw is.invalidParameterError('tune', 'one of: psnr, ssim, iq', options.tune);
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1191
1263
|
} else {
|
|
1192
1264
|
throw is.invalidParameterError('options', 'Object', options);
|
|
1193
1265
|
}
|
|
@@ -1635,11 +1707,13 @@ module.exports = (Sharp) => {
|
|
|
1635
1707
|
// Public
|
|
1636
1708
|
toFile,
|
|
1637
1709
|
toBuffer,
|
|
1710
|
+
toUint8Array,
|
|
1638
1711
|
keepExif,
|
|
1639
1712
|
withExif,
|
|
1640
1713
|
withExifMerge,
|
|
1641
1714
|
keepIccProfile,
|
|
1642
1715
|
withIccProfile,
|
|
1716
|
+
withGainMap,
|
|
1643
1717
|
keepXmp,
|
|
1644
1718
|
withXmp,
|
|
1645
1719
|
keepMetadata,
|
package/lib/resize.js
CHANGED
|
@@ -540,10 +540,19 @@ function extract (options) {
|
|
|
540
540
|
* })
|
|
541
541
|
* .toBuffer();
|
|
542
542
|
*
|
|
543
|
+
* @example
|
|
544
|
+
* // Trim image leaving (up to) a 10 pixel margin around the trimmed content.
|
|
545
|
+
* const output = await sharp(input)
|
|
546
|
+
* .trim({
|
|
547
|
+
* margin: 10
|
|
548
|
+
* })
|
|
549
|
+
* .toBuffer();
|
|
550
|
+
*
|
|
543
551
|
* @param {Object} [options]
|
|
544
552
|
* @param {string|Object} [options.background='top-left pixel'] - Background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to that of the top-left pixel.
|
|
545
553
|
* @param {number} [options.threshold=10] - Allowed difference from the above colour, a positive number.
|
|
546
554
|
* @param {boolean} [options.lineArt=false] - Does the input more closely resemble line art (e.g. vector) rather than being photographic?
|
|
555
|
+
* @param {number} [options.margin=0] - Leave a margin around trimmed content, value is in pixels.
|
|
547
556
|
* @returns {Sharp}
|
|
548
557
|
* @throws {Error} Invalid parameters
|
|
549
558
|
*/
|
|
@@ -564,6 +573,13 @@ function trim (options) {
|
|
|
564
573
|
if (is.defined(options.lineArt)) {
|
|
565
574
|
this._setBooleanOption('trimLineArt', options.lineArt);
|
|
566
575
|
}
|
|
576
|
+
if (is.defined(options.margin)) {
|
|
577
|
+
if (is.integer(options.margin) && options.margin >= 0) {
|
|
578
|
+
this.options.trimMargin = options.margin;
|
|
579
|
+
} else {
|
|
580
|
+
throw is.invalidParameterError('margin', 'positive integer', options.margin);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
567
583
|
} else {
|
|
568
584
|
throw is.invalidParameterError('trim', 'object', options);
|
|
569
585
|
}
|
package/lib/sharp.js
CHANGED
|
@@ -7,12 +7,13 @@
|
|
|
7
7
|
|
|
8
8
|
const { familySync, versionSync } = require('detect-libc');
|
|
9
9
|
|
|
10
|
+
const { version } = require('../package.json');
|
|
10
11
|
const { runtimePlatformArch, isUnsupportedNodeRuntime, prebuiltPlatforms, minimumLibvipsVersion } = require('./libvips');
|
|
11
12
|
const runtimePlatform = runtimePlatformArch();
|
|
12
13
|
|
|
13
14
|
const paths = [
|
|
14
|
-
`../src/build/Release/sharp-${runtimePlatform}.node`,
|
|
15
|
-
|
|
15
|
+
`../src/build/Release/sharp-${runtimePlatform}-${version}.node`,
|
|
16
|
+
`../src/build/Release/sharp-wasm32-${version}.node`,
|
|
16
17
|
`@img/sharp-${runtimePlatform}/sharp.node`,
|
|
17
18
|
'@img/sharp-wasm32/sharp.node'
|
|
18
19
|
];
|
|
@@ -72,6 +73,7 @@ if (sharp) {
|
|
|
72
73
|
} else {
|
|
73
74
|
help.push(
|
|
74
75
|
`- Manually install libvips >= ${minimumLibvipsVersion}`,
|
|
76
|
+
' See https://sharp.pixelplumbing.com/install#building-from-source',
|
|
75
77
|
'- Add experimental WebAssembly-based dependencies:',
|
|
76
78
|
' npm install --cpu=wasm32 sharp',
|
|
77
79
|
' npm install @img/sharp-wasm32'
|
package/lib/utility.js
CHANGED
|
@@ -24,7 +24,7 @@ const format = sharp.format();
|
|
|
24
24
|
format.heif.output.alias = ['avif', 'heic'];
|
|
25
25
|
format.jpeg.output.alias = ['jpe', 'jpg'];
|
|
26
26
|
format.tiff.output.alias = ['tif'];
|
|
27
|
-
format.
|
|
27
|
+
format.jp2.output.alias = ['j2c', 'j2k', 'jp2', 'jpx'];
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* An Object containing the available interpolators and their proper values
|
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.
|
|
4
|
+
"version": "0.35.0-rc.0",
|
|
5
5
|
"author": "Lovell Fuller <npm@lovell.info>",
|
|
6
6
|
"homepage": "https://sharp.pixelplumbing.com",
|
|
7
7
|
"contributors": [
|
|
@@ -89,12 +89,12 @@
|
|
|
89
89
|
"Lachlan Newman <lachnewman007@gmail.com>",
|
|
90
90
|
"Dennis Beatty <dennis@dcbeatty.com>",
|
|
91
91
|
"Ingvar Stepanyan <me@rreverser.com>",
|
|
92
|
-
"Don Denton <don@happycollision.com>"
|
|
92
|
+
"Don Denton <don@happycollision.com>",
|
|
93
|
+
"Dmytro Tiapukhin <cool.gegeg@gmail.com>"
|
|
93
94
|
],
|
|
94
95
|
"scripts": {
|
|
95
96
|
"build": "node install/build.js",
|
|
96
|
-
"
|
|
97
|
-
"clean": "rm -rf src/build/ .nyc_output/ coverage/ test/fixtures/output.*",
|
|
97
|
+
"clean": "rm -rf src/build/ test/fixtures/output.*",
|
|
98
98
|
"test": "npm run lint && npm run test-unit",
|
|
99
99
|
"lint": "npm run lint-cpp && npm run lint-js && npm run lint-types",
|
|
100
100
|
"lint-cpp": "cpplint --quiet src/*.h src/*.cc",
|
|
@@ -144,65 +144,58 @@
|
|
|
144
144
|
"semver": "^7.7.3"
|
|
145
145
|
},
|
|
146
146
|
"optionalDependencies": {
|
|
147
|
-
"@img/sharp-darwin-arm64": "0.
|
|
148
|
-
"@img/sharp-darwin-x64": "0.
|
|
149
|
-
"@img/sharp-libvips-darwin-arm64": "1.2
|
|
150
|
-
"@img/sharp-libvips-darwin-x64": "1.2
|
|
151
|
-
"@img/sharp-libvips-linux-arm": "1.2
|
|
152
|
-
"@img/sharp-libvips-linux-arm64": "1.2
|
|
153
|
-
"@img/sharp-libvips-linux-ppc64": "1.2
|
|
154
|
-
"@img/sharp-libvips-linux-riscv64": "1.2
|
|
155
|
-
"@img/sharp-libvips-linux-s390x": "1.2
|
|
156
|
-
"@img/sharp-libvips-linux-x64": "1.2
|
|
157
|
-
"@img/sharp-libvips-linuxmusl-arm64": "1.2
|
|
158
|
-
"@img/sharp-libvips-linuxmusl-x64": "1.2
|
|
159
|
-
"@img/sharp-linux-arm": "0.
|
|
160
|
-
"@img/sharp-linux-arm64": "0.
|
|
161
|
-
"@img/sharp-linux-ppc64": "0.
|
|
162
|
-
"@img/sharp-linux-riscv64": "0.
|
|
163
|
-
"@img/sharp-linux-s390x": "0.
|
|
164
|
-
"@img/sharp-linux-x64": "0.
|
|
165
|
-
"@img/sharp-linuxmusl-arm64": "0.
|
|
166
|
-
"@img/sharp-linuxmusl-x64": "0.
|
|
167
|
-
"@img/sharp-wasm32": "0.
|
|
168
|
-
"@img/sharp-win32-arm64": "0.
|
|
169
|
-
"@img/sharp-win32-ia32": "0.
|
|
170
|
-
"@img/sharp-win32-x64": "0.
|
|
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"
|
|
171
171
|
},
|
|
172
172
|
"devDependencies": {
|
|
173
|
-
"@biomejs/biome": "^2.3.
|
|
173
|
+
"@biomejs/biome": "^2.3.10",
|
|
174
174
|
"@cpplint/cli": "^0.1.0",
|
|
175
|
-
"@emnapi/runtime": "^1.7.
|
|
176
|
-
"@img/sharp-libvips-dev": "1.2
|
|
177
|
-
"@img/sharp-libvips-dev-wasm32": "1.2
|
|
178
|
-
"@img/sharp-libvips-win32-arm64": "1.2
|
|
179
|
-
"@img/sharp-libvips-win32-ia32": "1.2
|
|
180
|
-
"@img/sharp-libvips-win32-x64": "1.2
|
|
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",
|
|
181
181
|
"@types/node": "*",
|
|
182
|
-
"emnapi": "^1.7.
|
|
183
|
-
"exif-reader": "^2.0.
|
|
182
|
+
"emnapi": "^1.7.1",
|
|
183
|
+
"exif-reader": "^2.0.3",
|
|
184
184
|
"extract-zip": "^2.0.1",
|
|
185
185
|
"icc": "^3.0.0",
|
|
186
|
-
"jsdoc-to-markdown": "^9.1.3",
|
|
187
186
|
"node-addon-api": "^8.5.0",
|
|
188
|
-
"node-gyp": "^
|
|
187
|
+
"node-gyp": "^12.1.0",
|
|
189
188
|
"tar-fs": "^3.1.1",
|
|
190
189
|
"tsd": "^0.33.0"
|
|
191
190
|
},
|
|
192
191
|
"license": "Apache-2.0",
|
|
193
192
|
"engines": {
|
|
194
|
-
"node": "
|
|
193
|
+
"node": ">=20.9.0"
|
|
195
194
|
},
|
|
196
195
|
"config": {
|
|
197
|
-
"libvips": ">=8.
|
|
196
|
+
"libvips": ">=8.18.0"
|
|
198
197
|
},
|
|
199
198
|
"funding": {
|
|
200
199
|
"url": "https://opencollective.com/libvips"
|
|
201
|
-
},
|
|
202
|
-
"cc": {
|
|
203
|
-
"linelength": "120",
|
|
204
|
-
"filter": [
|
|
205
|
-
"build/include"
|
|
206
|
-
]
|
|
207
200
|
}
|
|
208
201
|
}
|
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_version': '<!(node -p "require(\'../package.json\').version")',
|
|
8
9
|
'sharp_libvips_version': '<!(node -p "require(\'../package.json\').optionalDependencies[\'@img/sharp-libvips-<(platform_and_arch)\']")',
|
|
9
10
|
'sharp_libvips_yarn_locator': '<!(node -p "require(\'../lib/libvips\').yarnLocator()")',
|
|
10
11
|
'sharp_libvips_include_dir': '<!(node -p "require(\'../lib/libvips\').buildSharpLibvipsIncludeDir()")',
|
|
@@ -81,7 +82,7 @@
|
|
|
81
82
|
}]
|
|
82
83
|
]
|
|
83
84
|
}, {
|
|
84
|
-
'target_name': 'sharp-<(platform_and_arch)',
|
|
85
|
+
'target_name': 'sharp-<(platform_and_arch)-<(sharp_version)',
|
|
85
86
|
'defines': [
|
|
86
87
|
'G_DISABLE_ASSERT',
|
|
87
88
|
'G_DISABLE_CAST_CHECKS',
|
|
@@ -120,7 +121,7 @@
|
|
|
120
121
|
'conditions': [
|
|
121
122
|
['use_global_libvips == "true"', {
|
|
122
123
|
# Use pkg-config for include and lib
|
|
123
|
-
'include_dirs': ['<!@(PKG_CONFIG_PATH="<(pkg_config_path)" pkg-config --cflags-only-I vips-cpp vips glib-2.0 | sed s
|
|
124
|
+
'include_dirs': ['<!@(PKG_CONFIG_PATH="<(pkg_config_path)" pkg-config --cflags-only-I vips-cpp vips glib-2.0 | sed s/-I//g)'],
|
|
124
125
|
'libraries': ['<!@(PKG_CONFIG_PATH="<(pkg_config_path)" pkg-config --libs vips-cpp)'],
|
|
125
126
|
'defines': [
|
|
126
127
|
'SHARP_USE_GLOBAL_LIBVIPS'
|
|
@@ -282,7 +283,7 @@
|
|
|
282
283
|
'target_name': 'copy-dll',
|
|
283
284
|
'type': 'none',
|
|
284
285
|
'dependencies': [
|
|
285
|
-
'sharp-<(platform_and_arch)'
|
|
286
|
+
'sharp-<(platform_and_arch)-<(sharp_version)'
|
|
286
287
|
],
|
|
287
288
|
'conditions': [
|
|
288
289
|
['OS == "win"', {
|
package/src/common.cc
CHANGED
|
@@ -289,6 +289,7 @@ namespace sharp {
|
|
|
289
289
|
case ImageType::JXL: id = "jxl"; break;
|
|
290
290
|
case ImageType::RAD: id = "rad"; break;
|
|
291
291
|
case ImageType::DCRAW: id = "dcraw"; break;
|
|
292
|
+
case ImageType::UHDR: id = "uhdr"; break;
|
|
292
293
|
case ImageType::VIPS: id = "vips"; break;
|
|
293
294
|
case ImageType::RAW: id = "raw"; break;
|
|
294
295
|
case ImageType::UNKNOWN: id = "unknown"; break;
|
|
@@ -339,6 +340,9 @@ namespace sharp {
|
|
|
339
340
|
{ "VipsForeignLoadRadBuffer", ImageType::RAD },
|
|
340
341
|
{ "VipsForeignLoadDcRawFile", ImageType::DCRAW },
|
|
341
342
|
{ "VipsForeignLoadDcRawBuffer", ImageType::DCRAW },
|
|
343
|
+
{ "VipsForeignLoadUhdr", ImageType::UHDR },
|
|
344
|
+
{ "VipsForeignLoadUhdrFile", ImageType::UHDR },
|
|
345
|
+
{ "VipsForeignLoadUhdrBuffer", ImageType::UHDR },
|
|
342
346
|
{ "VipsForeignLoadVips", ImageType::VIPS },
|
|
343
347
|
{ "VipsForeignLoadVipsFile", ImageType::VIPS },
|
|
344
348
|
{ "VipsForeignLoadRaw", ImageType::RAW }
|
|
@@ -356,6 +360,9 @@ namespace sharp {
|
|
|
356
360
|
imageType = it->second;
|
|
357
361
|
}
|
|
358
362
|
}
|
|
363
|
+
if (imageType == ImageType::UHDR) {
|
|
364
|
+
imageType = ImageType::JPEG;
|
|
365
|
+
}
|
|
359
366
|
return imageType;
|
|
360
367
|
}
|
|
361
368
|
|
|
@@ -375,6 +382,9 @@ namespace sharp {
|
|
|
375
382
|
imageType = ImageType::MISSING;
|
|
376
383
|
}
|
|
377
384
|
}
|
|
385
|
+
if (imageType == ImageType::UHDR) {
|
|
386
|
+
imageType = ImageType::JPEG;
|
|
387
|
+
}
|
|
378
388
|
return imageType;
|
|
379
389
|
}
|
|
380
390
|
|
|
@@ -1127,4 +1137,20 @@ namespace sharp {
|
|
|
1127
1137
|
}
|
|
1128
1138
|
return image;
|
|
1129
1139
|
}
|
|
1140
|
+
|
|
1141
|
+
/*
|
|
1142
|
+
Does this image have a gain map?
|
|
1143
|
+
*/
|
|
1144
|
+
bool HasGainMap(VImage image) {
|
|
1145
|
+
return image.get_typeof("gainmap-data") == VIPS_TYPE_BLOB;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
/*
|
|
1149
|
+
Removes gain map, if any.
|
|
1150
|
+
*/
|
|
1151
|
+
VImage RemoveGainMap(VImage image) {
|
|
1152
|
+
VImage copy = image.copy();
|
|
1153
|
+
copy.remove("gainmap-data");
|
|
1154
|
+
return copy;
|
|
1155
|
+
}
|
|
1130
1156
|
} // namespace sharp
|
package/src/common.h
CHANGED
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
// Verify platform and compiler compatibility
|
|
19
19
|
|
|
20
20
|
#if (VIPS_MAJOR_VERSION < 8) || \
|
|
21
|
-
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION <
|
|
22
|
-
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION ==
|
|
23
|
-
#error "libvips version 8.
|
|
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"
|
|
24
24
|
#endif
|
|
25
25
|
|
|
26
26
|
#if defined(__has_include)
|
|
@@ -173,6 +173,7 @@ namespace sharp {
|
|
|
173
173
|
JXL,
|
|
174
174
|
RAD,
|
|
175
175
|
DCRAW,
|
|
176
|
+
UHDR,
|
|
176
177
|
VIPS,
|
|
177
178
|
RAW,
|
|
178
179
|
UNKNOWN,
|
|
@@ -397,6 +398,16 @@ namespace sharp {
|
|
|
397
398
|
*/
|
|
398
399
|
VImage StaySequential(VImage image, bool condition = true);
|
|
399
400
|
|
|
401
|
+
/*
|
|
402
|
+
Does this image have a gain map?
|
|
403
|
+
*/
|
|
404
|
+
bool HasGainMap(VImage image);
|
|
405
|
+
|
|
406
|
+
/*
|
|
407
|
+
Removes gain map, if any.
|
|
408
|
+
*/
|
|
409
|
+
VImage RemoveGainMap(VImage image);
|
|
410
|
+
|
|
400
411
|
} // namespace sharp
|
|
401
412
|
|
|
402
413
|
#endif // SRC_COMMON_H_
|
package/src/metadata.cc
CHANGED
|
@@ -141,6 +141,14 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|
|
141
141
|
memcpy(baton->tifftagPhotoshop, tifftagPhotoshop, tifftagPhotoshopLength);
|
|
142
142
|
baton->tifftagPhotoshopLength = tifftagPhotoshopLength;
|
|
143
143
|
}
|
|
144
|
+
// Gain Map
|
|
145
|
+
if (image.get_typeof("gainmap-data") == VIPS_TYPE_BLOB) {
|
|
146
|
+
size_t gainMapLength;
|
|
147
|
+
void const *gainMap = image.get_blob("gainmap-data", &gainMapLength);
|
|
148
|
+
baton->gainMap = static_cast<char *>(g_malloc(gainMapLength));
|
|
149
|
+
memcpy(baton->gainMap, gainMap, gainMapLength);
|
|
150
|
+
baton->gainMapLength = gainMapLength;
|
|
151
|
+
}
|
|
144
152
|
// PNG comments
|
|
145
153
|
vips_image_map(image.get_image(), readPNGComment, &baton->comments);
|
|
146
154
|
}
|
|
@@ -182,10 +190,6 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|
|
182
190
|
info.Set("isPalette", baton->isPalette);
|
|
183
191
|
if (baton->bitsPerSample > 0) {
|
|
184
192
|
info.Set("bitsPerSample", baton->bitsPerSample);
|
|
185
|
-
if (baton->isPalette) {
|
|
186
|
-
// Deprecated, remove with libvips 8.17.0
|
|
187
|
-
info.Set("paletteBitDepth", baton->bitsPerSample);
|
|
188
|
-
}
|
|
189
193
|
}
|
|
190
194
|
if (baton->pages > 0) {
|
|
191
195
|
info.Set("pages", baton->pages);
|
|
@@ -276,6 +280,12 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|
|
276
280
|
Napi::Buffer<char>::NewOrCopy(env, baton->tifftagPhotoshop,
|
|
277
281
|
baton->tifftagPhotoshopLength, sharp::FreeCallback));
|
|
278
282
|
}
|
|
283
|
+
if (baton->gainMapLength > 0) {
|
|
284
|
+
Napi::Object gainMap = Napi::Object::New(env);
|
|
285
|
+
info.Set("gainMap", gainMap);
|
|
286
|
+
gainMap.Set("image",
|
|
287
|
+
Napi::Buffer<char>::NewOrCopy(env, baton->gainMap, baton->gainMapLength, sharp::FreeCallback));
|
|
288
|
+
}
|
|
279
289
|
if (baton->comments.size() > 0) {
|
|
280
290
|
int i = 0;
|
|
281
291
|
Napi::Array comments = Napi::Array::New(env, baton->comments.size());
|
package/src/metadata.h
CHANGED
|
@@ -53,6 +53,8 @@ struct MetadataBaton {
|
|
|
53
53
|
size_t xmpLength;
|
|
54
54
|
char *tifftagPhotoshop;
|
|
55
55
|
size_t tifftagPhotoshopLength;
|
|
56
|
+
char *gainMap;
|
|
57
|
+
size_t gainMapLength;
|
|
56
58
|
MetadataComments comments;
|
|
57
59
|
std::string err;
|
|
58
60
|
|
|
@@ -82,7 +84,9 @@ struct MetadataBaton {
|
|
|
82
84
|
xmp(nullptr),
|
|
83
85
|
xmpLength(0),
|
|
84
86
|
tifftagPhotoshop(nullptr),
|
|
85
|
-
tifftagPhotoshopLength(0)
|
|
87
|
+
tifftagPhotoshopLength(0),
|
|
88
|
+
gainMap(nullptr),
|
|
89
|
+
gainMapLength(0) {}
|
|
86
90
|
};
|
|
87
91
|
|
|
88
92
|
Napi::Value metadata(const Napi::CallbackInfo& info);
|
package/src/operations.cc
CHANGED
|
@@ -285,7 +285,7 @@ namespace sharp {
|
|
|
285
285
|
/*
|
|
286
286
|
Trim an image
|
|
287
287
|
*/
|
|
288
|
-
VImage Trim(VImage image, std::vector<double> background, double threshold, bool const lineArt) {
|
|
288
|
+
VImage Trim(VImage image, std::vector<double> background, double threshold, bool const lineArt, int const margin) {
|
|
289
289
|
if (image.width() < 3 && image.height() < 3) {
|
|
290
290
|
throw VError("Image to trim must be at least 3x3 pixels");
|
|
291
291
|
}
|
|
@@ -320,18 +320,36 @@ namespace sharp {
|
|
|
320
320
|
if (widthA > 0 && heightA > 0) {
|
|
321
321
|
if (width > 0 && height > 0) {
|
|
322
322
|
// Combined bounding box (B)
|
|
323
|
-
int
|
|
324
|
-
int
|
|
325
|
-
int
|
|
326
|
-
int
|
|
323
|
+
int leftB = std::min(left, leftA);
|
|
324
|
+
int topB = std::min(top, topA);
|
|
325
|
+
int widthB = std::max(left + width, leftA + widthA) - leftB;
|
|
326
|
+
int heightB = std::max(top + height, topA + heightA) - topB;
|
|
327
|
+
if (margin > 0) {
|
|
328
|
+
leftB = std::max(0, leftB - margin);
|
|
329
|
+
topB = std::max(0, topB - margin);
|
|
330
|
+
widthB = std::min(image.width() - leftB, widthB + 2 * margin);
|
|
331
|
+
heightB = std::min(image.height() - topB, heightB + 2 * margin);
|
|
332
|
+
}
|
|
327
333
|
return image.extract_area(leftB, topB, widthB, heightB);
|
|
328
334
|
} else {
|
|
329
335
|
// Use alpha only
|
|
336
|
+
if (margin > 0) {
|
|
337
|
+
leftA = std::max(0, leftA - margin);
|
|
338
|
+
topA = std::max(0, topA - margin);
|
|
339
|
+
widthA = std::min(image.width() - leftA, widthA + 2 * margin);
|
|
340
|
+
heightA = std::min(image.height() - topA, heightA + 2 * margin);
|
|
341
|
+
}
|
|
330
342
|
return image.extract_area(leftA, topA, widthA, heightA);
|
|
331
343
|
}
|
|
332
344
|
}
|
|
333
345
|
}
|
|
334
346
|
if (width > 0 && height > 0) {
|
|
347
|
+
if (margin > 0) {
|
|
348
|
+
left = std::max(0, left - margin);
|
|
349
|
+
top = std::max(0, top - margin);
|
|
350
|
+
width = std::min(image.width() - left, width + 2 * margin);
|
|
351
|
+
height = std::min(image.height() - top, height + 2 * margin);
|
|
352
|
+
}
|
|
335
353
|
return image.extract_area(left, top, width, height);
|
|
336
354
|
}
|
|
337
355
|
return image;
|
package/src/operations.h
CHANGED
|
@@ -82,7 +82,7 @@ namespace sharp {
|
|
|
82
82
|
/*
|
|
83
83
|
Trim an image
|
|
84
84
|
*/
|
|
85
|
-
VImage Trim(VImage image, std::vector<double> background, double threshold, bool const lineArt);
|
|
85
|
+
VImage Trim(VImage image, std::vector<double> background, double threshold, bool const lineArt, int const margin);
|
|
86
86
|
|
|
87
87
|
/*
|
|
88
88
|
* Linear adjustment (a * in + b)
|
package/src/pipeline.cc
CHANGED
|
@@ -153,7 +153,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
153
153
|
if (baton->trimThreshold >= 0.0) {
|
|
154
154
|
MultiPageUnsupported(nPages, "Trim");
|
|
155
155
|
image = sharp::StaySequential(image);
|
|
156
|
-
image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold, baton->trimLineArt);
|
|
156
|
+
image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold, baton->trimLineArt, baton->trimMargin);
|
|
157
157
|
baton->trimOffsetLeft = image.xoffset();
|
|
158
158
|
baton->trimOffsetTop = image.yoffset();
|
|
159
159
|
}
|
|
@@ -296,6 +296,14 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
296
296
|
if (baton->input->autoOrient) {
|
|
297
297
|
image = sharp::RemoveExifOrientation(image);
|
|
298
298
|
}
|
|
299
|
+
if (sharp::HasGainMap(image)) {
|
|
300
|
+
if (baton->withGainMap) {
|
|
301
|
+
image = image.uhdr2scRGB();
|
|
302
|
+
}
|
|
303
|
+
image = sharp::RemoveGainMap(image);
|
|
304
|
+
} else {
|
|
305
|
+
baton->withGainMap = false;
|
|
306
|
+
}
|
|
299
307
|
|
|
300
308
|
// Any pre-shrinking may already have been done
|
|
301
309
|
inputWidth = image.width();
|
|
@@ -335,7 +343,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
335
343
|
image.interpretation() != VIPS_INTERPRETATION_LABS &&
|
|
336
344
|
image.interpretation() != VIPS_INTERPRETATION_GREY16 &&
|
|
337
345
|
baton->colourspacePipeline != VIPS_INTERPRETATION_CMYK &&
|
|
338
|
-
!baton->input->ignoreIcc
|
|
346
|
+
!baton->input->ignoreIcc && !baton->withGainMap
|
|
339
347
|
) {
|
|
340
348
|
// Convert to sRGB/P3 using embedded profile
|
|
341
349
|
try {
|
|
@@ -957,6 +965,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
957
965
|
->set("effort", baton->webpEffort)
|
|
958
966
|
->set("min_size", baton->webpMinSize)
|
|
959
967
|
->set("mixed", baton->webpMixed)
|
|
968
|
+
->set("exact", baton->webpExact)
|
|
960
969
|
->set("alpha_q", baton->webpAlphaQuality)));
|
|
961
970
|
baton->bufferOut = static_cast<char*>(area->data);
|
|
962
971
|
baton->bufferOutLength = area->length;
|
|
@@ -1024,6 +1033,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1024
1033
|
->set("compression", baton->heifCompression)
|
|
1025
1034
|
->set("effort", baton->heifEffort)
|
|
1026
1035
|
->set("bitdepth", baton->heifBitdepth)
|
|
1036
|
+
->set("tune", baton->heifTune.c_str())
|
|
1027
1037
|
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
|
1028
1038
|
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
|
1029
1039
|
->set("lossless", baton->heifLossless)));
|
|
@@ -1168,6 +1178,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1168
1178
|
->set("effort", baton->webpEffort)
|
|
1169
1179
|
->set("min_size", baton->webpMinSize)
|
|
1170
1180
|
->set("mixed", baton->webpMixed)
|
|
1181
|
+
->set("exact", baton->webpExact)
|
|
1171
1182
|
->set("alpha_q", baton->webpAlphaQuality));
|
|
1172
1183
|
baton->formatOut = "webp";
|
|
1173
1184
|
} else if (baton->formatOut == "gif" || (mightMatchInput && isGif) ||
|
|
@@ -1223,6 +1234,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1223
1234
|
->set("compression", baton->heifCompression)
|
|
1224
1235
|
->set("effort", baton->heifEffort)
|
|
1225
1236
|
->set("bitdepth", baton->heifBitdepth)
|
|
1237
|
+
->set("tune", baton->heifTune.c_str())
|
|
1226
1238
|
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
|
1227
1239
|
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
|
1228
1240
|
->set("lossless", baton->heifLossless));
|
|
@@ -1337,12 +1349,21 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1337
1349
|
}
|
|
1338
1350
|
|
|
1339
1351
|
if (baton->bufferOutLength > 0) {
|
|
1340
|
-
// Add buffer size to info
|
|
1341
1352
|
info.Set("size", static_cast<uint32_t>(baton->bufferOutLength));
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
baton->bufferOutLength
|
|
1345
|
-
|
|
1353
|
+
if (baton->typedArrayOut) {
|
|
1354
|
+
// ECMAScript ArrayBuffer with Uint8Array view
|
|
1355
|
+
Napi::ArrayBuffer ab = Napi::ArrayBuffer::New(env, baton->bufferOutLength);
|
|
1356
|
+
memcpy(ab.Data(), baton->bufferOut, baton->bufferOutLength);
|
|
1357
|
+
sharp::FreeCallback(static_cast<char*>(baton->bufferOut), nullptr);
|
|
1358
|
+
Napi::TypedArrayOf<uint8_t> data = Napi::TypedArrayOf<uint8_t>::New(env,
|
|
1359
|
+
baton->bufferOutLength, ab, 0, napi_uint8_array);
|
|
1360
|
+
Callback().Call(Receiver().Value(), { env.Null(), data, info });
|
|
1361
|
+
} else {
|
|
1362
|
+
// Node.js Buffer
|
|
1363
|
+
Napi::Buffer<char> data = Napi::Buffer<char>::NewOrCopy(env, static_cast<char*>(baton->bufferOut),
|
|
1364
|
+
baton->bufferOutLength, sharp::FreeCallback);
|
|
1365
|
+
Callback().Call(Receiver().Value(), { env.Null(), data, info });
|
|
1366
|
+
}
|
|
1346
1367
|
} else {
|
|
1347
1368
|
// Add file size to info
|
|
1348
1369
|
if (baton->formatOut != "dz" || sharp::IsDzZip(baton->fileOut)) {
|
|
@@ -1469,6 +1490,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|
|
1469
1490
|
{"preset", vips_enum_nick(VIPS_TYPE_FOREIGN_WEBP_PRESET, baton->webpPreset)},
|
|
1470
1491
|
{"min_size", baton->webpMinSize ? "true" : "false"},
|
|
1471
1492
|
{"mixed", baton->webpMixed ? "true" : "false"},
|
|
1493
|
+
{"exact", baton->webpExact ? "true" : "false"},
|
|
1472
1494
|
{"effort", std::to_string(baton->webpEffort)}
|
|
1473
1495
|
};
|
|
1474
1496
|
suffix = AssembleSuffixString(".webp", options);
|
|
@@ -1615,6 +1637,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1615
1637
|
baton->trimBackground = sharp::AttrAsVectorOfDouble(options, "trimBackground");
|
|
1616
1638
|
baton->trimThreshold = sharp::AttrAsDouble(options, "trimThreshold");
|
|
1617
1639
|
baton->trimLineArt = sharp::AttrAsBool(options, "trimLineArt");
|
|
1640
|
+
baton->trimMargin = sharp::AttrAsUint32(options, "trimMargin");
|
|
1618
1641
|
baton->gamma = sharp::AttrAsDouble(options, "gamma");
|
|
1619
1642
|
baton->gammaOut = sharp::AttrAsDouble(options, "gammaOut");
|
|
1620
1643
|
baton->linearA = sharp::AttrAsVectorOfDouble(options, "linearA");
|
|
@@ -1692,6 +1715,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1692
1715
|
// Output
|
|
1693
1716
|
baton->formatOut = sharp::AttrAsStr(options, "formatOut");
|
|
1694
1717
|
baton->fileOut = sharp::AttrAsStr(options, "fileOut");
|
|
1718
|
+
baton->typedArrayOut = sharp::AttrAsBool(options, "typedArrayOut");
|
|
1695
1719
|
baton->keepMetadata = sharp::AttrAsUint32(options, "keepMetadata");
|
|
1696
1720
|
baton->withMetadataOrientation = sharp::AttrAsUint32(options, "withMetadataOrientation");
|
|
1697
1721
|
baton->withMetadataDensity = sharp::AttrAsDouble(options, "withMetadataDensity");
|
|
@@ -1706,6 +1730,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1706
1730
|
}
|
|
1707
1731
|
baton->withExifMerge = sharp::AttrAsBool(options, "withExifMerge");
|
|
1708
1732
|
baton->withXmp = sharp::AttrAsStr(options, "withXmp");
|
|
1733
|
+
baton->withGainMap = sharp::AttrAsBool(options, "withGainMap");
|
|
1709
1734
|
baton->timeoutSeconds = sharp::AttrAsUint32(options, "timeoutSeconds");
|
|
1710
1735
|
baton->loop = sharp::AttrAsUint32(options, "loop");
|
|
1711
1736
|
baton->delay = sharp::AttrAsInt32Vector(options, "delay");
|
|
@@ -1741,6 +1766,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1741
1766
|
baton->webpEffort = sharp::AttrAsUint32(options, "webpEffort");
|
|
1742
1767
|
baton->webpMinSize = sharp::AttrAsBool(options, "webpMinSize");
|
|
1743
1768
|
baton->webpMixed = sharp::AttrAsBool(options, "webpMixed");
|
|
1769
|
+
baton->webpExact = sharp::AttrAsBool(options, "webpExact");
|
|
1744
1770
|
baton->gifBitdepth = sharp::AttrAsUint32(options, "gifBitdepth");
|
|
1745
1771
|
baton->gifEffort = sharp::AttrAsUint32(options, "gifEffort");
|
|
1746
1772
|
baton->gifDither = sharp::AttrAsDouble(options, "gifDither");
|
|
@@ -1775,6 +1801,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|
|
1775
1801
|
baton->heifEffort = sharp::AttrAsUint32(options, "heifEffort");
|
|
1776
1802
|
baton->heifChromaSubsampling = sharp::AttrAsStr(options, "heifChromaSubsampling");
|
|
1777
1803
|
baton->heifBitdepth = sharp::AttrAsUint32(options, "heifBitdepth");
|
|
1804
|
+
baton->heifTune = sharp::AttrAsStr(options, "heifTune");
|
|
1778
1805
|
baton->jxlDistance = sharp::AttrAsDouble(options, "jxlDistance");
|
|
1779
1806
|
baton->jxlDecodingTier = sharp::AttrAsUint32(options, "jxlDecodingTier");
|
|
1780
1807
|
baton->jxlEffort = sharp::AttrAsUint32(options, "jxlEffort");
|
package/src/pipeline.h
CHANGED
|
@@ -48,6 +48,7 @@ struct PipelineBaton {
|
|
|
48
48
|
size_t bufferOutLength;
|
|
49
49
|
int pageHeightOut;
|
|
50
50
|
int pagesOut;
|
|
51
|
+
bool typedArrayOut;
|
|
51
52
|
std::vector<Composite *> composite;
|
|
52
53
|
std::vector<sharp::InputDescriptor *> joinChannelIn;
|
|
53
54
|
int topOffsetPre;
|
|
@@ -101,6 +102,7 @@ struct PipelineBaton {
|
|
|
101
102
|
bool trimLineArt;
|
|
102
103
|
int trimOffsetLeft;
|
|
103
104
|
int trimOffsetTop;
|
|
105
|
+
int trimMargin;
|
|
104
106
|
std::vector<double> linearA;
|
|
105
107
|
std::vector<double> linearB;
|
|
106
108
|
int dilateWidth;
|
|
@@ -167,6 +169,7 @@ struct PipelineBaton {
|
|
|
167
169
|
int webpEffort;
|
|
168
170
|
bool webpMinSize;
|
|
169
171
|
bool webpMixed;
|
|
172
|
+
bool webpExact;
|
|
170
173
|
int gifBitdepth;
|
|
171
174
|
int gifEffort;
|
|
172
175
|
double gifDither;
|
|
@@ -194,6 +197,7 @@ struct PipelineBaton {
|
|
|
194
197
|
std::string heifChromaSubsampling;
|
|
195
198
|
bool heifLossless;
|
|
196
199
|
int heifBitdepth;
|
|
200
|
+
std::string heifTune;
|
|
197
201
|
double jxlDistance;
|
|
198
202
|
int jxlDecodingTier;
|
|
199
203
|
int jxlEffort;
|
|
@@ -208,6 +212,7 @@ struct PipelineBaton {
|
|
|
208
212
|
std::unordered_map<std::string, std::string> withExif;
|
|
209
213
|
bool withExifMerge;
|
|
210
214
|
std::string withXmp;
|
|
215
|
+
bool withGainMap;
|
|
211
216
|
int timeoutSeconds;
|
|
212
217
|
std::vector<double> convKernel;
|
|
213
218
|
int convKernelWidth;
|
|
@@ -242,6 +247,7 @@ struct PipelineBaton {
|
|
|
242
247
|
bufferOutLength(0),
|
|
243
248
|
pageHeightOut(0),
|
|
244
249
|
pagesOut(0),
|
|
250
|
+
typedArrayOut(false),
|
|
245
251
|
topOffsetPre(-1),
|
|
246
252
|
topOffsetPost(-1),
|
|
247
253
|
channels(0),
|
|
@@ -281,6 +287,7 @@ struct PipelineBaton {
|
|
|
281
287
|
trimLineArt(false),
|
|
282
288
|
trimOffsetLeft(0),
|
|
283
289
|
trimOffsetTop(0),
|
|
290
|
+
trimMargin(0),
|
|
284
291
|
linearA{},
|
|
285
292
|
linearB{},
|
|
286
293
|
dilateWidth(0),
|
|
@@ -344,6 +351,7 @@ struct PipelineBaton {
|
|
|
344
351
|
webpEffort(4),
|
|
345
352
|
webpMinSize(false),
|
|
346
353
|
webpMixed(false),
|
|
354
|
+
webpExact(false),
|
|
347
355
|
gifBitdepth(8),
|
|
348
356
|
gifEffort(7),
|
|
349
357
|
gifDither(1.0),
|
|
@@ -371,6 +379,7 @@ struct PipelineBaton {
|
|
|
371
379
|
heifChromaSubsampling("4:4:4"),
|
|
372
380
|
heifLossless(false),
|
|
373
381
|
heifBitdepth(8),
|
|
382
|
+
heifTune("ssim"),
|
|
374
383
|
jxlDistance(1.0),
|
|
375
384
|
jxlDecodingTier(0),
|
|
376
385
|
jxlEffort(7),
|
|
@@ -381,6 +390,7 @@ struct PipelineBaton {
|
|
|
381
390
|
withMetadataOrientation(-1),
|
|
382
391
|
withMetadataDensity(0.0),
|
|
383
392
|
withExifMerge(true),
|
|
393
|
+
withGainMap(false),
|
|
384
394
|
timeoutSeconds(0),
|
|
385
395
|
convKernelWidth(0),
|
|
386
396
|
convKernelHeight(0),
|
package/src/utilities.cc
CHANGED
|
@@ -123,6 +123,7 @@ Napi::Value format(const Napi::CallbackInfo& info) {
|
|
|
123
123
|
"jpeg", "png", "webp", "tiff", "magick", "openslide", "dz",
|
|
124
124
|
"ppm", "fits", "gif", "svg", "heif", "pdf", "vips", "jp2k", "jxl", "rad", "dcraw"
|
|
125
125
|
}) {
|
|
126
|
+
std::string id = f == "jp2k" ? "jp2" : f;
|
|
126
127
|
// Input
|
|
127
128
|
const VipsObjectClass *oc = vips_class_find("VipsOperation", (f + "load").c_str());
|
|
128
129
|
Napi::Boolean hasInputFile = Napi::Boolean::New(env, oc);
|
|
@@ -154,11 +155,11 @@ Napi::Value format(const Napi::CallbackInfo& info) {
|
|
|
154
155
|
output.Set("stream", hasOutputBuffer);
|
|
155
156
|
// Other attributes
|
|
156
157
|
Napi::Object container = Napi::Object::New(env);
|
|
157
|
-
container.Set("id",
|
|
158
|
+
container.Set("id", id);
|
|
158
159
|
container.Set("input", input);
|
|
159
160
|
container.Set("output", output);
|
|
160
161
|
// Add to set of formats
|
|
161
|
-
format.Set(
|
|
162
|
+
format.Set(id, container);
|
|
162
163
|
}
|
|
163
164
|
|
|
164
165
|
// Raw, uncompressed data
|
package/install/check.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
Copyright 2013 Lovell Fuller and others.
|
|
3
|
-
SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
try {
|
|
7
|
-
const { useGlobalLibvips } = require('../lib/libvips');
|
|
8
|
-
if (useGlobalLibvips() || process.env.npm_config_build_from_source) {
|
|
9
|
-
process.exit(1);
|
|
10
|
-
}
|
|
11
|
-
} catch (err) {
|
|
12
|
-
const summary = err.message.split(/\n/).slice(0, 1);
|
|
13
|
-
console.log(`sharp: skipping install check: ${summary}`);
|
|
14
|
-
}
|