Skip to content

Incorrect VP8X Canvas Dimensions in Animated WebP Files #145

@skidder

Description

@skidder

Summary

Piexif incorrectly sets the VP8X canvas dimensions for certain animated WebP files, leading to a "Frame exceeds canvas" error when frames exceed the dimensions of the last frame.

Steps to Reproduce:

  1. Process an animated WebP file using Piexif where the frames vary in size.
  2. Ensure that the last frame is smaller than some of the previous frames.
  3. Run a tool like webpinfo on the output file to observe the error.

This can be reproduced with the pil_animated2.webp file in my fork: 5a12974

Input Test File

→ webpinfo -diag tests/images/pil_animated2.webp
File: tests/images/pil_animated2.webp
RIFF HEADER:
  File size:  37342
Chunk VP8X at offset     12, length     18
  ICCP: 0
  Alpha: 1
  EXIF: 0
  XMP: 0
  Animation: 1
  Canvas size 400 x 400
Chunk ANIM at offset     30, length     14
  Background color:(ARGB) ff 00 00 00
  Loop count      : 0
Chunk ANMF at offset     44, length   5190
  Offset_X: 0
  Offset_Y: 0
  Width: 400
  Height: 400
  Duration: 70
  Dispose: 0
  Blend: 1
Chunk VP8L at offset     68, length   5166
  Width: 400
  Height: 400
  Alpha: 0
  Animation: 0
  Format: Lossless (2)
  
  ...
  
Chunk ANMF at offset  34824, length   2518
  Offset_X: 0
  Offset_Y: 6
  Width: 320
  Height: 382
  Duration: 70
  Dispose: 0
  Blend: 0
Chunk VP8L at offset  34848, length   2494
  Width: 320
  Height: 382
  Alpha: 1
  Animation: 0
  Format: Lossless (2)
No error detected.

Output Test File

→ webpinfo -diag tests/images/out/i_pil_animated2.webp
File: tests/images/out/i_pil_animated2.webp
RIFF HEADER:
  File size:  37400
Chunk VP8X at offset     12, length     18
  ICCP: 0
  Alpha: 0
  EXIF: 1
  XMP: 0
  Animation: 1
  Canvas size 320 x 382
Chunk EXIF at offset     30, length     58
Chunk ANIM at offset     88, length     14
  Background color:(ARGB) ff 00 00 00
  Loop count      : 0
Chunk ANMF at offset    102, length   5190
  Offset_X: 0
  Offset_Y: 0
  Width: 400
  Height: 400
  Duration: 70
  Dispose: 0
  Blend: 1
Error: Frame exceeds canvas in ANMF chunk.
Errors detected.

Expected Behavior:

The VP8X chunk should reflect the maximum dimensions across all frames to correctly represent the entire canvas, preventing any "Frame exceeds canvas" errors.

Actual Behavior:

The VP8X chunk dimensions are set based on the last frame processed. If this frame is smaller than earlier frames, the overall canvas size is incorrect, leading to errors.

This issue affects users processing animated WebP files with frames of varying sizes. Ensuring the correct canvas size in the VP8X chunk is critical for maintaining compatibility and avoiding errors in tools that validate WebP file structure.

Technical Details

The issue arises because the set_vp8x function in the piexif library sets the width and height based on the last frame it processes. This approach fails to account for previous frames that may be larger, resulting in an incorrect canvas size.

WebP Image (OK)

For non-animated WebP files, the VP8X chunk correctly represents the image dimensions:

+--------------------------+
|   WebP Container          |
|                          |
|  +--------------------+  |
|  |     VP8X Chunk     |  |  <-- Flags and size info
|  +--------------------+  |
|                          |
|  +--------------------+  |
|  |    VP8L Chunk      |  |  <-- Image data (Lossless)
|  +--------------------+  |
|                          |
+--------------------------+

Animated WebP (Broken)

For animated WebP files, the VP8X chunk incorrectly sets the canvas dimensions based on the last frame processed, even if earlier frames are larger:

+--------------------------+
|   WebP Container          |
|                          |
|  +--------------------+  |
|  |     VP8X Chunk     |  |  <-- Flags and canvas size info (incorrectly set)
|  +--------------------+  |
|                          |
|  +--------------------+  |
|  |     ANIM Chunk     |  |  <-- Animation control info
|  +--------------------+  |
|                          |
|  +--------------------+  |
|  |    ANMF Chunk      |  |  <-- Frame 1 (larger than last frame)
|  |  +--------------+  |  |
|  |  | VP8L Chunk   |  |  |  <-- Image data
|  +--------------------+  |
|                          |
|  +--------------------+  |
|  |    ANMF Chunk      |  |  <-- Frame 2 (smaller, last frame processed)
|  |  +--------------+  |  |
|  |  | VP8L Chunk   |  |  |  <-- Image data
|  +--------------------+  |
|                          |
+--------------------------+

Proposal:

Modify the set_vp8x function to track the maximum width and height across all frames. The VP8X chunk should be updated to reflect these maximum dimensions, ensuring that the canvas size accommodates all frames.

I have a commit in my fork that appears to resolve this: 7c6522a

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions