0

Add PNG eXIf chunk support

The PNG eXIf chunk has been in the extension part of the PNG spec for a long
time now. libpng already supports eXIf (outside of push mode).

http://www.libpng.org/pub/png/spec/register/pngext-1.4.0-pdg.html

In PNG Third Edition, eXIf is becoming an official part of the main spec and
not just in the extensions. As such, Chromium should officially support it.

There is a WPT which tests if the eXIf chunk is recognized by setting an
orientation:
https://wpt.fyi/results/png/exif-chunk.html?label=experimental&label=master&aligned

This commit adds support for the eXIf PNG chunk (updating orientation) to Chromium.

Note, libpng supports eXIf in non-push mode. Chromium uses push mode.
It seems like when eXIf support was added to libpng they simply forgot push mode.
This commit also adds support for eXIf to libpng's push mode.

Change-Id: Ibda3b9a4f59ad5787fb441d6db015e564c1798ed
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5249880
Reviewed-by: Leon Scroggins <scroggo@google.com>
Commit-Queue: Chris Blume <cblume@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1256248}
This commit is contained in:
Chris Blume
2024-02-05 16:27:27 +00:00
committed by Chromium LUCI CQ
parent 9db650b40b
commit 694d9d3a5c
6 changed files with 27 additions and 7 deletions
third_party
blink
renderer
web_tests
libpng

@@ -43,6 +43,7 @@
#include "base/containers/adapters.h"
#include "base/numerics/checked_math.h"
#include "media/base/video_color_space.h"
#include "third_party/blink/renderer/platform/image-decoders/exif_reader.h"
#include "third_party/skia/include/core/SkColorSpace.h"
#include "third_party/skia/modules/skcms/skcms.h"
@@ -484,6 +485,19 @@ void PNGImageDecoder::HeaderAvailable() {
}
}
// process eXIf chunk
png_uint_32 exif_size = 0;
png_bytep exif_buffer = nullptr;
if (png_get_eXIf_1(png, info, &exif_size, &exif_buffer) != 0) {
// exif data exists
if (exif_size != 0 && exif_buffer) {
DecodedImageMetaData metadata;
base::span<const uint8_t> exif_span(exif_buffer, exif_size);
ReadExif(exif_span, metadata);
ApplyMetadata(metadata, gfx::Size(width, height));
}
}
// Tell libpng to send us rows for interlaced pngs.
if (interlace_type == PNG_INTERLACE_ADAM7) {
png_set_interlace_handling(png);

@@ -675,8 +675,8 @@ bool PNGImageReader::ParseSize(const FastSharedBufferReader& reader) {
ignore_animation_ = true;
} else {
auto is_necessary_ancillary = [](const png_byte* chunk) {
for (const char* tag :
{"tRNS", "cHRM", "iCCP", "sRGB", "gAMA", "cICP", "cLLi", "mDCv"}) {
for (const char* tag : {"tRNS", "cHRM", "iCCP", "sRGB", "gAMA", "cICP",
"cLLi", "mDCv", "eXIf"}) {
if (IsChunk(chunk, tag)) {
return true;
}

@@ -1,5 +0,0 @@
This is a testharness.js-based test.
[FAIL] test pixel values of a rotated PNG
assert_approx_equals: expected 0 +/- 2 but got 255
Harness: the test ran to completion.

@@ -25,3 +25,5 @@ Updated to 1.6.37, stripped all unneeded files.
- Applies the commit from
https://github.com/pnggroup/libpng/commit/893b8113f04d408cc6177c6de19c9889a48faa24
to address a build failure with the latest Clang for Apple targets.
- Applies the commit from
https://github.com/pnggroup/libpng/commit/7f1f960d4ffdb47ddb964b7d7753701b402f5214

@@ -68,6 +68,7 @@
#define PNG_READ_USER_CHUNKS_SUPPORTED
#define PNG_READ_USER_TRANSFORM_SUPPORTED
#define PNG_READ_cHRM_SUPPORTED
#define PNG_READ_eXIf_SUPPORTED
#define PNG_READ_gAMA_SUPPORTED
#define PNG_READ_iCCP_SUPPORTED
#define PNG_READ_sRGB_SUPPORTED
@@ -127,6 +128,7 @@
#define PNG_WRITE_tRNS_SUPPORTED
#define PNG_WRITE_zTXt_SUPPORTED
#define PNG_cHRM_SUPPORTED
#define PNG_eXIf_SUPPORTED
#define PNG_gAMA_SUPPORTED
#define PNG_iCCP_SUPPORTED
#define PNG_sBIT_SUPPORTED

@@ -293,6 +293,13 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_eXIf_SUPPORTED
else if (png_ptr->chunk_name == png_eXIf)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_eXIf(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_sRGB_SUPPORTED