Fix some webp images improperly marked as animated (#29713)

* Fix some webp images improperly marked as animated

* Add unit test for an unanimated webp file in extended file format

* Apply linting to webp test
This commit is contained in:
Peter Smit
2025-04-11 15:32:41 +02:00
committed by GitHub
parent d594441b53
commit ca56c2e091
3 changed files with 9 additions and 2 deletions

View File

@@ -31,13 +31,13 @@ export async function blobIsAnimated(mimeType: string | undefined, blob: Blob):
case "image/webp": { case "image/webp": {
// Only extended file format WEBP images support animation, so grab the expected data range and verify header. // Only extended file format WEBP images support animation, so grab the expected data range and verify header.
// Based on https://developers.google.com/speed/webp/docs/riff_container#extended_file_format // Based on https://developers.google.com/speed/webp/docs/riff_container#extended_file_format
const arr = await blob.slice(0, 17).arrayBuffer(); const arr = await blob.slice(0, 21).arrayBuffer();
if ( if (
arrayBufferReadStr(arr, 0, 4) === "RIFF" && arrayBufferReadStr(arr, 0, 4) === "RIFF" &&
arrayBufferReadStr(arr, 8, 4) === "WEBP" && arrayBufferReadStr(arr, 8, 4) === "WEBP" &&
arrayBufferReadStr(arr, 12, 4) === "VP8X" arrayBufferReadStr(arr, 12, 4) === "VP8X"
) { ) {
const [flags] = arrayBufferRead(arr, 16, 1); const [flags] = arrayBufferRead(arr, 20, 1);
// Flags: R R I L E X _A_ R (reversed) // Flags: R R I L E X _A_ R (reversed)
const animationFlagMask = 1 << 1; const animationFlagMask = 1 << 1;
return (flags & animationFlagMask) != 0; return (flags & animationFlagMask) != 0;

View File

@@ -51,6 +51,13 @@ describe("Image", () => {
expect(await blobIsAnimated("image/webp", img)).toBeFalsy(); expect(await blobIsAnimated("image/webp", img)).toBeFalsy();
}); });
it("Static WEBP in extended file format", async () => {
const img = new Blob([
fs.readFileSync(path.resolve(__dirname, "images", "static-logo-extended-file-format.webp")),
]);
expect(await blobIsAnimated("image/webp", img)).toBeFalsy();
});
it("Animated PNG", async () => { it("Animated PNG", async () => {
const img = new Blob([fs.readFileSync(path.resolve(__dirname, "images", "animated-logo.apng"))]); const img = new Blob([fs.readFileSync(path.resolve(__dirname, "images", "animated-logo.apng"))]);
expect(await blobIsAnimated("image/png", img)).toBeTruthy(); expect(await blobIsAnimated("image/png", img)).toBeTruthy();

Binary file not shown.

After

Width:  |  Height:  |  Size: 734 B