From 981b9a277e2d0c80382ae06a7ad4349ae1ca78bd Mon Sep 17 00:00:00 2001 From: maryla-uc Date: Mon, 16 Sep 2024 11:26:13 +0200 Subject: [PATCH] Add tests decoding files using 'idat' instead of 'mdat' (#2433) --- tests/CMakeLists.txt | 2 +- tests/data/README.md | 42 +++++++++++++ tests/data/draw_points_idat.avif | Bin 0 -> 498 bytes tests/data/draw_points_idat_metasize0.avif | Bin 0 -> 498 bytes tests/data/draw_points_idat_progressive.avif | Bin 0 -> 600 bytes ...raw_points_idat_progressive_metasize0.avif | Bin 0 -> 600 bytes tests/gtest/avifdecodetest.cc | 28 +++++++++ tests/gtest/avifprogressivetest.cc | 59 +++++++++++++++++- 8 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 tests/data/draw_points_idat.avif create mode 100644 tests/data/draw_points_idat_metasize0.avif create mode 100644 tests/data/draw_points_idat_progressive.avif create mode 100644 tests/data/draw_points_idat_progressive_metasize0.avif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index da1b0f96cb..0c67dbdaac 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -148,7 +148,7 @@ if(AVIF_ENABLE_GTEST) add_avif_gtest(avifopaquetest) add_avif_gtest_with_data(avifpng16bittest) - add_avif_gtest(avifprogressivetest) + add_avif_gtest_with_data(avifprogressivetest) add_avif_gtest(avifrangetest) add_avif_gtest_with_data(avifreadimagetest) add_avif_internal_gtest(avifrgbtest) diff --git a/tests/data/README.md b/tests/data/README.md index 73fa12ff75..d424f072a6 100644 --- a/tests/data/README.md +++ b/tests/data/README.md @@ -712,6 +712,48 @@ To export more images from sources/colors.psd: - For the wide color gamut version, choose Edit > Assign Profile... and set the color space to Rec.ITU-R BT.2020-1 +## Idat + +These files use the 'idat' box instead of the 'mdat' box to store data. + +### File [draw_points_idat.avif](draw_points_idat.avif) + +![](draw_points_idat.avif) + +License: [same as libavif](https://github.com/AOMediaCodec/libavif/blob/main/LICENSE) + +Source: generated with a modified libavif at https://github.com/maryla-uc/libavif/tree/idat +by running `./avifenc -q 100 ../tests/data/draw_points.png ../tests/data/draw_points_idat.avif`  + +### File [draw_points_idat_metasize0.avif](draw_points_idat_metasize0.avif) + +![](draw_points_idat_metasize0.avif) + +License: [same as libavif](https://github.com/AOMediaCodec/libavif/blob/main/LICENSE) + +Source: generated with a modified libavif at https://github.com/maryla-uc/libavif/tree/idat +after uncommenting the line under `// uncomment to make meta size zero` and running +`./avifenc -q 100 ../tests/data/draw_points.png ../tests/data/draw_points_idat_metasize0.avif`  + +### File [draw_points_idat_progressive.avif](draw_points_idat_progressive.avif) + +![](draw_points_idat_progressive.avif) + +License: [same as libavif](https://github.com/AOMediaCodec/libavif/blob/main/LICENSE) + +Source: generated with a modified libavif at https://github.com/maryla-uc/libavif/tree/idat +by running `./avifenc -q 100 --progressive ../tests/data/draw_points.png ../tests/data/draw_points_idat_progressive.avif`  + +### File [draw_points_idat_progressive_metasize0.avif](draw_points_idat_progressive_metasize0.avif) + +![](draw_points_idat_progressive_metasize0.avif) + +License: [same as libavif](https://github.com/AOMediaCodec/libavif/blob/main/LICENSE) + +Source: generated with a modified libavif at https://github.com/maryla-uc/libavif/tree/idat +after uncommenting the line under `// uncomment to make meta size zero` and running +`./avifenc -q 100 --progressive ../tests/data/draw_points.png ../tests/data/draw_points_idat_progressive_metasize0.avif`  + ## Animated Images ### File [colors-animated-8bpc.avif](colors-animated-8bpc.avif) diff --git a/tests/data/draw_points_idat.avif b/tests/data/draw_points_idat.avif new file mode 100644 index 0000000000000000000000000000000000000000..877e65413bcdb29441838a132f9fc3b7c4437192 GIT binary patch literal 498 zcmYLFu}%U(5S_zAPa%XT8YP54Vr9iqk*fqOOpJw**l&(Im}HmR+#LuVMq}YW*jid@ zV_{-rVrOY#426GSXW{H#klD=6%zJNkb{7CDems$Egg%g|DA2bBGXJ<~Hvx=y;l)gG zWYvC`he-+`(T(T%Jmw_ELKg<@HROS-k^_Jg7_{g-@-6Z`jU+Xd8fzgA^fibBC{p36 zMD?&y&29%g(9;(T(TZtu*=I^w#L!Dl0LZc7nE%gxK^aO?+@f>?iUo|Mr&`FWY5S@z`JxvHfqi6^r0V}Iqs&JJ_ECjI-gZ*;3O9pmx%iZOxizpWU2U|-^ zZ7c*E!GB;OlEQyrXW{G~F>}nmH*aQcW)}b|ems?Igg%fd6zJOmnSa`}n@SU2%oLJU z`&}L;6hNXIFZcp;5@VqQgU%ZAz*Xc3AO!|}pnZq%Kr2a1At{x&dJUBk8FYvMPCoJTGyA zN?5Thiy+HJcKfnI3}DL*csOwRgtjqZbw(0hHYqoj#ZXek4I156WEc({A-$eHT8@jZ zbfRe#dm?hE205~D>afN7Wt2kSgIejqOe1w=LdrDKH*2IEW0%F7u#w&^eBE!?GxVzO t7yb3~`B{Zjt3hf$e~9%GC4Npmem|eSd!6ftz5SOr@qAnE%pb?u*&lh_Vz&SQ literal 0 HcmV?d00001 diff --git a/tests/data/draw_points_idat_progressive.avif b/tests/data/draw_points_idat_progressive.avif new file mode 100644 index 0000000000000000000000000000000000000000..fe8b23db327e95a6ace804801b59c5fef7e92696 GIT binary patch literal 600 zcmYjNze~eV5Wdt_(pu_|cCjd=UEIV}(UQrw4x;Fy2;!iRn6?Km%_EJaT_nZ9#a&#T z-4q=Jad#5*A5i}TUEI9)YO5FS-QD-yUG5G5jB3yktc6t|k=Dhk=_0Fcl*|%9r06;U zlN?E|e#rfv3n0)A`hMT01O~1OGeIYg#(lk z8)__7m8HOu<+2ZJ&6yRCdup0LhG@x@xTrIknML2}bpS}Qqc$JR@s7e5lyQ&3_Q+~1C&AJ)RcNCpge+NsC4-e!p$H3sCWZY+d_du{SFg_(XZv%t8-5Wk>Zy6{(EwUI3ZEa7`aeK}&&!wM5BBeL A6#xJL literal 0 HcmV?d00001 diff --git a/tests/data/draw_points_idat_progressive_metasize0.avif b/tests/data/draw_points_idat_progressive_metasize0.avif new file mode 100644 index 0000000000000000000000000000000000000000..2eb8614edef2a7d898c4894daa70c6e64486f05d GIT binary patch literal 600 zcmYjN&o2W}5T318){oSW_CiROiLhQwFWYU?USt~w7k6=W zb|V}l;_f8jAHaXW#m&sCVm9->neUrR19YMjuPIkD|0*unWxjUL+XF zCdvmgY=-~}-KZ0HFs(51bz;!Dh%#_FSO!RdK_4T)IQas(M?R#LHczS6wloj0gjmsI z>8?>qJZ|TEM196C1~Smo{3#@}Qjn@FxN;OjuYChRTGSfycaAqyp`waARBk|+#j4_Y z*e1yP$OjcRkclqSGzt1e-7dB)iU2ZhAj66)8#GN4x?`dSgiWd5j4S9Z+TF%qFO0F0 zr%8$&)WVA6EALPrOOA`Ka;nX0Szpvxm4NJP^?^^!7u>fVj2Mo4a3)XZx~X!Q*zhXY+NM!~yG9TrsWrcy=-iQx5vP)x literal 0 HcmV?d00001 diff --git a/tests/gtest/avifdecodetest.cc b/tests/gtest/avifdecodetest.cc index b16f0d9890..e4b5a96d83 100644 --- a/tests/gtest/avifdecodetest.cc +++ b/tests/gtest/avifdecodetest.cc @@ -41,6 +41,34 @@ TEST(AvifDecodeTest, ParseEmptyData) { ASSERT_EQ(avifDecoderParse(decoder.get()), AVIF_RESULT_INVALID_FTYP); } +TEST(AvifDecodeTest, Idat) { + if (!testutil::Av1DecoderAvailable()) { + GTEST_SKIP() << "AV1 Codec unavailable, skip test."; + } + + const ImagePtr original = testutil::ReadImage(data_path, "draw_points.png"); + + for (const std::string file_name : + {"draw_points_idat.avif", "draw_points_idat_metasize0.avif", + "draw_points_idat_progressive.avif", + "draw_points_idat_progressive_metasize0.avif"}) { + SCOPED_TRACE(file_name); + DecoderPtr decoder(avifDecoderCreate()); + ASSERT_NE(decoder, nullptr); + ASSERT_EQ(avifDecoderSetIOFile( + decoder.get(), (std::string(data_path) + file_name).c_str()), + AVIF_RESULT_OK); + ASSERT_EQ(avifDecoderParse(decoder.get()), AVIF_RESULT_OK); + EXPECT_EQ(decoder->alphaPresent, AVIF_TRUE); + EXPECT_EQ(decoder->imageSequenceTrackPresent, AVIF_FALSE); + ASSERT_EQ(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK); + EXPECT_NE(decoder->image->alphaPlane, nullptr); + EXPECT_GT(decoder->image->alphaRowBytes, 0u); + + EXPECT_EQ(testutil::GetPsnr(*original, *decoder->image), 99.0); + } +} + // From https://crbug.com/334281983. TEST(AvifDecodeTest, PeekCompatibleFileTypeBad1) { constexpr uint8_t kData[] = {0x00, 0x00, 0x00, 0x1c, 0x66, diff --git a/tests/gtest/avifprogressivetest.cc b/tests/gtest/avifprogressivetest.cc index 4cb92daf62..ca251870ca 100644 --- a/tests/gtest/avifprogressivetest.cc +++ b/tests/gtest/avifprogressivetest.cc @@ -8,6 +8,9 @@ namespace avif { namespace { +// Used to pass the data folder path to the GoogleTest suites. +const char* data_path = nullptr; + class ProgressiveTest : public testing::Test { protected: static constexpr uint32_t kImageSize = 256; @@ -30,9 +33,9 @@ class ProgressiveTest : public testing::Test { testutil::FillImageGradient(image_.get()); } - void TestDecode(uint32_t expect_width, uint32_t expect_height) { - ASSERT_EQ(avifDecoderSetIOMemory(decoder_.get(), encoded_avif_.data, - encoded_avif_.size), + void TestDecode(uint8_t* data, size_t size, uint32_t expect_width, + uint32_t expect_height) { + 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); @@ -46,6 +49,11 @@ class ProgressiveTest : public testing::Test { ASSERT_EQ(decoder_->image->height, expect_height); // TODO(wtc): Check avifDecoderNthImageMaxExtent(). } + } + + void TestDecode(uint32_t expect_width, uint32_t expect_height) { + TestDecode(encoded_avif_.data, encoded_avif_.size, expect_width, + expect_height); // TODO(wtc): Check decoder_->image and image_ are similar, and better // quality layer is more similar. @@ -169,5 +177,50 @@ TEST_F(ProgressiveTest, TooFewLayers) { AVIF_RESULT_INVALID_ARGUMENT); } +// Test progressive decoding with files that use 'idat' (inside the 'meta') box +// instead of 'mdat' to store the image data. Note that for now (as of v1.1.1) +// the decoder waits to have the full meta box available before parsing it, so +// incremental decoding is not really possible and progressive decoding makes +// little sense. But this checks that the files are still processed correctly. +TEST(DecodeProgressiveTest, DecodeIdat) { + const ImagePtr original = testutil::ReadImage(data_path, "draw_points.png"); + + for (const std::string file_name : + {"draw_points_idat_progressive.avif", + "draw_points_idat_progressive_metasize0.avif"}) { + SCOPED_TRACE(file_name); + const int expected_layer_count = 2; + + DecoderPtr decoder(avifDecoderCreate()); + decoder->allowProgressive = true; + ASSERT_EQ(avifDecoderSetIOFile( + decoder.get(), (std::string(data_path) + file_name).c_str()), + AVIF_RESULT_OK); + ASSERT_EQ(avifDecoderParse(decoder.get()), AVIF_RESULT_OK); + ASSERT_EQ(decoder->progressiveState, AVIF_PROGRESSIVE_STATE_ACTIVE); + ASSERT_EQ(static_cast(decoder->imageCount), expected_layer_count); + + for (uint32_t layer = 0; layer < expected_layer_count; ++layer) { + ASSERT_EQ(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK); + ASSERT_EQ(decoder->image->width, original->width); + ASSERT_EQ(decoder->image->height, original->height); + } + ASSERT_EQ(avifDecoderNextImage(decoder.get()), + AVIF_RESULT_NO_IMAGES_REMAINING); + } +} + } // namespace } // namespace avif + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + if (argc != 2) { + std::cerr << "There must be exactly one argument containing the path to " + "the test data folder" + << std::endl; + return 1; + } + avif::data_path = argv[1]; + return RUN_ALL_TESTS(); +}