From 260879ce2383da96de411d440ed6adf9ea98bfe6 Mon Sep 17 00:00:00 2001 From: maryla-uc Date: Thu, 12 Dec 2024 16:43:27 +0100 Subject: [PATCH] Remove AVIF_ENABLE_GAIN_MAP flag. (#2516) --- .github/workflows/ci-fuzztest.yml | 1 - .github/workflows/ci-linux-golden-tests.yml | 1 - .../workflows/ci-linux-static-old-local.yml | 1 - .github/workflows/ci-unix-shared-local.yml | 1 - .github/workflows/ci-unix-static.yml | 1 - .github/workflows/ci-windows-installed.yml | 1 - .github/workflows/ci-windows-shared-local.yml | 1 - .github/workflows/ci-windows.yml | 1 - CHANGELOG.md | 4 +- CMakeLists.txt | 82 ++++++------- apps/avifenc.c | 21 ++-- apps/shared/avifjpeg.c | 12 +- apps/shared/avifjpeg.h | 7 +- apps/shared/avifutil.c | 2 - apps/shared/avifutil.h | 5 +- include/avif/avif.h | 34 ++---- include/avif/avif_cxx.h | 5 - include/avif/internal.h | 8 +- src/avif.c | 8 -- src/gainmap.c | 4 - src/read.c | 87 ++++---------- src/write.c | 85 +------------- tests/CMakeLists.txt | 31 ++--- tests/gtest/avif_fuzztest_enc_dec.cc | 48 +++++++- .../avif_fuzztest_enc_dec_experimental.cc | 97 ---------------- tests/gtest/avif_fuzztest_enc_dec_incr.cc | 37 +++++- ...avif_fuzztest_enc_dec_incr_experimental.cc | 109 ------------------ tests/gtest/avif_fuzztest_helpers.cc | 2 - tests/gtest/avif_fuzztest_helpers.h | 22 +--- tests/gtest/avifincrtest_helpers.cc | 8 +- tests/gtest/aviftest_helpers.cc | 2 - 31 files changed, 185 insertions(+), 543 deletions(-) delete mode 100644 tests/gtest/avif_fuzztest_enc_dec_experimental.cc delete mode 100644 tests/gtest/avif_fuzztest_enc_dec_incr_experimental.cc diff --git a/.github/workflows/ci-fuzztest.yml b/.github/workflows/ci-fuzztest.yml index 48f13f8b93..30c22f989c 100644 --- a/.github/workflows/ci-fuzztest.yml +++ b/.github/workflows/ci-fuzztest.yml @@ -50,7 +50,6 @@ jobs: -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=ON -DAVIF_GTEST=LOCAL -DAVIF_ENABLE_EXPERIMENTAL_YCGCO_R=ON - -DAVIF_ENABLE_GAIN_MAP=ON -DAVIF_ENABLE_EXPERIMENTAL_MINI=ON -DAVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM=ON -DAVIF_ENABLE_FUZZTEST=ON diff --git a/.github/workflows/ci-linux-golden-tests.yml b/.github/workflows/ci-linux-golden-tests.yml index c869467a83..53cdac1d59 100644 --- a/.github/workflows/ci-linux-golden-tests.yml +++ b/.github/workflows/ci-linux-golden-tests.yml @@ -46,7 +46,6 @@ jobs: -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DAVIF_CODEC_AOM=LOCAL -DAVIF_LIBYUV=LOCAL -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON - -DAVIF_ENABLE_GAIN_MAP=ON -DAVIF_LIBXML2=LOCAL -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GOLDEN_TESTS=ON -DAVIF_ENABLE_GTEST=OFF -DAVIF_ENABLE_WERROR=ON diff --git a/.github/workflows/ci-linux-static-old-local.yml b/.github/workflows/ci-linux-static-old-local.yml index 52d03d384c..2aab1d7c10 100644 --- a/.github/workflows/ci-linux-static-old-local.yml +++ b/.github/workflows/ci-linux-static-old-local.yml @@ -51,7 +51,6 @@ jobs: -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=ON -DAVIF_LOCAL_GTEST=ON -DAVIF_ENABLE_EXPERIMENTAL_YCGCO_R=ON - -DAVIF_ENABLE_GAIN_MAP=ON -DAVIF_ENABLE_EXPERIMENTAL_MINI=ON -DAVIF_ENABLE_WERROR=ON - name: Build libavif (ninja) diff --git a/.github/workflows/ci-unix-shared-local.yml b/.github/workflows/ci-unix-shared-local.yml index 13aba3602d..ddcd3921bf 100644 --- a/.github/workflows/ci-unix-shared-local.yml +++ b/.github/workflows/ci-unix-shared-local.yml @@ -55,7 +55,6 @@ jobs: -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=ON -DAVIF_GTEST=LOCAL -DAVIF_ENABLE_EXPERIMENTAL_YCGCO_R=ON - -DAVIF_ENABLE_GAIN_MAP=ON -DAVIF_ENABLE_EXPERIMENTAL_MINI=ON -DAVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM=ON -DAVIF_ENABLE_WERROR=ON diff --git a/.github/workflows/ci-unix-static.yml b/.github/workflows/ci-unix-static.yml index 5ed5257674..7f763cc0cc 100644 --- a/.github/workflows/ci-unix-static.yml +++ b/.github/workflows/ci-unix-static.yml @@ -59,7 +59,6 @@ jobs: -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=ON -DAVIF_GTEST=LOCAL -DAVIF_ENABLE_EXPERIMENTAL_YCGCO_R=ON - -DAVIF_ENABLE_GAIN_MAP=ON -DAVIF_ENABLE_EXPERIMENTAL_MINI=ON -DAVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM=ON -DAVIF_ENABLE_WERROR=ON diff --git a/.github/workflows/ci-windows-installed.yml b/.github/workflows/ci-windows-installed.yml index d0072f07d8..8b238ca84a 100644 --- a/.github/workflows/ci-windows-installed.yml +++ b/.github/workflows/ci-windows-installed.yml @@ -74,7 +74,6 @@ jobs: -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=ON -DAVIF_GTEST=LOCAL -DAVIF_ENABLE_EXPERIMENTAL_YCGCO_R=ON - -DAVIF_ENABLE_GAIN_MAP=ON -DAVIF_ENABLE_EXPERIMENTAL_MINI=ON -DAVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM=ON -DAVIF_ENABLE_WERROR=ON $env:AVIF_CMAKE_C_COMPILER $env:AVIF_CMAKE_CXX_COMPILER diff --git a/.github/workflows/ci-windows-shared-local.yml b/.github/workflows/ci-windows-shared-local.yml index c827962ef6..b403a12cb7 100644 --- a/.github/workflows/ci-windows-shared-local.yml +++ b/.github/workflows/ci-windows-shared-local.yml @@ -54,7 +54,6 @@ jobs: -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=ON -DAVIF_GTEST=LOCAL -DAVIF_ENABLE_EXPERIMENTAL_YCGCO_R=ON - -DAVIF_ENABLE_GAIN_MAP=ON -DAVIF_ENABLE_EXPERIMENTAL_MINI=ON -DAVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM=ON -DAVIF_ENABLE_WERROR=ON $env:AVIF_CMAKE_C_COMPILER $env:AVIF_CMAKE_CXX_COMPILER diff --git a/.github/workflows/ci-windows.yml b/.github/workflows/ci-windows.yml index 14fe116f56..57d13e4d52 100644 --- a/.github/workflows/ci-windows.yml +++ b/.github/workflows/ci-windows.yml @@ -67,7 +67,6 @@ jobs: -DAVIF_BUILD_EXAMPLES=ON -DAVIF_BUILD_APPS=ON -DAVIF_BUILD_TESTS=ON -DAVIF_ENABLE_GTEST=ON -DAVIF_GTEST=LOCAL -DAVIF_ENABLE_EXPERIMENTAL_YCGCO_R=ON - -DAVIF_ENABLE_GAIN_MAP=ON -DAVIF_ENABLE_EXPERIMENTAL_MINI=ON -DAVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM=ON -DAVIF_ENABLE_WERROR=ON diff --git a/CHANGELOG.md b/CHANGELOG.md index 298c508e04..383bfd2097 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,8 +37,8 @@ The changes are relative to the previous release, unless the baseline is specifi avifGainMapMetadataDouble structs. * Add avif(Un)SignedFraction structs and avifDoubleTo(Un)SignedFraction utility functions. -* Turn on the gain map API by default. Rename the compile flag from - AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP to AVIF_ENABLE_GAIN_MAP. +* Turn on the gain map API. Remove the + AVIF_ENABLE_EXPERIMENTAL_GAIN_MAP compile flag. ## [1.1.1] - 2024-07-30 diff --git a/CMakeLists.txt b/CMakeLists.txt index 16230390b9..c4edea5b38 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,10 +64,6 @@ option(BUILD_SHARED_LIBS "Build shared avif library" ON) option(AVIF_ENABLE_WERROR "Treat all compiler warnings as errors" OFF) -option(AVIF_ENABLE_GAIN_MAP - "Enable gain map code (for HDR images that look good both on HDR and SDR displays)" ON -) - option(AVIF_ENABLE_EXPERIMENTAL_YCGCO_R "Enable experimental YCgCo-R matrix code" OFF) option(AVIF_ENABLE_EXPERIMENTAL_MINI "Enable experimental reduced header" OFF) option(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM "Enable experimental sample transform code" OFF) @@ -273,13 +269,10 @@ if(AVIF_LIBSHARPYUV_ENABLED) endif(AVIF_LIBSHARPYUV_ENABLED) set_local_or_system_option( - "LIBXML2" "OFF" "Use libxml2. When enabled and AVIF_ENABLE_GAIN_MAP is ON, \ - allows converting JPEG files with gain maps to AVIF using avifenc" + "LIBXML2" "OFF" "Use libxml2. When enabled, allows converting JPEG files with gain maps to AVIF using avifenc" ) +check_avif_option(AVIF_LIBXML2 TARGET LibXml2::LibXml2 PKG_NAME LibXml2) -if(AVIF_ENABLE_GAIN_MAP) - check_avif_option(AVIF_LIBXML2 TARGET LibXml2::LibXml2 PKG_NAME LibXml2) -endif() # --------------------------------------------------------------------------------------- # Enable all warnings @@ -365,10 +358,6 @@ if(AVIF_ENABLE_EXPERIMENTAL_YCGCO_R) add_compile_definitions(AVIF_ENABLE_EXPERIMENTAL_YCGCO_R) endif() -if(AVIF_ENABLE_GAIN_MAP) - add_compile_definitions(AVIF_ENABLE_GAIN_MAP) -endif() - if(AVIF_ENABLE_EXPERIMENTAL_MINI) add_compile_definitions(AVIF_ENABLE_EXPERIMENTAL_MINI) endif() @@ -384,6 +373,7 @@ set(AVIF_SRCS src/colrconvert.c src/diag.c src/exif.c + src/gainmap.c src/io.c src/mem.c src/obu.c @@ -397,9 +387,6 @@ set(AVIF_SRCS src/utils.c src/write.c ) -if(AVIF_ENABLE_GAIN_MAP) - list(APPEND AVIF_SRCS src/gainmap.c) -endif() if(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM) list(APPEND AVIF_SRCS src/sampletransform.c) endif() @@ -585,7 +572,7 @@ if(NOT AVIF_CODEC_AOM_ENABLED message(WARNING "libavif: No decoding library is enabled.") endif() -if(AVIF_LIB_USE_CXX OR (AVIF_BUILD_APPS AND AVIF_ENABLE_GAIN_MAP) OR (AVIF_BUILD_TESTS AND (AVIF_ENABLE_FUZZTEST +if(AVIF_LIB_USE_CXX OR AVIF_BUILD_APPS OR (AVIF_BUILD_TESTS AND (AVIF_ENABLE_FUZZTEST OR AVIF_ENABLE_GTEST)) ) enable_language(CXX) @@ -677,13 +664,11 @@ if(AVIF_BUILD_APPS OR (AVIF_BUILD_TESTS AND (AVIF_ENABLE_FUZZTEST OR AVIF_ENABLE find_package(JPEG REQUIRED) endif() - if(AVIF_ENABLE_GAIN_MAP) - if(TARGET LibXml2::LibXml2) - set(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION TRUE) - add_compile_definitions(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) - else() - message(STATUS "libavif: libxml2 not found; avifenc will ignore any gain map in jpeg files") - endif() + if(TARGET LibXml2::LibXml2) + set(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION TRUE) + add_compile_definitions(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) + else() + message(STATUS "libavif: libxml2 not found; avifenc will ignore any gain map in JPEG files") endif() set(AVIF_APPS_SRCS apps/shared/avifexif.c apps/shared/avifjpeg.c apps/shared/avifpng.c apps/shared/avifutil.c @@ -696,7 +681,7 @@ if(AVIF_BUILD_APPS OR (AVIF_BUILD_TESTS AND (AVIF_ENABLE_FUZZTEST OR AVIF_ENABLE if(CMAKE_SYSTEM_NAME STREQUAL "Linux") target_link_libraries(avif_apps${suffix} PRIVATE m) endif() - if(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) + if(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) target_link_libraries(avif_apps${suffix} PRIVATE LibXml2::LibXml2) endif() target_include_directories(avif_apps${suffix} INTERFACE apps/shared) @@ -755,33 +740,32 @@ if(AVIF_BUILD_APPS) LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" ) endif() - if(AVIF_ENABLE_GAIN_MAP) - include(LocalLibargparse) - set(AVIFGAINMAPUTIL_SRCS - apps/avifgainmaputil/avifgainmaputil.cc - apps/avifgainmaputil/convert_command.cc - apps/avifgainmaputil/combine_command.cc - apps/avifgainmaputil/extractgainmap_command.cc - apps/avifgainmaputil/imageio.cc - apps/avifgainmaputil/printmetadata_command.cc - apps/avifgainmaputil/tonemap_command.cc - apps/avifgainmaputil/program_command.cc - apps/avifgainmaputil/swapbase_command.cc - ) + include(LocalLibargparse) + + set(AVIFGAINMAPUTIL_SRCS + apps/avifgainmaputil/avifgainmaputil.cc + apps/avifgainmaputil/convert_command.cc + apps/avifgainmaputil/combine_command.cc + apps/avifgainmaputil/extractgainmap_command.cc + apps/avifgainmaputil/imageio.cc + apps/avifgainmaputil/printmetadata_command.cc + apps/avifgainmaputil/tonemap_command.cc + apps/avifgainmaputil/program_command.cc + apps/avifgainmaputil/swapbase_command.cc + ) - add_executable(avifgainmaputil "${AVIFGAINMAPUTIL_SRCS}") - if(WIN32) - if(MSVC) - target_sources(avifgainmaputil PRIVATE apps/utf8.manifest) - elseif(MINGW) - target_sources(avifgainmaputil PRIVATE apps/utf8.rc) - endif() + add_executable(avifgainmaputil "${AVIFGAINMAPUTIL_SRCS}") + if(WIN32) + if(MSVC) + target_sources(avifgainmaputil PRIVATE apps/utf8.manifest) + elseif(MINGW) + target_sources(avifgainmaputil PRIVATE apps/utf8.rc) endif() - set_target_properties(avifgainmaputil PROPERTIES LINKER_LANGUAGE "CXX") - target_include_directories(avifgainmaputil PRIVATE apps/avifgainmaputil/) - target_link_libraries(avifgainmaputil libargparse avif_apps avif avif_enable_warnings) - # Don't add avifgainmaputil to installed apps for now. endif() + set_target_properties(avifgainmaputil PROPERTIES LINKER_LANGUAGE "CXX") + target_include_directories(avifgainmaputil PRIVATE apps/avifgainmaputil/) + target_link_libraries(avifgainmaputil libargparse avif_apps avif avif_enable_warnings) + # Don't add avifgainmaputil to installed apps for now. endif() if(AVIF_BUILD_TESTS) diff --git a/apps/avifenc.c b/apps/avifenc.c index 367f8a1026..ed7b051c29 100644 --- a/apps/avifenc.c +++ b/apps/avifenc.c @@ -57,8 +57,7 @@ typedef struct avifBool ignoreXMP; avifBool ignoreColorProfile; - // These settings are only relevant when compiled with AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION - // (which also implies AVIF_ENABLE_GAIN_MAP). + // These settings are only relevant when compiled with AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION. avifBool qualityGainMapIsConstrained; // true if qualityGainMap explicitly set by the user int qualityGainMap; avifBool ignoreGainMap; // ignore any gain map present in the input file. @@ -240,7 +239,7 @@ static void syntaxLong(void) printf(" --ignore-exif : If the input file contains embedded Exif metadata, ignore it (no-op if absent)\n"); printf(" --ignore-xmp : If the input file contains embedded XMP metadata, ignore it (no-op if absent)\n"); printf(" --ignore-profile,--ignore-icc : If the input file contains an embedded color profile, ignore it (no-op if absent)\n"); -#if defined(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) +#if defined(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) printf(" --ignore-gain-map : If the input file contains an embedded gain map, ignore it (no-op if absent)\n"); printf(" --qgain-map Q : Set quality for the gain map (%d-%d, where %d is lossless)\n", AVIF_QUALITY_WORST, @@ -525,7 +524,7 @@ static avifBool avifInputReadImage(avifInput * input, if (avifImageSetViewRect(image, cached->image, &rect) != AVIF_RESULT_OK) { assert(AVIF_FALSE); } -#if defined(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) +#if defined(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) if (cached->image->gainMap && cached->image->gainMap->image) { image->gainMap->image = avifImageCreateEmpty(); const avifCropRect gainMapRect = { 0, 0, cached->image->gainMap->image->width, cached->image->gainMap->image->height }; @@ -1143,7 +1142,7 @@ static avifBool avifEncodeImagesFixedQuality(const avifSettings * settings, if (settings->overrideQualityAlpha != INVALID_QUALITY) { encoder->qualityAlpha = settings->overrideQualityAlpha; } -#if defined(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) +#if defined(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) if (settings->qualityGainMap != INVALID_QUALITY) { encoder->qualityGainMap = settings->qualityGainMap; } @@ -1157,7 +1156,7 @@ static avifBool avifEncodeImagesFixedQuality(const avifSettings * settings, snprintf(speedStr, sizeof(speedStr), "%d", settings->speed); } char gainMapStr[100] = { 0 }; -#if defined(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) +#if defined(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) if (firstImage->gainMap && firstImage->gainMap->image) { snprintf(gainMapStr, sizeof(gainMapStr), ", gain map quality [%d (%s)]", encoder->qualityGainMap, qualityString(encoder->qualityGainMap)); } @@ -1241,7 +1240,7 @@ static avifBool avifEncodeImagesFixedQuality(const avifSettings * settings, success = AVIF_TRUE; byteSizes->colorSizeBytes = encoder->ioStats.colorOBUSize; byteSizes->alphaSizeBytes = encoder->ioStats.alphaOBUSize; -#if defined(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) +#if defined(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) byteSizes->gainMapSizeBytes = avifEncoderGetGainMapSizeBytes(encoder); #endif @@ -1269,7 +1268,7 @@ static avifBool avifEncodeImages(avifSettings * settings, avifBool hasGainMap = AVIF_FALSE; avifBool allQualitiesConstrained = settings->qualityIsConstrained && settings->qualityAlphaIsConstrained; -#if defined(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) +#if defined(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) hasGainMap = (firstImage->gainMap && firstImage->gainMap->image); if (hasGainMap) { allQualitiesConstrained = allQualitiesConstrained && settings->qualityGainMapIsConstrained; @@ -1814,7 +1813,7 @@ int main(int argc, char * argv[]) settings.ignoreXMP = AVIF_TRUE; } else if (!strcmp(arg, "--ignore-profile") || !strcmp(arg, "--ignore-icc")) { settings.ignoreColorProfile = AVIF_TRUE; -#if defined(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) +#if defined(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) } else if (!strcmp(arg, "--ignore-gain-map")) { settings.ignoreGainMap = AVIF_TRUE; } else if (!strcmp(arg, "--qgain-map")) { @@ -2253,7 +2252,7 @@ int main(int argc, char * argv[]) image->transferCharacteristics = AVIF_TRANSFER_CHARACTERISTICS_SRGB; } -#if defined(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) +#if defined(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) if (image->gainMap && !image->gainMap->altICC.size) { if (image->gainMap->altColorPrimaries == AVIF_COLOR_PRIMARIES_UNSPECIFIED) { // Assume the alternate image has the same primaries as the base image. @@ -2264,7 +2263,7 @@ int main(int argc, char * argv[]) image->gainMap->altTransferCharacteristics = AVIF_TRANSFER_CHARACTERISTICS_PQ; } } -#endif // AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION +#endif // AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION if (settings.paspPresent) { image->transformFlags |= AVIF_TRANSFORM_PASP; diff --git a/apps/shared/avifjpeg.c b/apps/shared/avifjpeg.c index 43b008cc12..de0aa7f3fd 100644 --- a/apps/shared/avifjpeg.c +++ b/apps/shared/avifjpeg.c @@ -18,7 +18,7 @@ #include "iccjpeg.h" -#if defined(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) +#if defined(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) #include #endif @@ -286,7 +286,7 @@ static const uint8_t * avifJPEGFindSubstr(const uint8_t * str, size_t strLength, return AVIF_FALSE; \ } while (0) -#if defined(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) +#if defined(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) // Reads a 4-byte unsigned integer in little-endian format from the raw bitstream src. static uint32_t avifJPEGReadUint32LittleEndian(const uint8_t * src) @@ -833,7 +833,7 @@ static avifBool avifJPEGExtractGainMapImage(FILE * f, } return AVIF_FALSE; } -#endif // AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION +#endif // AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION // Note on setjmp() and volatile variables: // @@ -1023,7 +1023,7 @@ static avifBool avifJPEGReadInternal(FILE * f, } avifBool readXMP = !ignoreXMP; -#if defined(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) +#if defined(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) readXMP = readXMP || !ignoreGainMap; // Gain map metadata is in XMP. #endif if (readXMP) { @@ -1172,7 +1172,7 @@ static avifBool avifJPEGReadInternal(FILE * f, avifImageFixXMP(avif); // Remove one trailing null character if any. } -#if defined(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) +#if defined(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) // The primary XMP block (for the main image) must contain a node with an hdrgm:Version field if and only if a gain map is present. if (!ignoreGainMap && avifJPEGHasGainMapXMPNode(avif->xmp.data, avif->xmp.size)) { avifGainMap * gainMap = avifGainMapCreate(); @@ -1209,7 +1209,7 @@ static avifBool avifJPEGReadInternal(FILE * f, assert(AVIF_FALSE); } } -#endif // AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION +#endif // AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION jpeg_finish_decompress(&cinfo); ret = AVIF_TRUE; cleanup: diff --git a/apps/shared/avifjpeg.h b/apps/shared/avifjpeg.h index 9c7d6d3d0a..a6d9a3cc7b 100644 --- a/apps/shared/avifjpeg.h +++ b/apps/shared/avifjpeg.h @@ -14,9 +14,8 @@ extern "C" { // At most sizeLimit pixels will be read or an error returned. At most sizeLimit // bytes of Exif or XMP metadata will be read or an error returned. // 'ignoreGainMap' is only relevant for jpeg files that have a gain map -// and only if AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION is ON -// (requires AVIF_ENABLE_GAIN_MAP and libxml2). Otherwise -// it has no effect. +// and only if AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION is ON +// (requires libxml2). Otherwise it has no effect. avifBool avifJPEGRead(const char * inputFilename, avifImage * avif, avifPixelFormat requestedFormat, @@ -29,7 +28,7 @@ avifBool avifJPEGRead(const char * inputFilename, uint32_t sizeLimit); avifBool avifJPEGWrite(const char * outputFilename, const avifImage * avif, int jpegQuality, avifChromaUpsampling chromaUpsampling); -#if defined(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) +#if defined(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) // Parses XMP gain map metadata. Visible for testing. avifBool avifJPEGParseGainMapXMP(const uint8_t * xmpData, size_t xmpSize, avifGainMap * gainMap); #endif diff --git a/apps/shared/avifutil.c b/apps/shared/avifutil.c index 7591afd585..2e6a756b30 100644 --- a/apps/shared/avifutil.c +++ b/apps/shared/avifutil.c @@ -125,7 +125,6 @@ static void avifImageDumpInternal(const avifImage * avif, uint32_t gridCols, uin printf(" * CLLI : %hu, %hu\n", avif->clli.maxCLL, avif->clli.maxPALL); } -#if defined(AVIF_ENABLE_GAIN_MAP) printf(" * Gain map : "); avifImage * gainMapImage = avif->gainMap ? avif->gainMap->image : NULL; if (gainMapImage != NULL) { @@ -161,7 +160,6 @@ static void avifImageDumpInternal(const avifImage * avif, uint32_t gridCols, uin } else { printf("Absent\n"); } -#endif // AVIF_ENABLE_GAIN_MAP } void avifImageDump(const avifImage * avif, uint32_t gridCols, uint32_t gridRows, avifProgressiveState progressiveState) diff --git a/apps/shared/avifutil.h b/apps/shared/avifutil.h index f396985823..3144ad5a12 100644 --- a/apps/shared/avifutil.h +++ b/apps/shared/avifutil.h @@ -66,9 +66,8 @@ struct y4mFrameIterator; // In case of a y4m file, sourceTiming and frameIter can be set. // Returns AVIF_APP_FILE_FORMAT_UNKNOWN in case of error. // 'ignoreGainMap' is only relevant for jpeg files that have a gain map -// and only if AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION is ON -// (requires AVIF_ENABLE_GAIN_MAP and libxml2). Otherwise -// it has no effect. +// and only if AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION is ON +// (requires libxml2). Otherwise it has no effect. avifAppFileFormat avifReadImage(const char * filename, avifPixelFormat requestedFormat, int requestedDepth, diff --git a/include/avif/avif.h b/include/avif/avif.h index f2bb05c19a..256abf61bb 100644 --- a/include/avif/avif.h +++ b/include/avif/avif.h @@ -193,11 +193,9 @@ typedef enum AVIF_NODISCARD avifResult AVIF_RESULT_CANNOT_CHANGE_SETTING = 27, // a setting that can't change is changed during encoding AVIF_RESULT_INCOMPATIBLE_IMAGE = 28, // the image is incompatible with already encoded images AVIF_RESULT_INTERNAL_ERROR = 29, // some invariants have not been satisfied (likely a bug in libavif) -#if defined(AVIF_ENABLE_GAIN_MAP) AVIF_RESULT_ENCODE_GAIN_MAP_FAILED = 30, AVIF_RESULT_DECODE_GAIN_MAP_FAILED = 31, AVIF_RESULT_INVALID_TONE_MAPPED_IMAGE = 32, -#endif #if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM) AVIF_RESULT_ENCODE_SAMPLE_TRANSFORM_FAILED = 33, AVIF_RESULT_DECODE_SAMPLE_TRANSFORM_FAILED = 34, @@ -590,7 +588,6 @@ typedef struct avifContentLightLevelInformationBox uint16_t maxPALL; } avifContentLightLevelInformationBox; -#if defined(AVIF_ENABLE_GAIN_MAP) // --------------------------------------------------------------------------- // avifGainMap // Gain Maps are a solution for a consistent and adaptive display of HDR images. @@ -700,8 +697,6 @@ AVIF_API avifGainMap * avifGainMapCreate(void); // Frees a gain map, including the 'image' field if non NULL. AVIF_API void avifGainMapDestroy(avifGainMap * gainMap); -#endif // AVIF_ENABLE_GAIN_MAP - // --------------------------------------------------------------------------- #if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM) @@ -828,22 +823,19 @@ typedef struct avifImage avifImageItemProperty * properties; // NULL only if numProperties is 0. size_t numProperties; -#if defined(AVIF_ENABLE_GAIN_MAP) // Gain map image and metadata. NULL if no gain map is present. // Owned by the avifImage and gets freed when calling avifImageDestroy(). // gainMap->image->transformFlags is always AVIF_TRANSFORM_NONE. avifGainMap * gainMap; -#endif } avifImage; // avifImageCreate() and avifImageCreateEmpty() return NULL if arguments are invalid or if a memory allocation failed. AVIF_NODISCARD AVIF_API avifImage * avifImageCreate(uint32_t width, uint32_t height, uint32_t depth, avifPixelFormat yuvFormat); AVIF_NODISCARD AVIF_API avifImage * avifImageCreateEmpty(void); // helper for making an image to decode into -// Performs a deep copy of an image, including all metadata and planes, and the gain map metadata/planes if present -// and if AVIF_ENABLE_GAIN_MAP is defined. +// Performs a deep copy of an image, including all metadata and planes, and the gain map metadata/planes if present. AVIF_API avifResult avifImageCopy(avifImage * dstImage, const avifImage * srcImage, avifPlanesFlags planes); // Performs a shallow copy of a rectangular area of an image. 'dstImage' does not own the planes. -// Ignores the gainMap field (which exists only if AVIF_ENABLE_GAIN_MAP is defined). +// Ignores the gainMap field. AVIF_API avifResult avifImageSetViewRect(avifImage * dstImage, const avifImage * srcImage, const avifCropRect * rect); AVIF_API void avifImageDestroy(avifImage * image); @@ -856,8 +848,7 @@ AVIF_API avifResult avifImageSetMetadataExif(avifImage * image, const uint8_t * // Sets XMP metadata. AVIF_API avifResult avifImageSetMetadataXMP(avifImage * image, const uint8_t * xmp, size_t xmpSize); -// Allocate/free/steal planes. These functions ignore the gainMap field (which exists only if -// AVIF_ENABLE_GAIN_MAP is defined). +// Allocate/free/steal planes. These functions ignore the gainMap field. AVIF_API avifResult avifImageAllocatePlanes(avifImage * image, avifPlanesFlags planes); // Ignores any pre-existing planes AVIF_API void avifImageFreePlanes(avifImage * image, avifPlanesFlags planes); // Ignores already-freed planes AVIF_API void avifImageStealPlanes(avifImage * dstImage, avifImage * srcImage, avifPlanesFlags planes); @@ -1199,12 +1190,8 @@ typedef enum avifImageContentTypeFlag AVIF_IMAGE_CONTENT_NONE = 0, // Color only or alpha only is not currently supported. AVIF_IMAGE_CONTENT_COLOR_AND_ALPHA = (1 << 0) | (1 << 1), -#if defined(AVIF_ENABLE_GAIN_MAP) AVIF_IMAGE_CONTENT_GAIN_MAP = (1 << 2), AVIF_IMAGE_CONTENT_ALL = AVIF_IMAGE_CONTENT_COLOR_AND_ALPHA | AVIF_IMAGE_CONTENT_GAIN_MAP, -#else - AVIF_IMAGE_CONTENT_ALL = AVIF_IMAGE_CONTENT_COLOR_AND_ALPHA, -#endif AVIF_IMAGE_CONTENT_DECODE_DEFAULT = AVIF_IMAGE_CONTENT_COLOR_AND_ALPHA, } avifImageContentTypeFlag; @@ -1394,10 +1381,10 @@ AVIF_API avifResult avifDecoderNthImageTiming(const avifDecoder * decoder, uint3 // function can be called next to retrieve the number of top rows that can be immediately accessed // from the luma plane of decoder->image, and alpha if any. The corresponding rows from the chroma planes, // if any, can also be accessed (half rounded up if subsampled, same number of rows otherwise). -// If a gain map is present and AVIF_ENABLE_GAIN_MAP is on and -// (imageContentToDecode & AVIF_IMAGE_CONTENT_GAIN_MAP) is nonzero, the gain map's planes can also be accessed -// in the same way. If the gain map's height is different from the main image, then the number of -// available gain map rows is at least: +// If a gain map is present and (imageContentToDecode & AVIF_IMAGE_CONTENT_GAIN_MAP) is nonzero, +// the gain map's planes can also be accessed in the same way. +// If the gain map's height is different from the main image, then the number of available gain map +// rows is at least: // roundf((float)decoded_row_count / decoder->image->height * decoder->image->gainMap.image->height) // When gain map scaling is needed, callers might choose to use a few less rows depending on how many rows // are needed by the scaling algorithm, to avoid the last row(s) changing when more data becomes available. @@ -1517,9 +1504,7 @@ typedef struct avifEncoder // Version 1.1.0 ends here. Add any new members after this line. -#if defined(AVIF_ENABLE_GAIN_MAP) int qualityGainMap; // changeable encoder setting -#endif #if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM) // Perform extra steps at encoding and decoding to extend AV1 features using bundled additional image items. @@ -1587,10 +1572,8 @@ AVIF_API avifResult avifEncoderFinish(avifEncoder * encoder, avifRWData * output // AVIF_RESULT_INVALID_CODEC_SPECIFIC_OPTION from avifEncoderWrite() or avifEncoderAddImage(). AVIF_API avifResult avifEncoderSetCodecSpecificOption(avifEncoder * encoder, const char * key, const char * value); -#if defined(AVIF_ENABLE_GAIN_MAP) // Returns the size in bytes of the AV1 image item containing gain map samples, or 0 if no gain map was encoded. AVIF_API size_t avifEncoderGetGainMapSizeBytes(avifEncoder * encoder); -#endif // Helpers AVIF_NODISCARD AVIF_API avifBool avifImageUsesU16(const avifImage * image); @@ -1605,7 +1588,6 @@ AVIF_API uint32_t avifImagePlaneHeight(const avifImage * image, int channel); // either the brand 'avif' or 'avis' (or both), without performing any allocations. AVIF_NODISCARD AVIF_API avifBool avifPeekCompatibleFileType(const avifROData * input); -#if defined(AVIF_ENABLE_GAIN_MAP) // --------------------------------------------------------------------------- // Gain Map utilities. // Gain Maps are a HIGHLY EXPERIMENTAL FEATURE, see comments in the avifGainMap @@ -1658,8 +1640,6 @@ AVIF_API avifResult avifImageComputeGainMap(const avifImage * baseImage, avifGainMap * gainMap, avifDiagnostics * diag); -#endif // AVIF_ENABLE_GAIN_MAP - #ifdef __cplusplus } // extern "C" #endif diff --git a/include/avif/avif_cxx.h b/include/avif/avif_cxx.h index 0a7ee95600..1b4e560189 100644 --- a/include/avif/avif_cxx.h +++ b/include/avif/avif_cxx.h @@ -21,19 +21,14 @@ struct UniquePtrDeleter void operator()(avifEncoder * encoder) const { avifEncoderDestroy(encoder); } void operator()(avifDecoder * decoder) const { avifDecoderDestroy(decoder); } void operator()(avifImage * image) const { avifImageDestroy(image); } -#if defined(AVIF_ENABLE_GAIN_MAP) void operator()(avifGainMap * gainMap) const { avifGainMapDestroy(gainMap); } -#endif }; // Use these unique_ptr to ensure the structs are automatically destroyed. using EncoderPtr = std::unique_ptr; using DecoderPtr = std::unique_ptr; using ImagePtr = std::unique_ptr; - -#if defined(AVIF_ENABLE_GAIN_MAP) using GainMapPtr = std::unique_ptr; -#endif } // namespace avif diff --git a/include/avif/internal.h b/include/avif/internal.h index 44a4ae5c38..8b6769d397 100644 --- a/include/avif/internal.h +++ b/include/avif/internal.h @@ -146,7 +146,7 @@ void avifImageCopyNoAlloc(avifImage * dstImage, const avifImage * srcImage); // Copies the samples from srcImage to dstImage. dstImage must be allocated. // srcImage and dstImage must have the same width, height, and depth. // If the AVIF_PLANES_YUV bit is set in planes, then srcImage and dstImage must have the same yuvFormat. -// Ignores the gainMap field (which exists only if AVIF_ENABLE_GAIN_MAP is defined). +// Ignores the gainMap field. void avifImageCopySamples(avifImage * dstImage, const avifImage * srcImage, avifPlanesFlags planes); // Appends an opaque image item property. @@ -391,9 +391,7 @@ typedef enum avifItemCategory { AVIF_ITEM_COLOR, AVIF_ITEM_ALPHA, -#if defined(AVIF_ENABLE_GAIN_MAP) AVIF_ITEM_GAIN_MAP, -#endif #if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM) AVIF_ITEM_SAMPLE_TRANSFORM, // Sample Transform derived image item 'sato'. // Extra input image items for AVIF_ITEM_SAMPLE_TRANSFORM. "Extra" because AVIF_ITEM_COLOR could be one too. @@ -779,8 +777,6 @@ AVIF_NODISCARD avifBool avifSequenceHeaderParse(avifSequenceHeader * header, con // --------------------------------------------------------------------------- // gain maps -#if defined(AVIF_ENABLE_GAIN_MAP) - // Finds the approximate min/max values from the given gain map values, excluding outliers. // Uses a histogram, with outliers defined as having at least one empty bucket between them // and the rest of the distribution. Discards at most 0.1% of values. @@ -789,8 +785,6 @@ avifResult avifFindMinMaxWithoutOutliers(const float * gainMapF, int numPixels, avifResult avifGainMapValidateMetadata(const avifGainMap * gainMap, avifDiagnostics * diag); -#endif // AVIF_ENABLE_GAIN_MAP - #define AVIF_INDEFINITE_DURATION64 UINT64_MAX #define AVIF_INDEFINITE_DURATION32 UINT32_MAX diff --git a/src/avif.c b/src/avif.c index 1ae949fb46..b7b6fd99f0 100644 --- a/src/avif.c +++ b/src/avif.c @@ -104,11 +104,9 @@ const char * avifResultToString(avifResult result) case AVIF_RESULT_CANNOT_CHANGE_SETTING: return "Cannot change some setting during encoding"; case AVIF_RESULT_INCOMPATIBLE_IMAGE: return "The image is incompatible with already encoded images"; case AVIF_RESULT_INTERNAL_ERROR: return "Internal error"; -#if defined(AVIF_ENABLE_GAIN_MAP) case AVIF_RESULT_ENCODE_GAIN_MAP_FAILED: return "Encoding of gain map planes failed"; case AVIF_RESULT_DECODE_GAIN_MAP_FAILED: return "Decoding of gain map planes failed"; case AVIF_RESULT_INVALID_TONE_MAPPED_IMAGE: return "Invalid tone mapped image item"; -#endif #if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM) case AVIF_RESULT_ENCODE_SAMPLE_TRANSFORM_FAILED: return "Encoding of sample transformed image failed"; case AVIF_RESULT_DECODE_SAMPLE_TRANSFORM_FAILED: return "Decoding of sample transformed image failed"; @@ -283,7 +281,6 @@ avifResult avifImageCopy(avifImage * dstImage, const avifImage * srcImage, avifP } avifImageCopySamples(dstImage, srcImage, planes); -#if defined(AVIF_ENABLE_GAIN_MAP) if (srcImage->gainMap) { if (!dstImage->gainMap) { dstImage->gainMap = avifGainMapCreate(); @@ -320,7 +317,6 @@ avifResult avifImageCopy(avifImage * dstImage, const avifImage * srcImage, avifP avifGainMapDestroy(dstImage->gainMap); dstImage->gainMap = NULL; } -#endif // defined(AVIF_ENABLE_GAIN_MAP) return AVIF_RESULT_OK; } @@ -361,11 +357,9 @@ avifResult avifImageSetViewRect(avifImage * dstImage, const avifImage * srcImage void avifImageDestroy(avifImage * image) { -#if defined(AVIF_ENABLE_GAIN_MAP) if (image->gainMap) { avifGainMapDestroy(image->gainMap); } -#endif avifImageFreePlanes(image, AVIF_PLANES_ALL); avifRWDataFree(&image->icc); avifRWDataFree(&image->exif); @@ -1245,7 +1239,6 @@ void avifCodecVersions(char outBuffer[256]) } } -#if defined(AVIF_ENABLE_GAIN_MAP) avifGainMap * avifGainMapCreate(void) { avifGainMap * gainMap = (avifGainMap *)avifAlloc(sizeof(avifGainMap)); @@ -1280,4 +1273,3 @@ void avifGainMapDestroy(avifGainMap * gainMap) avifRWDataFree(&gainMap->altICC); avifFree(gainMap); } -#endif // AVIF_ENABLE_GAIN_MAP diff --git a/src/gainmap.c b/src/gainmap.c index 5f35411407..d7acc700a5 100644 --- a/src/gainmap.c +++ b/src/gainmap.c @@ -7,8 +7,6 @@ #include #include -#if defined(AVIF_ENABLE_GAIN_MAP) - static void avifGainMapSetDefaults(avifGainMap * gainMap) { for (int i = 0; i < 3; ++i) { @@ -848,5 +846,3 @@ avifResult avifImageComputeGainMap(const avifImage * baseImage, const avifImage avifRGBImageFreePixels(&altImageRgb); return res; } - -#endif // AVIF_ENABLE_GAIN_MAP diff --git a/src/read.c b/src/read.c index b317577d85..2a8b4ce096 100644 --- a/src/read.c +++ b/src/read.c @@ -2016,8 +2016,6 @@ static avifBool avifParseImageGridBox(avifImageGrid * grid, return avifROStreamRemainingBytes(&s) == 0; } -#if defined(AVIF_ENABLE_GAIN_MAP) - static avifBool avifParseGainMapMetadata(avifGainMap * gainMap, avifROStream * s) { uint32_t isMultichannel; @@ -2095,7 +2093,6 @@ static avifResult avifParseToneMappedImageBox(avifGainMap * gainMap, const uint8 return AVIF_RESULT_OK; } -#endif // AVIF_ENABLE_GAIN_MAP #if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM) // bit_depth is assumed to be 2 (32-bit). @@ -2317,7 +2314,7 @@ static avifResult avifParseContentLightLevelInformationBox(avifProperty * prop, return AVIF_RESULT_OK; } -#if defined(AVIF_ENABLE_EXPERIMENTAL_MINI) && defined(AVIF_ENABLE_GAIN_MAP) +#if defined(AVIF_ENABLE_EXPERIMENTAL_MINI) static avifResult avifSkipMasteringDisplayColourVolume(avifROStream * s) { for (int c = 0; c < 3; c++) { @@ -2418,7 +2415,7 @@ static avifResult avifParseMiniHDRProperties(avifROStream * s, uint32_t * hasCll } return AVIF_RESULT_OK; } -#endif // AVIF_ENABLE_EXPERIMENTAL_MINI && AVIF_ENABLE_GAIN_MAP +#endif // AVIF_ENABLE_EXPERIMENTAL_MINI // Implementation of section 2.3.3 of AV1 Codec ISO Media File Format Binding specification v1.2.0. // See https://aomediacodec.github.io/av1-isobmff/v1.2.0.html#av1codecconfigurationbox-syntax. @@ -3864,7 +3861,6 @@ static avifResult avifParseMinimizedImageBox(avifDecoderData * data, uint32_t hasClli = AVIF_FALSE, tmapHasClli = AVIF_FALSE; avifContentLightLevelInformationBox clli = {}, tmapClli = {}; if (hasHdr) { -#if defined(AVIF_ENABLE_GAIN_MAP) AVIF_CHECKERR(avifROStreamReadBitsU32(&s, &hasGainmap, 1), AVIF_RESULT_BMFF_PARSE_FAILED); // bit(1) gainmap_flag; if (hasGainmap) { // avifDecoderReset() requires the 'tmap' brand to be registered for the tone mapping derived image item to be parsed. @@ -3930,9 +3926,6 @@ static avifResult avifParseMinimizedImageBox(avifDecoderData * data, if (hasGainmap) { AVIF_CHECKRES(avifParseMiniHDRProperties(&s, &tmapHasClli, &tmapClli)); } -#else - return AVIF_RESULT_NOT_IMPLEMENTED; -#endif // AVIF_ENABLE_GAIN_MAP } // Chunk sizes @@ -4410,10 +4403,8 @@ static avifResult avifParse(avifDecoder * decoder) avifBool miniSeen = AVIF_FALSE; avifBool needsMini = AVIF_FALSE; #endif -#if defined(AVIF_ENABLE_GAIN_MAP) avifBool needsTmap = AVIF_FALSE; avifBool tmapSeen = AVIF_FALSE; -#endif avifFileType ftyp = {}; for (;;) { @@ -4532,12 +4523,10 @@ static avifResult avifParse(avifDecoder * decoder) AVIF_RESULT_BMFF_PARSE_FAILED); } #endif // AVIF_ENABLE_EXPERIMENTAL_MINI -#if defined(AVIF_ENABLE_GAIN_MAP) needsTmap = avifFileTypeHasBrand(&ftyp, "tmap"); if (needsTmap) { needsMeta = AVIF_TRUE; } -#endif } else if (isMeta) { AVIF_CHECKERR(!metaSeen, AVIF_RESULT_BMFF_PARSE_FAILED); #if defined(AVIF_ENABLE_EXPERIMENTAL_MINI) @@ -4546,14 +4535,12 @@ static avifResult avifParse(avifDecoder * decoder) AVIF_CHECKRES(avifParseMetaBox(data->meta, boxOffset, boxContents.data, boxContents.size, data->diag)); metaSeen = AVIF_TRUE; -#if defined(AVIF_ENABLE_GAIN_MAP) for (uint32_t itemIndex = 0; itemIndex < data->meta->items.count; ++itemIndex) { if (!memcmp(data->meta->items.item[itemIndex]->type, "tmap", 4)) { tmapSeen = AVIF_TRUE; break; } } -#endif #if defined(AVIF_ENABLE_EXPERIMENTAL_MINI) } else if (isMini) { @@ -4584,12 +4571,9 @@ static avifResult avifParse(avifDecoder * decoder) // * If the brand 'avif' is present, require a meta box // * If the brand 'avis' is present, require a moov box // * If AVIF_ENABLE_EXPERIMENTAL_MINI is defined and the brand 'mif3' is present, require a mini box - avifBool sawEverythingNeeded = ftypSeen && (!needsMeta || metaSeen) && (!needsMoov || moovSeen); + avifBool sawEverythingNeeded = ftypSeen && (!needsMeta || metaSeen) && (!needsMoov || moovSeen) && (!needsTmap || tmapSeen); #if defined(AVIF_ENABLE_EXPERIMENTAL_MINI) sawEverythingNeeded = sawEverythingNeeded && (!needsMini || miniSeen); -#endif -#if defined(AVIF_ENABLE_GAIN_MAP) - sawEverythingNeeded = sawEverythingNeeded && (!needsTmap || tmapSeen); #endif if (sawEverythingNeeded) { return AVIF_RESULT_OK; @@ -4601,13 +4585,9 @@ static avifResult avifParse(avifDecoder * decoder) if ((needsMeta && !metaSeen) || (needsMoov && !moovSeen)) { return AVIF_RESULT_TRUNCATED_DATA; } -#if defined(AVIF_ENABLE_GAIN_MAP) if (needsTmap && !tmapSeen) { return metaIsSizeZero ? AVIF_RESULT_TRUNCATED_DATA : AVIF_RESULT_BMFF_PARSE_FAILED; } -#else - (void)metaIsSizeZero; -#endif #if defined(AVIF_ENABLE_EXPERIMENTAL_MINI) if (needsMini && !miniSeen) { return AVIF_RESULT_TRUNCATED_DATA; @@ -4666,7 +4646,6 @@ avifBool avifPeekCompatibleFileType(const avifROData * input) return avifFileTypeIsCompatible(&ftyp); } -#if defined(AVIF_ENABLE_GAIN_MAP) static avifBool avifBrandArrayHasBrand(avifBrandArray * brands, const char * brand) { for (uint32_t brandIndex = 0; brandIndex < brands->count; ++brandIndex) { @@ -4676,7 +4655,6 @@ static avifBool avifBrandArrayHasBrand(avifBrandArray * brands, const char * bra } return AVIF_FALSE; } -#endif // --------------------------------------------------------------------------- @@ -5280,7 +5258,6 @@ static avifResult avifReadColorProperties(avifIO * io, return avifReadColorNclxProperty(properties, colorPrimaries, transferCharacteristics, matrixCoefficients, yuvRange, cicpSet); } -#if defined(AVIF_ENABLE_GAIN_MAP) // Finds a 'tmap' (tone mapped image item) box associated with the given 'colorItem'. // If found, fills 'toneMappedImageItem' and sets 'gainMapItemID' to the id of the gain map // item associated with the box. Otherwise, sets 'toneMappedImageItem' to NULL. @@ -5465,7 +5442,6 @@ static avifResult aviDecoderCheckGainMapProperties(avifDecoder * decoder, const } return AVIF_RESULT_OK; } -#endif // AVIF_ENABLE_GAIN_MAP #if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM) // Finds a 'sato' Sample Transform derived image item box. @@ -5598,9 +5574,7 @@ avifResult avifDecoderReset(avifDecoder * decoder) avifCodecType colorCodecType = AVIF_CODEC_TYPE_UNKNOWN; const avifPropertyArray * colorProperties = NULL; -#if defined(AVIF_ENABLE_GAIN_MAP) const avifPropertyArray * gainMapProperties = NULL; -#endif if (data->source == AVIF_DECODER_SOURCE_TRACKS) { avifTrack * colorTrack = NULL; avifTrack * alphaTrack = NULL; @@ -5768,7 +5742,6 @@ avifResult avifDecoderReset(avifDecoder * decoder) &codecType[AVIF_ITEM_ALPHA])); } -#if defined(AVIF_ENABLE_GAIN_MAP) // Section 10.2.6 of 23008-12:2024/AMD 1:2024(E): // 'tmap' brand // This brand enables file players to identify and decode HEIF files containing tone-map derived image @@ -5805,7 +5778,6 @@ avifResult avifDecoderReset(avifDecoder * decoder) } } } -#endif // AVIF_ENABLE_GAIN_MAP #if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM) // AVIF_ITEM_SAMPLE_TRANSFORM (not used through mainItems because not a coded item (well grids are not coded items either but it's different)). @@ -5956,7 +5928,6 @@ avifResult avifDecoderReset(avifDecoder * decoder) decoder->image->alphaPremultiplied = decoder->alphaPresent && (mainItems[AVIF_ITEM_COLOR]->premByID == mainItems[AVIF_ITEM_ALPHA]->id); -#if defined(AVIF_ENABLE_GAIN_MAP) if (mainItems[AVIF_ITEM_GAIN_MAP]) { AVIF_ASSERT_OR_RETURN(decoder->image->gainMap && decoder->image->gainMap->image); decoder->image->gainMap->image->width = mainItems[AVIF_ITEM_GAIN_MAP]->width; @@ -5968,7 +5939,6 @@ avifResult avifDecoderReset(avifDecoder * decoder) codecType[AVIF_ITEM_GAIN_MAP])); gainMapProperties = &mainItems[AVIF_ITEM_GAIN_MAP]->properties; } -#endif } uint32_t firstTileIndex = 0; @@ -6030,11 +6000,9 @@ avifResult avifDecoderReset(avifDecoder * decoder) decoder->image->transformFlags |= AVIF_TRANSFORM_IMIR; decoder->image->imir = imirProp->u.imir; } -#if defined(AVIF_ENABLE_GAIN_MAP) if (gainMapProperties != NULL) { AVIF_CHECKRES(aviDecoderCheckGainMapProperties(decoder, gainMapProperties)); } -#endif if (!data->cicpSet && (data->tiles.count > 0)) { avifTile * firstTile = &data->tiles.tile[0]; @@ -6149,11 +6117,9 @@ static avifResult avifImageLimitedToFullAlpha(avifImage * image) static avifResult avifGetErrorForItemCategory(avifItemCategory itemCategory) { -#if defined(AVIF_ENABLE_GAIN_MAP) if (itemCategory == AVIF_ITEM_GAIN_MAP) { return AVIF_RESULT_DECODE_GAIN_MAP_FAILED; } -#endif #if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM) if (itemCategory >= AVIF_SAMPLE_TRANSFORM_MIN_CATEGORY && itemCategory <= AVIF_SAMPLE_TRANSFORM_MAX_CATEGORY) { return AVIF_RESULT_DECODE_SAMPLE_TRANSFORM_FAILED; @@ -6276,12 +6242,10 @@ static avifResult avifDecoderDecodeTiles(avifDecoder * decoder, uint32_t nextIma if (!stealPlanes) { avifImage * dstImage = decoder->image; -#if defined(AVIF_ENABLE_GAIN_MAP) if (tile->input->itemCategory == AVIF_ITEM_GAIN_MAP) { AVIF_ASSERT_OR_RETURN(dstImage->gainMap && dstImage->gainMap->image); dstImage = dstImage->gainMap->image; } -#endif if (tileIndex == 0) { AVIF_CHECKRES(avifDecoderDataAllocateImagePlanes(decoder->data, info, dstImage)); } @@ -6291,39 +6255,32 @@ static avifResult avifDecoderDecodeTiles(avifDecoder * decoder, uint32_t nextIma AVIF_ASSERT_OR_RETURN(tileIndex == 0); avifImage * src = tile->image; - switch (tile->input->itemCategory) { -#if defined(AVIF_ENABLE_GAIN_MAP) - case AVIF_ITEM_GAIN_MAP: - AVIF_ASSERT_OR_RETURN(decoder->image->gainMap && decoder->image->gainMap->image); - decoder->image->gainMap->image->width = src->width; - decoder->image->gainMap->image->height = src->height; - decoder->image->gainMap->image->depth = src->depth; - break; -#endif - default: - if ((decoder->image->width != src->width) || (decoder->image->height != src->height) || - (decoder->image->depth != src->depth)) { - if (avifIsAlpha(tile->input->itemCategory)) { - avifDiagnosticsPrintf(&decoder->diag, - "The color image item does not match the alpha image item in width, height, or bit depth"); - return AVIF_RESULT_DECODE_ALPHA_FAILED; - } - avifImageFreePlanes(decoder->image, AVIF_PLANES_ALL); - - decoder->image->width = src->width; - decoder->image->height = src->height; - decoder->image->depth = src->depth; + if (tile->input->itemCategory == AVIF_ITEM_GAIN_MAP) { + AVIF_ASSERT_OR_RETURN(decoder->image->gainMap && decoder->image->gainMap->image); + decoder->image->gainMap->image->width = src->width; + decoder->image->gainMap->image->height = src->height; + decoder->image->gainMap->image->depth = src->depth; + } else { + if ((decoder->image->width != src->width) || (decoder->image->height != src->height) || + (decoder->image->depth != src->depth)) { + if (avifIsAlpha(tile->input->itemCategory)) { + avifDiagnosticsPrintf(&decoder->diag, + "The color image item does not match the alpha image item in width, height, or bit depth"); + return AVIF_RESULT_DECODE_ALPHA_FAILED; } - break; + avifImageFreePlanes(decoder->image, AVIF_PLANES_ALL); + + decoder->image->width = src->width; + decoder->image->height = src->height; + decoder->image->depth = src->depth; + } } if (avifIsAlpha(tile->input->itemCategory)) { avifImageStealPlanes(decoder->image, src, AVIF_PLANES_A); -#if defined(AVIF_ENABLE_GAIN_MAP) } else if (tile->input->itemCategory == AVIF_ITEM_GAIN_MAP) { AVIF_ASSERT_OR_RETURN(decoder->image->gainMap && decoder->image->gainMap->image); avifImageStealPlanes(decoder->image->gainMap->image, src, AVIF_PLANES_YUV); -#endif } else { // AVIF_ITEM_COLOR avifImageStealPlanes(decoder->image, src, AVIF_PLANES_YUV); } @@ -6647,7 +6604,6 @@ uint32_t avifDecoderDecodedRowCount(const avifDecoder * decoder) { uint32_t minRowCount = decoder->image->height; for (int c = 0; c < AVIF_ITEM_CATEGORY_COUNT; ++c) { -#if defined(AVIF_ENABLE_GAIN_MAP) if (c == AVIF_ITEM_GAIN_MAP) { const avifImage * const gainMap = decoder->image->gainMap ? decoder->image->gainMap->image : NULL; if ((decoder->imageContentToDecode & AVIF_IMAGE_CONTENT_GAIN_MAP) && gainMap != NULL && gainMap->height != 0) { @@ -6665,7 +6621,6 @@ uint32_t avifDecoderDecodedRowCount(const avifDecoder * decoder) } continue; } -#endif const uint32_t rowCount = avifGetDecodedRowCount(decoder, &decoder->data->tileInfos[c], decoder->image); minRowCount = AVIF_MIN(minRowCount, rowCount); } diff --git a/src/write.c b/src/write.c index 8c4bb3a80b..da76d7c93d 100644 --- a/src/write.c +++ b/src/write.c @@ -214,9 +214,7 @@ typedef struct avifEncoderData // Map the encoder settings quality and qualityAlpha to quantizer and quantizerAlpha int quantizer; int quantizerAlpha; -#if defined(AVIF_ENABLE_GAIN_MAP) int quantizerGainMap; -#endif // tileRowsLog2 and tileColsLog2 are the actual tiling values after automatic tiling is handled int tileRowsLog2; int tileColsLog2; @@ -229,11 +227,9 @@ typedef struct avifEncoderData int lastTileRowsLog2; int lastTileColsLog2; avifImage * imageMetadata; -#if defined(AVIF_ENABLE_GAIN_MAP) // For convenience, holds metadata derived from the avifGainMap struct (when present) about the // altenate image avifImage * altImageMetadata; -#endif uint16_t lastItemID; uint16_t primaryItemID; avifEncoderItemIdArray alternativeItemIDs; // list of item ids for an 'altr' box (group of alternatives to each other) @@ -259,12 +255,10 @@ static avifEncoderData * avifEncoderDataCreate(void) if (!data->imageMetadata) { goto error; } -#if defined(AVIF_ENABLE_GAIN_MAP) data->altImageMetadata = avifImageCreateEmpty(); if (!data->altImageMetadata) { goto error; } -#endif if (!avifArrayCreate(&data->items, sizeof(avifEncoderItem), 8)) { goto error; } @@ -336,11 +330,9 @@ static void avifEncoderDataDestroy(avifEncoderData * data) if (data->imageMetadata) { avifImageDestroy(data->imageMetadata); } -#if defined(AVIF_ENABLE_GAIN_MAP) if (data->altImageMetadata) { avifImageDestroy(data->altImageMetadata); } -#endif avifArrayDestroy(&data->items); avifArrayDestroy(&data->frames); avifArrayDestroy(&data->alternativeItemIDs); @@ -467,9 +459,7 @@ avifEncoder * avifEncoderCreate(void) encoder->repetitionCount = AVIF_REPETITION_COUNT_INFINITE; encoder->quality = AVIF_QUALITY_DEFAULT; encoder->qualityAlpha = AVIF_QUALITY_DEFAULT; -#if defined(AVIF_ENABLE_GAIN_MAP) encoder->qualityGainMap = AVIF_QUALITY_DEFAULT; -#endif encoder->minQuantizer = AVIF_QUANTIZER_BEST_QUALITY; encoder->maxQuantizer = AVIF_QUANTIZER_WORST_QUALITY; encoder->minQuantizerAlpha = AVIF_QUANTIZER_BEST_QUALITY; @@ -710,7 +700,7 @@ static avifResult avifEncoderWriteHDRProperties(avifRWStream * dedupStream, return AVIF_RESULT_OK; } -#if defined(AVIF_ENABLE_EXPERIMENTAL_MINI) && defined(AVIF_ENABLE_GAIN_MAP) +#if defined(AVIF_ENABLE_EXPERIMENTAL_MINI) static avifResult avifEncoderWriteMiniHDRProperties(avifRWStream * outputStream, const avifImage * imageMetadata) { const avifBool hasClli = imageMetadata->clli.maxCLL != 0 || imageMetadata->clli.maxPALL != 0; @@ -747,7 +737,7 @@ static avifResult avifEncoderWriteMiniHDRProperties(avifRWStream * outputStream, } return AVIF_RESULT_OK; } -#endif // AVIF_ENABLE_EXPERIMENTAL_MINI && AVIF_ENABLE_GAIN_MAP +#endif // AVIF_ENABLE_EXPERIMENTAL_MINI static avifResult avifEncoderWriteExtendedColorProperties(avifRWStream * dedupStream, avifRWStream * outputStream, @@ -935,8 +925,6 @@ static avifResult avifWriteGridPayload(avifRWData * data, uint32_t gridCols, uin return AVIF_RESULT_OK; } -#if defined(AVIF_ENABLE_GAIN_MAP) - static avifBool avifGainMapIdenticalChannels(const avifGainMap * gainMap) { return gainMap->gainMapMin[0].n == gainMap->gainMapMin[1].n && gainMap->gainMapMin[0].n == gainMap->gainMapMin[2].n && @@ -1041,7 +1029,6 @@ static avifResult avifImageCopyAltImageMetadata(avifImage * altImageMetadata, co altImageMetadata->clli = imageWithGainMap->gainMap->altCLLI; return AVIF_RESULT_OK; } -#endif // AVIF_ENABLE_GAIN_MAP #if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM) static avifResult avifEncoderWriteSampleTransformTokens(avifRWStream * s, const avifSampleTransformExpression * expression) @@ -1202,9 +1189,7 @@ static int avifQualityToQuantizer(int quality, int minQuantizer, int maxQuantize static const char infeNameColor[] = "Color"; static const char infeNameAlpha[] = "Alpha"; -#if defined(AVIF_ENABLE_GAIN_MAP) static const char infeNameGainMap[] = "GMap"; -#endif #if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM) static const char infeNameSampleTransform[] = "SampleTransform"; #endif @@ -1214,11 +1199,9 @@ static const char * getInfeName(avifItemCategory itemCategory) if (avifIsAlpha(itemCategory)) { return infeNameAlpha; } -#if defined(AVIF_ENABLE_GAIN_MAP) if (itemCategory == AVIF_ITEM_GAIN_MAP) { return infeNameGainMap; } -#endif #if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM) if (itemCategory >= AVIF_SAMPLE_TRANSFORM_MIN_CATEGORY && itemCategory <= AVIF_SAMPLE_TRANSFORM_MAX_CATEGORY) { return infeNameSampleTransform; @@ -1563,11 +1546,9 @@ static avifBool avifEncoderDataShouldForceKeyframeForAlpha(const avifEncoderData static avifResult avifGetErrorForItemCategory(avifItemCategory itemCategory) { -#if defined(AVIF_ENABLE_GAIN_MAP) if (itemCategory == AVIF_ITEM_GAIN_MAP) { return AVIF_RESULT_ENCODE_GAIN_MAP_FAILED; } -#endif #if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM) if (itemCategory == AVIF_ITEM_SAMPLE_TRANSFORM || (itemCategory >= AVIF_SAMPLE_TRANSFORM_MIN_CATEGORY && itemCategory <= AVIF_SAMPLE_TRANSFORM_MAX_CATEGORY)) { @@ -1596,26 +1577,22 @@ static avifResult avifValidateGrid(uint32_t gridCols, const uint32_t cellCount = gridCols * gridRows; const avifImage * firstCell = cellImages[0]; const avifImage * bottomRightCell = cellImages[cellCount - 1]; -#if defined(AVIF_ENABLE_GAIN_MAP) if (validateGainMap) { AVIF_ASSERT_OR_RETURN(firstCell->gainMap && firstCell->gainMap->image); firstCell = firstCell->gainMap->image; AVIF_ASSERT_OR_RETURN(bottomRightCell->gainMap && bottomRightCell->gainMap->image); bottomRightCell = bottomRightCell->gainMap->image; } -#endif const uint32_t tileWidth = firstCell->width; const uint32_t tileHeight = firstCell->height; const uint32_t gridWidth = avifGridWidth(gridCols, firstCell, bottomRightCell); const uint32_t gridHeight = avifGridHeight(gridRows, firstCell, bottomRightCell); for (uint32_t cellIndex = 0; cellIndex < cellCount; ++cellIndex) { const avifImage * cellImage = cellImages[cellIndex]; -#if defined(AVIF_ENABLE_GAIN_MAP) if (validateGainMap) { AVIF_ASSERT_OR_RETURN(cellImage->gainMap && cellImage->gainMap->image); cellImage = cellImage->gainMap->image; } -#endif const uint32_t expectedCellWidth = ((cellIndex + 1) % gridCols) ? tileWidth : bottomRightCell->width; const uint32_t expectedCellHeight = (cellIndex < (cellCount - gridCols)) ? tileHeight : bottomRightCell->height; if ((cellImage->width != expectedCellWidth) || (cellImage->height != expectedCellHeight)) { @@ -1709,7 +1686,6 @@ static avifResult avifEncoderAddImageInternal(avifEncoder * encoder, AVIF_CHECKRES(avifValidateGrid(gridCols, gridRows, cellImages, /*validateGainMap=*/AVIF_FALSE, &encoder->diag)); -#if defined(AVIF_ENABLE_GAIN_MAP) const avifBool hasGainMap = (firstCell->gainMap && firstCell->gainMap->image != NULL); // Check that either all cells have a gain map, or none of them do. @@ -1775,7 +1751,6 @@ static avifResult avifEncoderAddImageInternal(avifEncoder * encoder, return AVIF_RESULT_INVALID_ARGUMENT; } } -#endif // AVIF_ENABLE_GAIN_MAP // ----------------------------------------------------------------------- // Validate flags @@ -1823,10 +1798,8 @@ static avifResult avifEncoderAddImageInternal(avifEncoder * encoder, // Map quality and qualityAlpha to quantizer and quantizerAlpha encoder->data->quantizer = avifQualityToQuantizer(encoder->quality, encoder->minQuantizer, encoder->maxQuantizer); encoder->data->quantizerAlpha = avifQualityToQuantizer(encoder->qualityAlpha, encoder->minQuantizerAlpha, encoder->maxQuantizerAlpha); -#if defined(AVIF_ENABLE_GAIN_MAP) encoder->data->quantizerGainMap = avifQualityToQuantizer(encoder->qualityGainMap, AVIF_QUANTIZER_BEST_QUALITY, AVIF_QUANTIZER_WORST_QUALITY); -#endif // ----------------------------------------------------------------------- // Handle automatic tiling @@ -1858,11 +1831,9 @@ static avifResult avifEncoderAddImageInternal(avifEncoder * encoder, if (encoder->data->items.count == 0) { // Make a copy of the first image's metadata (sans pixels) for future writing/validation AVIF_CHECKRES(avifImageCopy(encoder->data->imageMetadata, firstCell, 0)); -#if defined(AVIF_ENABLE_GAIN_MAP) if (hasGainMap) { AVIF_CHECKRES(avifImageCopyAltImageMetadata(encoder->data->altImageMetadata, encoder->data->imageMetadata)); } -#endif // Prepare all AV1 items uint16_t colorItemID; @@ -1907,7 +1878,6 @@ static avifResult avifEncoderAddImageInternal(avifEncoder * encoder, } } -#if defined(AVIF_ENABLE_GAIN_MAP) if (firstCell->gainMap && firstCell->gainMap->image) { avifEncoderItem * toneMappedItem = avifEncoderDataCreateItem(encoder->data, "tmap", @@ -1951,7 +1921,6 @@ static avifResult avifEncoderAddImageInternal(avifEncoder * encoder, colorItem->dimgFromID = toneMappedItemID; gainMapItem->dimgFromID = toneMappedItemID; } -#endif // AVIF_ENABLE_GAIN_MAP #if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM) if (encoder->sampleTransformRecipe == AVIF_SAMPLE_TRANSFORM_BIT_DEPTH_EXTENSION_8B_8B || @@ -1959,9 +1928,7 @@ static avifResult avifEncoderAddImageInternal(avifEncoder * encoder, encoder->sampleTransformRecipe == AVIF_SAMPLE_TRANSFORM_BIT_DEPTH_EXTENSION_12B_8B_OVERLAP_4B) { // For now, only 16-bit depth is supported. AVIF_ASSERT_OR_RETURN(firstCell->depth == 16); -#if defined(AVIF_ENABLE_GAIN_MAP) AVIF_CHECKERR(!firstCell->gainMap, AVIF_RESULT_NOT_IMPLEMENTED); // TODO(yguyon): Implement 16-bit HDR -#endif AVIF_CHECKRES(avifEncoderCreateBitDepthExtensionItems(encoder, gridCols, gridRows, gridWidth, gridHeight, colorItemID)); } else { AVIF_CHECKERR(encoder->sampleTransformRecipe == AVIF_SAMPLE_TRANSFORM_NONE, AVIF_RESULT_NOT_IMPLEMENTED); @@ -1987,12 +1954,10 @@ static avifResult avifEncoderAddImageInternal(avifEncoder * encoder, } else { // Another frame in an image sequence, or layer in a layered image -#if defined(AVIF_ENABLE_GAIN_MAP) if (hasGainMap) { avifDiagnosticsPrintf(&encoder->diag, "gain maps are not supported for image sequences or layered images"); return AVIF_RESULT_NOT_IMPLEMENTED; } -#endif const avifImage * imageMetadata = encoder->data->imageMetadata; // Image metadata that are copied to the configuration property and nclx boxes are not allowed to change. @@ -2037,14 +2002,12 @@ static avifResult avifEncoderAddImageInternal(avifEncoder * encoder, avifImage * cellImagePlaceholder = NULL; // May be used as a temporary, modified cellImage. Left as NULL otherwise. const avifImage * firstCellImage = firstCell; -#if defined(AVIF_ENABLE_GAIN_MAP) if (item->itemCategory == AVIF_ITEM_GAIN_MAP) { AVIF_ASSERT_OR_RETURN(cellImage->gainMap && cellImage->gainMap->image); cellImage = cellImage->gainMap->image; AVIF_ASSERT_OR_RETURN(firstCell->gainMap && firstCell->gainMap->image); firstCellImage = firstCell->gainMap->image; } -#endif if ((cellImage->width != firstCellImage->width) || (cellImage->height != firstCellImage->height)) { // Pad the right-most and/or bottom-most tiles so that all tiles share the same dimensions. @@ -2060,10 +2023,8 @@ static avifResult avifEncoderAddImageInternal(avifEncoder * encoder, } const avifBool isAlpha = avifIsAlpha(item->itemCategory); - int quantizer = isAlpha ? encoder->data->quantizerAlpha -#if defined(AVIF_ENABLE_GAIN_MAP) + int quantizer = isAlpha ? encoder->data->quantizerAlpha : (item->itemCategory == AVIF_ITEM_GAIN_MAP) ? encoder->data->quantizerGainMap -#endif : encoder->data->quantizer; #if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM) @@ -2222,11 +2183,7 @@ static avifResult avifEncoderWriteMediaDataBox(avifEncoder * encoder, continue; } const avifBool isAlpha = avifIsAlpha(item->itemCategory); - const avifBool isAlphaOrGainMap = isAlpha -#if defined(AVIF_ENABLE_GAIN_MAP) - || item->itemCategory == AVIF_ITEM_GAIN_MAP -#endif - ; + const avifBool isAlphaOrGainMap = isAlpha || item->itemCategory == AVIF_ITEM_GAIN_MAP; if (alphaAndGainMapPass != isAlphaOrGainMap) { // only process alpha payloads when alphaPass is true continue; @@ -2267,10 +2224,8 @@ static avifResult avifEncoderWriteMediaDataBox(avifEncoder * encoder, encoder->ioStats.alphaOBUSize += sample->data.size; } else if (item->itemCategory == AVIF_ITEM_COLOR) { encoder->ioStats.colorOBUSize += sample->data.size; -#if defined(AVIF_ENABLE_GAIN_MAP) } else if (item->itemCategory == AVIF_ITEM_GAIN_MAP) { encoder->data->gainMapSizeBytes += sample->data.size; -#endif } } } else { @@ -2389,7 +2344,6 @@ static avifBool avifEncoderIsMiniCompatible(const avifEncoder * encoder) encoder->data->imageMetadata->xmp.size > (1 << 20)) { return AVIF_FALSE; } -#if defined(AVIF_ENABLE_GAIN_MAP) // gainmap_width_minus1 and gainmap_height_minus1 if (encoder->data->imageMetadata->gainMap != NULL && encoder->data->imageMetadata->gainMap->image != NULL && (encoder->data->imageMetadata->gainMap->image->width > (1 << 15) || @@ -2404,7 +2358,6 @@ static avifBool avifEncoderIsMiniCompatible(const avifEncoder * encoder) if (encoder->data->imageMetadata->gainMap != NULL && avifGainMapMetadataSize(encoder->data->imageMetadata->gainMap) >= (1 << 20)) { return AVIF_FALSE; } -#endif // 4:4:4, 4:2:2, 4:2:0 and 4:0:0 are supported by a MinimizedImageBox. // chroma_subsampling @@ -2414,7 +2367,6 @@ static avifBool avifEncoderIsMiniCompatible(const avifEncoder * encoder) encoder->data->imageMetadata->yuvFormat != AVIF_PIXEL_FORMAT_YUV400) { return AVIF_FALSE; } -#if defined(AVIF_ENABLE_GAIN_MAP) // gainmap_chroma_subsampling if (encoder->data->imageMetadata->gainMap != NULL && encoder->data->imageMetadata->gainMap->image != NULL && (encoder->data->imageMetadata->gainMap->image->yuvFormat != AVIF_PIXEL_FORMAT_YUV444 && @@ -2423,14 +2375,12 @@ static avifBool avifEncoderIsMiniCompatible(const avifEncoder * encoder) encoder->data->imageMetadata->gainMap->image->yuvFormat != AVIF_PIXEL_FORMAT_YUV400)) { return AVIF_FALSE; } -#endif // colour_primaries, transfer_characteristics and matrix_coefficients if (encoder->data->imageMetadata->colorPrimaries > 255 || encoder->data->imageMetadata->transferCharacteristics > 255 || encoder->data->imageMetadata->matrixCoefficients > 255) { return AVIF_FALSE; } -#if defined(AVIF_ENABLE_GAIN_MAP) // gainmap_colour_primaries, gainmap_transfer_characteristics and gainmap_matrix_coefficients if (encoder->data->imageMetadata->gainMap != NULL && encoder->data->imageMetadata->gainMap->image != NULL && (encoder->data->imageMetadata->gainMap->image->colorPrimaries > 255 || @@ -2443,7 +2393,6 @@ static avifBool avifEncoderIsMiniCompatible(const avifEncoder * encoder) encoder->data->altImageMetadata->matrixCoefficients > 255) { return AVIF_FALSE; } -#endif const avifEncoderItem * colorItem = NULL; for (uint32_t itemIndex = 0; itemIndex < encoder->data->items.count; ++itemIndex) { @@ -2470,7 +2419,6 @@ static avifBool avifEncoderIsMiniCompatible(const avifEncoder * encoder) } continue; // The alpha auxiliary item can be stored in the MinimizedImageBox. } -#if defined(AVIF_ENABLE_GAIN_MAP) if (item->itemCategory == AVIF_ITEM_GAIN_MAP) { // gainmap_item_data_size if (item->encodeOutput->samples.count != 1 || item->encodeOutput->samples.sample[0].data.size >= (1 << 28)) { @@ -2482,7 +2430,6 @@ static avifBool avifEncoderIsMiniCompatible(const avifEncoder * encoder) assert(item->itemCategory == AVIF_ITEM_COLOR); // Cannot be differentiated from the primary item by its itemCategory. continue; // The tone mapping derived image item can be represented in the MinimizedImageBox. } -#endif if (!memcmp(item->type, "mime", 4) && !memcmp(item->infeName, "XMP", item->infeNameSize)) { assert(item->metadataPayload.size == encoder->data->imageMetadata->xmp.size); continue; // XMP metadata can be stored in the MinimizedImageBox. @@ -2541,12 +2488,10 @@ static avifResult avifEncoderWriteMiniBox(avifEncoder * encoder, avifRWStream * AVIF_ASSERT_OR_RETURN(!alphaItem); alphaItem = item; } -#if defined(AVIF_ENABLE_GAIN_MAP) if (item->itemCategory == AVIF_ITEM_GAIN_MAP) { AVIF_ASSERT_OR_RETURN(!gainmapItem); gainmapItem = item; } -#endif } AVIF_ASSERT_OR_RETURN(colorItem); @@ -2617,7 +2562,6 @@ static avifResult avifEncoderWriteMiniBox(avifEncoder * encoder, avifRWStream * uint32_t fewItemDataBytesFlag = colorData->size <= (1 << 15) && (!alphaData || alphaData->size < (1 << 15)); uint32_t fewMetadataBytesFlag = image->icc.size <= (1 << 10) && image->exif.size <= (1 << 10) && image->xmp.size <= (1 << 10); -#if defined(AVIF_ENABLE_GAIN_MAP) if (hasGainmap) { AVIF_ASSERT_OR_RETURN(image->gainMap != NULL && image->gainMap->image != NULL); gainmapMetadataSize = avifGainMapMetadataSize(image->gainMap); @@ -2628,7 +2572,6 @@ static avifResult avifEncoderWriteMiniBox(avifEncoder * encoder, avifRWStream * fewMetadataBytesFlag &= encoder->data->altImageMetadata->icc.size <= (1 << 10) && gainmapMetadataSize <= (1 << 10); // image->gainMap->image->icc is ignored. } -#endif avifBoxMarker mini; AVIF_CHECKRES(avifRWStreamWriteBox(s, "mini", AVIF_BOX_SIZE_TBD, &mini)); @@ -2700,7 +2643,6 @@ static avifResult avifEncoderWriteMiniBox(avifEncoder * encoder, avifRWStream * // High Dynamic Range properties size_t tmapIccSize = 0; if (hasHdr) { -#if defined(AVIF_ENABLE_GAIN_MAP) AVIF_CHECKRES(avifRWStreamWriteBits(s, hasGainmap, 1)); // bit(1) gainmap_flag; if (hasGainmap) { const avifImage * tmap = encoder->data->altImageMetadata; @@ -2760,7 +2702,6 @@ static avifResult avifEncoderWriteMiniBox(avifEncoder * encoder, avifRWStream * if (hasGainmap) { AVIF_CHECKRES(avifEncoderWriteMiniHDRProperties(s, encoder->data->altImageMetadata)); } -#endif // AVIF_ENABLE_GAIN_MAP } // Chunk sizes @@ -2773,7 +2714,6 @@ static avifResult avifEncoderWriteMiniBox(avifEncoder * encoder, avifRWStream * if (hasIcc) { AVIF_CHECKRES(avifRWStreamWriteBits(s, (uint32_t)image->icc.size - 1, fewMetadataBytesFlag ? 10 : 20)); // unsigned int(few_metadata_bytes_flag ? 10 : 20) icc_data_size_minus1; } -#if defined(AVIF_ENABLE_GAIN_MAP) if (hasHdr && hasGainmap && tmapIccSize != 0) { AVIF_CHECKRES(avifRWStreamWriteBits(s, (uint32_t)tmapIccSize - 1, fewMetadataBytesFlag ? 10 : 20)); // unsigned int(few_metadata_bytes_flag ? 10 : 20) tmap_icc_data_size_minus1; } @@ -2787,7 +2727,6 @@ static avifResult avifEncoderWriteMiniBox(avifEncoder * encoder, avifRWStream * if (hasHdr && hasGainmap && gainmapData->size != 0) { AVIF_CHECKRES(avifRWStreamWriteBits(s, codecConfigSize, fewCodecConfigBytesFlag ? 3 : 12)); // unsigned int(few_codec_config_bytes_flag ? 3 : 12) gainmap_item_codec_config_size; } -#endif AVIF_CHECKRES(avifRWStreamWriteBits(s, codecConfigSize, fewCodecConfigBytesFlag ? 3 : 12)); // unsigned int(few_codec_config_bytes_flag ? 3 : 12) main_item_codec_config_size; AVIF_CHECKRES(avifRWStreamWriteBits(s, (uint32_t)colorData->size - 1, fewItemDataBytesFlag ? 15 : 28)); // unsigned int(few_item_data_bytes_flag ? 15 : 28) main_item_data_size_minus1; @@ -2826,14 +2765,12 @@ static avifResult avifEncoderWriteMiniBox(avifEncoder * encoder, avifRWStream * if (hasIcc) { AVIF_CHECKRES(avifRWStreamWrite(s, image->icc.data, image->icc.size)); // unsigned int(8) icc_data[icc_data_size_minus1 + 1]; } -#if defined(AVIF_ENABLE_GAIN_MAP) if (hasHdr && hasGainmap && tmapIccSize != 0) { AVIF_CHECKRES(avifRWStreamWrite(s, encoder->data->altImageMetadata->icc.data, tmapIccSize)); // unsigned int(8) tmap_icc_data[tmap_icc_data_size_minus1 + 1]; } if (hasHdr && hasGainmap && gainmapMetadataSize != 0) { AVIF_CHECKRES(avifWriteGainmapMetadata(s, image->gainMap, &encoder->diag)); // unsigned int(8) gainmap_metadata[gainmap_metadata_size]; } -#endif if (hasAlpha && alphaData->size != 0) { AVIF_CHECKRES(avifRWStreamWrite(s, alphaData->data, alphaData->size)); // unsigned int(8) alpha_item_data[alpha_item_data_size]; @@ -2872,12 +2809,10 @@ static avifResult avifRWStreamWriteProperties(avifItemPropertyDedup * const dedu const avifBool isGrid = (item->gridCols > 0); // Whether there is ipma to write for this item. avifBool hasIpmaToWrite = item->codec || isGrid; -#if defined(AVIF_ENABLE_GAIN_MAP) const avifBool isToneMappedImage = !memcmp(item->type, "tmap", 4); if (isToneMappedImage) { hasIpmaToWrite = AVIF_TRUE; } -#endif #if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM) const avifBool isSampleTransformImage = !memcmp(item->type, "sato", 4); if (isSampleTransformImage) { @@ -2914,16 +2849,12 @@ static avifResult avifRWStreamWriteProperties(avifItemPropertyDedup * const dedu } const avifImage * itemMetadata = imageMetadata; -#if defined(AVIF_ENABLE_GAIN_MAP) if (isToneMappedImage) { itemMetadata = altImageMetadata; } else if (item->itemCategory == AVIF_ITEM_GAIN_MAP) { AVIF_ASSERT_OR_RETURN(itemMetadata->gainMap && itemMetadata->gainMap->image); itemMetadata = itemMetadata->gainMap->image; } -#else - (void)altImageMetadata; -#endif uint32_t imageWidth = itemMetadata->width; uint32_t imageHeight = itemMetadata->height; if (isGrid) { @@ -2943,12 +2874,10 @@ static avifResult avifRWStreamWriteProperties(avifItemPropertyDedup * const dedu // pixi = pixel information (depth, channel count) avifBool hasPixi = AVIF_TRUE; -#if defined(AVIF_ENABLE_GAIN_MAP) // Pixi is optional for the 'tmap' item. if (isToneMappedImage && imageMetadata->gainMap->altDepth == 0 && imageMetadata->gainMap->altPlaneCount == 0) { hasPixi = AVIF_FALSE; } -#endif const avifBool isAlpha = avifIsAlpha(item->itemCategory); uint8_t depth = (uint8_t)itemMetadata->depth; #if defined(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM) @@ -3009,7 +2938,6 @@ static avifResult avifRWStreamWriteProperties(avifItemPropertyDedup * const dedu AVIF_CHECKRES(avifEncoderWriteColorProperties(s, itemMetadata, &item->ipma, dedup)); AVIF_CHECKRES(avifEncoderWriteHDRProperties(&dedup->s, s, itemMetadata, &item->ipma, dedup)); -#if defined(AVIF_ENABLE_GAIN_MAP) } else if (item->itemCategory == AVIF_ITEM_GAIN_MAP) { // Gain map specific properties @@ -3052,7 +2980,6 @@ static avifResult avifRWStreamWriteProperties(avifItemPropertyDedup * const dedu // To enforce that, the transformative properties of the gain map cannot be set explicitly in the API. AVIF_CHECKERR(itemMetadata->transformFlags == AVIF_TRANSFORM_NONE, AVIF_RESULT_ENCODE_GAIN_MAP_FAILED); AVIF_CHECKRES(avifEncoderWriteExtendedColorProperties(&dedup->s, s, imageMetadata, &item->ipma, dedup)); -#endif } if (item->extraLayerCount > 0) { @@ -3246,7 +3173,6 @@ avifResult avifEncoderFinish(avifEncoder * encoder, avifRWData * output) AVIF_CHECKRES(avifRWStreamWriteChars(&s, "MA1A", 4)); // ... compatible_brands[] } } -#if defined(AVIF_ENABLE_GAIN_MAP) for (uint32_t itemIndex = 0; itemIndex < encoder->data->items.count; ++itemIndex) { if (!memcmp(encoder->data->items.item[itemIndex].type, "tmap", 4)) { // ISO/IEC 23008-12:2024/AMD 1:2024(E) @@ -3257,7 +3183,6 @@ avifResult avifEncoderFinish(avifEncoder * encoder, avifRWData * output) break; } } -#endif avifRWStreamFinishBox(&s, ftyp); // ----------------------------------------------------------------------- @@ -3418,9 +3343,7 @@ avifResult avifEncoderFinish(avifEncoder * encoder, avifRWData * output) avifBoxMarker ipco; AVIF_CHECKRES(avifRWStreamWriteBox(&s, "ipco", AVIF_BOX_SIZE_TBD, &ipco)); avifImage * altImageMetadata = NULL; -#if defined(AVIF_ENABLE_GAIN_MAP) altImageMetadata = encoder->data->altImageMetadata; -#endif avifResult result = avifRWStreamWriteProperties(dedup, &s, encoder, imageMetadata, altImageMetadata); avifItemPropertyDedupDestroy(dedup); AVIF_CHECKRES(result); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ca34391916..90df893319 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -112,13 +112,10 @@ if(AVIF_ENABLE_GTEST) add_avif_gtest_with_data(avifdecodetest) add_avif_gtest_with_data(avifdimgtest avifincrtest_helpers) add_avif_gtest_with_data(avifencodetest) + add_avif_internal_gtest_with_data(avifgainmaptest avifincrtest_helpers_internal) - if(AVIF_ENABLE_GAIN_MAP) - add_avif_internal_gtest_with_data(avifgainmaptest avifincrtest_helpers_internal) - - if(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) - add_avif_gtest_with_data(avifjpeggainmaptest) - endif() + if(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) + add_avif_gtest_with_data(avifjpeggainmaptest) endif() add_avif_gtest(avifgridapitest) @@ -131,7 +128,7 @@ if(AVIF_ENABLE_GTEST) add_avif_gtest_with_data(aviflosslesstest) add_avif_gtest_with_data(avifmetadatatest) - if(AVIF_ENABLE_EXPERIMENTAL_MINI AND AVIF_ENABLE_GAIN_MAP) + if(AVIF_ENABLE_EXPERIMENTAL_MINI) add_avif_gtest(avifminitest) endif() @@ -222,11 +219,6 @@ if(AVIF_ENABLE_FUZZTEST) add_avif_fuzztest(avif_fuzztest_enc_dec_incr gtest/avifincrtest_helpers.cc) add_avif_fuzztest(avif_fuzztest_read_image) add_avif_fuzztest(avif_fuzztest_yuvrgb) - - if(AVIF_ENABLE_GAIN_MAP) - add_avif_fuzztest(avif_fuzztest_enc_dec_experimental) - add_avif_fuzztest(avif_fuzztest_enc_dec_incr_experimental gtest/avifincrtest_helpers.cc) - endif() else() message(STATUS "FuzzTest targets are disabled because AVIF_ENABLE_FUZZTEST is OFF.") endif() @@ -271,7 +263,7 @@ if(AVIF_BUILD_APPS) ${CMAKE_CURRENT_SOURCE_DIR}/data ) - if(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) + if(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) add_test(NAME test_cmd_avifgainmaputil COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/test_cmd_avifgainmaputil.sh ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/data ) @@ -292,7 +284,7 @@ if(AVIF_BUILD_APPS) ${CMAKE_CURRENT_SOURCE_DIR}/data ${GOLDEN_TESTS_OUTPUT_DIR} ) - if(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) + if(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) add_test(NAME test_cmd_gainmap COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/test_cmd_gainmap.sh ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/data ) @@ -371,15 +363,12 @@ if(AVIF_CODEC_AVM_ENABLED) PROPERTIES DISABLED True ) - if(AVIF_ENABLE_EXPERIMENTAL_MINI AND AVIF_ENABLE_GAIN_MAP) + if(AVIF_ENABLE_EXPERIMENTAL_MINI) set_tests_properties(avifminitest PROPERTIES DISABLED True) endif() - if(AVIF_ENABLE_GAIN_MAP) - set_tests_properties(avifgainmaptest PROPERTIES DISABLED True) - - if(AVIF_ENABLE_EXPERIMENTAL_JPEG_GAIN_MAP_CONVERSION) - set_tests_properties(avifjpeggainmaptest PROPERTIES DISABLED True) - endif() + set_tests_properties(avifgainmaptest PROPERTIES DISABLED True) + if(AVIF_ENABLE_JPEG_GAIN_MAP_CONVERSION) + set_tests_properties(avifjpeggainmaptest PROPERTIES DISABLED True) endif() if(AVIF_ENABLE_EXPERIMENTAL_SAMPLE_TRANSFORM) set_tests_properties(avif16bittest PROPERTIES DISABLED True) diff --git a/tests/gtest/avif_fuzztest_enc_dec.cc b/tests/gtest/avif_fuzztest_enc_dec.cc index f31afc4081..80dd79b834 100644 --- a/tests/gtest/avif_fuzztest_enc_dec.cc +++ b/tests/gtest/avif_fuzztest_enc_dec.cc @@ -1,6 +1,10 @@ // Copyright 2022 Google LLC // SPDX-License-Identifier: BSD-2-Clause +#include +#include +#include +#include #include #include "avif/avif.h" @@ -13,6 +17,27 @@ namespace avif { namespace testutil { namespace { +void CheckGainMapMetadataMatches(const avifGainMap& actual, + const avifGainMap& expected) { + EXPECT_EQ(actual.baseHdrHeadroom.n, expected.baseHdrHeadroom.n); + EXPECT_EQ(actual.baseHdrHeadroom.d, expected.baseHdrHeadroom.d); + EXPECT_EQ(actual.alternateHdrHeadroom.n, expected.alternateHdrHeadroom.n); + EXPECT_EQ(actual.alternateHdrHeadroom.d, expected.alternateHdrHeadroom.d); + for (int c = 0; c < 3; ++c) { + SCOPED_TRACE(c); + EXPECT_EQ(actual.baseOffset[c].n, expected.baseOffset[c].n); + EXPECT_EQ(actual.baseOffset[c].d, expected.baseOffset[c].d); + EXPECT_EQ(actual.alternateOffset[c].n, expected.alternateOffset[c].n); + EXPECT_EQ(actual.alternateOffset[c].d, expected.alternateOffset[c].d); + EXPECT_EQ(actual.gainMapGamma[c].n, expected.gainMapGamma[c].n); + EXPECT_EQ(actual.gainMapGamma[c].d, expected.gainMapGamma[c].d); + EXPECT_EQ(actual.gainMapMin[c].n, expected.gainMapMin[c].n); + EXPECT_EQ(actual.gainMapMin[c].d, expected.gainMapMin[c].d); + EXPECT_EQ(actual.gainMapMax[c].n, expected.gainMapMax[c].n); + EXPECT_EQ(actual.gainMapMax[c].d, expected.gainMapMax[c].d); + } +} + void EncodeDecodeValid(ImagePtr image, EncoderPtr encoder, DecoderPtr decoder) { ImagePtr decoded_image(avifImageCreateEmpty()); ASSERT_NE(image.get(), nullptr); @@ -36,6 +61,24 @@ void EncodeDecodeValid(ImagePtr image, EncoderPtr encoder, DecoderPtr decoder) { EXPECT_EQ(decoded_image->depth, image->depth); EXPECT_EQ(decoded_image->yuvFormat, image->yuvFormat); + EXPECT_EQ(decoded_image->gainMap != nullptr, image->gainMap != nullptr); + if (decoded_image->gainMap != nullptr && + (decoder->imageContentToDecode & AVIF_IMAGE_CONTENT_GAIN_MAP)) { + ASSERT_NE(decoded_image->gainMap->image, nullptr); + EXPECT_EQ(decoded_image->gainMap->image->width, + image->gainMap->image->width); + EXPECT_EQ(decoded_image->gainMap->image->height, + image->gainMap->image->height); + EXPECT_EQ(decoded_image->gainMap->image->depth, + image->gainMap->image->depth); + EXPECT_EQ(decoded_image->gainMap->image->yuvFormat, + image->gainMap->image->yuvFormat); + EXPECT_EQ(image->gainMap->image->gainMap, nullptr); + EXPECT_EQ(decoded_image->gainMap->image->alphaPlane, nullptr); + + CheckGainMapMetadataMatches(*decoded_image->gainMap, *image->gainMap); + } + // Verify that an opaque input leads to an opaque output. if (avifImageIsOpaque(image.get())) { EXPECT_TRUE(avifImageIsOpaque(decoded_image.get())); @@ -45,8 +88,9 @@ void EncodeDecodeValid(ImagePtr image, EncoderPtr encoder, DecoderPtr decoder) { } FUZZ_TEST(EncodeDecodeAvifFuzzTest, EncodeDecodeValid) - .WithDomains(ArbitraryAvifImage(), ArbitraryAvifEncoder(), - ArbitraryAvifDecoder()); + .WithDomains(fuzztest::OneOf(ArbitraryAvifImage(), + ArbitraryAvifImageWithGainMap()), + ArbitraryAvifEncoder(), ArbitraryAvifDecoder()); } // namespace } // namespace testutil diff --git a/tests/gtest/avif_fuzztest_enc_dec_experimental.cc b/tests/gtest/avif_fuzztest_enc_dec_experimental.cc deleted file mode 100644 index 80dd79b834..0000000000 --- a/tests/gtest/avif_fuzztest_enc_dec_experimental.cc +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2022 Google LLC -// SPDX-License-Identifier: BSD-2-Clause - -#include -#include -#include -#include -#include - -#include "avif/avif.h" -#include "avif_fuzztest_helpers.h" -#include "aviftest_helpers.h" -#include "fuzztest/fuzztest.h" -#include "gtest/gtest.h" - -namespace avif { -namespace testutil { -namespace { - -void CheckGainMapMetadataMatches(const avifGainMap& actual, - const avifGainMap& expected) { - EXPECT_EQ(actual.baseHdrHeadroom.n, expected.baseHdrHeadroom.n); - EXPECT_EQ(actual.baseHdrHeadroom.d, expected.baseHdrHeadroom.d); - EXPECT_EQ(actual.alternateHdrHeadroom.n, expected.alternateHdrHeadroom.n); - EXPECT_EQ(actual.alternateHdrHeadroom.d, expected.alternateHdrHeadroom.d); - for (int c = 0; c < 3; ++c) { - SCOPED_TRACE(c); - EXPECT_EQ(actual.baseOffset[c].n, expected.baseOffset[c].n); - EXPECT_EQ(actual.baseOffset[c].d, expected.baseOffset[c].d); - EXPECT_EQ(actual.alternateOffset[c].n, expected.alternateOffset[c].n); - EXPECT_EQ(actual.alternateOffset[c].d, expected.alternateOffset[c].d); - EXPECT_EQ(actual.gainMapGamma[c].n, expected.gainMapGamma[c].n); - EXPECT_EQ(actual.gainMapGamma[c].d, expected.gainMapGamma[c].d); - EXPECT_EQ(actual.gainMapMin[c].n, expected.gainMapMin[c].n); - EXPECT_EQ(actual.gainMapMin[c].d, expected.gainMapMin[c].d); - EXPECT_EQ(actual.gainMapMax[c].n, expected.gainMapMax[c].n); - EXPECT_EQ(actual.gainMapMax[c].d, expected.gainMapMax[c].d); - } -} - -void EncodeDecodeValid(ImagePtr image, EncoderPtr encoder, DecoderPtr decoder) { - ImagePtr decoded_image(avifImageCreateEmpty()); - ASSERT_NE(image.get(), nullptr); - ASSERT_NE(encoder.get(), nullptr); - ASSERT_NE(decoder.get(), nullptr); - ASSERT_NE(decoded_image.get(), nullptr); - - AvifRwData encoded_data; - const avifResult encoder_result = - avifEncoderWrite(encoder.get(), image.get(), &encoded_data); - ASSERT_EQ(encoder_result, AVIF_RESULT_OK) - << avifResultToString(encoder_result); - - const avifResult decoder_result = avifDecoderReadMemory( - decoder.get(), decoded_image.get(), encoded_data.data, encoded_data.size); - ASSERT_EQ(decoder_result, AVIF_RESULT_OK) - << avifResultToString(decoder_result); - - EXPECT_EQ(decoded_image->width, image->width); - EXPECT_EQ(decoded_image->height, image->height); - EXPECT_EQ(decoded_image->depth, image->depth); - EXPECT_EQ(decoded_image->yuvFormat, image->yuvFormat); - - EXPECT_EQ(decoded_image->gainMap != nullptr, image->gainMap != nullptr); - if (decoded_image->gainMap != nullptr && - (decoder->imageContentToDecode & AVIF_IMAGE_CONTENT_GAIN_MAP)) { - ASSERT_NE(decoded_image->gainMap->image, nullptr); - EXPECT_EQ(decoded_image->gainMap->image->width, - image->gainMap->image->width); - EXPECT_EQ(decoded_image->gainMap->image->height, - image->gainMap->image->height); - EXPECT_EQ(decoded_image->gainMap->image->depth, - image->gainMap->image->depth); - EXPECT_EQ(decoded_image->gainMap->image->yuvFormat, - image->gainMap->image->yuvFormat); - EXPECT_EQ(image->gainMap->image->gainMap, nullptr); - EXPECT_EQ(decoded_image->gainMap->image->alphaPlane, nullptr); - - CheckGainMapMetadataMatches(*decoded_image->gainMap, *image->gainMap); - } - - // Verify that an opaque input leads to an opaque output. - if (avifImageIsOpaque(image.get())) { - EXPECT_TRUE(avifImageIsOpaque(decoded_image.get())); - } - // A transparent image may be heavily compressed to an opaque image. This is - // hard to verify so do not check it. -} - -FUZZ_TEST(EncodeDecodeAvifFuzzTest, EncodeDecodeValid) - .WithDomains(fuzztest::OneOf(ArbitraryAvifImage(), - ArbitraryAvifImageWithGainMap()), - ArbitraryAvifEncoder(), ArbitraryAvifDecoder()); - -} // namespace -} // namespace testutil -} // namespace avif diff --git a/tests/gtest/avif_fuzztest_enc_dec_incr.cc b/tests/gtest/avif_fuzztest_enc_dec_incr.cc index e3d52ac3b8..001e4b11c5 100644 --- a/tests/gtest/avif_fuzztest_enc_dec_incr.cc +++ b/tests/gtest/avif_fuzztest_enc_dec_incr.cc @@ -38,6 +38,19 @@ void EncodeDecodeGridValid(ImagePtr image, EncoderPtr encoder, const uint32_t encoded_height = std::min(image->height, grid_rows * cell_height); + const avifImage* gain_map = + image->gainMap != nullptr ? image->gainMap->image : nullptr; + if (gain_map != nullptr) { + std::vector gain_map_cells = + ImageToGrid(gain_map, grid_cols, grid_rows); + if (gain_map_cells.empty()) return; + ASSERT_EQ(gain_map_cells.size(), cells.size()); + for (size_t i = 0; i < gain_map_cells.size(); ++i) { + cells[i]->gainMap = avifGainMapCreate(); + cells[i]->gainMap->image = gain_map_cells[i].release(); + } + } + AvifRwData encoded_data; const avifResult encoder_result = avifEncoderAddImageGrid( encoder.get(), grid_cols, grid_rows, UniquePtrToRawPtr(cells).data(), @@ -50,6 +63,21 @@ void EncodeDecodeGridValid(ImagePtr image, EncoderPtr encoder, << avifResultToString(encoder_result); return; } + if ((gain_map != nullptr) && + ((grid_cols > 1 || grid_rows > 1) && + !avifAreGridDimensionsValid( + gain_map->yuvFormat, + std::min(gain_map->width, + grid_cols * cells.front()->gainMap->image->width), + std::min(gain_map->height, + grid_rows * cells.front()->gainMap->image->height), + cells.front()->gainMap->image->width, + cells.front()->gainMap->image->height, nullptr))) { + ASSERT_TRUE(encoder_result == AVIF_RESULT_INVALID_IMAGE_GRID) + << avifResultToString(encoder_result); + return; + } + ASSERT_EQ(encoder_result, AVIF_RESULT_OK) << avifResultToString(encoder_result); @@ -57,17 +85,20 @@ void EncodeDecodeGridValid(ImagePtr image, EncoderPtr encoder, avifEncoderFinish(encoder.get(), &encoded_data); ASSERT_EQ(finish_result, AVIF_RESULT_OK) << avifResultToString(finish_result); + const bool expect_whole_file_read = + (decoder->imageContentToDecode == AVIF_IMAGE_CONTENT_ALL); const avifResult decode_result = DecodeNonIncrementallyAndIncrementally( encoded_data, decoder.get(), is_encoded_data_persistent, give_size_hint_to_decoder, /*use_nth_image_api=*/true, cell_height, - /*enable_fine_incremental_check=*/false, /*expect_whole_file_read=*/true, + /*enable_fine_incremental_check=*/false, expect_whole_file_read, /*expect_parse_success_from_partial_file=*/false); ASSERT_EQ(decode_result, AVIF_RESULT_OK) << avifResultToString(decode_result); } FUZZ_TEST(EncodeDecodeAvifFuzzTest, EncodeDecodeGridValid) - .WithDomains(ArbitraryAvifImage(), ArbitraryAvifEncoder(), - ArbitraryAvifDecoder(), + .WithDomains(fuzztest::OneOf(ArbitraryAvifImage(), + ArbitraryAvifImageWithGainMap()), + ArbitraryAvifEncoder(), ArbitraryAvifDecoder(), /*grid_cols=*/InRange(1, 32), /*grid_rows=*/InRange(1, 32), /*is_encoded_data_persistent=*/Arbitrary(), diff --git a/tests/gtest/avif_fuzztest_enc_dec_incr_experimental.cc b/tests/gtest/avif_fuzztest_enc_dec_incr_experimental.cc deleted file mode 100644 index 821582bfb9..0000000000 --- a/tests/gtest/avif_fuzztest_enc_dec_incr_experimental.cc +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2023 Google LLC -// SPDX-License-Identifier: BSD-2-Clause -// Encode a fuzzed image split into a grid and decode it incrementally. -// Compare the output with a non-incremental decode. - -#include -#include -#include - -#include "avif/internal.h" -#include "avif_fuzztest_helpers.h" -#include "avifincrtest_helpers.h" -#include "aviftest_helpers.h" -#include "fuzztest/fuzztest.h" -#include "gtest/gtest.h" - -using ::fuzztest::Arbitrary; -using ::fuzztest::InRange; - -namespace avif { -namespace testutil { -namespace { - -// Encodes an image into an AVIF grid then decodes it. -void EncodeDecodeGridValid(ImagePtr image, EncoderPtr encoder, - DecoderPtr decoder, uint32_t grid_cols, - uint32_t grid_rows, bool is_encoded_data_persistent, - bool give_size_hint_to_decoder) { - ASSERT_NE(image, nullptr); - ASSERT_NE(encoder, nullptr); - - const std::vector cells = - ImageToGrid(image.get(), grid_cols, grid_rows); - if (cells.empty()) return; - const uint32_t cell_width = cells.front()->width; - const uint32_t cell_height = cells.front()->height; - const uint32_t encoded_width = std::min(image->width, grid_cols * cell_width); - const uint32_t encoded_height = - std::min(image->height, grid_rows * cell_height); - - const avifImage* gain_map = - image->gainMap != nullptr ? image->gainMap->image : nullptr; - if (gain_map != nullptr) { - std::vector gain_map_cells = - ImageToGrid(gain_map, grid_cols, grid_rows); - if (gain_map_cells.empty()) return; - ASSERT_EQ(gain_map_cells.size(), cells.size()); - for (size_t i = 0; i < gain_map_cells.size(); ++i) { - cells[i]->gainMap = avifGainMapCreate(); - cells[i]->gainMap->image = gain_map_cells[i].release(); - } - } - - AvifRwData encoded_data; - const avifResult encoder_result = avifEncoderAddImageGrid( - encoder.get(), grid_cols, grid_rows, UniquePtrToRawPtr(cells).data(), - AVIF_ADD_IMAGE_FLAG_SINGLE); - if (((grid_cols > 1 || grid_rows > 1) && - !avifAreGridDimensionsValid(image->yuvFormat, encoded_width, - encoded_height, cell_width, cell_height, - nullptr))) { - ASSERT_TRUE(encoder_result == AVIF_RESULT_INVALID_IMAGE_GRID) - << avifResultToString(encoder_result); - return; - } - if ((gain_map != nullptr) && - ((grid_cols > 1 || grid_rows > 1) && - !avifAreGridDimensionsValid( - gain_map->yuvFormat, - std::min(gain_map->width, - grid_cols * cells.front()->gainMap->image->width), - std::min(gain_map->height, - grid_rows * cells.front()->gainMap->image->height), - cells.front()->gainMap->image->width, - cells.front()->gainMap->image->height, nullptr))) { - ASSERT_TRUE(encoder_result == AVIF_RESULT_INVALID_IMAGE_GRID) - << avifResultToString(encoder_result); - return; - } - - ASSERT_EQ(encoder_result, AVIF_RESULT_OK) - << avifResultToString(encoder_result); - - const avifResult finish_result = - avifEncoderFinish(encoder.get(), &encoded_data); - ASSERT_EQ(finish_result, AVIF_RESULT_OK) << avifResultToString(finish_result); - - const bool expect_whole_file_read = - (decoder->imageContentToDecode == AVIF_IMAGE_CONTENT_ALL); - const avifResult decode_result = DecodeNonIncrementallyAndIncrementally( - encoded_data, decoder.get(), is_encoded_data_persistent, - give_size_hint_to_decoder, /*use_nth_image_api=*/true, cell_height, - /*enable_fine_incremental_check=*/false, expect_whole_file_read, - /*expect_parse_success_from_partial_file=*/false); - ASSERT_EQ(decode_result, AVIF_RESULT_OK) << avifResultToString(decode_result); -} - -FUZZ_TEST(EncodeDecodeAvifFuzzTest, EncodeDecodeGridValid) - .WithDomains(fuzztest::OneOf(ArbitraryAvifImage(), - ArbitraryAvifImageWithGainMap()), - ArbitraryAvifEncoder(), ArbitraryAvifDecoder(), - /*grid_cols=*/InRange(1, 32), - /*grid_rows=*/InRange(1, 32), - /*is_encoded_data_persistent=*/Arbitrary(), - /*give_size_hint_to_decoder=*/Arbitrary()); - -} // namespace -} // namespace testutil -} // namespace avif diff --git a/tests/gtest/avif_fuzztest_helpers.cc b/tests/gtest/avif_fuzztest_helpers.cc index b46e85ab33..cf5633c61c 100644 --- a/tests/gtest/avif_fuzztest_helpers.cc +++ b/tests/gtest/avif_fuzztest_helpers.cc @@ -156,7 +156,6 @@ DecoderPtr CreateAvifDecoder(avifCodecChoice codec_choice, int max_threads, ImagePtr AvifImageToUniquePtr(avifImage* image) { return ImagePtr(image); } -#if defined(AVIF_ENABLE_GAIN_MAP) DecoderPtr AddGainMapOptionsToDecoder( DecoderPtr decoder, avifImageContentTypeFlags image_content_to_decode) { decoder->imageContentToDecode = image_content_to_decode; @@ -213,7 +212,6 @@ ImagePtr AddGainMapToImage( return image; } -#endif //------------------------------------------------------------------------------ diff --git a/tests/gtest/avif_fuzztest_helpers.h b/tests/gtest/avif_fuzztest_helpers.h index cfb5750d94..2f11f8cdd1 100644 --- a/tests/gtest/avif_fuzztest_helpers.h +++ b/tests/gtest/avif_fuzztest_helpers.h @@ -50,10 +50,8 @@ DecoderPtr CreateAvifDecoder(avifCodecChoice codec_choice, int max_threads, uint32_t image_dimension_limit, uint32_t image_count_limit, avifStrictFlags strict_flags); -#if defined(AVIF_ENABLE_GAIN_MAP) DecoderPtr AddGainMapOptionsToDecoder( DecoderPtr decoder, avifImageContentTypeFlags image_content_to_decode); -#endif //------------------------------------------------------------------------------ // Custom fuzztest generators. @@ -169,7 +167,6 @@ inline auto ArbitraryAvifAnim() { return fuzztest::OneOf(ArbitraryAvifAnim8b(), ArbitraryAvifAnim16b()); } -#if defined(AVIF_ENABLE_GAIN_MAP) // TODO: Try StructOf(StructOf())? ImagePtr AddGainMapToImage( ImagePtr image, ImagePtr gain_map, int32_t gain_map_min_n0, @@ -224,7 +221,6 @@ inline auto ArbitraryAvifImageWithGainMap() { fuzztest::InRange(1, std::numeric_limits::max()), fuzztest::Arbitrary()); } -#endif // Generator for an arbitrary EncoderPtr. inline auto ArbitraryAvifEncoder() { @@ -278,30 +274,22 @@ inline auto ArbitraryBaseAvifDecoder() { AVIF_STRICT_ALPHA_ISPE_REQUIRED})); } -#if defined(AVIF_ENABLE_GAIN_MAP) // Generator for an arbitrary DecoderPtr with base options and gain map // options fuzzed. inline auto ArbitraryAvifDecoderWithGainMapOptions() { // Always decode at least color+alpha, since most tests // assume that if the file/buffer is successfully decoded. - return fuzztest::Map(AddGainMapOptionsToDecoder, ArbitraryBaseAvifDecoder(), - fuzztest::ElementOf({ - AVIF_IMAGE_CONTENT_COLOR_AND_ALPHA -#if defined(AVIF_ENABLE_GAIN_MAP) - , AVIF_IMAGE_CONTENT_COLOR_AND_ALPHA | - AVIF_IMAGE_CONTENT_GAIN_MAP -#endif - })); + return fuzztest::Map( + AddGainMapOptionsToDecoder, ArbitraryBaseAvifDecoder(), + fuzztest::ElementOf( + {AVIF_IMAGE_CONTENT_COLOR_AND_ALPHA, + AVIF_IMAGE_CONTENT_COLOR_AND_ALPHA | AVIF_IMAGE_CONTENT_GAIN_MAP})); } // Generator for an arbitrary DecoderPtr. inline auto ArbitraryAvifDecoder() { return ArbitraryAvifDecoderWithGainMapOptions(); } -#else -// Generator for an arbitrary DecoderPtr. -inline auto ArbitraryAvifDecoder() { return ArbitraryBaseAvifDecoder(); } -#endif // AVIF_ENABLE_GAIN_MAP //------------------------------------------------------------------------------ diff --git a/tests/gtest/avifincrtest_helpers.cc b/tests/gtest/avifincrtest_helpers.cc index 2a766bd7bf..371133d1ab 100644 --- a/tests/gtest/avifincrtest_helpers.cc +++ b/tests/gtest/avifincrtest_helpers.cc @@ -65,7 +65,6 @@ void ComparePartialYuva(const avifImage& image1, const avifImage& image2, } } -#if defined(AVIF_ENABLE_GAIN_MAP) if (image1.gainMap != nullptr && image1.gainMap->image != nullptr && image2.gainMap != nullptr && image2.gainMap->image != nullptr) { const uint32_t gain_map_row_count = (uint32_t)roundf( @@ -73,7 +72,6 @@ void ComparePartialYuva(const avifImage& image1, const avifImage& image2, ComparePartialYuva(*image1.gainMap->image, *image2.gainMap->image, gain_map_row_count); } -#endif } // Returns the expected number of decoded rows when available_byte_count out of @@ -364,13 +362,9 @@ avifResult DecodeIncrementally(const avifRWData& encoded_avif, previously_decoded_row_count, decoded_row_count); AVIF_CHECKERR(false, AVIF_RESULT_INVALID_ARGUMENT); } - bool has_gain_map = false; -#if defined(AVIF_ENABLE_GAIN_MAP) - has_gain_map = (reference.gainMap != nullptr); -#endif const uint32_t min_decoded_row_count = GetMinDecodedRowCount( reference.height, cell_height, reference.alphaPlane != nullptr, - has_gain_map, data.available.size, data.full_size, + reference.gainMap != nullptr, data.available.size, data.full_size, enable_fine_incremental_check); if (decoded_row_count < min_decoded_row_count) { printf( diff --git a/tests/gtest/aviftest_helpers.cc b/tests/gtest/aviftest_helpers.cc index 47824ee7ae..851e7c63e1 100644 --- a/tests/gtest/aviftest_helpers.cc +++ b/tests/gtest/aviftest_helpers.cc @@ -510,9 +510,7 @@ AvifRwData Encode(const avifImage* image, int speed, int quality) { encoder->speed = speed; encoder->quality = quality; encoder->qualityAlpha = quality; -#if defined(AVIF_ENABLE_GAIN_MAP) encoder->qualityGainMap = quality; -#endif testutil::AvifRwData bytes; if (avifEncoderWrite(encoder.get(), image, &bytes) != AVIF_RESULT_OK) { return {};