Explicitly handle gainmaps where the base and alt headrooms are equal. (#1876)

diff --git a/src/gainmap.c b/src/gainmap.c
index 44ba129..e1c84ba 100644
--- a/src/gainmap.c
+++ b/src/gainmap.c
@@ -77,6 +77,11 @@
 {
     const float baseHdrHeadroom = (float)metadata->baseHdrHeadroom;
     const float alternateHdrHeadroom = (float)metadata->alternateHdrHeadroom;
+    if (baseHdrHeadroom == alternateHdrHeadroom) {
+        // Do not apply the gain map if the HDR headroom is the same.
+        // This case is not handled in the specification and does not make practical sense.
+        return 0.0f;
+    }
     float w = AVIF_CLAMP((hdrHeadroom - baseHdrHeadroom) / (alternateHdrHeadroom - baseHdrHeadroom), 0.0f, 1.0f);
     if (metadata->backwardDirection) {
         w *= -1.0f;
diff --git a/tests/gtest/avifgainmaptest.cc b/tests/gtest/avifgainmaptest.cc
index b938085..6d63aa6 100644
--- a/tests/gtest/avifgainmaptest.cc
+++ b/tests/gtest/avifgainmaptest.cc
@@ -1217,6 +1217,44 @@
             /*out_rgb_format=*/AVIF_RGB_FORMAT_RGB,
             /*reference=*/"", /*min_psnr=*/0.0f, /*max_psnr=*/0.0f)));
 
+TEST(ToneMapTest, ToneMapImageSameHeadroom) {
+  const std::string path =
+      std::string(data_path) + "seine_sdr_gainmap_srgb.avif";
+  ImagePtr image(avifImageCreateEmpty());
+  ASSERT_NE(image, nullptr);
+  DecoderPtr decoder(avifDecoderCreate());
+  ASSERT_NE(decoder, nullptr);
+  decoder->enableDecodingGainMap = true;
+  decoder->enableParsingGainMapMetadata = true;
+  avifResult result =
+      avifDecoderReadFile(decoder.get(), image.get(), path.c_str());
+  ASSERT_EQ(result, AVIF_RESULT_OK)
+      << avifResultToString(result) << " " << decoder->diag.error;
+
+  ASSERT_NE(image->gainMap, nullptr);
+  ASSERT_NE(image->gainMap->image, nullptr);
+
+  // Force the alternate and base HDR headroom to the same value.
+  image->gainMap->metadata.baseHdrHeadroomN =
+      image->gainMap->metadata.alternateHdrHeadroomN;
+  image->gainMap->metadata.baseHdrHeadroomD =
+      image->gainMap->metadata.alternateHdrHeadroomD;
+  const float headroom = static_cast<float>(
+      static_cast<float>(image->gainMap->metadata.baseHdrHeadroomN) /
+      image->gainMap->metadata.baseHdrHeadroomD);
+
+  // Check that when the two headrooms are the same, the gain map is not applied
+  // whatever the target headroom is.
+  for (const float tonemap_to : {headroom, headroom - 0.5f, headroom + 0.5f}) {
+    ToneMapImageAndCompareToReference(
+        image.get(), *image->gainMap, /*hdr_headroom=*/tonemap_to,
+        /*out_depth=*/image->depth,
+        /*out_transfer_characteristics=*/image->transferCharacteristics,
+        AVIF_RGB_FORMAT_RGB, /*reference_image=*/image.get(),
+        /*min_psnr=*/60, /*max_psnr=*/100);
+  }
+}
+
 class CreateGainMapTest : public testing::TestWithParam<std::tuple<
                               /*downscaling=*/int, /*gain_map_depth=*/int,
                               /*gain_map_format=*/avifPixelFormat,