mirror of
https://github.com/lovell/sharp.git
synced 2026-02-11 09:06:15 +01:00
Compare commits
10 Commits
006d37b2d0
...
temp-std-r
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17d4a684df | ||
|
|
ed6b7384d0 | ||
|
|
ef77388a73 | ||
|
|
66764b359b | ||
|
|
8561f0da1d | ||
|
|
0468c1be9f | ||
|
|
4b1680c312 | ||
|
|
2346722c0d | ||
|
|
a5e726002c | ||
|
|
d161e45e06 |
@@ -326,3 +326,6 @@ GitHub: https://github.com/tpatel
|
|||||||
|
|
||||||
Name: Maël Nison
|
Name: Maël Nison
|
||||||
GitHub: https://github.com/arcanis
|
GitHub: https://github.com/arcanis
|
||||||
|
|
||||||
|
Name: Dmytro Tiapukhin
|
||||||
|
GitHub: https://github.com/eddienubes
|
||||||
|
|||||||
@@ -717,7 +717,7 @@ instead of providing `xres` and `yres` in pixels/mm.
|
|||||||
| [options.xres] | <code>number</code> | <code>1.0</code> | horizontal resolution in pixels/mm |
|
| [options.xres] | <code>number</code> | <code>1.0</code> | horizontal resolution in pixels/mm |
|
||||||
| [options.yres] | <code>number</code> | <code>1.0</code> | vertical resolution in pixels/mm |
|
| [options.yres] | <code>number</code> | <code>1.0</code> | vertical resolution in pixels/mm |
|
||||||
| [options.resolutionUnit] | <code>string</code> | <code>"'inch'"</code> | resolution unit options: inch, cm |
|
| [options.resolutionUnit] | <code>string</code> | <code>"'inch'"</code> | resolution unit options: inch, cm |
|
||||||
| [options.bitdepth] | <code>number</code> | <code>8</code> | reduce bitdepth to 1, 2 or 4 bit |
|
| [options.bitdepth] | <code>number</code> | <code>0</code> | reduce bitdepth to 1, 2 or 4 bit |
|
||||||
| [options.miniswhite] | <code>boolean</code> | <code>false</code> | write 1-bit images as miniswhite |
|
| [options.miniswhite] | <code>boolean</code> | <code>false</code> | write 1-bit images as miniswhite |
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
@@ -758,7 +758,7 @@ When using Windows ARM64, this feature requires a CPU with ARM64v8.4 or later.
|
|||||||
| [options.effort] | <code>number</code> | <code>4</code> | CPU effort, between 0 (fastest) and 9 (slowest) |
|
| [options.effort] | <code>number</code> | <code>4</code> | CPU effort, between 0 (fastest) and 9 (slowest) |
|
||||||
| [options.chromaSubsampling] | <code>string</code> | <code>"'4:4:4'"</code> | set to '4:2:0' to use chroma subsampling |
|
| [options.chromaSubsampling] | <code>string</code> | <code>"'4:4:4'"</code> | set to '4:2:0' to use chroma subsampling |
|
||||||
| [options.bitdepth] | <code>number</code> | <code>8</code> | set bitdepth to 8, 10 or 12 bit |
|
| [options.bitdepth] | <code>number</code> | <code>8</code> | set bitdepth to 8, 10 or 12 bit |
|
||||||
| [options.tune] | <code>string</code> | <code>"'iq'"</code> | tune output for a quality metric, one of 'iq' (default), 'ssim' or 'psnr' |
|
| [options.tune] | <code>string</code> | <code>"'iq'"</code> | tune output for a quality metric, one of 'iq' (default), 'ssim' (default when lossless) or 'psnr' |
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
```js
|
```js
|
||||||
|
|||||||
@@ -284,6 +284,7 @@ The `info` response Object will contain `trimOffsetLeft` and `trimOffsetTop` pro
|
|||||||
| [options.background] | <code>string</code> \| <code>Object</code> | <code>"'top-left pixel'"</code> | Background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to that of the top-left pixel. |
|
| [options.background] | <code>string</code> \| <code>Object</code> | <code>"'top-left pixel'"</code> | Background colour, parsed by the [color](https://www.npmjs.org/package/color) module, defaults to that of the top-left pixel. |
|
||||||
| [options.threshold] | <code>number</code> | <code>10</code> | Allowed difference from the above colour, a positive number. |
|
| [options.threshold] | <code>number</code> | <code>10</code> | Allowed difference from the above colour, a positive number. |
|
||||||
| [options.lineArt] | <code>boolean</code> | <code>false</code> | Does the input more closely resemble line art (e.g. vector) rather than being photographic? |
|
| [options.lineArt] | <code>boolean</code> | <code>false</code> | Does the input more closely resemble line art (e.g. vector) rather than being photographic? |
|
||||||
|
| [options.margin] | <code>number</code> | <code>0</code> | Leave a margin around trimmed content, value is in pixels. |
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
```js
|
```js
|
||||||
@@ -320,4 +321,13 @@ const output = await sharp(input)
|
|||||||
threshold: 42,
|
threshold: 42,
|
||||||
})
|
})
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
|
```
|
||||||
|
**Example**
|
||||||
|
```js
|
||||||
|
// Trim image leaving (up to) a 10 pixel margin around the trimmed content.
|
||||||
|
const output = await sharp(input)
|
||||||
|
.trim({
|
||||||
|
margin: 10
|
||||||
|
})
|
||||||
|
.toBuffer();
|
||||||
```
|
```
|
||||||
@@ -16,8 +16,12 @@ slug: changelog/v0.35.0
|
|||||||
|
|
||||||
* Breaking: Remove deprecated properties from `sharpen` operation.
|
* Breaking: Remove deprecated properties from `sharpen` operation.
|
||||||
|
|
||||||
|
* Breaking: Rename `format.jp2k` as `format.jp2` for API consistency.
|
||||||
|
|
||||||
* Upgrade to libvips v8.18.0 for upstream bug fixes.
|
* Upgrade to libvips v8.18.0 for upstream bug fixes.
|
||||||
|
|
||||||
|
* Ensure TIFF output `bitdepth` option is limited to 1, 2 or 4.
|
||||||
|
|
||||||
* Deprecate Windows 32-bit (win32-ia32) prebuilt binaries.
|
* Deprecate Windows 32-bit (win32-ia32) prebuilt binaries.
|
||||||
|
|
||||||
* Add AVIF/HEIF `tune` option for control over quality metrics.
|
* Add AVIF/HEIF `tune` option for control over quality metrics.
|
||||||
@@ -29,4 +33,14 @@ slug: changelog/v0.35.0
|
|||||||
* Add `toUint8Array` for output image as a `TypedArray` backed by a transferable `ArrayBuffer`.
|
* Add `toUint8Array` for output image as a `TypedArray` backed by a transferable `ArrayBuffer`.
|
||||||
[#4355](https://github.com/lovell/sharp/issues/4355)
|
[#4355](https://github.com/lovell/sharp/issues/4355)
|
||||||
|
|
||||||
|
* TypeScript: Ensure `FormatEnum` keys match reality.
|
||||||
|
[#4475](https://github.com/lovell/sharp/issues/4475)
|
||||||
|
|
||||||
|
* Add `margin` option to `trim` operation.
|
||||||
|
[#4480](https://github.com/lovell/sharp/issues/4480)
|
||||||
|
[@eddienubes](https://github.com/eddienubes)
|
||||||
|
|
||||||
|
* Ensure HEIF primary item is used as default page/frame.
|
||||||
|
[#4487](https://github.com/lovell/sharp/issues/4487)
|
||||||
|
|
||||||
* Add WebP `exact` option for control over transparent pixel colour values.
|
* Add WebP `exact` option for control over transparent pixel colour values.
|
||||||
|
|||||||
@@ -278,6 +278,7 @@ const Sharp = function (input, options) {
|
|||||||
trimBackground: [],
|
trimBackground: [],
|
||||||
trimThreshold: -1,
|
trimThreshold: -1,
|
||||||
trimLineArt: false,
|
trimLineArt: false,
|
||||||
|
trimMargin: 0,
|
||||||
dilateWidth: 0,
|
dilateWidth: 0,
|
||||||
erodeWidth: 0,
|
erodeWidth: 0,
|
||||||
gamma: 0,
|
gamma: 0,
|
||||||
@@ -365,7 +366,7 @@ const Sharp = function (input, options) {
|
|||||||
tiffPredictor: 'horizontal',
|
tiffPredictor: 'horizontal',
|
||||||
tiffPyramid: false,
|
tiffPyramid: false,
|
||||||
tiffMiniswhite: false,
|
tiffMiniswhite: false,
|
||||||
tiffBitdepth: 8,
|
tiffBitdepth: 0,
|
||||||
tiffTile: false,
|
tiffTile: false,
|
||||||
tiffTileHeight: 256,
|
tiffTileHeight: 256,
|
||||||
tiffTileWidth: 256,
|
tiffTileWidth: 256,
|
||||||
|
|||||||
14
lib/index.d.ts
vendored
14
lib/index.d.ts
vendored
@@ -840,7 +840,7 @@ declare namespace sharp {
|
|||||||
* @returns A sharp instance that can be used to chain operations
|
* @returns A sharp instance that can be used to chain operations
|
||||||
*/
|
*/
|
||||||
toFormat(
|
toFormat(
|
||||||
format: keyof FormatEnum | AvailableFormatInfo,
|
format: keyof FormatEnum | AvailableFormatInfo | "avif",
|
||||||
options?:
|
options?:
|
||||||
| OutputOptions
|
| OutputOptions
|
||||||
| JpegOptions
|
| JpegOptions
|
||||||
@@ -1479,8 +1479,8 @@ declare namespace sharp {
|
|||||||
xres?: number | undefined;
|
xres?: number | undefined;
|
||||||
/** Vertical resolution in pixels/mm (optional, default 1.0) */
|
/** Vertical resolution in pixels/mm (optional, default 1.0) */
|
||||||
yres?: number | undefined;
|
yres?: number | undefined;
|
||||||
/** Reduce bitdepth to 1, 2 or 4 bit (optional, default 8) */
|
/** Reduce bitdepth to 1, 2 or 4 bit (optional) */
|
||||||
bitdepth?: 1 | 2 | 4 | 8 | undefined;
|
bitdepth?: 1 | 2 | 4 | undefined;
|
||||||
/** Write 1-bit images as miniswhite (optional, default false) */
|
/** Write 1-bit images as miniswhite (optional, default false) */
|
||||||
miniswhite?: boolean | undefined;
|
miniswhite?: boolean | undefined;
|
||||||
/** Resolution unit options: inch, cm (optional, default 'inch') */
|
/** Resolution unit options: inch, cm (optional, default 'inch') */
|
||||||
@@ -1606,6 +1606,8 @@ declare namespace sharp {
|
|||||||
threshold?: number | undefined;
|
threshold?: number | undefined;
|
||||||
/** Does the input more closely resemble line art (e.g. vector) rather than being photographic? (optional, default false) */
|
/** Does the input more closely resemble line art (e.g. vector) rather than being photographic? (optional, default false) */
|
||||||
lineArt?: boolean | undefined;
|
lineArt?: boolean | undefined;
|
||||||
|
/** Leave a margin around trimmed content, value is in pixels. (optional, default 0) */
|
||||||
|
margin?: number | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RawOptions {
|
interface RawOptions {
|
||||||
@@ -1911,16 +1913,13 @@ declare namespace sharp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface FormatEnum {
|
interface FormatEnum {
|
||||||
avif: AvailableFormatInfo;
|
|
||||||
dcraw: AvailableFormatInfo;
|
dcraw: AvailableFormatInfo;
|
||||||
dz: AvailableFormatInfo;
|
dz: AvailableFormatInfo;
|
||||||
exr: AvailableFormatInfo;
|
exr: AvailableFormatInfo;
|
||||||
fits: AvailableFormatInfo;
|
fits: AvailableFormatInfo;
|
||||||
gif: AvailableFormatInfo;
|
gif: AvailableFormatInfo;
|
||||||
heif: AvailableFormatInfo;
|
heif: AvailableFormatInfo;
|
||||||
input: AvailableFormatInfo;
|
|
||||||
jpeg: AvailableFormatInfo;
|
jpeg: AvailableFormatInfo;
|
||||||
jpg: AvailableFormatInfo;
|
|
||||||
jp2: AvailableFormatInfo;
|
jp2: AvailableFormatInfo;
|
||||||
jxl: AvailableFormatInfo;
|
jxl: AvailableFormatInfo;
|
||||||
magick: AvailableFormatInfo;
|
magick: AvailableFormatInfo;
|
||||||
@@ -1932,8 +1931,7 @@ declare namespace sharp {
|
|||||||
raw: AvailableFormatInfo;
|
raw: AvailableFormatInfo;
|
||||||
svg: AvailableFormatInfo;
|
svg: AvailableFormatInfo;
|
||||||
tiff: AvailableFormatInfo;
|
tiff: AvailableFormatInfo;
|
||||||
tif: AvailableFormatInfo;
|
vips: AvailableFormatInfo;
|
||||||
v: AvailableFormatInfo;
|
|
||||||
webp: AvailableFormatInfo;
|
webp: AvailableFormatInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ function toFile (fileOut, callback) {
|
|||||||
err = new Error('Missing output file path');
|
err = new Error('Missing output file path');
|
||||||
} else if (is.string(this.options.input.file) && path.resolve(this.options.input.file) === path.resolve(fileOut)) {
|
} else if (is.string(this.options.input.file) && path.resolve(this.options.input.file) === path.resolve(fileOut)) {
|
||||||
err = new Error('Cannot use same file for input and output');
|
err = new Error('Cannot use same file for input and output');
|
||||||
} else if (jp2Regex.test(path.extname(fileOut)) && !this.constructor.format.jp2k.output.file) {
|
} else if (jp2Regex.test(path.extname(fileOut)) && !this.constructor.format.jp2.output.file) {
|
||||||
err = errJp2Save();
|
err = errJp2Save();
|
||||||
}
|
}
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -950,7 +950,7 @@ function gif (options) {
|
|||||||
*/
|
*/
|
||||||
function jp2 (options) {
|
function jp2 (options) {
|
||||||
/* node:coverage ignore next 41 */
|
/* node:coverage ignore next 41 */
|
||||||
if (!this.constructor.format.jp2k.output.buffer) {
|
if (!this.constructor.format.jp2.output.buffer) {
|
||||||
throw errJp2Save();
|
throw errJp2Save();
|
||||||
}
|
}
|
||||||
if (is.object(options)) {
|
if (is.object(options)) {
|
||||||
@@ -1055,7 +1055,7 @@ function trySetAnimationOptions (source, target) {
|
|||||||
* @param {number} [options.xres=1.0] - horizontal resolution in pixels/mm
|
* @param {number} [options.xres=1.0] - horizontal resolution in pixels/mm
|
||||||
* @param {number} [options.yres=1.0] - vertical resolution in pixels/mm
|
* @param {number} [options.yres=1.0] - vertical resolution in pixels/mm
|
||||||
* @param {string} [options.resolutionUnit='inch'] - resolution unit options: inch, cm
|
* @param {string} [options.resolutionUnit='inch'] - resolution unit options: inch, cm
|
||||||
* @param {number} [options.bitdepth=8] - reduce bitdepth to 1, 2 or 4 bit
|
* @param {number} [options.bitdepth=0] - reduce bitdepth to 1, 2 or 4 bit
|
||||||
* @param {boolean} [options.miniswhite=false] - write 1-bit images as miniswhite
|
* @param {boolean} [options.miniswhite=false] - write 1-bit images as miniswhite
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
* @throws {Error} Invalid options
|
* @throws {Error} Invalid options
|
||||||
@@ -1070,10 +1070,10 @@ function tiff (options) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is.defined(options.bitdepth)) {
|
if (is.defined(options.bitdepth)) {
|
||||||
if (is.integer(options.bitdepth) && is.inArray(options.bitdepth, [1, 2, 4, 8])) {
|
if (is.integer(options.bitdepth) && is.inArray(options.bitdepth, [1, 2, 4])) {
|
||||||
this.options.tiffBitdepth = options.bitdepth;
|
this.options.tiffBitdepth = options.bitdepth;
|
||||||
} else {
|
} else {
|
||||||
throw is.invalidParameterError('bitdepth', '1, 2, 4 or 8', options.bitdepth);
|
throw is.invalidParameterError('bitdepth', '1, 2 or 4', options.bitdepth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// tiling
|
// tiling
|
||||||
@@ -1175,7 +1175,7 @@ function tiff (options) {
|
|||||||
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
|
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 9 (slowest)
|
||||||
* @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
|
* @param {string} [options.chromaSubsampling='4:4:4'] - set to '4:2:0' to use chroma subsampling
|
||||||
* @param {number} [options.bitdepth=8] - set bitdepth to 8, 10 or 12 bit
|
* @param {number} [options.bitdepth=8] - set bitdepth to 8, 10 or 12 bit
|
||||||
* @param {string} [options.tune='iq'] - tune output for a quality metric, one of 'iq' (default), 'ssim' or 'psnr'
|
* @param {string} [options.tune='iq'] - tune output for a quality metric, one of 'iq' (default), 'ssim' (default when lossless) or 'psnr'
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
* @throws {Error} Invalid options
|
* @throws {Error} Invalid options
|
||||||
*/
|
*/
|
||||||
@@ -1255,7 +1255,11 @@ function heif (options) {
|
|||||||
}
|
}
|
||||||
if (is.defined(options.tune)) {
|
if (is.defined(options.tune)) {
|
||||||
if (is.string(options.tune) && is.inArray(options.tune, ['iq', 'ssim', 'psnr'])) {
|
if (is.string(options.tune) && is.inArray(options.tune, ['iq', 'ssim', 'psnr'])) {
|
||||||
this.options.heifTune = options.tune;
|
if (this.options.heifLossless && options.tune === 'iq') {
|
||||||
|
this.options.heifTune = 'ssim';
|
||||||
|
} else {
|
||||||
|
this.options.heifTune = options.tune;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw is.invalidParameterError('tune', 'one of: psnr, ssim, iq', options.tune);
|
throw is.invalidParameterError('tune', 'one of: psnr, ssim, iq', options.tune);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -540,10 +540,19 @@ function extract (options) {
|
|||||||
* })
|
* })
|
||||||
* .toBuffer();
|
* .toBuffer();
|
||||||
*
|
*
|
||||||
|
* @example
|
||||||
|
* // Trim image leaving (up to) a 10 pixel margin around the trimmed content.
|
||||||
|
* const output = await sharp(input)
|
||||||
|
* .trim({
|
||||||
|
* margin: 10
|
||||||
|
* })
|
||||||
|
* .toBuffer();
|
||||||
|
*
|
||||||
* @param {Object} [options]
|
* @param {Object} [options]
|
||||||
* @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.
|
* @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.
|
||||||
* @param {number} [options.threshold=10] - Allowed difference from the above colour, a positive number.
|
* @param {number} [options.threshold=10] - Allowed difference from the above colour, a positive number.
|
||||||
* @param {boolean} [options.lineArt=false] - Does the input more closely resemble line art (e.g. vector) rather than being photographic?
|
* @param {boolean} [options.lineArt=false] - Does the input more closely resemble line art (e.g. vector) rather than being photographic?
|
||||||
|
* @param {number} [options.margin=0] - Leave a margin around trimmed content, value is in pixels.
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
* @throws {Error} Invalid parameters
|
* @throws {Error} Invalid parameters
|
||||||
*/
|
*/
|
||||||
@@ -564,6 +573,13 @@ function trim (options) {
|
|||||||
if (is.defined(options.lineArt)) {
|
if (is.defined(options.lineArt)) {
|
||||||
this._setBooleanOption('trimLineArt', options.lineArt);
|
this._setBooleanOption('trimLineArt', options.lineArt);
|
||||||
}
|
}
|
||||||
|
if (is.defined(options.margin)) {
|
||||||
|
if (is.integer(options.margin) && options.margin >= 0) {
|
||||||
|
this.options.trimMargin = options.margin;
|
||||||
|
} else {
|
||||||
|
throw is.invalidParameterError('margin', 'positive integer', options.margin);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw is.invalidParameterError('trim', 'object', options);
|
throw is.invalidParameterError('trim', 'object', options);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ const format = sharp.format();
|
|||||||
format.heif.output.alias = ['avif', 'heic'];
|
format.heif.output.alias = ['avif', 'heic'];
|
||||||
format.jpeg.output.alias = ['jpe', 'jpg'];
|
format.jpeg.output.alias = ['jpe', 'jpg'];
|
||||||
format.tiff.output.alias = ['tif'];
|
format.tiff.output.alias = ['tif'];
|
||||||
format.jp2k.output.alias = ['j2c', 'j2k', 'jp2', 'jpx'];
|
format.jp2.output.alias = ['j2c', 'j2k', 'jp2', 'jpx'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An Object containing the available interpolators and their proper values
|
* An Object containing the available interpolators and their proper values
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-darwin-arm64",
|
"name": "@img/sharp-darwin-arm64",
|
||||||
"version": "0.34.5",
|
"version": "0.35.0-rc.0",
|
||||||
"description": "Prebuilt sharp for use with macOS 64-bit ARM",
|
"description": "Prebuilt sharp for use with macOS 64-bit ARM",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-darwin-arm64": "1.3.0-rc.1"
|
"@img/sharp-libvips-darwin-arm64": "1.3.0-rc.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"index.cjs",
|
"index.cjs",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-darwin-x64",
|
"name": "@img/sharp-darwin-x64",
|
||||||
"version": "0.34.5",
|
"version": "0.35.0-rc.0",
|
||||||
"description": "Prebuilt sharp for use with macOS x64",
|
"description": "Prebuilt sharp for use with macOS x64",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-darwin-x64": "1.3.0-rc.1"
|
"@img/sharp-libvips-darwin-x64": "1.3.0-rc.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"index.cjs",
|
"index.cjs",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linux-arm",
|
"name": "@img/sharp-linux-arm",
|
||||||
"version": "0.34.5",
|
"version": "0.35.0-rc.0",
|
||||||
"description": "Prebuilt sharp for use with Linux (glibc) ARM (32-bit)",
|
"description": "Prebuilt sharp for use with Linux (glibc) ARM (32-bit)",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linux-arm": "1.3.0-rc.1"
|
"@img/sharp-libvips-linux-arm": "1.3.0-rc.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"index.cjs",
|
"index.cjs",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linux-arm64",
|
"name": "@img/sharp-linux-arm64",
|
||||||
"version": "0.34.5",
|
"version": "0.35.0-rc.0",
|
||||||
"description": "Prebuilt sharp for use with Linux (glibc) 64-bit ARM",
|
"description": "Prebuilt sharp for use with Linux (glibc) 64-bit ARM",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linux-arm64": "1.3.0-rc.1"
|
"@img/sharp-libvips-linux-arm64": "1.3.0-rc.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"index.cjs",
|
"index.cjs",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linux-ppc64",
|
"name": "@img/sharp-linux-ppc64",
|
||||||
"version": "0.34.5",
|
"version": "0.35.0-rc.0",
|
||||||
"description": "Prebuilt sharp for use with Linux (glibc) ppc64",
|
"description": "Prebuilt sharp for use with Linux (glibc) ppc64",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linux-ppc64": "1.3.0-rc.1"
|
"@img/sharp-libvips-linux-ppc64": "1.3.0-rc.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"index.cjs",
|
"index.cjs",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linux-riscv64",
|
"name": "@img/sharp-linux-riscv64",
|
||||||
"version": "0.34.5",
|
"version": "0.35.0-rc.0",
|
||||||
"description": "Prebuilt sharp for use with Linux (glibc) RISC-V 64-bit",
|
"description": "Prebuilt sharp for use with Linux (glibc) RISC-V 64-bit",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linux-riscv64": "1.3.0-rc.1"
|
"@img/sharp-libvips-linux-riscv64": "1.3.0-rc.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"index.cjs",
|
"index.cjs",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linux-s390x",
|
"name": "@img/sharp-linux-s390x",
|
||||||
"version": "0.34.5",
|
"version": "0.35.0-rc.0",
|
||||||
"description": "Prebuilt sharp for use with Linux (glibc) s390x",
|
"description": "Prebuilt sharp for use with Linux (glibc) s390x",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linux-s390x": "1.3.0-rc.1"
|
"@img/sharp-libvips-linux-s390x": "1.3.0-rc.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"index.cjs",
|
"index.cjs",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linux-x64",
|
"name": "@img/sharp-linux-x64",
|
||||||
"version": "0.34.5",
|
"version": "0.35.0-rc.0",
|
||||||
"description": "Prebuilt sharp for use with Linux (glibc) x64",
|
"description": "Prebuilt sharp for use with Linux (glibc) x64",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linux-x64": "1.3.0-rc.1"
|
"@img/sharp-libvips-linux-x64": "1.3.0-rc.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"index.cjs",
|
"index.cjs",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linuxmusl-arm64",
|
"name": "@img/sharp-linuxmusl-arm64",
|
||||||
"version": "0.34.5",
|
"version": "0.35.0-rc.0",
|
||||||
"description": "Prebuilt sharp for use with Linux (musl) 64-bit ARM",
|
"description": "Prebuilt sharp for use with Linux (musl) 64-bit ARM",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linuxmusl-arm64": "1.3.0-rc.1"
|
"@img/sharp-libvips-linuxmusl-arm64": "1.3.0-rc.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"index.cjs",
|
"index.cjs",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-linuxmusl-x64",
|
"name": "@img/sharp-linuxmusl-x64",
|
||||||
"version": "0.34.5",
|
"version": "0.35.0-rc.0",
|
||||||
"description": "Prebuilt sharp for use with Linux (musl) x64",
|
"description": "Prebuilt sharp for use with Linux (musl) x64",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
},
|
},
|
||||||
"preferUnplugged": true,
|
"preferUnplugged": true,
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-libvips-linuxmusl-x64": "1.3.0-rc.1"
|
"@img/sharp-libvips-linuxmusl-x64": "1.3.0-rc.2"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"index.cjs",
|
"index.cjs",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp",
|
"name": "@img/sharp",
|
||||||
"version": "0.34.5",
|
"version": "0.35.0-rc.0",
|
||||||
"private": "true",
|
"private": "true",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"darwin-arm64",
|
"darwin-arm64",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-wasm32",
|
"name": "@img/sharp-wasm32",
|
||||||
"version": "0.34.5",
|
"version": "0.35.0-rc.0",
|
||||||
"description": "Prebuilt sharp for use with wasm32",
|
"description": "Prebuilt sharp for use with wasm32",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-win32-arm64",
|
"name": "@img/sharp-win32-arm64",
|
||||||
"version": "0.34.5",
|
"version": "0.35.0-rc.0",
|
||||||
"description": "Prebuilt sharp for use with Windows 64-bit ARM",
|
"description": "Prebuilt sharp for use with Windows 64-bit ARM",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-win32-ia32",
|
"name": "@img/sharp-win32-ia32",
|
||||||
"version": "0.34.5",
|
"version": "0.35.0-rc.0",
|
||||||
"description": "Prebuilt sharp for use with Windows x86 (deprecated)",
|
"description": "Prebuilt sharp for use with Windows x86 (deprecated)",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@img/sharp-win32-x64",
|
"name": "@img/sharp-win32-x64",
|
||||||
"version": "0.34.5",
|
"version": "0.35.0-rc.0",
|
||||||
"description": "Prebuilt sharp for use with Windows x64",
|
"description": "Prebuilt sharp for use with Windows x64",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
|
|||||||
63
package.json
63
package.json
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "sharp",
|
"name": "sharp",
|
||||||
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images",
|
"description": "High performance Node.js image processing, the fastest module to resize JPEG, PNG, WebP, GIF, AVIF and TIFF images",
|
||||||
"version": "0.34.5",
|
"version": "0.35.0-rc.0",
|
||||||
"author": "Lovell Fuller <npm@lovell.info>",
|
"author": "Lovell Fuller <npm@lovell.info>",
|
||||||
"homepage": "https://sharp.pixelplumbing.com",
|
"homepage": "https://sharp.pixelplumbing.com",
|
||||||
"contributors": [
|
"contributors": [
|
||||||
@@ -89,7 +89,8 @@
|
|||||||
"Lachlan Newman <lachnewman007@gmail.com>",
|
"Lachlan Newman <lachnewman007@gmail.com>",
|
||||||
"Dennis Beatty <dennis@dcbeatty.com>",
|
"Dennis Beatty <dennis@dcbeatty.com>",
|
||||||
"Ingvar Stepanyan <me@rreverser.com>",
|
"Ingvar Stepanyan <me@rreverser.com>",
|
||||||
"Don Denton <don@happycollision.com>"
|
"Don Denton <don@happycollision.com>",
|
||||||
|
"Dmytro Tiapukhin <cool.gegeg@gmail.com>"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "node install/build.js",
|
"build": "node install/build.js",
|
||||||
@@ -143,40 +144,40 @@
|
|||||||
"semver": "^7.7.3"
|
"semver": "^7.7.3"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@img/sharp-darwin-arm64": "0.34.5",
|
"@img/sharp-darwin-arm64": "0.35.0-rc.0",
|
||||||
"@img/sharp-darwin-x64": "0.34.5",
|
"@img/sharp-darwin-x64": "0.35.0-rc.0",
|
||||||
"@img/sharp-libvips-darwin-arm64": "1.3.0-rc.1",
|
"@img/sharp-libvips-darwin-arm64": "1.3.0-rc.2",
|
||||||
"@img/sharp-libvips-darwin-x64": "1.3.0-rc.1",
|
"@img/sharp-libvips-darwin-x64": "1.3.0-rc.2",
|
||||||
"@img/sharp-libvips-linux-arm": "1.3.0-rc.1",
|
"@img/sharp-libvips-linux-arm": "1.3.0-rc.2",
|
||||||
"@img/sharp-libvips-linux-arm64": "1.3.0-rc.1",
|
"@img/sharp-libvips-linux-arm64": "1.3.0-rc.2",
|
||||||
"@img/sharp-libvips-linux-ppc64": "1.3.0-rc.1",
|
"@img/sharp-libvips-linux-ppc64": "1.3.0-rc.2",
|
||||||
"@img/sharp-libvips-linux-riscv64": "1.3.0-rc.1",
|
"@img/sharp-libvips-linux-riscv64": "1.3.0-rc.2",
|
||||||
"@img/sharp-libvips-linux-s390x": "1.3.0-rc.1",
|
"@img/sharp-libvips-linux-s390x": "1.3.0-rc.2",
|
||||||
"@img/sharp-libvips-linux-x64": "1.3.0-rc.1",
|
"@img/sharp-libvips-linux-x64": "1.3.0-rc.2",
|
||||||
"@img/sharp-libvips-linuxmusl-arm64": "1.3.0-rc.1",
|
"@img/sharp-libvips-linuxmusl-arm64": "1.3.0-rc.2",
|
||||||
"@img/sharp-libvips-linuxmusl-x64": "1.3.0-rc.1",
|
"@img/sharp-libvips-linuxmusl-x64": "1.3.0-rc.2",
|
||||||
"@img/sharp-linux-arm": "0.34.5",
|
"@img/sharp-linux-arm": "0.35.0-rc.0",
|
||||||
"@img/sharp-linux-arm64": "0.34.5",
|
"@img/sharp-linux-arm64": "0.35.0-rc.0",
|
||||||
"@img/sharp-linux-ppc64": "0.34.5",
|
"@img/sharp-linux-ppc64": "0.35.0-rc.0",
|
||||||
"@img/sharp-linux-riscv64": "0.34.5",
|
"@img/sharp-linux-riscv64": "0.35.0-rc.0",
|
||||||
"@img/sharp-linux-s390x": "0.34.5",
|
"@img/sharp-linux-s390x": "0.35.0-rc.0",
|
||||||
"@img/sharp-linux-x64": "0.34.5",
|
"@img/sharp-linux-x64": "0.35.0-rc.0",
|
||||||
"@img/sharp-linuxmusl-arm64": "0.34.5",
|
"@img/sharp-linuxmusl-arm64": "0.35.0-rc.0",
|
||||||
"@img/sharp-linuxmusl-x64": "0.34.5",
|
"@img/sharp-linuxmusl-x64": "0.35.0-rc.0",
|
||||||
"@img/sharp-wasm32": "0.34.5",
|
"@img/sharp-wasm32": "0.35.0-rc.0",
|
||||||
"@img/sharp-win32-arm64": "0.34.5",
|
"@img/sharp-win32-arm64": "0.35.0-rc.0",
|
||||||
"@img/sharp-win32-ia32": "0.34.5",
|
"@img/sharp-win32-ia32": "0.35.0-rc.0",
|
||||||
"@img/sharp-win32-x64": "0.34.5"
|
"@img/sharp-win32-x64": "0.35.0-rc.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "^2.3.10",
|
"@biomejs/biome": "^2.3.10",
|
||||||
"@cpplint/cli": "^0.1.0",
|
"@cpplint/cli": "^0.1.0",
|
||||||
"@emnapi/runtime": "^1.7.1",
|
"@emnapi/runtime": "^1.7.1",
|
||||||
"@img/sharp-libvips-dev": "1.3.0-rc.1",
|
"@img/sharp-libvips-dev": "1.3.0-rc.2",
|
||||||
"@img/sharp-libvips-dev-wasm32": "1.3.0-rc.1",
|
"@img/sharp-libvips-dev-wasm32": "1.3.0-rc.2",
|
||||||
"@img/sharp-libvips-win32-arm64": "1.3.0-rc.1",
|
"@img/sharp-libvips-win32-arm64": "1.3.0-rc.2",
|
||||||
"@img/sharp-libvips-win32-ia32": "1.3.0-rc.1",
|
"@img/sharp-libvips-win32-ia32": "1.3.0-rc.2",
|
||||||
"@img/sharp-libvips-win32-x64": "1.3.0-rc.1",
|
"@img/sharp-libvips-win32-x64": "1.3.0-rc.2",
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"emnapi": "^1.7.1",
|
"emnapi": "^1.7.1",
|
||||||
"exif-reader": "^2.0.3",
|
"exif-reader": "^2.0.3",
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
'defines': [
|
'defines': [
|
||||||
'_VIPS_PUBLIC=__declspec(dllexport)',
|
'_VIPS_PUBLIC=__declspec(dllexport)',
|
||||||
'_ALLOW_KEYWORD_MACROS',
|
'_ALLOW_KEYWORD_MACROS',
|
||||||
|
'_HAS_EXCEPTIONS=1',
|
||||||
'G_DISABLE_ASSERT',
|
'G_DISABLE_ASSERT',
|
||||||
'G_DISABLE_CAST_CHECKS',
|
'G_DISABLE_CAST_CHECKS',
|
||||||
'G_DISABLE_CHECKS'
|
'G_DISABLE_CHECKS'
|
||||||
@@ -148,7 +149,8 @@
|
|||||||
['OS == "win"', {
|
['OS == "win"', {
|
||||||
'defines': [
|
'defines': [
|
||||||
'_ALLOW_KEYWORD_MACROS',
|
'_ALLOW_KEYWORD_MACROS',
|
||||||
'_FILE_OFFSET_BITS=64'
|
'_FILE_OFFSET_BITS=64',
|
||||||
|
'_HAS_EXCEPTIONS=1'
|
||||||
],
|
],
|
||||||
'link_settings': {
|
'link_settings': {
|
||||||
'libraries': [
|
'libraries': [
|
||||||
|
|||||||
@@ -426,7 +426,7 @@ namespace sharp {
|
|||||||
}
|
}
|
||||||
if (ImageTypeSupportsPage(imageType)) {
|
if (ImageTypeSupportsPage(imageType)) {
|
||||||
option->set("n", descriptor->pages);
|
option->set("n", descriptor->pages);
|
||||||
option->set("page", descriptor->page);
|
option->set("page", std::max(0, descriptor->page));
|
||||||
}
|
}
|
||||||
switch (imageType) {
|
switch (imageType) {
|
||||||
case ImageType::SVG:
|
case ImageType::SVG:
|
||||||
@@ -456,6 +456,22 @@ namespace sharp {
|
|||||||
return option;
|
return option;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Should HEIF image be re-opened using the primary item?
|
||||||
|
*/
|
||||||
|
static bool HeifPrimaryPageReopen(VImage image, InputDescriptor *descriptor) {
|
||||||
|
if (image.get_typeof(VIPS_META_N_PAGES) == G_TYPE_INT && image.get_typeof("heif-primary") == G_TYPE_INT) {
|
||||||
|
if (image.get_int(VIPS_META_N_PAGES) > 1 && descriptor->pages == 1 && descriptor->page == -1) {
|
||||||
|
int const pagePrimary = image.get_int("heif-primary");
|
||||||
|
if (pagePrimary != 0) {
|
||||||
|
descriptor->page = pagePrimary;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Open an image from the given InputDescriptor (filesystem, compressed buffer, raw pixel data)
|
Open an image from the given InputDescriptor (filesystem, compressed buffer, raw pixel data)
|
||||||
*/
|
*/
|
||||||
@@ -490,12 +506,15 @@ namespace sharp {
|
|||||||
image = VImage::new_from_buffer(descriptor->buffer, descriptor->bufferLength, nullptr, option);
|
image = VImage::new_from_buffer(descriptor->buffer, descriptor->bufferLength, nullptr, option);
|
||||||
if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
|
if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
|
||||||
image = SetDensity(image, descriptor->density);
|
image = SetDensity(image, descriptor->density);
|
||||||
|
} else if (imageType == ImageType::HEIF && HeifPrimaryPageReopen(image, descriptor)) {
|
||||||
|
option = GetOptionsForImageType(imageType, descriptor);
|
||||||
|
image = VImage::new_from_buffer(descriptor->buffer, descriptor->bufferLength, nullptr, option);
|
||||||
}
|
}
|
||||||
} catch (vips::VError const &err) {
|
} catch (std::runtime_error const &err) {
|
||||||
throw vips::VError(std::string("Input buffer has corrupt header: ") + err.what());
|
throw std::runtime_error(std::string("Input buffer has corrupt header: ") + err.what());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw vips::VError("Input buffer contains unsupported image format");
|
throw std::runtime_error("Input buffer contains unsupported image format");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -566,10 +585,10 @@ namespace sharp {
|
|||||||
imageType = DetermineImageType(descriptor->file.data());
|
imageType = DetermineImageType(descriptor->file.data());
|
||||||
if (imageType == ImageType::MISSING) {
|
if (imageType == ImageType::MISSING) {
|
||||||
if (descriptor->file.find("<svg") != std::string::npos) {
|
if (descriptor->file.find("<svg") != std::string::npos) {
|
||||||
throw vips::VError("Input file is missing, did you mean "
|
throw std::runtime_error("Input file is missing, did you mean "
|
||||||
"sharp(Buffer.from('" + descriptor->file.substr(0, 8) + "...')?");
|
"sharp(Buffer.from('" + descriptor->file.substr(0, 8) + "...')?");
|
||||||
}
|
}
|
||||||
throw vips::VError("Input file is missing: " + descriptor->file);
|
throw std::runtime_error("Input file is missing: " + descriptor->file);
|
||||||
}
|
}
|
||||||
if (imageType != ImageType::UNKNOWN) {
|
if (imageType != ImageType::UNKNOWN) {
|
||||||
try {
|
try {
|
||||||
@@ -577,12 +596,15 @@ namespace sharp {
|
|||||||
image = VImage::new_from_file(descriptor->file.data(), option);
|
image = VImage::new_from_file(descriptor->file.data(), option);
|
||||||
if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
|
if (imageType == ImageType::SVG || imageType == ImageType::PDF || imageType == ImageType::MAGICK) {
|
||||||
image = SetDensity(image, descriptor->density);
|
image = SetDensity(image, descriptor->density);
|
||||||
|
} else if (imageType == ImageType::HEIF && HeifPrimaryPageReopen(image, descriptor)) {
|
||||||
|
option = GetOptionsForImageType(imageType, descriptor);
|
||||||
|
image = VImage::new_from_file(descriptor->file.data(), option);
|
||||||
}
|
}
|
||||||
} catch (vips::VError const &err) {
|
} catch (std::runtime_error const &err) {
|
||||||
throw vips::VError(std::string("Input file has corrupt header: ") + err.what());
|
throw std::runtime_error(std::string("Input file has corrupt header: ") + err.what());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw vips::VError("Input file contains unsupported image format");
|
throw std::runtime_error("Input file contains unsupported image format");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -590,7 +612,7 @@ namespace sharp {
|
|||||||
// Limit input images to a given number of pixels, where pixels = width * height
|
// Limit input images to a given number of pixels, where pixels = width * height
|
||||||
if (descriptor->limitInputPixels > 0 &&
|
if (descriptor->limitInputPixels > 0 &&
|
||||||
static_cast<uint64_t>(image.width()) * image.height() > descriptor->limitInputPixels) {
|
static_cast<uint64_t>(image.width()) * image.height() > descriptor->limitInputPixels) {
|
||||||
throw vips::VError("Input image exceeds pixel limit");
|
throw std::runtime_error("Input image exceeds pixel limit");
|
||||||
}
|
}
|
||||||
return std::make_tuple(image, imageType);
|
return std::make_tuple(image, imageType);
|
||||||
}
|
}
|
||||||
@@ -766,19 +788,19 @@ namespace sharp {
|
|||||||
: image.height();
|
: image.height();
|
||||||
if (imageType == ImageType::JPEG) {
|
if (imageType == ImageType::JPEG) {
|
||||||
if (image.width() > 65535 || height > 65535) {
|
if (image.width() > 65535 || height > 65535) {
|
||||||
throw vips::VError("Processed image is too large for the JPEG format");
|
throw std::runtime_error("Processed image is too large for the JPEG format");
|
||||||
}
|
}
|
||||||
} else if (imageType == ImageType::WEBP) {
|
} else if (imageType == ImageType::WEBP) {
|
||||||
if (image.width() > 16383 || height > 16383) {
|
if (image.width() > 16383 || height > 16383) {
|
||||||
throw vips::VError("Processed image is too large for the WebP format");
|
throw std::runtime_error("Processed image is too large for the WebP format");
|
||||||
}
|
}
|
||||||
} else if (imageType == ImageType::GIF) {
|
} else if (imageType == ImageType::GIF) {
|
||||||
if (image.width() > 65535 || height > 65535) {
|
if (image.width() > 65535 || height > 65535) {
|
||||||
throw vips::VError("Processed image is too large for the GIF format");
|
throw std::runtime_error("Processed image is too large for the GIF format");
|
||||||
}
|
}
|
||||||
} else if (imageType == ImageType::HEIF) {
|
} else if (imageType == ImageType::HEIF) {
|
||||||
if (image.width() > 16384 || height > 16384) {
|
if (image.width() > 16384 || height > 16384) {
|
||||||
throw vips::VError("Processed image is too large for the HEIF format");
|
throw std::runtime_error("Processed image is too large for the HEIF format");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ namespace sharp {
|
|||||||
rawPremultiplied(false),
|
rawPremultiplied(false),
|
||||||
rawPageHeight(0),
|
rawPageHeight(0),
|
||||||
pages(1),
|
pages(1),
|
||||||
page(0),
|
page(-1),
|
||||||
createChannels(0),
|
createChannels(0),
|
||||||
createWidth(0),
|
createWidth(0),
|
||||||
createHeight(0),
|
createHeight(0),
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class MetadataWorker : public Napi::AsyncWorker {
|
|||||||
sharp::ImageType imageType = sharp::ImageType::UNKNOWN;
|
sharp::ImageType imageType = sharp::ImageType::UNKNOWN;
|
||||||
try {
|
try {
|
||||||
std::tie(image, imageType) = OpenInput(baton->input);
|
std::tie(image, imageType) = OpenInput(baton->input);
|
||||||
} catch (vips::VError const &err) {
|
} catch (std::runtime_error const &err) {
|
||||||
(baton->err).append(err.what());
|
(baton->err).append(err.what());
|
||||||
}
|
}
|
||||||
if (imageType != sharp::ImageType::UNKNOWN) {
|
if (imageType != sharp::ImageType::UNKNOWN) {
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
#include "./operations.h"
|
#include "./operations.h"
|
||||||
|
|
||||||
using vips::VImage;
|
using vips::VImage;
|
||||||
using vips::VError;
|
|
||||||
|
|
||||||
namespace sharp {
|
namespace sharp {
|
||||||
/*
|
/*
|
||||||
@@ -285,9 +284,9 @@ namespace sharp {
|
|||||||
/*
|
/*
|
||||||
Trim an image
|
Trim an image
|
||||||
*/
|
*/
|
||||||
VImage Trim(VImage image, std::vector<double> background, double threshold, bool const lineArt) {
|
VImage Trim(VImage image, std::vector<double> background, double threshold, bool const lineArt, int const margin) {
|
||||||
if (image.width() < 3 && image.height() < 3) {
|
if (image.width() < 3 && image.height() < 3) {
|
||||||
throw VError("Image to trim must be at least 3x3 pixels");
|
throw std::runtime_error("Image to trim must be at least 3x3 pixels");
|
||||||
}
|
}
|
||||||
if (background.size() == 0) {
|
if (background.size() == 0) {
|
||||||
// Top-left pixel provides the default background colour if none is given
|
// Top-left pixel provides the default background colour if none is given
|
||||||
@@ -320,18 +319,36 @@ namespace sharp {
|
|||||||
if (widthA > 0 && heightA > 0) {
|
if (widthA > 0 && heightA > 0) {
|
||||||
if (width > 0 && height > 0) {
|
if (width > 0 && height > 0) {
|
||||||
// Combined bounding box (B)
|
// Combined bounding box (B)
|
||||||
int const leftB = std::min(left, leftA);
|
int leftB = std::min(left, leftA);
|
||||||
int const topB = std::min(top, topA);
|
int topB = std::min(top, topA);
|
||||||
int const widthB = std::max(left + width, leftA + widthA) - leftB;
|
int widthB = std::max(left + width, leftA + widthA) - leftB;
|
||||||
int const heightB = std::max(top + height, topA + heightA) - topB;
|
int heightB = std::max(top + height, topA + heightA) - topB;
|
||||||
|
if (margin > 0) {
|
||||||
|
leftB = std::max(0, leftB - margin);
|
||||||
|
topB = std::max(0, topB - margin);
|
||||||
|
widthB = std::min(image.width() - leftB, widthB + 2 * margin);
|
||||||
|
heightB = std::min(image.height() - topB, heightB + 2 * margin);
|
||||||
|
}
|
||||||
return image.extract_area(leftB, topB, widthB, heightB);
|
return image.extract_area(leftB, topB, widthB, heightB);
|
||||||
} else {
|
} else {
|
||||||
// Use alpha only
|
// Use alpha only
|
||||||
|
if (margin > 0) {
|
||||||
|
leftA = std::max(0, leftA - margin);
|
||||||
|
topA = std::max(0, topA - margin);
|
||||||
|
widthA = std::min(image.width() - leftA, widthA + 2 * margin);
|
||||||
|
heightA = std::min(image.height() - topA, heightA + 2 * margin);
|
||||||
|
}
|
||||||
return image.extract_area(leftA, topA, widthA, heightA);
|
return image.extract_area(leftA, topA, widthA, heightA);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (width > 0 && height > 0) {
|
if (width > 0 && height > 0) {
|
||||||
|
if (margin > 0) {
|
||||||
|
left = std::max(0, left - margin);
|
||||||
|
top = std::max(0, top - margin);
|
||||||
|
width = std::min(image.width() - left, width + 2 * margin);
|
||||||
|
height = std::min(image.height() - top, height + 2 * margin);
|
||||||
|
}
|
||||||
return image.extract_area(left, top, width, height);
|
return image.extract_area(left, top, width, height);
|
||||||
}
|
}
|
||||||
return image;
|
return image;
|
||||||
@@ -343,7 +360,7 @@ namespace sharp {
|
|||||||
VImage Linear(VImage image, std::vector<double> const a, std::vector<double> const b) {
|
VImage Linear(VImage image, std::vector<double> const a, std::vector<double> const b) {
|
||||||
size_t const bands = static_cast<size_t>(image.bands());
|
size_t const bands = static_cast<size_t>(image.bands());
|
||||||
if (a.size() > bands) {
|
if (a.size() > bands) {
|
||||||
throw VError("Band expansion using linear is unsupported");
|
throw std::runtime_error("Band expansion using linear is unsupported");
|
||||||
}
|
}
|
||||||
bool const uchar = !Is16Bit(image.interpretation());
|
bool const uchar = !Is16Bit(image.interpretation());
|
||||||
if (image.has_alpha() && a.size() != bands && (a.size() == 1 || a.size() == bands - 1 || bands - 1 == 1)) {
|
if (image.has_alpha() && a.size() != bands && (a.size() == 1 || a.size() == bands - 1 || bands - 1 == 1)) {
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ namespace sharp {
|
|||||||
/*
|
/*
|
||||||
Trim an image
|
Trim an image
|
||||||
*/
|
*/
|
||||||
VImage Trim(VImage image, std::vector<double> background, double threshold, bool const lineArt);
|
VImage Trim(VImage image, std::vector<double> background, double threshold, bool const lineArt, int const margin);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Linear adjustment (a * in + b)
|
* Linear adjustment (a * in + b)
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
if (nPages == -1) {
|
if (nPages == -1) {
|
||||||
// Resolve the number of pages if we need to render until the end of the document
|
// Resolve the number of pages if we need to render until the end of the document
|
||||||
nPages = image.get_typeof(VIPS_META_N_PAGES) != 0
|
nPages = image.get_typeof(VIPS_META_N_PAGES) != 0
|
||||||
? image.get_int(VIPS_META_N_PAGES) - baton->input->page
|
? image.get_int(VIPS_META_N_PAGES) - std::max(0, baton->input->page)
|
||||||
: 1;
|
: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
if (baton->trimThreshold >= 0.0) {
|
if (baton->trimThreshold >= 0.0) {
|
||||||
MultiPageUnsupported(nPages, "Trim");
|
MultiPageUnsupported(nPages, "Trim");
|
||||||
image = sharp::StaySequential(image);
|
image = sharp::StaySequential(image);
|
||||||
image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold, baton->trimLineArt);
|
image = sharp::Trim(image, baton->trimBackground, baton->trimThreshold, baton->trimLineArt, baton->trimMargin);
|
||||||
baton->trimOffsetLeft = image.xoffset();
|
baton->trimOffsetLeft = image.xoffset();
|
||||||
baton->trimOffsetTop = image.yoffset();
|
baton->trimOffsetTop = image.yoffset();
|
||||||
}
|
}
|
||||||
@@ -274,7 +274,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
}
|
}
|
||||||
sharp::SetDensity(image, baton->input->density);
|
sharp::SetDensity(image, baton->input->density);
|
||||||
if (image.width() > 32767 || image.height() > 32767) {
|
if (image.width() > 32767 || image.height() > 32767) {
|
||||||
throw vips::VError("Input SVG image will exceed 32767x32767 pixel limit when scaled");
|
throw std::runtime_error("Input SVG image will exceed 32767x32767 pixel limit when scaled");
|
||||||
}
|
}
|
||||||
} else if (inputImageType == sharp::ImageType::PDF) {
|
} else if (inputImageType == sharp::ImageType::PDF) {
|
||||||
if (baton->input->buffer != nullptr) {
|
if (baton->input->buffer != nullptr) {
|
||||||
@@ -290,7 +290,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (inputImageType == sharp::ImageType::SVG && (image.width() > 32767 || image.height() > 32767)) {
|
if (inputImageType == sharp::ImageType::SVG && (image.width() > 32767 || image.height() > 32767)) {
|
||||||
throw vips::VError("Input SVG image exceeds 32767x32767 pixel limit");
|
throw std::runtime_error("Input SVG image exceeds 32767x32767 pixel limit");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (baton->input->autoOrient) {
|
if (baton->input->autoOrient) {
|
||||||
@@ -675,7 +675,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
|
|
||||||
// Verify within current dimensions
|
// Verify within current dimensions
|
||||||
if (compositeImage.width() > image.width() || compositeImage.height() > image.height()) {
|
if (compositeImage.width() > image.width() || compositeImage.height() > image.height()) {
|
||||||
throw vips::VError("Image to composite must have same dimensions or smaller");
|
throw std::runtime_error("Image to composite must have same dimensions or smaller");
|
||||||
}
|
}
|
||||||
// Check if overlay is tiled
|
// Check if overlay is tiled
|
||||||
if (composite->tile) {
|
if (composite->tile) {
|
||||||
@@ -1086,20 +1086,19 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
// Get raw image data
|
// Get raw image data
|
||||||
baton->bufferOut = static_cast<char*>(image.write_to_memory(&baton->bufferOutLength));
|
baton->bufferOut = static_cast<char*>(image.write_to_memory(&baton->bufferOutLength));
|
||||||
if (baton->bufferOut == nullptr) {
|
if (baton->bufferOut == nullptr) {
|
||||||
(baton->err).append("Could not allocate enough memory for raw output");
|
throw std::runtime_error("Could not allocate enough memory for raw output");
|
||||||
return Error();
|
|
||||||
}
|
}
|
||||||
baton->formatOut = "raw";
|
baton->formatOut = "raw";
|
||||||
} else {
|
} else {
|
||||||
// Unsupported output format
|
// Unsupported output format
|
||||||
(baton->err).append("Unsupported output format ");
|
auto unsupported = std::string("Unsupported output format ");
|
||||||
if (baton->formatOut == "input") {
|
if (baton->formatOut == "input") {
|
||||||
(baton->err).append("when trying to match input format of ");
|
unsupported.append("when trying to match input format of ");
|
||||||
(baton->err).append(ImageTypeId(inputImageType));
|
unsupported.append(ImageTypeId(inputImageType));
|
||||||
} else {
|
} else {
|
||||||
(baton->err).append(baton->formatOut);
|
unsupported.append(baton->formatOut);
|
||||||
}
|
}
|
||||||
return Error();
|
throw std::runtime_error(unsupported);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// File output
|
// File output
|
||||||
@@ -1274,7 +1273,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
return Error();
|
return Error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (vips::VError const &err) {
|
} catch (std::runtime_error const &err) {
|
||||||
char const *what = err.what();
|
char const *what = err.what();
|
||||||
if (what && what[0]) {
|
if (what && what[0]) {
|
||||||
(baton->err).append(what);
|
(baton->err).append(what);
|
||||||
@@ -1306,7 +1305,6 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
}
|
}
|
||||||
warning = sharp::VipsWarningPop();
|
warning = sharp::VipsWarningPop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (baton->err.empty()) {
|
if (baton->err.empty()) {
|
||||||
int width = baton->width;
|
int width = baton->width;
|
||||||
int height = baton->height;
|
int height = baton->height;
|
||||||
@@ -1407,7 +1405,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
|
|
||||||
void MultiPageUnsupported(int const pages, std::string op) {
|
void MultiPageUnsupported(int const pages, std::string op) {
|
||||||
if (pages > 1) {
|
if (pages > 1) {
|
||||||
throw vips::VError(op + " is not supported for multi-page images");
|
throw std::runtime_error(op + " is not supported for multi-page images");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1637,6 +1635,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|||||||
baton->trimBackground = sharp::AttrAsVectorOfDouble(options, "trimBackground");
|
baton->trimBackground = sharp::AttrAsVectorOfDouble(options, "trimBackground");
|
||||||
baton->trimThreshold = sharp::AttrAsDouble(options, "trimThreshold");
|
baton->trimThreshold = sharp::AttrAsDouble(options, "trimThreshold");
|
||||||
baton->trimLineArt = sharp::AttrAsBool(options, "trimLineArt");
|
baton->trimLineArt = sharp::AttrAsBool(options, "trimLineArt");
|
||||||
|
baton->trimMargin = sharp::AttrAsUint32(options, "trimMargin");
|
||||||
baton->gamma = sharp::AttrAsDouble(options, "gamma");
|
baton->gamma = sharp::AttrAsDouble(options, "gamma");
|
||||||
baton->gammaOut = sharp::AttrAsDouble(options, "gammaOut");
|
baton->gammaOut = sharp::AttrAsDouble(options, "gammaOut");
|
||||||
baton->linearA = sharp::AttrAsVectorOfDouble(options, "linearA");
|
baton->linearA = sharp::AttrAsVectorOfDouble(options, "linearA");
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ struct PipelineBaton {
|
|||||||
bool trimLineArt;
|
bool trimLineArt;
|
||||||
int trimOffsetLeft;
|
int trimOffsetLeft;
|
||||||
int trimOffsetTop;
|
int trimOffsetTop;
|
||||||
|
int trimMargin;
|
||||||
std::vector<double> linearA;
|
std::vector<double> linearA;
|
||||||
std::vector<double> linearB;
|
std::vector<double> linearB;
|
||||||
int dilateWidth;
|
int dilateWidth;
|
||||||
@@ -286,6 +287,7 @@ struct PipelineBaton {
|
|||||||
trimLineArt(false),
|
trimLineArt(false),
|
||||||
trimOffsetLeft(0),
|
trimOffsetLeft(0),
|
||||||
trimOffsetTop(0),
|
trimOffsetTop(0),
|
||||||
|
trimMargin(0),
|
||||||
linearA{},
|
linearA{},
|
||||||
linearB{},
|
linearB{},
|
||||||
dilateWidth(0),
|
dilateWidth(0),
|
||||||
@@ -363,7 +365,7 @@ struct PipelineBaton {
|
|||||||
tiffBigtiff(false),
|
tiffBigtiff(false),
|
||||||
tiffPredictor(VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL),
|
tiffPredictor(VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL),
|
||||||
tiffPyramid(false),
|
tiffPyramid(false),
|
||||||
tiffBitdepth(8),
|
tiffBitdepth(0),
|
||||||
tiffMiniswhite(false),
|
tiffMiniswhite(false),
|
||||||
tiffTile(false),
|
tiffTile(false),
|
||||||
tiffTileHeight(256),
|
tiffTileHeight(256),
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class StatsWorker : public Napi::AsyncWorker {
|
|||||||
sharp::ImageType imageType = sharp::ImageType::UNKNOWN;
|
sharp::ImageType imageType = sharp::ImageType::UNKNOWN;
|
||||||
try {
|
try {
|
||||||
std::tie(image, imageType) = OpenInput(baton->input);
|
std::tie(image, imageType) = OpenInput(baton->input);
|
||||||
} catch (vips::VError const &err) {
|
} catch (std::runtime_error const &err) {
|
||||||
(baton->err).append(err.what());
|
(baton->err).append(err.what());
|
||||||
}
|
}
|
||||||
if (imageType != sharp::ImageType::UNKNOWN) {
|
if (imageType != sharp::ImageType::UNKNOWN) {
|
||||||
@@ -92,7 +92,7 @@ class StatsWorker : public Napi::AsyncWorker {
|
|||||||
baton->dominantRed = dx * 16 + 8;
|
baton->dominantRed = dx * 16 + 8;
|
||||||
baton->dominantGreen = dy * 16 + 8;
|
baton->dominantGreen = dy * 16 + 8;
|
||||||
baton->dominantBlue = dz * 16 + 8;
|
baton->dominantBlue = dz * 16 + 8;
|
||||||
} catch (vips::VError const &err) {
|
} catch (std::runtime_error const &err) {
|
||||||
(baton->err).append(err.what());
|
(baton->err).append(err.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,7 +112,6 @@ class StatsWorker : public Napi::AsyncWorker {
|
|||||||
debuglog.Call(Receiver().Value(), { Napi::String::New(env, warning) });
|
debuglog.Call(Receiver().Value(), { Napi::String::New(env, warning) });
|
||||||
warning = sharp::VipsWarningPop();
|
warning = sharp::VipsWarningPop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (baton->err.empty()) {
|
if (baton->err.empty()) {
|
||||||
// Stats Object
|
// Stats Object
|
||||||
Napi::Object info = Napi::Object::New(env);
|
Napi::Object info = Napi::Object::New(env);
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ Napi::Value format(const Napi::CallbackInfo& info) {
|
|||||||
"jpeg", "png", "webp", "tiff", "magick", "openslide", "dz",
|
"jpeg", "png", "webp", "tiff", "magick", "openslide", "dz",
|
||||||
"ppm", "fits", "gif", "svg", "heif", "pdf", "vips", "jp2k", "jxl", "rad", "dcraw"
|
"ppm", "fits", "gif", "svg", "heif", "pdf", "vips", "jp2k", "jxl", "rad", "dcraw"
|
||||||
}) {
|
}) {
|
||||||
|
std::string id = f == "jp2k" ? "jp2" : f;
|
||||||
// Input
|
// Input
|
||||||
const VipsObjectClass *oc = vips_class_find("VipsOperation", (f + "load").c_str());
|
const VipsObjectClass *oc = vips_class_find("VipsOperation", (f + "load").c_str());
|
||||||
Napi::Boolean hasInputFile = Napi::Boolean::New(env, oc);
|
Napi::Boolean hasInputFile = Napi::Boolean::New(env, oc);
|
||||||
@@ -154,11 +155,11 @@ Napi::Value format(const Napi::CallbackInfo& info) {
|
|||||||
output.Set("stream", hasOutputBuffer);
|
output.Set("stream", hasOutputBuffer);
|
||||||
// Other attributes
|
// Other attributes
|
||||||
Napi::Object container = Napi::Object::New(env);
|
Napi::Object container = Napi::Object::New(env);
|
||||||
container.Set("id", f);
|
container.Set("id", id);
|
||||||
container.Set("input", input);
|
container.Set("input", input);
|
||||||
container.Set("output", output);
|
container.Set("output", output);
|
||||||
// Add to set of formats
|
// Add to set of formats
|
||||||
format.Set(f, container);
|
format.Set(id, container);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Raw, uncompressed data
|
// Raw, uncompressed data
|
||||||
@@ -243,7 +244,7 @@ Napi::Value _maxColourDistance(const Napi::CallbackInfo& info) {
|
|||||||
}
|
}
|
||||||
// Calculate colour distance
|
// Calculate colour distance
|
||||||
maxColourDistance = image1.dE00(image2).max();
|
maxColourDistance = image1.dE00(image2).max();
|
||||||
} catch (vips::VError const &err) {
|
} catch (std::runtime_error const &err) {
|
||||||
throw Napi::Error::New(env, err.what());
|
throw Napi::Error::New(env, err.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
3
test/fixtures/index.js
vendored
3
test/fixtures/index.js
vendored
@@ -74,6 +74,7 @@ module.exports = {
|
|||||||
|
|
||||||
inputPng: getPath('50020484-00001.png'), // http://c.searspartsdirect.com/lis_png/PLDM/50020484-00001.png
|
inputPng: getPath('50020484-00001.png'), // http://c.searspartsdirect.com/lis_png/PLDM/50020484-00001.png
|
||||||
inputPngGradients: getPath('gradients-rgb8.png'),
|
inputPngGradients: getPath('gradients-rgb8.png'),
|
||||||
|
inputPngWithSlightGradientBorder: getPath('slight-gradient-border.png'),
|
||||||
inputPngWithTransparency: getPath('blackbug.png'), // public domain
|
inputPngWithTransparency: getPath('blackbug.png'), // public domain
|
||||||
inputPngCompleteTransparency: getPath('full-transparent.png'),
|
inputPngCompleteTransparency: getPath('full-transparent.png'),
|
||||||
inputPngWithGreyAlpha: getPath('grey-8bit-alpha.png'),
|
inputPngWithGreyAlpha: getPath('grey-8bit-alpha.png'),
|
||||||
@@ -126,7 +127,7 @@ module.exports = {
|
|||||||
inputSvgSmallViewBox: getPath('circle.svg'),
|
inputSvgSmallViewBox: getPath('circle.svg'),
|
||||||
inputSvgWithEmbeddedImages: getPath('struct-image-04-t.svg'), // https://dev.w3.org/SVG/profiles/1.2T/test/svg/struct-image-04-t.svg
|
inputSvgWithEmbeddedImages: getPath('struct-image-04-t.svg'), // https://dev.w3.org/SVG/profiles/1.2T/test/svg/struct-image-04-t.svg
|
||||||
inputAvif: getPath('sdr_cosmos12920_cicp1-13-6_yuv444_full_qp10.avif'), // CC by-nc-nd https://github.com/AOMediaCodec/av1-avif/tree/master/testFiles/Netflix
|
inputAvif: getPath('sdr_cosmos12920_cicp1-13-6_yuv444_full_qp10.avif'), // CC by-nc-nd https://github.com/AOMediaCodec/av1-avif/tree/master/testFiles/Netflix
|
||||||
|
inputAvifWithPitmBox: getPath('pitm.avif'), // https://github.com/lovell/sharp/issues/4487
|
||||||
inputJPGBig: getPath('flowers.jpeg'),
|
inputJPGBig: getPath('flowers.jpeg'),
|
||||||
|
|
||||||
inputPngDotAndLines: getPath('dot-and-lines.png'),
|
inputPngDotAndLines: getPath('dot-and-lines.png'),
|
||||||
|
|||||||
BIN
test/fixtures/pitm.avif
vendored
Normal file
BIN
test/fixtures/pitm.avif
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
BIN
test/fixtures/slight-gradient-border.png
vendored
Normal file
BIN
test/fixtures/slight-gradient-border.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
@@ -234,7 +234,7 @@ sharp(input)
|
|||||||
|
|
||||||
sharp(input)
|
sharp(input)
|
||||||
.resize(100, 100)
|
.resize(100, 100)
|
||||||
.toFormat('jpg')
|
.toFormat('avif')
|
||||||
.toBuffer({ resolveWithObject: false })
|
.toBuffer({ resolveWithObject: false })
|
||||||
.then((outputBuffer: Buffer) => {
|
.then((outputBuffer: Buffer) => {
|
||||||
// Resolves with a Buffer object when resolveWithObject is false
|
// Resolves with a Buffer object when resolveWithObject is false
|
||||||
@@ -267,9 +267,7 @@ sharp(input)
|
|||||||
// Output to tif
|
// Output to tif
|
||||||
sharp(input)
|
sharp(input)
|
||||||
.resize(100, 100)
|
.resize(100, 100)
|
||||||
.toFormat('tif')
|
|
||||||
.toFormat('tiff')
|
.toFormat('tiff')
|
||||||
.toFormat(sharp.format.tif)
|
|
||||||
.toFormat(sharp.format.tiff)
|
.toFormat(sharp.format.tiff)
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
|
|
||||||
@@ -601,7 +599,7 @@ const vertexSplitQuadraticBasisSpline: string = sharp.interpolators.vertexSplitQ
|
|||||||
// Triming
|
// Triming
|
||||||
sharp(input).trim({ background: '#000' }).toBuffer();
|
sharp(input).trim({ background: '#000' }).toBuffer();
|
||||||
sharp(input).trim({ threshold: 10, lineArt: true }).toBuffer();
|
sharp(input).trim({ threshold: 10, lineArt: true }).toBuffer();
|
||||||
sharp(input).trim({ background: '#bf1942', threshold: 30 }).toBuffer();
|
sharp(input).trim({ background: '#bf1942', threshold: 30, margin: 20 }).toBuffer();
|
||||||
|
|
||||||
// Text input
|
// Text input
|
||||||
sharp({
|
sharp({
|
||||||
@@ -774,3 +772,35 @@ sharp().erode();
|
|||||||
sharp().erode(1);
|
sharp().erode(1);
|
||||||
sharp().dilate();
|
sharp().dilate();
|
||||||
sharp().dilate(1);
|
sharp().dilate(1);
|
||||||
|
|
||||||
|
sharp.format.dcraw;
|
||||||
|
sharp.format.dz;
|
||||||
|
sharp.format.fits;
|
||||||
|
sharp.format.gif;
|
||||||
|
sharp.format.heif;
|
||||||
|
sharp.format.jp2;
|
||||||
|
sharp.format.jpeg;
|
||||||
|
sharp.format.jxl;
|
||||||
|
sharp.format.magick;
|
||||||
|
sharp.format.openslide;
|
||||||
|
sharp.format.pdf;
|
||||||
|
sharp.format.png;
|
||||||
|
sharp.format.ppm;
|
||||||
|
sharp.format.rad;
|
||||||
|
sharp.format.raw;
|
||||||
|
sharp.format.svg;
|
||||||
|
sharp.format.tiff;
|
||||||
|
sharp.format.vips;
|
||||||
|
sharp.format.webp;
|
||||||
|
// @ts-expect-error
|
||||||
|
sharp.format.avif;
|
||||||
|
// @ts-expect-error
|
||||||
|
sharp.format.input;
|
||||||
|
// @ts-expect-error
|
||||||
|
sharp.format.jp2k;
|
||||||
|
// @ts-expect-error
|
||||||
|
sharp.format.jpg;
|
||||||
|
// @ts-expect-error
|
||||||
|
sharp.format.tif;
|
||||||
|
// @ts-expect-error
|
||||||
|
sharp.format.v;
|
||||||
|
|||||||
@@ -7,7 +7,13 @@ const { describe, it } = require('node:test');
|
|||||||
const assert = require('node:assert');
|
const assert = require('node:assert');
|
||||||
|
|
||||||
const sharp = require('../../');
|
const sharp = require('../../');
|
||||||
const { inputAvif, inputJpg, inputGifAnimated } = require('../fixtures');
|
const {
|
||||||
|
inputAvif,
|
||||||
|
inputAvifWithPitmBox,
|
||||||
|
inputJpg,
|
||||||
|
inputGifAnimated,
|
||||||
|
inputPng,
|
||||||
|
} = require('../fixtures');
|
||||||
|
|
||||||
describe('AVIF', () => {
|
describe('AVIF', () => {
|
||||||
it('called without options does not throw an error', () => {
|
it('called without options does not throw an error', () => {
|
||||||
@@ -17,16 +23,13 @@ describe('AVIF', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('can convert AVIF to JPEG', async () => {
|
it('can convert AVIF to JPEG', async () => {
|
||||||
const data = await sharp(inputAvif)
|
const data = await sharp(inputAvif).resize(32).jpeg().toBuffer();
|
||||||
.resize(32)
|
|
||||||
.jpeg()
|
|
||||||
.toBuffer();
|
|
||||||
const { size, ...metadata } = await sharp(data).metadata();
|
const { size, ...metadata } = await sharp(data).metadata();
|
||||||
void size;
|
void size;
|
||||||
assert.deepStrictEqual(metadata, {
|
assert.deepStrictEqual(metadata, {
|
||||||
autoOrient: {
|
autoOrient: {
|
||||||
height: 13,
|
height: 13,
|
||||||
width: 32
|
width: 32,
|
||||||
},
|
},
|
||||||
channels: 3,
|
channels: 3,
|
||||||
chromaSubsampling: '4:2:0',
|
chromaSubsampling: '4:2:0',
|
||||||
@@ -41,7 +44,7 @@ describe('AVIF', () => {
|
|||||||
isProgressive: false,
|
isProgressive: false,
|
||||||
isPalette: false,
|
isPalette: false,
|
||||||
space: 'srgb',
|
space: 'srgb',
|
||||||
width: 32
|
width: 32,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -55,7 +58,7 @@ describe('AVIF', () => {
|
|||||||
assert.deepStrictEqual(metadata, {
|
assert.deepStrictEqual(metadata, {
|
||||||
autoOrient: {
|
autoOrient: {
|
||||||
height: 26,
|
height: 26,
|
||||||
width: 32
|
width: 32,
|
||||||
},
|
},
|
||||||
channels: 3,
|
channels: 3,
|
||||||
compression: 'av1',
|
compression: 'av1',
|
||||||
@@ -70,20 +73,47 @@ describe('AVIF', () => {
|
|||||||
pagePrimary: 0,
|
pagePrimary: 0,
|
||||||
pages: 1,
|
pages: 1,
|
||||||
space: 'srgb',
|
space: 'srgb',
|
||||||
width: 32
|
width: 32,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can passthrough AVIF', async () => {
|
it('can convert PNG to lossless AVIF', async () => {
|
||||||
const data = await sharp(inputAvif)
|
const data = await sharp(inputPng)
|
||||||
.resize(32)
|
.resize(32)
|
||||||
|
.avif({ lossless: true, effort: 0 })
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
const { size, ...metadata } = await sharp(data).metadata();
|
const { size, ...metadata } = await sharp(data).metadata();
|
||||||
void size;
|
void size;
|
||||||
|
assert.deepStrictEqual(metadata, {
|
||||||
|
autoOrient: {
|
||||||
|
height: 24,
|
||||||
|
width: 32,
|
||||||
|
},
|
||||||
|
channels: 3,
|
||||||
|
compression: 'av1',
|
||||||
|
depth: 'uchar',
|
||||||
|
format: 'heif',
|
||||||
|
hasAlpha: false,
|
||||||
|
hasProfile: false,
|
||||||
|
height: 24,
|
||||||
|
isProgressive: false,
|
||||||
|
isPalette: false,
|
||||||
|
bitsPerSample: 8,
|
||||||
|
pagePrimary: 0,
|
||||||
|
pages: 1,
|
||||||
|
space: 'srgb',
|
||||||
|
width: 32,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can passthrough AVIF', async () => {
|
||||||
|
const data = await sharp(inputAvif).resize(32).toBuffer();
|
||||||
|
const { size, ...metadata } = await sharp(data).metadata();
|
||||||
|
void size;
|
||||||
assert.deepStrictEqual(metadata, {
|
assert.deepStrictEqual(metadata, {
|
||||||
autoOrient: {
|
autoOrient: {
|
||||||
height: 13,
|
height: 13,
|
||||||
width: 32
|
width: 32,
|
||||||
},
|
},
|
||||||
channels: 3,
|
channels: 3,
|
||||||
compression: 'av1',
|
compression: 'av1',
|
||||||
@@ -98,7 +128,7 @@ describe('AVIF', () => {
|
|||||||
pagePrimary: 0,
|
pagePrimary: 0,
|
||||||
pages: 1,
|
pages: 1,
|
||||||
space: 'srgb',
|
space: 'srgb',
|
||||||
width: 32
|
width: 32,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -112,7 +142,7 @@ describe('AVIF', () => {
|
|||||||
assert.deepStrictEqual(metadata, {
|
assert.deepStrictEqual(metadata, {
|
||||||
autoOrient: {
|
autoOrient: {
|
||||||
height: 300,
|
height: 300,
|
||||||
width: 10
|
width: 10,
|
||||||
},
|
},
|
||||||
channels: 4,
|
channels: 4,
|
||||||
compression: 'av1',
|
compression: 'av1',
|
||||||
@@ -127,7 +157,7 @@ describe('AVIF', () => {
|
|||||||
pagePrimary: 0,
|
pagePrimary: 0,
|
||||||
pages: 1,
|
pages: 1,
|
||||||
space: 'srgb',
|
space: 'srgb',
|
||||||
width: 10
|
width: 10,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -142,7 +172,7 @@ describe('AVIF', () => {
|
|||||||
assert.deepStrictEqual(metadata, {
|
assert.deepStrictEqual(metadata, {
|
||||||
autoOrient: {
|
autoOrient: {
|
||||||
height: 26,
|
height: 26,
|
||||||
width: 32
|
width: 32,
|
||||||
},
|
},
|
||||||
channels: 3,
|
channels: 3,
|
||||||
compression: 'av1',
|
compression: 'av1',
|
||||||
@@ -157,30 +187,37 @@ describe('AVIF', () => {
|
|||||||
pagePrimary: 0,
|
pagePrimary: 0,
|
||||||
pages: 1,
|
pages: 1,
|
||||||
space: 'srgb',
|
space: 'srgb',
|
||||||
width: 32
|
width: 32,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Invalid width - too large', async () =>
|
it('Invalid width - too large', async () =>
|
||||||
assert.rejects(
|
assert.rejects(
|
||||||
() => sharp({ create: { width: 16385, height: 16, channels: 3, background: 'red' } }).avif().toBuffer(),
|
() =>
|
||||||
/Processed image is too large for the HEIF format/
|
sharp({
|
||||||
)
|
create: { width: 16385, height: 16, channels: 3, background: 'red' },
|
||||||
);
|
})
|
||||||
|
.avif()
|
||||||
|
.toBuffer(),
|
||||||
|
/Processed image is too large for the HEIF format/,
|
||||||
|
));
|
||||||
|
|
||||||
it('Invalid height - too large', async () =>
|
it('Invalid height - too large', async () =>
|
||||||
assert.rejects(
|
assert.rejects(
|
||||||
() => sharp({ create: { width: 16, height: 16385, channels: 3, background: 'red' } }).avif().toBuffer(),
|
() =>
|
||||||
/Processed image is too large for the HEIF format/
|
sharp({
|
||||||
)
|
create: { width: 16, height: 16385, channels: 3, background: 'red' },
|
||||||
);
|
})
|
||||||
|
.avif()
|
||||||
|
.toBuffer(),
|
||||||
|
/Processed image is too large for the HEIF format/,
|
||||||
|
));
|
||||||
|
|
||||||
it('Invalid bitdepth value throws error', () =>
|
it('Invalid bitdepth value throws error', () =>
|
||||||
assert.throws(
|
assert.throws(
|
||||||
() => sharp().avif({ bitdepth: 11 }),
|
() => sharp().avif({ bitdepth: 11 }),
|
||||||
/Expected 8, 10 or 12 for bitdepth but received 11 of type number/
|
/Expected 8, 10 or 12 for bitdepth but received 11 of type number/,
|
||||||
)
|
));
|
||||||
);
|
|
||||||
|
|
||||||
it('Different tune options result in different file sizes', async () => {
|
it('Different tune options result in different file sizes', async () => {
|
||||||
const ssim = await sharp(inputJpg)
|
const ssim = await sharp(inputJpg)
|
||||||
@@ -192,5 +229,47 @@ describe('AVIF', () => {
|
|||||||
.avif({ tune: 'iq', effort: 0 })
|
.avif({ tune: 'iq', effort: 0 })
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
assert(ssim.length < iq.length);
|
assert(ssim.length < iq.length);
|
||||||
})
|
});
|
||||||
|
|
||||||
|
it('AVIF with non-zero primary item uses it as default page', async () => {
|
||||||
|
const { exif, ...metadata } = await sharp(inputAvifWithPitmBox).metadata();
|
||||||
|
void exif;
|
||||||
|
assert.deepStrictEqual(metadata, {
|
||||||
|
format: 'heif',
|
||||||
|
width: 4096,
|
||||||
|
height: 800,
|
||||||
|
space: 'srgb',
|
||||||
|
channels: 3,
|
||||||
|
depth: 'uchar',
|
||||||
|
isProgressive: false,
|
||||||
|
isPalette: false,
|
||||||
|
bitsPerSample: 8,
|
||||||
|
pages: 5,
|
||||||
|
pagePrimary: 4,
|
||||||
|
compression: 'av1',
|
||||||
|
resolutionUnit: 'cm',
|
||||||
|
hasProfile: false,
|
||||||
|
hasAlpha: false,
|
||||||
|
autoOrient: { width: 4096, height: 800 },
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await sharp(inputAvifWithPitmBox)
|
||||||
|
.png({ compressionLevel: 0 })
|
||||||
|
.toBuffer();
|
||||||
|
const { size, ...pngMetadata } = await sharp(data).metadata();
|
||||||
|
assert.deepStrictEqual(pngMetadata, {
|
||||||
|
format: 'png',
|
||||||
|
width: 4096,
|
||||||
|
height: 800,
|
||||||
|
space: 'srgb',
|
||||||
|
channels: 3,
|
||||||
|
depth: 'uchar',
|
||||||
|
isProgressive: false,
|
||||||
|
isPalette: false,
|
||||||
|
bitsPerSample: 8,
|
||||||
|
hasProfile: false,
|
||||||
|
hasAlpha: false,
|
||||||
|
autoOrient: { width: 4096, height: 800 },
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const sharp = require('../../');
|
|||||||
const fixtures = require('../fixtures');
|
const fixtures = require('../fixtures');
|
||||||
|
|
||||||
describe('JP2 output', () => {
|
describe('JP2 output', () => {
|
||||||
if (!sharp.format.jp2k.input.buffer) {
|
if (!sharp.format.jp2.input.buffer) {
|
||||||
it('JP2 output should fail due to missing OpenJPEG', () =>
|
it('JP2 output should fail due to missing OpenJPEG', () =>
|
||||||
assert.rejects(async () =>
|
assert.rejects(async () =>
|
||||||
sharp(fixtures.inputJpg)
|
sharp(fixtures.inputJpg)
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ describe('libvips binaries', () => {
|
|||||||
process.env.npm_config_arch = 's390x';
|
process.env.npm_config_arch = 's390x';
|
||||||
process.env.npm_config_libc = '';
|
process.env.npm_config_libc = '';
|
||||||
const locatorHash = libvips.yarnLocator();
|
const locatorHash = libvips.yarnLocator();
|
||||||
assert.strictEqual(locatorHash, '8cdba194cb');
|
assert.strictEqual(locatorHash, 'f7e557e9d6');
|
||||||
delete process.env.npm_config_platform;
|
delete process.env.npm_config_platform;
|
||||||
delete process.env.npm_config_arch;
|
delete process.env.npm_config_arch;
|
||||||
delete process.env.npm_config_libc;
|
delete process.env.npm_config_libc;
|
||||||
|
|||||||
@@ -122,7 +122,6 @@ describe('TIFF', () => {
|
|||||||
sharp(fixtures.inputTiff8BitDepth)
|
sharp(fixtures.inputTiff8BitDepth)
|
||||||
.toColourspace('b-w') // can only squash 1 band uchar images
|
.toColourspace('b-w') // can only squash 1 band uchar images
|
||||||
.tiff({
|
.tiff({
|
||||||
bitdepth: 8,
|
|
||||||
compression: 'none',
|
compression: 'none',
|
||||||
predictor: 'none'
|
predictor: 'none'
|
||||||
})
|
})
|
||||||
@@ -154,7 +153,7 @@ describe('TIFF', () => {
|
|||||||
it('Invalid TIFF bitdepth value throws error', () => {
|
it('Invalid TIFF bitdepth value throws error', () => {
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
sharp().tiff({ bitdepth: 3 });
|
sharp().tiff({ bitdepth: 3 });
|
||||||
}, /Error: Expected 1, 2, 4 or 8 for bitdepth but received 3 of type number/);
|
}, /Error: Expected 1, 2 or 4 for bitdepth but received 3 of type number/);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('TIFF setting xres and yres on file', () =>
|
it('TIFF setting xres and yres on file', () =>
|
||||||
|
|||||||
@@ -222,6 +222,9 @@ describe('Trim borders', () => {
|
|||||||
},
|
},
|
||||||
'Invalid lineArt': {
|
'Invalid lineArt': {
|
||||||
lineArt: 'fail'
|
lineArt: 'fail'
|
||||||
|
},
|
||||||
|
'Invalid margin': {
|
||||||
|
margin: -1
|
||||||
}
|
}
|
||||||
}).forEach(([description, parameter]) => {
|
}).forEach(([description, parameter]) => {
|
||||||
it(description, () => {
|
it(description, () => {
|
||||||
@@ -289,4 +292,42 @@ describe('Trim borders', () => {
|
|||||||
assert.strictEqual(trimOffsetLeft, 0);
|
assert.strictEqual(trimOffsetLeft, 0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Adds margin around content', () => {
|
||||||
|
it('Should trim complex gradients', async () => {
|
||||||
|
const { info } = await sharp(fixtures.inputPngGradients)
|
||||||
|
.trim({ threshold: 50, margin: 100 })
|
||||||
|
.toBuffer({ resolveWithObject: true });
|
||||||
|
|
||||||
|
const { width, height, trimOffsetTop, trimOffsetLeft } = info;
|
||||||
|
assert.strictEqual(width, 1000);
|
||||||
|
assert.strictEqual(height, 443);
|
||||||
|
assert.strictEqual(trimOffsetTop, -557);
|
||||||
|
assert.strictEqual(trimOffsetLeft, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should trim simple gradients', async () => {
|
||||||
|
const { info } = await sharp(fixtures.inputPngWithSlightGradientBorder)
|
||||||
|
.trim({ threshold: 70, margin: 50 })
|
||||||
|
.toBuffer({ resolveWithObject: true });
|
||||||
|
|
||||||
|
const { width, height, trimOffsetTop, trimOffsetLeft } = info;
|
||||||
|
assert.strictEqual(width, 900);
|
||||||
|
assert.strictEqual(height, 900);
|
||||||
|
assert.strictEqual(trimOffsetTop, -50);
|
||||||
|
assert.strictEqual(trimOffsetLeft, -50);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should not overflow image bounding box', async () => {
|
||||||
|
const { info } = await sharp(fixtures.inputPngWithSlightGradientBorder)
|
||||||
|
.trim({ threshold: 70, margin: 9999999 })
|
||||||
|
.toBuffer({ resolveWithObject: true });
|
||||||
|
|
||||||
|
const { width, height, trimOffsetTop, trimOffsetLeft } = info;
|
||||||
|
assert.strictEqual(width, 1000);
|
||||||
|
assert.strictEqual(height, 1000);
|
||||||
|
assert.strictEqual(trimOffsetTop, 0);
|
||||||
|
assert.strictEqual(trimOffsetLeft, 0);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user