Add ignore exif/xmp to avifginmaputil (#3300)
Fixes #3297
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8af3be1..218207e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,7 @@
* Support ignoring alpha in avifDecoder::imageContentToDecode.
* avifenc: add --ignore-alpha flag to discard alpha channel on encode
* avifgainmaputil: add --ignore-alpha flag to discard alpha channel
+* avifgainmaputil: add --ignore-exif and --ignore-xmp flags
### Changed since 1.4.2
diff --git a/apps/avifgainmaputil/combine_command.cc b/apps/avifgainmaputil/combine_command.cc
index 420a193..b58b73b 100644
--- a/apps/avifgainmaputil/combine_command.cc
+++ b/apps/avifgainmaputil/combine_command.cc
@@ -98,7 +98,8 @@
}
avifResult result = ReadImage(
base_image.get(), arg_base_filename_, pixel_format, arg_image_read_.depth,
- arg_image_read_.ignore_profile, arg_image_read_.ignore_alpha,
+ arg_image_read_.ignore_profile, arg_image_read_.ignore_exif,
+ arg_image_read_.ignore_xmp, arg_image_read_.ignore_alpha,
/*ignore_gain_map=*/true, arg_jobs_.jobs.value());
if (result != AVIF_RESULT_OK) {
std::cout << "Failed to read base image: " << avifResultToString(result)
@@ -117,6 +118,7 @@
result =
ReadImage(alternate_image.get(), arg_alternate_filename_, pixel_format,
arg_image_read_.depth, arg_image_read_.ignore_profile,
+ arg_image_read_.ignore_exif, arg_image_read_.ignore_xmp,
arg_image_read_.ignore_alpha, /*ignore_gain_map=*/true,
arg_jobs_.jobs.value());
if (result != AVIF_RESULT_OK) {
diff --git a/apps/avifgainmaputil/convert_command.cc b/apps/avifgainmaputil/convert_command.cc
index 54e4744..b6ba6b3 100644
--- a/apps/avifgainmaputil/convert_command.cc
+++ b/apps/avifgainmaputil/convert_command.cc
@@ -62,6 +62,7 @@
avifResult result =
ReadImage(image.get(), arg_input_filename_.value(), pixel_format,
arg_image_read_.depth, arg_image_read_.ignore_profile,
+ arg_image_read_.ignore_exif, arg_image_read_.ignore_xmp,
arg_image_read_.ignore_alpha, /*ignore_gain_map=*/false,
arg_jobs_.jobs.value());
if (result != AVIF_RESULT_OK) {
diff --git a/apps/avifgainmaputil/imageio.cc b/apps/avifgainmaputil/imageio.cc
index c1a0725..900f30c 100644
--- a/apps/avifgainmaputil/imageio.cc
+++ b/apps/avifgainmaputil/imageio.cc
@@ -191,8 +191,8 @@
avifResult ReadImage(avifImage* image, const std::string& input_filename,
avifPixelFormat requested_format, uint32_t requested_depth,
- bool ignore_profile, bool ignore_alpha,
- bool ignore_gain_map, int jobs) {
+ bool ignore_profile, bool ignore_exif, bool ignore_xmp,
+ bool ignore_alpha, bool ignore_gain_map, int jobs) {
avifAppFileFormat input_format = avifGuessFileFormat(input_filename.c_str());
if (input_format == AVIF_APP_FILE_FORMAT_UNKNOWN) {
std::cerr << "Cannot determine input format: " << input_filename;
@@ -210,6 +210,8 @@
decoder->imageContentToDecode |= AVIF_IMAGE_CONTENT_GAIN_MAP;
}
decoder->ignoreICC = ignore_profile;
+ decoder->ignoreExif = ignore_exif;
+ decoder->ignoreXMP = ignore_xmp;
avifResult result = ReadAvif(decoder.get(), input_filename);
if (result != AVIF_RESULT_OK) {
return result;
@@ -236,9 +238,9 @@
const avifAppFileFormat file_format = avifReadImage(
input_filename.c_str(), AVIF_APP_FILE_FORMAT_UNKNOWN /* guess format */,
requested_format, static_cast<int>(requested_depth),
- AVIF_CHROMA_DOWNSAMPLING_AUTOMATIC, ignore_profile,
- /*ignoreExif=*/false, /*ignoreXMP=*/false, ignore_alpha,
- ignore_gain_map, AVIF_DEFAULT_IMAGE_SIZE_LIMIT, image,
+ AVIF_CHROMA_DOWNSAMPLING_AUTOMATIC, ignore_profile, ignore_exif,
+ ignore_xmp, ignore_alpha, ignore_gain_map,
+ AVIF_DEFAULT_IMAGE_SIZE_LIMIT, image,
/*outDepth=*/nullptr,
/*sourceTiming=*/nullptr, /*frameIter=*/nullptr);
if (file_format == AVIF_APP_FILE_FORMAT_UNKNOWN) {
diff --git a/apps/avifgainmaputil/imageio.h b/apps/avifgainmaputil/imageio.h
index 48d0275..74dcacc 100644
--- a/apps/avifgainmaputil/imageio.h
+++ b/apps/avifgainmaputil/imageio.h
@@ -19,8 +19,8 @@
// Reads an image in any of the supported formats. Ignores any gain map.
avifResult ReadImage(avifImage* image, const std::string& input_filename,
avifPixelFormat requested_format, uint32_t requested_depth,
- bool ignore_profile, bool ignore_alpha,
- bool ignore_gain_map, int jobs);
+ bool ignore_profile, bool ignore_exif, bool ignore_xmp,
+ bool ignore_alpha, bool ignore_gain_map, int jobs);
// Writes an image in avif format given a pre-configured encoder.
avifResult WriteAvif(const avifImage* image, avifEncoder* encoder,
diff --git a/apps/avifgainmaputil/program_command.h b/apps/avifgainmaputil/program_command.h
index 5c18b0b..c60fb96 100644
--- a/apps/avifgainmaputil/program_command.h
+++ b/apps/avifgainmaputil/program_command.h
@@ -134,6 +134,8 @@
argparse::ArgValue<int> pixel_format;
argparse::ArgValue<bool> ignore_profile;
argparse::ArgValue<bool> ignore_alpha;
+ argparse::ArgValue<bool> ignore_exif;
+ argparse::ArgValue<bool> ignore_xmp;
void Init(argparse::ArgumentParser& argparse) {
argparse
@@ -154,6 +156,18 @@
"(no-op if absent)")
.action(argparse::Action::STORE_TRUE)
.default_value("false");
+ argparse.add_argument(ignore_exif, "--ignore-exif")
+ .help(
+ "If the input file contains embedded Exif metadata, ignore it "
+ "(no-op if absent)")
+ .action(argparse::Action::STORE_TRUE)
+ .default_value("false");
+ argparse.add_argument(ignore_xmp, "--ignore-xmp")
+ .help(
+ "If the input file contains embedded XMP metadata, ignore it "
+ "(no-op if absent)")
+ .action(argparse::Action::STORE_TRUE)
+ .default_value("false");
}
};
diff --git a/apps/avifgainmaputil/swapbase_command.cc b/apps/avifgainmaputil/swapbase_command.cc
index fdabf8c..67a9aa4 100644
--- a/apps/avifgainmaputil/swapbase_command.cc
+++ b/apps/avifgainmaputil/swapbase_command.cc
@@ -169,6 +169,8 @@
}
decoder->imageContentToDecode |= AVIF_IMAGE_CONTENT_GAIN_MAP;
decoder->ignoreICC = arg_image_read_.ignore_profile;
+ decoder->ignoreExif = arg_image_read_.ignore_exif;
+ decoder->ignoreXMP = arg_image_read_.ignore_xmp;
avifResult result = ReadAvif(decoder.get(), arg_input_filename_);
if (result != AVIF_RESULT_OK) {
return result;
diff --git a/apps/avifgainmaputil/tonemap_command.cc b/apps/avifgainmaputil/tonemap_command.cc
index b307fd6..05825e9 100644
--- a/apps/avifgainmaputil/tonemap_command.cc
+++ b/apps/avifgainmaputil/tonemap_command.cc
@@ -71,6 +71,8 @@
}
decoder->imageContentToDecode |= AVIF_IMAGE_CONTENT_GAIN_MAP;
decoder->ignoreICC = arg_image_read_.ignore_profile;
+ decoder->ignoreExif = arg_image_read_.ignore_exif;
+ decoder->ignoreXMP = arg_image_read_.ignore_xmp;
avifResult result = ReadAvif(decoder.get(), arg_input_filename_);
if (result != AVIF_RESULT_OK) {
return result;
diff --git a/tests/test_cmd_avifgainmaputil.sh b/tests/test_cmd_avifgainmaputil.sh
index b25061d..a5da841 100755
--- a/tests/test_cmd_avifgainmaputil.sh
+++ b/tests/test_cmd_avifgainmaputil.sh
@@ -59,11 +59,25 @@
"${AVIFGAINMAPUTIL}" tonemap "${INPUT_AVIF_GAINMAP_SDR}" "${PNG_OUTPUT}" --headroom 0 --clli 400,500
"${ARE_IMAGES_EQUAL}" "${PNG_OUTPUT}" "${INPUT_JPEG_GAINMAP_SDR}" 0 40 1
# Check that metadata is copied over.
- "${AVIFGAINMAPUTIL}" tonemap "${AVIF_OUTPUT}" "${AVIF_OUTPUT}" --headroom 0 > "${OUT_MSG}"
+ "${AVIFGAINMAPUTIL}" tonemap "${AVIF_OUTPUT}" "${AVIF_OUTPUT}.tonemapped.avif" --headroom 0 > "${OUT_MSG}"
cat "${OUT_MSG}"
grep "XMP Metadata : Present" "${OUT_MSG}"
grep "Exif Metadata : Present" "${OUT_MSG}"
+ # Check that metadata can be ignored (tonemap command).
+ "${AVIFGAINMAPUTIL}" tonemap "${AVIF_OUTPUT}" "${AVIF_OUTPUT}.ignored.avif" --headroom 0 --ignore-xmp --ignore-exif > "${OUT_MSG}"
+ cat "${OUT_MSG}"
+ grep "XMP Metadata : Absent" "${OUT_MSG}"
+ grep "Exif Metadata : Absent" "${OUT_MSG}"
+
+ # Check that metadata can be ignored (combine command).
+ "${AVIFGAINMAPUTIL}" combine "${INPUT_AVIF_GAINMAP_HDR}" "${INPUT_AVIF_GAINMAP_SDR}" "${AVIF_OUTPUT}.ignored-combine.avif" \
+ -q 90 --qgain-map 90 --ignore-xmp --ignore-exif
+ "${AVIFGAINMAPUTIL}" tonemap "${AVIF_OUTPUT}.ignored-combine.avif" "${AVIF_OUTPUT}.ignored-combine.tonemapped.avif" --headroom 0 > "${OUT_MSG}"
+ cat "${OUT_MSG}"
+ grep "XMP Metadata : Absent" "${OUT_MSG}"
+ grep "Exif Metadata : Absent" "${OUT_MSG}"
+
# Test combine with overridden cicp values. Matrix coefficient 0 (identity) makes it obvious if there is an issue.
"${AVIFGAINMAPUTIL}" combine "${INPUT_JPEG_GAINMAP_SDR}" "${INPUT_AVIF_HDR2020}" "${AVIF_OUTPUT}" \
-q 100 --qgain-map 100 --cicp-base 1/13/0 --ignore-profile