Remove unsupported animation props from AVIF #2870

This commit is contained in:
Lovell Fuller 2021-09-05 08:46:15 +01:00
parent e044788f63
commit 5d98bcd8d8
7 changed files with 51 additions and 1 deletions

View File

@ -374,6 +374,8 @@ Use these AVIF options for output image.
Whilst it is possible to create AVIF images smaller than 16x16 pixels, Whilst it is possible to create AVIF images smaller than 16x16 pixels,
most web browsers do not display these properly. most web browsers do not display these properly.
AVIF image sequences are not supported.
### Parameters ### Parameters
* `options` **[Object][6]?** output options * `options` **[Object][6]?** output options

View File

@ -18,6 +18,9 @@ Requires libvips v8.11.3
* Ensure images with P3 profiles retain full gamut. * Ensure images with P3 profiles retain full gamut.
[#2862](https://github.com/lovell/sharp/issues/2862) [#2862](https://github.com/lovell/sharp/issues/2862)
* Remove unsupported animation properties from AVIF output.
[#2870](https://github.com/lovell/sharp/issues/2870)
### v0.29.0 - 17th August 2021 ### v0.29.0 - 17th August 2021
* Drop support for Node.js 10, now requires Node.js >= 12.13.0. * Drop support for Node.js 10, now requires Node.js >= 12.13.0.

View File

@ -656,6 +656,8 @@ function tiff (options) {
* Whilst it is possible to create AVIF images smaller than 16x16 pixels, * Whilst it is possible to create AVIF images smaller than 16x16 pixels,
* most web browsers do not display these properly. * most web browsers do not display these properly.
* *
* AVIF image sequences are not supported.
*
* @since 0.27.0 * @since 0.27.0
* *
* @param {Object} [options] - output options * @param {Object} [options] - output options

View File

@ -510,6 +510,17 @@ namespace sharp {
return copy; return copy;
} }
/*
Remove animation properties from image.
*/
VImage RemoveAnimationProperties(VImage image) {
VImage copy = image.copy();
copy.remove(VIPS_META_PAGE_HEIGHT);
copy.remove("delay");
copy.remove("loop");
return copy;
}
/* /*
Does this image have a non-default density? Does this image have a non-default density?
*/ */

View File

@ -208,6 +208,11 @@ namespace sharp {
*/ */
VImage SetAnimationProperties(VImage image, int pageHeight, std::vector<int> delay, int loop); VImage SetAnimationProperties(VImage image, int pageHeight, std::vector<int> delay, int loop);
/*
Remove animation properties from image.
*/
VImage RemoveAnimationProperties(VImage image);
/* /*
Does this image have a non-default density? Does this image have a non-default density?
*/ */

View File

@ -872,6 +872,7 @@ class PipelineWorker : public Napi::AsyncWorker {
} else if (baton->formatOut == "heif" || } else if (baton->formatOut == "heif" ||
(baton->formatOut == "input" && inputImageType == sharp::ImageType::HEIF)) { (baton->formatOut == "input" && inputImageType == sharp::ImageType::HEIF)) {
// Write HEIF to buffer // Write HEIF to buffer
image = sharp::RemoveAnimationProperties(image);
VipsArea *area = reinterpret_cast<VipsArea*>(image.heifsave_buffer(VImage::option() VipsArea *area = reinterpret_cast<VipsArea*>(image.heifsave_buffer(VImage::option()
->set("strip", !baton->withMetadata) ->set("strip", !baton->withMetadata)
->set("Q", baton->heifQuality) ->set("Q", baton->heifQuality)
@ -1012,6 +1013,7 @@ class PipelineWorker : public Napi::AsyncWorker {
} else if (baton->formatOut == "heif" || (mightMatchInput && isHeif) || } else if (baton->formatOut == "heif" || (mightMatchInput && isHeif) ||
(willMatchInput && inputImageType == sharp::ImageType::HEIF)) { (willMatchInput && inputImageType == sharp::ImageType::HEIF)) {
// Write HEIF to file // Write HEIF to file
image = sharp::RemoveAnimationProperties(image);
image.heifsave(const_cast<char*>(baton->fileOut.data()), VImage::option() image.heifsave(const_cast<char*>(baton->fileOut.data()), VImage::option()
->set("strip", !baton->withMetadata) ->set("strip", !baton->withMetadata)
->set("Q", baton->heifQuality) ->set("Q", baton->heifQuality)

View File

@ -3,7 +3,7 @@
const assert = require('assert'); const assert = require('assert');
const sharp = require('../../'); const sharp = require('../../');
const { inputAvif, inputJpg } = require('../fixtures'); const { inputAvif, inputJpg, inputGifAnimated } = require('../fixtures');
describe('AVIF', () => { describe('AVIF', () => {
it('called without options does not throw an error', () => { it('called without options does not throw an error', () => {
@ -81,4 +81,29 @@ describe('AVIF', () => {
width: 32 width: 32
}); });
}); });
it('can convert animated GIF to non-animated AVIF', async () => {
const data = await sharp(inputGifAnimated, { animated: true })
.resize(10)
.avif({ speed: 8 })
.toBuffer();
const metadata = await sharp(data)
.metadata();
const { size, ...metadataWithoutSize } = metadata;
assert.deepStrictEqual(metadataWithoutSize, {
channels: 4,
compression: 'av1',
depth: 'uchar',
format: 'heif',
hasAlpha: true,
hasProfile: false,
height: 300,
isProgressive: false,
pageHeight: 300,
pagePrimary: 0,
pages: 1,
space: 'srgb',
width: 10
});
});
}); });