Opened 21 months ago
Last modified 21 months ago
#11279 open defect
Aspect ratio defined by the PNG resolution chunk “pHYs” is misinterpreted as its reciprocal
| Reported by: | goodbye | Owned by: | |
|---|---|---|---|
| Priority: | normal | Component: | avcodec |
| Version: | git-master | Keywords: | png |
| Cc: | MasterQuestionable | Blocked By: | |
| Blocking: | Reproduced by developer: | no | |
| Analyzed by developer: | no |
Description (last modified by )
The PNG pHYs chunk describes the resolution/pixel density of an image, which can be in abstract units (in which case it only defines the pixel aspect ratio) or in pixels per metre.
FFmpeg interprets the X:Y resolution ratio directly as a X:Y PAR, but in actuality, it’s the reciprocal. This is because the resolution is specified as a “pixels per unit” value and not “units per pixel”, as is typically the case with PARs. The X:Y PAR is equal to the Y:X ratio of resolutions specified in the chunk.
Both of these images, from the libpng test suite, are supposed to have a DAR of 1:1, but FFmpeg misinterprets them to have DARs of 16:1 and 1:16:
- http://www.libpng.org/pub/png/PngSuite/cdhn2c08.png
- http://www.libpng.org/pub/png/PngSuite/cdfn2c08.png
The issue has been present from the very beginning, since parsing the pHYs chunk was introduced in commit 8288c2b6cb072b61f664bc8ab4c1b0a5a8db0ead, and is still present as of commit 1864025458021a2d2c542f56e268ee1106f84460 (libavcodec/pngdec.c lines 648–649)
The PNG encoder has the complementary problem of writing a reciprocal ratio into the pHYs chunk, introduced with commit f58f90238fc63090da34c9fdb1d06d724d929f6d (now libavcodec/pngenc.c lines 394–395)
Change History (11)
comment:1 by , 21 months ago
| Component: | undetermined → avcodec |
|---|---|
| Description: | modified (diff) |
| Version: | 7.1 → git-master |
comment:2 by , 21 months ago
| Description: | modified (diff) |
|---|
comment:3 by , 21 months ago
| Description: | modified (diff) |
|---|
follow-up: 7 comment:4 by , 21 months ago
comment:5 by , 21 months ago
| Cc: | added |
|---|
͏ Likely per the spec it doesn't... But unfixable at this point.
͏ (back-compatibility havoc)
comment:6 by , 21 months ago
Nah, Browsers render it differently compared to ffmpeg and mpv. So I think they render them correct.
comment:7 by , 21 months ago
Replying to Balling:
As I understand Chrome shows it correctly, right? First link is horizontal image, and second is vertical.
No, it just ignores the chunk and renders the image with square pixels.
comment:8 by , 21 months ago
| Status: | new → open |
|---|
Right, https://issues.chromium.org/issues/40509465#comment19 I see
So the result image is just a square and indeed if you invert how you read the pHYs it will be square.
comment:9 by , 21 months ago
͏ Differently broken in different implementations in different manner... 3D broken now.
follow-up: 11 comment:10 by , 21 months ago
Is the fix simply changing to
avctx->sample_aspect_ratio.den = bytestream2_get_be32(&s->gb);
+ avctx->sample_aspect_ratio.num = bytestream2_get_be32(&s->gb);
?
comment:11 by , 21 months ago
Yes, it's sufficient to swap num and den. And probably swap them in the encoder too. And ensure the test suite covers this.



As I understand Chrome shows it correctly, right? First link is horizontal image, and second is vertical.