From 775559567cde1f227117baec6ae297f8790d0746 Mon Sep 17 00:00:00 2001 From: Larry Gritz Date: Thu, 18 Dec 2025 16:44:58 -0800 Subject: [PATCH 1/2] fix(png): We were not correctly suppressing hint metadata Each file writer that is capable of writing arbitrary metadata is supposed to tace care to suppress hints meant for other writers, or for OIIO in general, not interpret them as literal metadata to write to the file. PNG was not doing so, and ended up writing hints as literal metadata. This brings it in line with our behavior when writing OpenEXR and other formats. Signed-off-by: Larry Gritz --- src/png.imageio/png_pvt.h | 20 ++++++++++++++++++++ testsuite/png-damaged/ref/out.txt | 8 ++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/png.imageio/png_pvt.h b/src/png.imageio/png_pvt.h index 3c103eb836..ca1803cec1 100644 --- a/src/png.imageio/png_pvt.h +++ b/src/png.imageio/png_pvt.h @@ -568,12 +568,32 @@ put_parameter(png_structp& sp, png_infop& ip, const std::string& _name, return true; } #endif + + // Before handling general named metadata, suppress format-specific + // metadata hints meant for other formats that are not meant to be literal + // metadata written to the file. This includes anything with a namespace + // prefix of "oiio:" or the name of any other file format. + auto colonpos = name.find(':'); + if (colonpos != std::string::npos) { + auto parts = Strutil::splitsv(name, ":", 2); + OIIO_DASSERT(parts.size() == 2); + std::string prefix = Strutil::lower(name.substr(0, colonpos)); + if (prefix != "png" && is_imageio_format_name(prefix)) + return false; + if (prefix == "oiio") + return false; + } + if (type == TypeDesc::STRING) { + // We can save arbitrary string metadata in multiple png text entries. + // Is that ok? Should we also do it for other types by converting to + // string? png_text t; t.compression = PNG_TEXT_COMPRESSION_NONE; t.key = (char*)ustring(name).c_str(); t.text = *(char**)data; // Already uniquified text.push_back(t); + return true; } return false; diff --git a/testsuite/png-damaged/ref/out.txt b/testsuite/png-damaged/ref/out.txt index 0c2636e3d3..4998469ba9 100644 --- a/testsuite/png-damaged/ref/out.txt +++ b/testsuite/png-damaged/ref/out.txt @@ -4,10 +4,10 @@ iconvert ERROR copying "../oiio-images/png/broken/invalid_gray_alpha_sbit.png" t PNG read error: IDAT: Read error: hit end of file in png reader libpng error: No IDATs written into file Comparing "../oiio-images/png/broken/invalid_gray_alpha_sbit.png" and "invalid_gray_alpha_sbit.png" -libpng error: tEXt: Read error: hit end of file in png reader -libpng error: tEXt: Read error: hit end of file in png reader +libpng error: oFFs: Read error: hit end of file in png reader +libpng error: oFFs: Read error: hit end of file in png reader idiff ERROR: Could not read invalid_gray_alpha_sbit.png: Invalid image file "invalid_gray_alpha_sbit.png": Read error: hit end of file in png reader -PNG read error: tEXt: Read error: hit end of file in png reader +PNG read error: oFFs: Read error: hit end of file in png reader Invalid image file "invalid_gray_alpha_sbit.png": Read error: hit end of file in png reader -PNG read error: tEXt: Read error: hit end of file in png reader +PNG read error: oFFs: Read error: hit end of file in png reader From 492a246d08294af799bb5947535ec8431598bf1e Mon Sep 17 00:00:00 2001 From: Larry Gritz Date: Thu, 18 Dec 2025 20:50:39 -0800 Subject: [PATCH 2/2] fix lines that should have been removed Signed-off-by: Larry Gritz --- src/png.imageio/png_pvt.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/png.imageio/png_pvt.h b/src/png.imageio/png_pvt.h index ca1803cec1..f7b6bbbb62 100644 --- a/src/png.imageio/png_pvt.h +++ b/src/png.imageio/png_pvt.h @@ -575,8 +575,6 @@ put_parameter(png_structp& sp, png_infop& ip, const std::string& _name, // prefix of "oiio:" or the name of any other file format. auto colonpos = name.find(':'); if (colonpos != std::string::npos) { - auto parts = Strutil::splitsv(name, ":", 2); - OIIO_DASSERT(parts.size() == 2); std::string prefix = Strutil::lower(name.substr(0, colonpos)); if (prefix != "png" && is_imageio_format_name(prefix)) return false;