Fix layered image decoding with alpha
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ea61f7b..a94d870 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@
 * Use AOM_TUNE_IQ for layered image inter-frame encoding.
 * Update aom.cmd/LocalAom.cmake: v3.13.3
 * Update LocalAvm.cmake: research-v14.0.0
+* Fix decoding layered image with multiple scaled alpha layers
 
 ## [1.4.1] - 2026-03-20
 
diff --git a/src/codec_aom.c b/src/codec_aom.c
index c918ae8..92a348c 100644
--- a/src/codec_aom.c
+++ b/src/codec_aom.c
@@ -224,13 +224,6 @@
             yuvFormat = AVIF_PIXEL_FORMAT_YUV400;
         }
 
-        if (image->width && image->height) {
-            if ((image->width != codec->internal->image->d_w) || (image->height != codec->internal->image->d_h) ||
-                (image->depth != codec->internal->image->bit_depth) || (image->yuvFormat != yuvFormat)) {
-                // Throw it all out
-                avifImageFreePlanes(image, AVIF_PLANES_ALL);
-            }
-        }
         image->width = codec->internal->image->d_w;
         image->height = codec->internal->image->d_h;
         image->depth = codec->internal->image->bit_depth;
@@ -252,15 +245,8 @@
         }
         image->imageOwnsYUVPlanes = AVIF_FALSE;
     } else {
-        // Alpha plane - ensure image is correct size, fill color
+        // Alpha plane - set image to correct size, fill alpha
 
-        if (image->width && image->height) {
-            if ((image->width != codec->internal->image->d_w) || (image->height != codec->internal->image->d_h) ||
-                (image->depth != codec->internal->image->bit_depth)) {
-                // Alpha plane doesn't match previous alpha plane decode, bail out
-                return AVIF_FALSE;
-            }
-        }
         image->width = codec->internal->image->d_w;
         image->height = codec->internal->image->d_h;
         image->depth = codec->internal->image->bit_depth;
diff --git a/src/codec_avm.c b/src/codec_avm.c
index e08ffc9..2328d6e 100644
--- a/src/codec_avm.c
+++ b/src/codec_avm.c
@@ -142,13 +142,6 @@
             yuvFormat = AVIF_PIXEL_FORMAT_YUV400;
         }
 
-        if (image->width && image->height) {
-            if ((image->width != codec->internal->image->d_w) || (image->height != codec->internal->image->d_h) ||
-                (image->depth != codec->internal->image->bit_depth) || (image->yuvFormat != yuvFormat)) {
-                // Throw it all out
-                avifImageFreePlanes(image, AVIF_PLANES_ALL);
-            }
-        }
         image->width = codec->internal->image->d_w;
         image->height = codec->internal->image->d_h;
         image->depth = codec->internal->image->bit_depth;
@@ -203,15 +196,8 @@
             image->imageOwnsYUVPlanes = AVIF_FALSE;
         }
     } else {
-        // Alpha plane - ensure image is correct size, fill color
+        // Alpha plane - set image to correct size, fill alpha
 
-        if (image->width && image->height) {
-            if ((image->width != codec->internal->image->d_w) || (image->height != codec->internal->image->d_h) ||
-                (image->depth != codec->internal->image->bit_depth)) {
-                // Alpha plane doesn't match previous alpha plane decode, bail out
-                return AVIF_FALSE;
-            }
-        }
         image->width = codec->internal->image->d_w;
         image->height = codec->internal->image->d_h;
         image->depth = codec->internal->image->bit_depth;
diff --git a/src/codec_dav1d.c b/src/codec_dav1d.c
index 666dcef..3f83c35 100644
--- a/src/codec_dav1d.c
+++ b/src/codec_dav1d.c
@@ -189,13 +189,6 @@
                 break;
         }
 
-        if (image->width && image->height) {
-            if ((image->width != (uint32_t)dav1dImage->p.w) || (image->height != (uint32_t)dav1dImage->p.h) ||
-                (image->depth != (uint32_t)dav1dImage->p.bpc) || (image->yuvFormat != yuvFormat)) {
-                // Throw it all out
-                avifImageFreePlanes(image, AVIF_PLANES_ALL);
-            }
-        }
         image->width = dav1dImage->p.w;
         image->height = dav1dImage->p.h;
         image->depth = dav1dImage->p.bpc;
@@ -217,15 +210,8 @@
         }
         image->imageOwnsYUVPlanes = AVIF_FALSE;
     } else {
-        // Alpha plane - ensure image is correct size, fill color
+        // Alpha plane - set image to correct size, fill alpha
 
-        if (image->width && image->height) {
-            if ((image->width != (uint32_t)dav1dImage->p.w) || (image->height != (uint32_t)dav1dImage->p.h) ||
-                (image->depth != (uint32_t)dav1dImage->p.bpc)) {
-                // Alpha plane doesn't match previous alpha plane decode, bail out
-                return AVIF_FALSE;
-            }
-        }
         image->width = dav1dImage->p.w;
         image->height = dav1dImage->p.h;
         image->depth = dav1dImage->p.bpc;
diff --git a/src/codec_libgav1.c b/src/codec_libgav1.c
index 43cb81f..7d07adf 100644
--- a/src/codec_libgav1.c
+++ b/src/codec_libgav1.c
@@ -96,14 +96,6 @@
                 break;
         }
 
