mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 10:30:15 +02:00
Expose delay/loop metadata for animated images #1905
This commit is contained in:
parent
057074b238
commit
4a745f2d2e
@ -9,6 +9,9 @@ Requires libvips v8.9.0.
|
||||
* Drop support for Node.js 8.
|
||||
[#1910](https://github.com/lovell/sharp/issues/1910)
|
||||
|
||||
* Expose `delay` and `loop` metadata for animated images.
|
||||
[#1905](https://github.com/lovell/sharp/issues/1905)
|
||||
|
||||
* Ensure correct colour output for 16-bit, 2-channel PNG input with ICC profile.
|
||||
[#2013](https://github.com/lovell/sharp/issues/2013)
|
||||
|
||||
|
@ -77,6 +77,12 @@ class MetadataWorker : public Nan::AsyncWorker {
|
||||
if (image.get_typeof(VIPS_META_PAGE_HEIGHT) == G_TYPE_INT) {
|
||||
baton->pageHeight = image.get_int(VIPS_META_PAGE_HEIGHT);
|
||||
}
|
||||
if (image.get_typeof("loop") == G_TYPE_INT) {
|
||||
baton->loop = image.get_int("loop");
|
||||
}
|
||||
if (image.get_typeof("delay") == VIPS_TYPE_ARRAY_INT) {
|
||||
baton->delay = image.get_array_int("delay");
|
||||
}
|
||||
if (image.get_typeof("heif-primary") == G_TYPE_INT) {
|
||||
baton->pagePrimary = image.get_int("heif-primary");
|
||||
}
|
||||
@ -169,6 +175,17 @@ class MetadataWorker : public Nan::AsyncWorker {
|
||||
if (baton->pageHeight > 0) {
|
||||
Set(info, New("pageHeight").ToLocalChecked(), New<v8::Uint32>(baton->pageHeight));
|
||||
}
|
||||
if (baton->loop >= 0) {
|
||||
Set(info, New("loop").ToLocalChecked(), New<v8::Uint32>(baton->loop));
|
||||
}
|
||||
if (!baton->delay.empty()) {
|
||||
int i = 0;
|
||||
v8::Local<v8::Array> delay = New<v8::Array>(baton->delay.size());
|
||||
for (int const d : baton->delay) {
|
||||
Set(delay, i++, New<v8::Number>(d));
|
||||
}
|
||||
Set(info, New("delay").ToLocalChecked(), delay);
|
||||
}
|
||||
if (baton->pagePrimary > -1) {
|
||||
Set(info, New("pagePrimary").ToLocalChecked(), New<v8::Uint32>(baton->pagePrimary));
|
||||
}
|
||||
|
@ -36,6 +36,8 @@ struct MetadataBaton {
|
||||
int paletteBitDepth;
|
||||
int pages;
|
||||
int pageHeight;
|
||||
int loop;
|
||||
std::vector<int> delay;
|
||||
int pagePrimary;
|
||||
bool hasProfile;
|
||||
bool hasAlpha;
|
||||
@ -62,6 +64,7 @@ struct MetadataBaton {
|
||||
paletteBitDepth(0),
|
||||
pages(0),
|
||||
pageHeight(0),
|
||||
loop(-1),
|
||||
pagePrimary(-1),
|
||||
hasProfile(false),
|
||||
hasAlpha(false),
|
||||
|
BIN
test/fixtures/animated-loop-3.gif
vendored
Normal file
BIN
test/fixtures/animated-loop-3.gif
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.6 KiB |
1
test/fixtures/index.js
vendored
1
test/fixtures/index.js
vendored
@ -102,6 +102,7 @@ module.exports = {
|
||||
inputGif: getPath('Crash_test.gif'), // http://upload.wikimedia.org/wikipedia/commons/e/e3/Crash_test.gif
|
||||
inputGifGreyPlusAlpha: getPath('grey-plus-alpha.gif'), // http://i.imgur.com/gZ5jlmE.gif
|
||||
inputGifAnimated: getPath('rotating-squares.gif'), // CC0 https://loading.io/spinner/blocks/-rotating-squares-preloader-gif
|
||||
inputGifAnimatedLoop3: getPath('animated-loop-3.gif'), // CC-BY-SA-4.0 Petrus3743 https://commons.wikimedia.org/wiki/File:01-Goldener_Schnitt_Formel-Animation.gif
|
||||
inputSvg: getPath('check.svg'), // http://dev.w3.org/SVG/tools/svgweb/samples/svg-files/check.svg
|
||||
inputSvgWithEmbeddedImages: getPath('struct-image-04-t.svg'), // https://dev.w3.org/SVG/profiles/1.2T/test/svg/struct-image-04-t.svg
|
||||
|
||||
|
@ -232,6 +232,55 @@ describe('Image metadata', function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Animated GIF', () =>
|
||||
sharp(fixtures.inputGifAnimated)
|
||||
.metadata()
|
||||
.then(({
|
||||
format, width, height, space, channels, depth,
|
||||
isProgressive, pages, pageHeight, loop, delay,
|
||||
hasProfile, hasAlpha
|
||||
}) => {
|
||||
assert.strictEqual(format, 'gif');
|
||||
assert.strictEqual(width, 80);
|
||||
assert.strictEqual(height, 80);
|
||||
assert.strictEqual(space, 'srgb');
|
||||
assert.strictEqual(channels, 4);
|
||||
assert.strictEqual(depth, 'uchar');
|
||||
assert.strictEqual(isProgressive, false);
|
||||
assert.strictEqual(pages, 30);
|
||||
assert.strictEqual(pageHeight, 80);
|
||||
assert.strictEqual(loop, 0);
|
||||
assert.deepStrictEqual(delay, Array(30).fill(30));
|
||||
assert.strictEqual(hasProfile, false);
|
||||
assert.strictEqual(hasAlpha, true);
|
||||
})
|
||||
);
|
||||
|
||||
it('Animated GIF with limited looping', () =>
|
||||
sharp(fixtures.inputGifAnimatedLoop3)
|
||||
.metadata()
|
||||
.then(({
|
||||
format, width, height, space, channels, depth,
|
||||
isProgressive, pages, pageHeight, loop, delay,
|
||||
hasProfile, hasAlpha
|
||||
}) => {
|
||||
assert.strictEqual(format, 'gif');
|
||||
assert.strictEqual(width, 370);
|
||||
assert.strictEqual(height, 285);
|
||||
assert.strictEqual(space, 'srgb');
|
||||
assert.strictEqual(channels, 4);
|
||||
assert.strictEqual(depth, 'uchar');
|
||||
assert.strictEqual(isProgressive, false);
|
||||
assert.strictEqual(pages, 10);
|
||||
assert.strictEqual(pageHeight, 285);
|
||||
assert.strictEqual(loop, 3);
|
||||
assert.deepStrictEqual(delay, [...Array(9).fill(3000), 15000]);
|
||||
assert.strictEqual(hasProfile, false);
|
||||
assert.strictEqual(hasAlpha, true);
|
||||
})
|
||||
);
|
||||
|
||||
it('vips', () =>
|
||||
sharp(fixtures.inputV)
|
||||
.metadata()
|
||||
|
Loading…
x
Reference in New Issue
Block a user