mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 10:30:15 +02:00
Add mixed and minSize animation options for WebP output
This commit is contained in:
parent
1b84ccbbe9
commit
d247c02762
@ -291,6 +291,8 @@ Use these WebP options for output image.
|
|||||||
* `options.effort` **[number][12]** CPU effort, between 0 (fastest) and 6 (slowest) (optional, default `4`)
|
* `options.effort` **[number][12]** CPU effort, between 0 (fastest) and 6 (slowest) (optional, default `4`)
|
||||||
* `options.loop` **[number][12]** number of animation iterations, use 0 for infinite animation (optional, default `0`)
|
* `options.loop` **[number][12]** number of animation iterations, use 0 for infinite animation (optional, default `0`)
|
||||||
* `options.delay` **([number][12] | [Array][13]<[number][12]>)?** delay(s) between animation frames (in milliseconds)
|
* `options.delay` **([number][12] | [Array][13]<[number][12]>)?** delay(s) between animation frames (in milliseconds)
|
||||||
|
* `options.minSize` **[boolean][10]** prevent use of animation key frames to minimise file size (slow) (optional, default `false`)
|
||||||
|
* `options.mixed` **[boolean][10]** allow mixture of lossy and lossless animation frames (slow) (optional, default `false`)
|
||||||
* `options.force` **[boolean][10]** force WebP output, otherwise attempt to use input format (optional, default `true`)
|
* `options.force` **[boolean][10]** force WebP output, otherwise attempt to use input format (optional, default `true`)
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
|
@ -8,6 +8,8 @@ Requires libvips v8.13.0
|
|||||||
|
|
||||||
* Drop support for Node.js 12, now requires Node.js >= 14.15.0.
|
* Drop support for Node.js 12, now requires Node.js >= 14.15.0.
|
||||||
|
|
||||||
|
* Add WebP `minSize` and `mixed` options for greater control over animation frames.
|
||||||
|
|
||||||
* Use combined bounding box of alpha and non-alpha channels for `trim` operation.
|
* Use combined bounding box of alpha and non-alpha channels for `trim` operation.
|
||||||
[#2166](https://github.com/lovell/sharp/issues/2166)
|
[#2166](https://github.com/lovell/sharp/issues/2166)
|
||||||
|
|
||||||
|
File diff suppressed because one or more lines are too long
@ -251,6 +251,8 @@ const Sharp = function (input, options) {
|
|||||||
webpNearLossless: false,
|
webpNearLossless: false,
|
||||||
webpSmartSubsample: false,
|
webpSmartSubsample: false,
|
||||||
webpEffort: 4,
|
webpEffort: 4,
|
||||||
|
webpMinSize: false,
|
||||||
|
webpMixed: false,
|
||||||
gifBitdepth: 8,
|
gifBitdepth: 8,
|
||||||
gifEffort: 7,
|
gifEffort: 7,
|
||||||
gifDither: 1,
|
gifDither: 1,
|
||||||
|
@ -469,6 +469,8 @@ function png (options) {
|
|||||||
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 6 (slowest)
|
* @param {number} [options.effort=4] - CPU effort, between 0 (fastest) and 6 (slowest)
|
||||||
* @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|number[]} [options.delay] - delay(s) between animation frames (in milliseconds)
|
* @param {number|number[]} [options.delay] - delay(s) between animation frames (in milliseconds)
|
||||||
|
* @param {boolean} [options.minSize=false] - prevent use of animation key frames to minimise file size (slow)
|
||||||
|
* @param {boolean} [options.mixed=false] - allow mixture of lossy and lossless animation frames (slow)
|
||||||
* @param {boolean} [options.force=true] - force WebP output, otherwise attempt to use input format
|
* @param {boolean} [options.force=true] - force WebP output, otherwise attempt to use input format
|
||||||
* @returns {Sharp}
|
* @returns {Sharp}
|
||||||
* @throws {Error} Invalid options
|
* @throws {Error} Invalid options
|
||||||
@ -506,6 +508,12 @@ function webp (options) {
|
|||||||
throw is.invalidParameterError('effort', 'integer between 0 and 6', effort);
|
throw is.invalidParameterError('effort', 'integer between 0 and 6', effort);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (is.defined(options.minSize)) {
|
||||||
|
this._setBooleanOption('webpMinSize', options.minSize);
|
||||||
|
}
|
||||||
|
if (is.defined(options.mixed)) {
|
||||||
|
this._setBooleanOption('webpMixed', options.mixed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
trySetAnimationOptions(options, this.options);
|
trySetAnimationOptions(options, this.options);
|
||||||
return this._updateFormatOut('webp', options);
|
return this._updateFormatOut('webp', options);
|
||||||
|
@ -872,6 +872,8 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
->set("near_lossless", baton->webpNearLossless)
|
->set("near_lossless", baton->webpNearLossless)
|
||||||
->set("smart_subsample", baton->webpSmartSubsample)
|
->set("smart_subsample", baton->webpSmartSubsample)
|
||||||
->set("effort", baton->webpEffort)
|
->set("effort", baton->webpEffort)
|
||||||
|
->set("min_size", baton->webpMinSize)
|
||||||
|
->set("mixed", baton->webpMixed)
|
||||||
->set("alpha_q", baton->webpAlphaQuality)));
|
->set("alpha_q", baton->webpAlphaQuality)));
|
||||||
baton->bufferOut = static_cast<char*>(area->data);
|
baton->bufferOut = static_cast<char*>(area->data);
|
||||||
baton->bufferOutLength = area->length;
|
baton->bufferOutLength = area->length;
|
||||||
@ -1039,6 +1041,8 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
->set("near_lossless", baton->webpNearLossless)
|
->set("near_lossless", baton->webpNearLossless)
|
||||||
->set("smart_subsample", baton->webpSmartSubsample)
|
->set("smart_subsample", baton->webpSmartSubsample)
|
||||||
->set("effort", baton->webpEffort)
|
->set("effort", baton->webpEffort)
|
||||||
|
->set("min_size", baton->webpMinSize)
|
||||||
|
->set("mixed", baton->webpMixed)
|
||||||
->set("alpha_q", baton->webpAlphaQuality));
|
->set("alpha_q", baton->webpAlphaQuality));
|
||||||
baton->formatOut = "webp";
|
baton->formatOut = "webp";
|
||||||
} else if (baton->formatOut == "gif" || (mightMatchInput && isGif) ||
|
} else if (baton->formatOut == "gif" || (mightMatchInput && isGif) ||
|
||||||
@ -1109,6 +1113,8 @@ class PipelineWorker : public Napi::AsyncWorker {
|
|||||||
{"lossless", baton->webpLossless ? "TRUE" : "FALSE"},
|
{"lossless", baton->webpLossless ? "TRUE" : "FALSE"},
|
||||||
{"near_lossless", baton->webpNearLossless ? "TRUE" : "FALSE"},
|
{"near_lossless", baton->webpNearLossless ? "TRUE" : "FALSE"},
|
||||||
{"smart_subsample", baton->webpSmartSubsample ? "TRUE" : "FALSE"},
|
{"smart_subsample", baton->webpSmartSubsample ? "TRUE" : "FALSE"},
|
||||||
|
{"min_size", baton->webpMinSize ? "TRUE" : "FALSE"},
|
||||||
|
{"mixed", baton->webpMixed ? "TRUE" : "FALSE"},
|
||||||
{"effort", std::to_string(baton->webpEffort)}
|
{"effort", std::to_string(baton->webpEffort)}
|
||||||
};
|
};
|
||||||
suffix = AssembleSuffixString(".webp", options);
|
suffix = AssembleSuffixString(".webp", options);
|
||||||
@ -1526,6 +1532,8 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|||||||
baton->webpNearLossless = sharp::AttrAsBool(options, "webpNearLossless");
|
baton->webpNearLossless = sharp::AttrAsBool(options, "webpNearLossless");
|
||||||
baton->webpSmartSubsample = sharp::AttrAsBool(options, "webpSmartSubsample");
|
baton->webpSmartSubsample = sharp::AttrAsBool(options, "webpSmartSubsample");
|
||||||
baton->webpEffort = sharp::AttrAsUint32(options, "webpEffort");
|
baton->webpEffort = sharp::AttrAsUint32(options, "webpEffort");
|
||||||
|
baton->webpMinSize = sharp::AttrAsBool(options, "webpMinSize");
|
||||||
|
baton->webpMixed = sharp::AttrAsBool(options, "webpMixed");
|
||||||
baton->gifBitdepth = sharp::AttrAsUint32(options, "gifBitdepth");
|
baton->gifBitdepth = sharp::AttrAsUint32(options, "gifBitdepth");
|
||||||
baton->gifEffort = sharp::AttrAsUint32(options, "gifEffort");
|
baton->gifEffort = sharp::AttrAsUint32(options, "gifEffort");
|
||||||
baton->gifDither = sharp::AttrAsDouble(options, "gifDither");
|
baton->gifDither = sharp::AttrAsDouble(options, "gifDither");
|
||||||
|
@ -157,6 +157,8 @@ struct PipelineBaton {
|
|||||||
bool webpLossless;
|
bool webpLossless;
|
||||||
bool webpSmartSubsample;
|
bool webpSmartSubsample;
|
||||||
int webpEffort;
|
int webpEffort;
|
||||||
|
bool webpMinSize;
|
||||||
|
bool webpMixed;
|
||||||
int gifBitdepth;
|
int gifBitdepth;
|
||||||
int gifEffort;
|
int gifEffort;
|
||||||
double gifDither;
|
double gifDither;
|
||||||
@ -302,6 +304,8 @@ struct PipelineBaton {
|
|||||||
webpLossless(false),
|
webpLossless(false),
|
||||||
webpSmartSubsample(false),
|
webpSmartSubsample(false),
|
||||||
webpEffort(4),
|
webpEffort(4),
|
||||||
|
webpMinSize(false),
|
||||||
|
webpMixed(false),
|
||||||
tiffQuality(80),
|
tiffQuality(80),
|
||||||
tiffCompression(VIPS_FOREIGN_TIFF_COMPRESSION_JPEG),
|
tiffCompression(VIPS_FOREIGN_TIFF_COMPRESSION_JPEG),
|
||||||
tiffPredictor(VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL),
|
tiffPredictor(VIPS_FOREIGN_TIFF_PREDICTOR_HORIZONTAL),
|
||||||
|
@ -139,6 +139,28 @@ describe('WebP', function () {
|
|||||||
assert.strictEqual(effort, 0);
|
assert.strictEqual(effort, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('valid minSize', () => {
|
||||||
|
assert.doesNotThrow(() => sharp().webp({ minSize: true }));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('invalid minSize throws', () => {
|
||||||
|
assert.throws(
|
||||||
|
() => sharp().webp({ minSize: 1 }),
|
||||||
|
/Expected boolean for webpMinSize but received 1 of type number/
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('valid mixed', () => {
|
||||||
|
assert.doesNotThrow(() => sharp().webp({ mixed: true }));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('invalid mixed throws', () => {
|
||||||
|
assert.throws(
|
||||||
|
() => sharp().webp({ mixed: 'fail' }),
|
||||||
|
/Expected boolean for webpMixed but received fail of type string/
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('invalid loop throws', () => {
|
it('invalid loop throws', () => {
|
||||||
assert.throws(() => {
|
assert.throws(() => {
|
||||||
sharp().webp({ loop: -1 });
|
sharp().webp({ loop: -1 });
|
||||||
|
Loading…
x
Reference in New Issue
Block a user