hMatoba / Piexif

Exif manipulation with pure python script.
MIT License
373 stars 83 forks source link

Incorrect Detection of Nested ALPH Chunk in Animated WebP Files #144

Open skidder opened 2 months ago

skidder commented 2 months ago

Summary

Piexif corrupts the VP8X flags for animated WebP data.

Steps to Reproduce

The following commit on my fork adds two animated webp test files: https://github.com/hMatoba/Piexif/commit/5a12974343580d5f6fbbed74966bc56f2859ffe9

The tests will fail for pil_animated3.webp due to the unexpected presence of an ALPH chunk in the output file since the Alpha flag was incorrect removed from the VP8X flags. The webpinfo tool confirms this:

Input Test File

→ webpinfo -diag tests/images/pil_animated3.webp | head -n 30
File: tests/images/pil_animated3.webp
RIFF HEADER:
  File size: 2058520
Chunk VP8X at offset     12, length     18
  ICCP: 0
  Alpha: 1
  EXIF: 0
  XMP: 0
  Animation: 1
  Canvas size 1280 x 531
Chunk ANIM at offset     30, length     14
  Background color:(ARGB) ff ff ff ff
  Loop count      : 0
Chunk ANMF at offset     44, length  81288
  Offset_X: 0
  Offset_Y: 0
  Width: 1280
  Height: 531
  Duration: 50
  Dispose: 0
  Blend: 1
Chunk VP8  at offset     68, length  81264
  Width: 1280
  Height: 531
  Alpha: 0
  Animation: 0
  Format: Lossy (1)

...

Chunk ANMF at offset 1977418, length  81102
  Offset_X: 0
  Offset_Y: 0
  Width: 1280
  Height: 531
  Duration: 50
  Dispose: 0
  Blend: 0
Chunk ALPH at offset 1977442, length    110
Chunk VP8  at offset 1977552, length  80968
  Width: 1280
  Height: 531
  Alpha: 0
  Animation: 0
  Format: Lossy (1)
No error detected.

Output Test File

→ webpinfo -diag tests/images/out/i_pil_animated3.webp
File: tests/images/out/i_pil_animated3.webp
RIFF HEADER:
  File size: 2058578
Chunk VP8X at offset     12, length     18
  ICCP: 0
  Alpha: 0
  EXIF: 1
  XMP: 0
  Animation: 1
  Canvas size 1280 x 531
Chunk EXIF at offset     30, length     58
Chunk ANIM at offset     88, length     14
  Background color:(ARGB) ff ff ff ff
  Loop count      : 0
Chunk ANMF at offset    102, length  81288
  Offset_X: 0
  Offset_Y: 0
  Width: 1280
  Height: 531
  Duration: 50
  Dispose: 0
  Blend: 1
Chunk VP8  at offset    126, length  81264
  Width: 1280
  Height: 531
  Alpha: 0
  Animation: 0
  Format: Lossy (1)

...

Chunk ANMF at offset 1977476, length  81102
  Offset_X: 0
  Offset_Y: 0
  Width: 1280
  Height: 531
  Duration: 50
  Dispose: 0
  Blend: 0
Chunk ALPH at offset 1977500, length    110
Chunk VP8  at offset 1977610, length  80968
  Width: 1280
  Height: 531
  Alpha: 0
  Animation: 0
  Format: Lossy (1)
Error: Unexpected alpha data detected.
Errors detected.

Proposal

Recursively examine sub-chunks within the ANMF chunk. I have a commit on my fork that could work for this: https://github.com/hMatoba/Piexif/commit/fe92a5b007668a8c444948b371ced8c2bd84a7df

Expected Behavior:

The piexif library should correctly identify the structure of the WebP file and detect ALPH chunks that are present at the appropriate levels. Specifically, the presence of an ALPH chunk nested within an ANMF chunk should correctly set the animation flag in the VP8X chunk at the container level. The WebP Extended File Format allows for the ANMF chunk to contain an ALPH sub-chunk which, if present, must result in the VP8X chunk Animation flag being enabled.

Actual Behavior:

The library fails to detect the nested ALPH chunk correctly, resulting in incorrect flag settings in the VP8X chunk. This causes the library to corrupts the contents of animated WebP files.

Technical Details:

The issue seems to stem from the set_vp8x function, which does not recursively check for ALPH chunks nested within ANMF chunks. As a result, the library fails to set the animation flag correctly.

WebP Image (OK)

The detection of ALPH chunks works fine for single frame, non-animated WebP files having a structure like the following:

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

Animated WebP (Broken)

The issue arises with animated WebP files having a nested ALPH sub-chunk:

+--------------------------+
|   WebP Container          |
|                          |
|  +--------------------+  |
|  |     VP8X Chunk     |  |  <-- Flags and size info
|  +--------------------+  |
|                          |
|  +--------------------+  |
|  |     ANIM Chunk     |  |  <-- Animation control info
|  +--------------------+  |
|                          |
|  +--------------------+  |
|  |    ANMF Chunk      |  |  <-- Frame 1
|  |  +--------------+  |  |
|  |  | ALPH Chunk   |  |  |  <-- Nested Alpha data (Transparency)
|  |  +--------------+  |  |
|  |  | VP8L Chunk   |  |  |  <-- Image data
|  +--------------------+  |
|                          |
|  +--------------------+  |
|  |    ANMF Chunk      |  |  <-- Frame 2
|  |  +--------------+  |  |
|  |  | ALPH Chunk   |  |  |  <-- Nested Alpha data (Transparency)
|  |  +--------------+  |  |
|  |  | VP8L Chunk   |  |  |  <-- Image data
|  +--------------------+  |
|                          |
+--------------------------+
6446plm commented 2 months ago

كيف تديره 👀😎