mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 18:40:16 +02:00
Standardise HEIF effort option name, deprecate speed
This commit is contained in:
parent
2b1f5cbe07
commit
e1ba2a7fd8
@ -282,7 +282,7 @@ Use these WebP options for output image.
|
|||||||
* `options.lossless` **[boolean][7]** use lossless compression mode (optional, default `false`)
|
* `options.lossless` **[boolean][7]** use lossless compression mode (optional, default `false`)
|
||||||
* `options.nearLossless` **[boolean][7]** use near_lossless compression mode (optional, default `false`)
|
* `options.nearLossless` **[boolean][7]** use near_lossless compression mode (optional, default `false`)
|
||||||
* `options.smartSubsample` **[boolean][7]** use high quality chroma subsampling (optional, default `false`)
|
* `options.smartSubsample` **[boolean][7]** use high quality chroma subsampling (optional, default `false`)
|
||||||
* `options.effort` **[number][9]** level of CPU effort to reduce file size, integer 0-6 (optional, default `4`)
|
* `options.effort` **[number][9]** CPU effort, between 0 (fastest) and 6 (slowest) (optional, default `4`)
|
||||||
* `options.pageHeight` **[number][9]?** page height for animated output
|
* `options.pageHeight` **[number][9]?** page height for animated output
|
||||||
* `options.loop` **[number][9]** number of animation iterations, use 0 for infinite animation (optional, default `0`)
|
* `options.loop` **[number][9]** number of animation iterations, use 0 for infinite animation (optional, default `0`)
|
||||||
* `options.delay` **[Array][10]<[number][9]>?** list of delays between animation frames (in milliseconds)
|
* `options.delay` **[Array][10]<[number][9]>?** list of delays between animation frames (in milliseconds)
|
||||||
@ -460,7 +460,7 @@ AVIF image sequences are not supported.
|
|||||||
|
|
||||||
* `options.quality` **[number][9]** quality, integer 1-100 (optional, default `50`)
|
* `options.quality` **[number][9]** quality, integer 1-100 (optional, default `50`)
|
||||||
* `options.lossless` **[boolean][7]** use lossless compression (optional, default `false`)
|
* `options.lossless` **[boolean][7]** use lossless compression (optional, default `false`)
|
||||||
* `options.speed` **[number][9]** CPU effort vs file size, 0 (slowest/smallest) to 9 (fastest/largest) (optional, default `5`)
|
* `options.effort` **[number][9]** CPU effort, between 0 (fastest) and 9 (slowest) (optional, default `4`)
|
||||||
* `options.chromaSubsampling` **[string][2]** set to '4:2:0' to use chroma subsampling (optional, default `'4:4:4'`)
|
* `options.chromaSubsampling` **[string][2]** set to '4:2:0' to use chroma subsampling (optional, default `'4:4:4'`)
|
||||||
|
|
||||||
<!---->
|
<!---->
|
||||||
@ -487,7 +487,7 @@ globally-installed libvips compiled with support for libheif, libde265 and x265.
|
|||||||
* `options.quality` **[number][9]** quality, integer 1-100 (optional, default `50`)
|
* `options.quality` **[number][9]** quality, integer 1-100 (optional, default `50`)
|
||||||
* `options.compression` **[string][2]** compression format: av1, hevc (optional, default `'av1'`)
|
* `options.compression` **[string][2]** compression format: av1, hevc (optional, default `'av1'`)
|
||||||
* `options.lossless` **[boolean][7]** use lossless compression (optional, default `false`)
|
* `options.lossless` **[boolean][7]** use lossless compression (optional, default `false`)
|
||||||
* `options.speed` **[number][9]** CPU effort vs file size, 0 (slowest/smallest) to 9 (fastest/largest) (optional, default `5`)
|
* `options.effort` **[number][9]** CPU effort, between 0 (fastest) and 9 (slowest) (optional, default `4`)
|
||||||
* `options.chromaSubsampling` **[string][2]** set to '4:2:0' to use chroma subsampling (optional, default `'4:4:4'`)
|
* `options.chromaSubsampling` **[string][2]** set to '4:2:0' to use chroma subsampling (optional, default `'4:4:4'`)
|
||||||
|
|
||||||
<!---->
|
<!---->
|
||||||
|
@ -12,6 +12,8 @@ Requires libvips v8.12.0
|
|||||||
|
|
||||||
* Standardise WebP `effort` option name, deprecate `reductionEffort`.
|
* Standardise WebP `effort` option name, deprecate `reductionEffort`.
|
||||||
|
|
||||||
|
* Standardise HEIF `effort` option name, deprecate `speed`.
|
||||||
|
|
||||||
* Expose control over CPU effort for palette-based PNG output.
|
* Expose control over CPU effort for palette-based PNG output.
|
||||||
[#2541](https://github.com/lovell/sharp/issues/2541)
|
[#2541](https://github.com/lovell/sharp/issues/2541)
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ const Sharp = function (input, options) {
|
|||||||
heifQuality: 50,
|
heifQuality: 50,
|
||||||
heifLossless: false,
|
heifLossless: false,
|
||||||
heifCompression: 'av1',
|
heifCompression: 'av1',
|
||||||
heifSpeed: 5,
|
heifEffort: 4,
|
||||||
heifChromaSubsampling: '4:4:4',
|
heifChromaSubsampling: '4:4:4',
|
||||||
rawDepth: 'uchar',
|
rawDepth: 'uchar',
|
||||||
tileSize: 256,
|
tileSize: 256,
|
||||||
|
@ -457,7 +457,7 @@ function png (options) {
|
|||||||
* @param {boolean} [options.lossless=false] - use lossless compression mode
|
* @param {boolean} [options.lossless=false] - use lossless compression mode
|
||||||
* @param {boolean} [options.nearLossless=false] - use near_lossless compression mode
|
* @param {boolean} [options.nearLossless=false] - use near_lossless compression mode
|
||||||
* @param {boolean} [options.smartSubsample=false] - use high quality chroma subsampling
|
* @param {boolean} [options.smartSubsample=false] - use high quality chroma subsampling
|
||||||
* @param {number} [options.effort=4] - level of CPU effort to reduce file size, integer 0-6
|
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 6 (slowest)
|
||||||
* @param {number} [options.pageHeight] - page height for animated output
|
* @param {number} [options.pageHeight] - page height for animated output
|
||||||
* @param {number} [options.loop=0] - number of animation iterations, use 0 for infinite animation
|
* @param {number} [options.loop=0] - number of animation iterations, use 0 for infinite animation
|
||||||
* @param {number[]} [options.delay] - list of delays between animation frames (in milliseconds)
|
* @param {number[]} [options.delay] - list of delays between animation frames (in milliseconds)
|
||||||
@ -806,7 +806,7 @@ function tiff (options) {
|
|||||||
* @param {Object} [options] - output options
|
* @param {Object} [options] - output options
|
||||||
* @param {number} [options.quality=50] - quality, integer 1-100
|
* @param {number} [options.quality=50] - quality, integer 1-100
|
||||||
* @param {boolean} [options.lossless=false] - use lossless compression
|
* @param {boolean} [options.lossless=false] - use lossless compression
|
||||||
* @param {number} [options.speed=5] - CPU effort vs file size, 0 (slowest/smallest) to 9 (fastest/largest)
|
* @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
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
* @throws {Error} Invalid options
|
* @throws {Error} Invalid options
|
||||||
@ -827,7 +827,7 @@ function avif (options) {
|
|||||||
* @param {number} [options.quality=50] - quality, integer 1-100
|
* @param {number} [options.quality=50] - quality, integer 1-100
|
||||||
* @param {string} [options.compression='av1'] - compression format: av1, hevc
|
* @param {string} [options.compression='av1'] - compression format: av1, hevc
|
||||||
* @param {boolean} [options.lossless=false] - use lossless compression
|
* @param {boolean} [options.lossless=false] - use lossless compression
|
||||||
* @param {number} [options.speed=5] - CPU effort vs file size, 0 (slowest/smallest) to 9 (fastest/largest)
|
* @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
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
* @throws {Error} Invalid options
|
* @throws {Error} Invalid options
|
||||||
@ -855,9 +855,15 @@ function heif (options) {
|
|||||||
throw is.invalidParameterError('compression', 'one of: av1, hevc', options.compression);
|
throw is.invalidParameterError('compression', 'one of: av1, hevc', options.compression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is.defined(options.speed)) {
|
if (is.defined(options.effort)) {
|
||||||
|
if (is.integer(options.effort) && is.inRange(options.effort, 0, 9)) {
|
||||||
|
this.options.heifEffort = options.effort;
|
||||||
|
} else {
|
||||||
|
throw is.invalidParameterError('effort', 'integer between 0 and 9', options.effort);
|
||||||
|
}
|
||||||
|
} else if (is.defined(options.speed)) {
|
||||||
if (is.integer(options.speed) && is.inRange(options.speed, 0, 9)) {
|
if (is.integer(options.speed) && is.inRange(options.speed, 0, 9)) {
|
||||||
this.options.heifSpeed = options.speed;
|
this.options.heifEffort = 9 - options.speed;
|
||||||
} else {
|
} else {
|
||||||
throw is.invalidParameterError('speed', 'integer between 0 and 9', options.speed);
|
throw is.invalidParameterError('speed', 'integer between 0 and 9', options.speed);
|
||||||
}
|
}
|
||||||
|
@ -899,7 +899,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
->set("strip", !baton->withMetadata)
|
->set("strip", !baton->withMetadata)
|
||||||
->set("Q", baton->heifQuality)
|
->set("Q", baton->heifQuality)
|
||||||
->set("compression", baton->heifCompression)
|
->set("compression", baton->heifCompression)
|
||||||
->set("speed", baton->heifSpeed)
|
->set("effort", baton->heifEffort)
|
||||||
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
||||||
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
||||||
->set("lossless", baton->heifLossless)));
|
->set("lossless", baton->heifLossless)));
|
||||||
@ -1053,7 +1053,7 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
->set("strip", !baton->withMetadata)
|
->set("strip", !baton->withMetadata)
|
||||||
->set("Q", baton->heifQuality)
|
->set("Q", baton->heifQuality)
|
||||||
->set("compression", baton->heifCompression)
|
->set("compression", baton->heifCompression)
|
||||||
->set("speed", baton->heifSpeed)
|
->set("effort", baton->heifEffort)
|
||||||
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
->set("subsample_mode", baton->heifChromaSubsampling == "4:4:4"
|
||||||
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
? VIPS_FOREIGN_SUBSAMPLE_OFF : VIPS_FOREIGN_SUBSAMPLE_ON)
|
||||||
->set("lossless", baton->heifLossless));
|
->set("lossless", baton->heifLossless));
|
||||||
@ -1512,7 +1512,7 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|||||||
baton->heifCompression = static_cast<VipsForeignHeifCompression>(
|
baton->heifCompression = static_cast<VipsForeignHeifCompression>(
|
||||||
vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_HEIF_COMPRESSION,
|
vips_enum_from_nick(nullptr, VIPS_TYPE_FOREIGN_HEIF_COMPRESSION,
|
||||||
sharp::AttrAsStr(options, "heifCompression").data()));
|
sharp::AttrAsStr(options, "heifCompression").data()));
|
||||||
baton->heifSpeed = sharp::AttrAsUint32(options, "heifSpeed");
|
baton->heifEffort = sharp::AttrAsUint32(options, "heifEffort");
|
||||||
baton->heifChromaSubsampling = sharp::AttrAsStr(options, "heifChromaSubsampling");
|
baton->heifChromaSubsampling = sharp::AttrAsStr(options, "heifChromaSubsampling");
|
||||||
|
|
||||||
// Raw output
|
// Raw output
|
||||||
|
@ -176,7 +176,7 @@ struct PipelineBaton {
|
|||||||
double tiffYres;
|
double tiffYres;
|
||||||
int heifQuality;
|
int heifQuality;
|
||||||
VipsForeignHeifCompression heifCompression;
|
VipsForeignHeifCompression heifCompression;
|
||||||
int heifSpeed;
|
int heifEffort;
|
||||||
std::string heifChromaSubsampling;
|
std::string heifChromaSubsampling;
|
||||||
bool heifLossless;
|
bool heifLossless;
|
||||||
VipsBandFormat rawDepth;
|
VipsBandFormat rawDepth;
|
||||||
@ -314,7 +314,7 @@ struct PipelineBaton {
|
|||||||
tiffYres(1.0),
|
tiffYres(1.0),
|
||||||
heifQuality(50),
|
heifQuality(50),
|
||||||
heifCompression(VIPS_FOREIGN_HEIF_COMPRESSION_AV1),
|
heifCompression(VIPS_FOREIGN_HEIF_COMPRESSION_AV1),
|
||||||
heifSpeed(5),
|
heifEffort(4),
|
||||||
heifChromaSubsampling("4:4:4"),
|
heifChromaSubsampling("4:4:4"),
|
||||||
heifLossless(false),
|
heifLossless(false),
|
||||||
rawDepth(VIPS_FORMAT_UCHAR),
|
rawDepth(VIPS_FORMAT_UCHAR),
|
||||||
|
@ -17,10 +17,9 @@ describe('AVIF', () => {
|
|||||||
.resize(32)
|
.resize(32)
|
||||||
.jpeg()
|
.jpeg()
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
const metadata = await sharp(data)
|
const { size, ...metadata } = await sharp(data)
|
||||||
.metadata();
|
.metadata();
|
||||||
const { compression, size, ...metadataWithoutSize } = metadata;
|
assert.deepStrictEqual(metadata, {
|
||||||
assert.deepStrictEqual(metadataWithoutSize, {
|
|
||||||
channels: 3,
|
channels: 3,
|
||||||
chromaSubsampling: '4:2:0',
|
chromaSubsampling: '4:2:0',
|
||||||
density: 72,
|
density: 72,
|
||||||
@ -38,13 +37,13 @@ describe('AVIF', () => {
|
|||||||
it('can convert JPEG to AVIF', async () => {
|
it('can convert JPEG to AVIF', async () => {
|
||||||
const data = await sharp(inputJpg)
|
const data = await sharp(inputJpg)
|
||||||
.resize(32)
|
.resize(32)
|
||||||
.avif()
|
.avif({ effort: 0 })
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
const metadata = await sharp(data)
|
const { size, ...metadata } = await sharp(data)
|
||||||
.metadata();
|
.metadata();
|
||||||
const { compression, size, ...metadataWithoutSize } = metadata;
|
assert.deepStrictEqual(metadata, {
|
||||||
assert.deepStrictEqual(metadataWithoutSize, {
|
|
||||||
channels: 3,
|
channels: 3,
|
||||||
|
compression: 'av1',
|
||||||
depth: 'uchar',
|
depth: 'uchar',
|
||||||
format: 'heif',
|
format: 'heif',
|
||||||
hasAlpha: false,
|
hasAlpha: false,
|
||||||
@ -63,11 +62,11 @@ describe('AVIF', () => {
|
|||||||
const data = await sharp(inputAvif)
|
const data = await sharp(inputAvif)
|
||||||
.resize(32)
|
.resize(32)
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
const metadata = await sharp(data)
|
const { size, ...metadata } = await sharp(data)
|
||||||
.metadata();
|
.metadata();
|
||||||
const { compression, size, ...metadataWithoutSize } = metadata;
|
assert.deepStrictEqual(metadata, {
|
||||||
assert.deepStrictEqual(metadataWithoutSize, {
|
|
||||||
channels: 3,
|
channels: 3,
|
||||||
|
compression: 'av1',
|
||||||
depth: 'uchar',
|
depth: 'uchar',
|
||||||
format: 'heif',
|
format: 'heif',
|
||||||
hasAlpha: false,
|
hasAlpha: false,
|
||||||
@ -85,12 +84,11 @@ describe('AVIF', () => {
|
|||||||
it('can convert animated GIF to non-animated AVIF', async () => {
|
it('can convert animated GIF to non-animated AVIF', async () => {
|
||||||
const data = await sharp(inputGifAnimated, { animated: true })
|
const data = await sharp(inputGifAnimated, { animated: true })
|
||||||
.resize(10)
|
.resize(10)
|
||||||
.avif({ speed: 8 })
|
.avif({ effort: 0 })
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
const metadata = await sharp(data)
|
const { size, ...metadata } = await sharp(data)
|
||||||
.metadata();
|
.metadata();
|
||||||
const { size, ...metadataWithoutSize } = metadata;
|
assert.deepStrictEqual(metadata, {
|
||||||
assert.deepStrictEqual(metadataWithoutSize, {
|
|
||||||
channels: 4,
|
channels: 4,
|
||||||
compression: 'av1',
|
compression: 'av1',
|
||||||
depth: 'uchar',
|
depth: 'uchar',
|
||||||
|
@ -50,6 +50,21 @@ describe('HEIF', () => {
|
|||||||
sharp().heif({ compression: 1 });
|
sharp().heif({ compression: 1 });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('valid effort does not throw an error', () => {
|
||||||
|
assert.doesNotThrow(() => {
|
||||||
|
sharp().heif({ speed: 6 });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('out of range effort should throw an error', () => {
|
||||||
|
assert.throws(() => {
|
||||||
|
sharp().heif({ effort: 10 });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('invalid effort should throw an error', () => {
|
||||||
|
assert.throws(() => {
|
||||||
|
sharp().heif({ effort: 'fail' });
|
||||||
|
});
|
||||||
|
});
|
||||||
it('valid speed does not throw an error', () => {
|
it('valid speed does not throw an error', () => {
|
||||||
assert.doesNotThrow(() => {
|
assert.doesNotThrow(() => {
|
||||||
sharp().heif({ speed: 6 });
|
sharp().heif({ speed: 6 });
|
||||||
@ -62,7 +77,7 @@ describe('HEIF', () => {
|
|||||||
});
|
});
|
||||||
it('invalid speed should throw an error', () => {
|
it('invalid speed should throw an error', () => {
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
sharp().heif({ compression: 'fail' });
|
sharp().heif({ speed: 'fail' });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('invalid chromaSubsampling should throw an error', () => {
|
it('invalid chromaSubsampling should throw an error', () => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user