mirror of
https://github.com/lovell/sharp.git
synced 2025-07-09 10:30:15 +02:00
Non-animated GIF output defaults to no-loop #3394
This commit is contained in:
parent
3fd818c4b5
commit
3e41f8b65e
@ -14,6 +14,9 @@ Requires libvips v8.16.1
|
|||||||
* Breaking: Ensure `removeAlpha` removes all alpha channels.
|
* Breaking: Ensure `removeAlpha` removes all alpha channels.
|
||||||
[#2266](https://github.com/lovell/sharp/issues/2266)
|
[#2266](https://github.com/lovell/sharp/issues/2266)
|
||||||
|
|
||||||
|
* Breaking: Non-animated GIF output defaults to no-loop instead of loop-forever.
|
||||||
|
[#3394](https://github.com/lovell/sharp/issues/3394)
|
||||||
|
|
||||||
* Breaking: Support `info.size` on wide-character systems via upgrade to C++17.
|
* Breaking: Support `info.size` on wide-character systems via upgrade to C++17.
|
||||||
[#3943](https://github.com/lovell/sharp/issues/3943)
|
[#3943](https://github.com/lovell/sharp/issues/3943)
|
||||||
|
|
||||||
|
@ -296,6 +296,8 @@ const Sharp = function (input, options) {
|
|||||||
withExif: {},
|
withExif: {},
|
||||||
withExifMerge: true,
|
withExifMerge: true,
|
||||||
resolveWithObject: false,
|
resolveWithObject: false,
|
||||||
|
loop: 1,
|
||||||
|
delay: [],
|
||||||
// output format
|
// output format
|
||||||
jpegQuality: 80,
|
jpegQuality: 80,
|
||||||
jpegProgressive: false,
|
jpegProgressive: false,
|
||||||
|
@ -1705,6 +1705,8 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|||||||
}
|
}
|
||||||
baton->withExifMerge = sharp::AttrAsBool(options, "withExifMerge");
|
baton->withExifMerge = sharp::AttrAsBool(options, "withExifMerge");
|
||||||
baton->timeoutSeconds = sharp::AttrAsUint32(options, "timeoutSeconds");
|
baton->timeoutSeconds = sharp::AttrAsUint32(options, "timeoutSeconds");
|
||||||
|
baton->loop = sharp::AttrAsUint32(options, "loop");
|
||||||
|
baton->delay = sharp::AttrAsInt32Vector(options, "delay");
|
||||||
// Format-specific
|
// Format-specific
|
||||||
baton->jpegQuality = sharp::AttrAsUint32(options, "jpegQuality");
|
baton->jpegQuality = sharp::AttrAsUint32(options, "jpegQuality");
|
||||||
baton->jpegProgressive = sharp::AttrAsBool(options, "jpegProgressive");
|
baton->jpegProgressive = sharp::AttrAsBool(options, "jpegProgressive");
|
||||||
@ -1774,13 +1776,6 @@ Napi::Value pipeline(const Napi::CallbackInfo& info) {
|
|||||||
baton->jxlEffort = sharp::AttrAsUint32(options, "jxlEffort");
|
baton->jxlEffort = sharp::AttrAsUint32(options, "jxlEffort");
|
||||||
baton->jxlLossless = sharp::AttrAsBool(options, "jxlLossless");
|
baton->jxlLossless = sharp::AttrAsBool(options, "jxlLossless");
|
||||||
baton->rawDepth = sharp::AttrAsEnum<VipsBandFormat>(options, "rawDepth", VIPS_TYPE_BAND_FORMAT);
|
baton->rawDepth = sharp::AttrAsEnum<VipsBandFormat>(options, "rawDepth", VIPS_TYPE_BAND_FORMAT);
|
||||||
// Animated output properties
|
|
||||||
if (sharp::HasAttr(options, "loop")) {
|
|
||||||
baton->loop = sharp::AttrAsUint32(options, "loop");
|
|
||||||
}
|
|
||||||
if (sharp::HasAttr(options, "delay")) {
|
|
||||||
baton->delay = sharp::AttrAsInt32Vector(options, "delay");
|
|
||||||
}
|
|
||||||
baton->tileSize = sharp::AttrAsUint32(options, "tileSize");
|
baton->tileSize = sharp::AttrAsUint32(options, "tileSize");
|
||||||
baton->tileOverlap = sharp::AttrAsUint32(options, "tileOverlap");
|
baton->tileOverlap = sharp::AttrAsUint32(options, "tileOverlap");
|
||||||
baton->tileAngle = sharp::AttrAsInt32(options, "tileAngle");
|
baton->tileAngle = sharp::AttrAsInt32(options, "tileAngle");
|
||||||
|
@ -380,7 +380,7 @@ struct PipelineBaton {
|
|||||||
ensureAlpha(-1.0),
|
ensureAlpha(-1.0),
|
||||||
colourspacePipeline(VIPS_INTERPRETATION_LAST),
|
colourspacePipeline(VIPS_INTERPRETATION_LAST),
|
||||||
colourspace(VIPS_INTERPRETATION_LAST),
|
colourspace(VIPS_INTERPRETATION_LAST),
|
||||||
loop(-1),
|
loop(1),
|
||||||
tileSize(256),
|
tileSize(256),
|
||||||
tileOverlap(0),
|
tileOverlap(0),
|
||||||
tileContainer(VIPS_FOREIGN_DZ_CONTAINER_FS),
|
tileContainer(VIPS_FOREIGN_DZ_CONTAINER_FS),
|
||||||
|
@ -224,4 +224,18 @@ describe('GIF input', () => {
|
|||||||
const after = await input.gif({ interPaletteMaxError: 100 }).toBuffer();
|
const after = await input.gif({ interPaletteMaxError: 100 }).toBuffer();
|
||||||
assert.strict(before.length > after.length);
|
assert.strict(before.length > after.length);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('non-animated input defaults to no-loop', async () => {
|
||||||
|
for (const input of [fixtures.inputGif, fixtures.inputPng]) {
|
||||||
|
const data = await sharp(input)
|
||||||
|
.resize(8)
|
||||||
|
.gif({ effort: 1 })
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
const { format, pages, loop } = await sharp(data).metadata();
|
||||||
|
assert.strictEqual('gif', format);
|
||||||
|
assert.strictEqual(1, pages);
|
||||||
|
assert.strictEqual(1, loop);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user