Add support for animated WebP and GIF (via magick) (#2012)

This commit is contained in:
Tomáš Szabo
2020-08-17 15:48:38 +02:00
committed by GitHub
parent 45653ca2e7
commit cb1baede87
12 changed files with 328 additions and 7 deletions

View File

@@ -11,7 +11,8 @@ const formats = new Map([
['png', 'png'],
['raw', 'raw'],
['tiff', 'tiff'],
['webp', 'webp']
['webp', 'webp'],
['gif', 'gif']
]);
/**
@@ -340,6 +341,9 @@ function png (options) {
* @param {boolean} [options.nearLossless=false] - use near_lossless compression mode
* @param {boolean} [options.smartSubsample=false] - use high quality chroma subsampling
* @param {number} [options.reductionEffort=4] - level of CPU effort to reduce file size, integer 0-6
* @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.delay] - list of delays between animation frames (in milliseconds)
* @param {boolean} [options.force=true] - force WebP output, otherwise attempt to use input format
* @returns {Sharp}
* @throws {Error} Invalid options
@@ -375,9 +379,66 @@ function webp (options) {
throw is.invalidParameterError('reductionEffort', 'integer between 0 and 6', options.reductionEffort);
}
}
trySetAnimationOptions(options, this.options);
return this._updateFormatOut('webp', options);
}
/**
* Use these GIF options for output image.
*
* Requires a custom, globally-installed libvips compiled with support for imageMagick.
*
* @param {Object} [options] - output options
* @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.delay] - list of delays between animation frames (in milliseconds)
* @param {boolean} [options.force=true] - force GIF output, otherwise attempt to use input format
* @returns {Sharp}
* @throws {Error} Invalid options
*/
function gif (options) {
trySetAnimationOptions(options, this.options);
return this._updateFormatOut('gif', options);
}
/**
* Set animation options if available.
*
* @param {Object} [source] - output options
* @param {number} [source.pageHeight] - page height for animated output
* @param {number} [source.loop=0] - number of animation iterations, use 0 for infinite animation
* @param {number[]} [source.delay] - list of delays between animation frames (in milliseconds)
* @param {Object} [target] - target object for valid options
* @throws {Error} Invalid options
*/
function trySetAnimationOptions (source, target) {
if (is.object(source) && is.defined(source.pageHeight)) {
if (is.integer(source.pageHeight) && source.pageHeight > 0) {
target.pageHeight = source.pageHeight;
} else {
throw is.invalidParameterError('pageHeight', 'integer larger than 0', source.pageHeight);
}
}
if (is.object(source) && is.defined(source.loop)) {
if (is.integer(source.loop) && is.inRange(source.loop, 0, 65535)) {
target.loop = source.loop;
} else {
throw is.invalidParameterError('loop', 'integer between 0 and 65535', source.loop);
}
}
if (is.object(source) && is.defined(source.delay)) {
if (
Array.isArray(source.delay) &&
source.delay.every(is.integer) &&
source.delay.every(v => is.inRange(v, 0, 65535))) {
target.delay = source.delay;
} else {
throw is.invalidParameterError('delay', 'array of integers between 0 and 65535', source.delay);
}
}
}
/**
* Use these TIFF options for output image.
*
@@ -808,6 +869,7 @@ module.exports = function (Sharp) {
webp,
tiff,
heif,
gif,
raw,
tile,
// Private