-        if (image->width && image->height) {
-            if ((image->width != (uint32_t)gav1Image->displayed_width[0]) ||
-                (image->height != (uint32_t)gav1Image->displayed_height[0]) || (image->depth != (uint32_t)gav1Image->bitdepth) ||
-                (image->yuvFormat != yuvFormat)) {
-                // Throw it all out
-                avifImageFreePlanes(image, AVIF_PLANES_ALL);
-            }
-        }
         image->width = gav1Image->displayed_width[0];
         image->height = gav1Image->displayed_height[0];
         image->depth = gav1Image->bitdepth;
@@ -125,15 +117,8 @@
         }
         image->imageOwnsYUVPlanes = AVIF_FALSE;
     } else {
-        // Alpha plane - ensure image is correct size, fill color
+        // Alpha plane - set image to correct size, fill alpha
 
-        if (image->width && image->height) {
-            if ((image->width != (uint32_t)gav1Image->displayed_width[0]) ||
-                (image->height != (uint32_t)gav1Image->displayed_height[0]) || (image->depth != (uint32_t)gav1Image->bitdepth)) {
-                // Alpha plane doesn't match previous alpha plane decode, bail out
-                return AVIF_FALSE;
-            }
-        }
         image->width = gav1Image->displayed_width[0];
         image->height = gav1Image->displayed_height[0];
         image->depth = gav1Image->bitdepth;
diff --git a/tests/gtest/avifprogressivetest.cc b/tests/gtest/avifprogressivetest.cc
index d9e211a..3071b56 100644
--- a/tests/gtest/avifprogressivetest.cc
+++ b/tests/gtest/avifprogressivetest.cc
@@ -34,26 +34,31 @@
   }
 
   void TestDecode(uint8_t* data, size_t size, uint32_t expect_width,
-                  uint32_t expect_height) {
+                  uint32_t expect_height, bool expect_alpha = false) {
     ASSERT_EQ(avifDecoderSetIOMemory(decoder_.get(), data, size),
               AVIF_RESULT_OK);
     ASSERT_EQ(avifDecoderParse(decoder_.get()), AVIF_RESULT_OK);
     ASSERT_EQ(decoder_->progressiveState, AVIF_PROGRESSIVE_STATE_ACTIVE);
     ASSERT_EQ(static_cast<uint32_t>(decoder_->imageCount),
               encoder_->extraLayerCount + 1);
+    EXPECT_EQ(decoder_->alphaPresent, expect_alpha);
 
     for (uint32_t layer = 0; layer < encoder_->extraLayerCount + 1; ++layer) {
       ASSERT_EQ(avifDecoderNextImage(decoder_.get()), AVIF_RESULT_OK);
       // libavif scales frame automatically.
       ASSERT_EQ(decoder_->image->width, expect_width);
       ASSERT_EQ(decoder_->image->height, expect_height);
+      if (expect_alpha) {
+        ASSERT_NE(decoder_->image->alphaPlane, nullptr);
+      }
       // TODO(wtc): Check avifDecoderNthImageMaxExtent().
     }
   }
 
-  void TestDecode(uint32_t expect_width, uint32_t expect_height) {
+  void TestDecode(uint32_t expect_width, uint32_t expect_height,
+                  bool expect_alpha = false) {
     TestDecode(encoded_avif_.data, encoded_avif_.size, expect_width,
-               expect_height);
+               expect_height, expect_alpha);
 
     // TODO(wtc): Check decoder_->image and image_ are similar, and better
     // quality layer is more similar.
@@ -147,6 +152,41 @@
   TestDecode(kImageSize, kImageSize);
 }
 
+TEST_F(ProgressiveTest, DimensionChangeWithAlpha) {
+  if (avifLibYUVVersion() == 0) {
+    GTEST_SKIP() << "libyuv not available, skip test.";
+  }
+
+  const auto image =
+      testutil::CreateImage(kImageSize, kImageSize, 8, AVIF_PIXEL_FORMAT_YUV444,
+                            AVIF_PLANES_ALL, AVIF_RANGE_FULL);
+  ASSERT_NE(image, nullptr);
+  testutil::FillImageGradient(image.get());
+
+  encoder_->extraLayerCount = 2;
+  encoder_->quality = 100;
+  encoder_->scalingMode = {{1, 2}, {1, 2}};
+
+  ASSERT_EQ(avifEncoderAddImage(encoder_.get(), image.get(), 1,
+                                AVIF_ADD_IMAGE_FLAG_NONE),
+            AVIF_RESULT_OK);
+
+  // Encode the scaled image twice to verify frame buffer reallocation
+  // behavior during decode
+  ASSERT_EQ(avifEncoderAddImage(encoder_.get(), image.get(), 1,
+                                AVIF_ADD_IMAGE_FLAG_NONE),
+            AVIF_RESULT_OK);
+
+  encoder_->scalingMode = {{1, 1}, {1, 1}};
+  ASSERT_EQ(avifEncoderAddImage(encoder_.get(), image.get(), 1,
+                                AVIF_ADD_IMAGE_FLAG_NONE),
+            AVIF_RESULT_OK);
+
+  ASSERT_EQ(avifEncoderFinish(encoder_.get(), &encoded_avif_), AVIF_RESULT_OK);
+
+  TestDecode(kImageSize, kImageSize, /*expect_alpha=*/true);
+}
+
 TEST_F(ProgressiveTest, LayeredGrid) {
   encoder_->extraLayerCount = 1;
   encoder_->quality = 21;