diff options
Diffstat (limited to 'third_party/jpeg-xl/lib/jxl/jxl_test.cc')
-rw-r--r-- | third_party/jpeg-xl/lib/jxl/jxl_test.cc | 326 |
1 files changed, 223 insertions, 103 deletions
diff --git a/third_party/jpeg-xl/lib/jxl/jxl_test.cc b/third_party/jpeg-xl/lib/jxl/jxl_test.cc index a91dbd0672..b0933d5d50 100644 --- a/third_party/jpeg-xl/lib/jxl/jxl_test.cc +++ b/third_party/jpeg-xl/lib/jxl/jxl_test.cc @@ -33,7 +33,6 @@ #include "lib/jxl/codec_in_out.h" #include "lib/jxl/color_encoding_internal.h" #include "lib/jxl/common.h" // JXL_HIGH_PRECISION -#include "lib/jxl/enc_butteraugli_comparator.h" #include "lib/jxl/enc_params.h" #include "lib/jxl/fake_parallel_runner_testonly.h" #include "lib/jxl/image.h" @@ -72,7 +71,7 @@ TEST(JxlTest, RoundtripSinglePixelWithAlpha) { TestImage t; t.SetDimensions(1, 1).SetChannels(4).AddFrame().ZeroFill(); PackedPixelFile ppf_out; - EXPECT_EQ(Roundtrip(t.ppf(), {}, {}, nullptr, &ppf_out), 59); + EXPECT_EQ(Roundtrip(t.ppf(), {}, {}, nullptr, &ppf_out), 58); } // Changing serialized signature causes Decode to fail. @@ -87,7 +86,7 @@ TEST(JxlTest, RoundtripMarker) { compressed[i] ^= 0xFF; PackedPixelFile ppf_out; EXPECT_FALSE(extras::DecodeImageJXL(compressed.data(), compressed.size(), - {}, /*decodec_bytes=*/nullptr, + {}, /* decoded_bytes */ nullptr, &ppf_out)); } } @@ -121,7 +120,7 @@ TEST(JxlTest, RoundtripSmallD1) { { PackedPixelFile ppf_out; EXPECT_NEAR(Roundtrip(t.ppf(), {}, {}, pool, &ppf_out), 916, 40); - EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(0.888)); + EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.888); } // With a lower intensity target than the default, the bitrate should be @@ -131,7 +130,7 @@ TEST(JxlTest, RoundtripSmallD1) { { PackedPixelFile ppf_out; EXPECT_NEAR(Roundtrip(t.ppf(), {}, {}, pool, &ppf_out), 745, 20); - EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(1.3)); + EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.3); EXPECT_EQ(ppf_out.info.intensity_target, t.ppf().info.intensity_target); } } @@ -147,8 +146,8 @@ TEST(JxlTest, RoundtripResample2) { cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 3); // kFalcon PackedPixelFile ppf_out; - EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 18500, 200); - EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(90)); + EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 17300, 500); + EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 90); } TEST(JxlTest, RoundtripResample2Slow) { @@ -165,7 +164,7 @@ TEST(JxlTest, RoundtripResample2Slow) { PackedPixelFile ppf_out; EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 3888, 200); - EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(250)); + EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 250); } TEST(JxlTest, RoundtripResample2MT) { @@ -180,8 +179,8 @@ TEST(JxlTest, RoundtripResample2MT) { cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 3); // kFalcon PackedPixelFile ppf_out; - EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 223310, 2000); - EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(340)); + EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 203300, 2000); + EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 340); } // Roundtrip the image using a parallel runner that executes single-threaded but @@ -237,7 +236,7 @@ TEST(JxlTest, RoundtripResample4) { PackedPixelFile ppf_out; EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 5758, 100); - EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(22)); + EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 22); } TEST(JxlTest, RoundtripResample8) { @@ -252,7 +251,7 @@ TEST(JxlTest, RoundtripResample8) { PackedPixelFile ppf_out; EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 2036, 50); - EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(50)); + EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 50); } TEST(JxlTest, RoundtripUnalignedD2) { @@ -270,7 +269,7 @@ TEST(JxlTest, RoundtripUnalignedD2) { PackedPixelFile ppf_out; EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 506, 30); - EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(1.72)); + EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.72); } TEST(JxlTest, RoundtripMultiGroup) { @@ -289,8 +288,8 @@ TEST(JxlTest, RoundtripMultiGroup) { PackedPixelFile ppf_out; EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), expected_size, 700); - EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), - IsSlightlyBelow(expected_distance)); + EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), + expected_distance); }; auto run_kitten = std::async(std::launch::async, test, SpeedTier::kKitten, @@ -339,10 +338,11 @@ TEST(JxlTest, RoundtripRGBToGrayscale) { ASSERT_TRUE(io.frames[0].TransformTo(srgb_gamma, *JxlGetDefaultCms())); io.metadata.m.color_encoding = io2.Main().c_current(); io.Main().OverrideProfile(io2.Main().c_current()); - EXPECT_THAT(ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(), - *JxlGetDefaultCms(), - /*distmap=*/nullptr, &pool), - IsSlightlyBelow(1.36)); + EXPECT_SLIGHTLY_BELOW( + ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(), + *JxlGetDefaultCms(), + /*distmap=*/nullptr, &pool), + 1.4); } TEST(JxlTest, RoundtripLargeFast) { @@ -355,8 +355,57 @@ TEST(JxlTest, RoundtripLargeFast) { cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 7); // kSquirrel PackedPixelFile ppf_out; - EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 492867, 5000); - EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(78)); + EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 503000, 12000); + EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 78); +} + +TEST(JxlTest, JXL_X86_64_TEST(RoundtripLargeEmptyModular)) { + ThreadPoolForTests pool(8); + TestImage t; + t.SetDimensions(4096, 4096).SetDataType(JXL_TYPE_UINT8).SetChannels(4); + TestImage::Frame frame = t.AddFrame(); + frame.ZeroFill(); + for (size_t c = 0; c < 4; ++c) { + for (size_t y = 0; y < 1024; y += (c + 1)) { + for (size_t x = 0; x < 1024; x += ((y % 4) + 3)) { + frame.SetValue(y, x, c, 0.88); + } + } + } + + JXLCompressParams cparams; + cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 1); + cparams.AddOption(JXL_ENC_FRAME_SETTING_MODULAR, 1); + cparams.AddOption(JXL_ENC_FRAME_SETTING_RESPONSIVE, 1); + cparams.AddOption(JXL_ENC_FRAME_SETTING_DECODING_SPEED, 2); + + PackedPixelFile ppf_out; + EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 3474795, + 100000); + EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), +#if JXL_HIGH_PRECISION + 2050 +#else + 12100 +#endif + ); +} + +TEST(JxlTest, RoundtripOutputColorSpace) { + ThreadPoolForTests pool(8); + const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png"); + TestImage t; + t.DecodeFromBytes(orig).ClearMetadata(); + + JXLCompressParams cparams; + cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 7); // kSquirrel + + JXLDecompressParams dparams; + dparams.color_space = "RGB_D65_DCI_Rel_709"; + PackedPixelFile ppf_out; + EXPECT_NEAR(Roundtrip(t.ppf(), cparams, dparams, &pool, &ppf_out), 503000, + 12000); + EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 78); } TEST(JxlTest, RoundtripDotsForceEpf) { @@ -373,7 +422,7 @@ TEST(JxlTest, RoundtripDotsForceEpf) { PackedPixelFile ppf_out; EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 41355, 300); - EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(18)); + EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 18); } // Checks for differing size/distance in two consecutive runs of distance 2, @@ -453,7 +502,7 @@ TEST(JxlTest, RoundtripSmallNL) { PackedPixelFile ppf_out; EXPECT_NEAR(Roundtrip(t.ppf(), {}, {}, pool, &ppf_out), 916, 45); - EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(0.82)); + EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.82); } TEST(JxlTest, RoundtripNoGaborishNoAR) { @@ -469,7 +518,7 @@ TEST(JxlTest, RoundtripNoGaborishNoAR) { PackedPixelFile ppf_out; EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 41142, 400); - EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(1.8)); + EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.8); } TEST(JxlTest, RoundtripSmallNoGaborish) { @@ -487,7 +536,7 @@ TEST(JxlTest, RoundtripSmallNoGaborish) { PackedPixelFile ppf_out; EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 1006, 20); - EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(1.1)); + EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.1); } TEST(JxlTest, RoundtripSmallPatchesAlpha) { @@ -513,7 +562,7 @@ TEST(JxlTest, RoundtripSmallPatchesAlpha) { PackedPixelFile ppf_out; EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 597, 100); - EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(0.018f)); + EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.018f); } TEST(JxlTest, RoundtripSmallPatches) { @@ -538,17 +587,17 @@ TEST(JxlTest, RoundtripSmallPatches) { PackedPixelFile ppf_out; EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 486, 100); - EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(0.018f)); + EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.018f); } // TODO(szabadka) Add encoder and decoder API functions that accept frame // buffers in arbitrary unsigned and floating point formats, and then roundtrip // test the lossless codepath to make sure the exact binary representations // are preserved. -#if 0 +#if JXL_FALSE TEST(JxlTest, RoundtripImageBundleOriginalBits) { // Image does not matter, only io.metadata.m and io2.metadata.m are tested. - Image3F image(1, 1); + JXL_ASSIGN_OR_DIE(Image3F image, Image3F::Create(1, 1)); ZeroFillImage(&image); CodecInOut io; io.metadata.m.color_encoding = ColorEncoding::LinearSRGB(); @@ -639,10 +688,11 @@ TEST(JxlTest, RoundtripGrayscale) { EXPECT_TRUE(io2.Main().IsGray()); EXPECT_LE(compressed.size(), 7000u); - EXPECT_THAT(ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(), - *JxlGetDefaultCms(), - /*distmap=*/nullptr), - IsSlightlyBelow(1.6)); + EXPECT_SLIGHTLY_BELOW( + ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(), + *JxlGetDefaultCms(), + /*distmap=*/nullptr), + 1.6); } // Test with larger butteraugli distance and other settings enabled so @@ -658,10 +708,11 @@ TEST(JxlTest, RoundtripGrayscale) { EXPECT_TRUE(io2.Main().IsGray()); EXPECT_LE(compressed.size(), 1300u); - EXPECT_THAT(ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(), - *JxlGetDefaultCms(), - /*distmap=*/nullptr), - IsSlightlyBelow(6.7)); + EXPECT_SLIGHTLY_BELOW( + ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(), + *JxlGetDefaultCms(), + /*distmap=*/nullptr), + 6.7); } { @@ -678,10 +729,11 @@ TEST(JxlTest, RoundtripGrayscale) { EXPECT_FALSE(io2.Main().IsGray()); EXPECT_LE(compressed.size(), 7000u); - EXPECT_THAT(ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(), - *JxlGetDefaultCms(), - /*distmap=*/nullptr), - IsSlightlyBelow(1.6)); + EXPECT_SLIGHTLY_BELOW( + ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(), + *JxlGetDefaultCms(), + /*distmap=*/nullptr), + 1.6); } } @@ -706,7 +758,7 @@ TEST(JxlTest, RoundtripAlpha) { std::vector<uint8_t> compressed; EXPECT_TRUE(test::EncodeFile(cparams, &io, &compressed)); - EXPECT_LE(compressed.size(), 10077u); + EXPECT_LE(compressed.size(), 20000u); for (bool use_image_callback : {false, true}) { for (bool unpremul_alpha : {false, true}) { @@ -715,10 +767,11 @@ TEST(JxlTest, RoundtripAlpha) { dparams.use_image_callback = use_image_callback; dparams.unpremultiply_alpha = unpremul_alpha; EXPECT_TRUE(test::DecodeFile(dparams, Bytes(compressed), &io2)); - EXPECT_THAT(ButteraugliDistance(io.frames, io2.frames, - ButteraugliParams(), *JxlGetDefaultCms(), - /*distmap=*/nullptr), - IsSlightlyBelow(1.15)); + EXPECT_SLIGHTLY_BELOW( + ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(), + *JxlGetDefaultCms(), + /*distmap=*/nullptr), + 1.15); } } } @@ -781,7 +834,8 @@ bool UnpremultiplyAlpha(CodecInOut& io) { TEST(JxlTest, RoundtripAlphaPremultiplied) { const std::vector<uint8_t> orig = ReadTestData("external/wesaturate/500px/tmshre_riaphotographs_alpha.png"); - CodecInOut io, io_nopremul; + CodecInOut io; + CodecInOut io_nopremul; ASSERT_TRUE(SetFromBytes(Bytes(orig), &io)); ASSERT_TRUE(SetFromBytes(Bytes(orig), &io_nopremul)); @@ -803,7 +857,7 @@ TEST(JxlTest, RoundtripAlphaPremultiplied) { std::vector<uint8_t> compressed; EXPECT_TRUE(test::EncodeFile(cparams, &io, &compressed)); - EXPECT_LE(compressed.size(), 10000u); + EXPECT_LE(compressed.size(), 18000u); for (bool use_image_callback : {false, true}) { for (bool unpremul_alpha : {false, true}) { @@ -826,19 +880,19 @@ TEST(JxlTest, RoundtripAlphaPremultiplied) { EXPECT_EQ(unpremul_alpha, !io2.Main().AlphaIsPremultiplied()); if (!unpremul_alpha) { - EXPECT_THAT( + EXPECT_SLIGHTLY_BELOW( ButteraugliDistance(io.frames, io2.frames, ButteraugliParams(), *JxlGetDefaultCms(), /*distmap=*/nullptr), - IsSlightlyBelow(1.111)); + 1.111); EXPECT_TRUE(UnpremultiplyAlpha(io2)); EXPECT_FALSE(io2.Main().AlphaIsPremultiplied()); } - EXPECT_THAT( + EXPECT_SLIGHTLY_BELOW( ButteraugliDistance(io_nopremul.frames, io2.frames, ButteraugliParams(), *JxlGetDefaultCms(), /*distmap=*/nullptr), - IsSlightlyBelow(1.55)); + 1.0); } } } @@ -854,13 +908,14 @@ TEST(JxlTest, RoundtripAlphaResampling) { ASSERT_TRUE(t.ppf().info.alpha_bits > 0); JXLCompressParams cparams; + cparams.alpha_distance = 1.0; cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 5); // kHare cparams.AddOption(JXL_ENC_FRAME_SETTING_RESAMPLING, 2); cparams.AddOption(JXL_ENC_FRAME_SETTING_EXTRA_CHANNEL_RESAMPLING, 2); PackedPixelFile ppf_out; EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 13507, 130); - EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(5.2)); + EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 5.2); } TEST(JxlTest, RoundtripAlphaResamplingOnlyAlpha) { @@ -873,12 +928,13 @@ TEST(JxlTest, RoundtripAlphaResamplingOnlyAlpha) { ASSERT_TRUE(t.ppf().info.alpha_bits > 0); JXLCompressParams cparams; + cparams.alpha_distance = 1.0; cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 3); // kFalcon cparams.AddOption(JXL_ENC_FRAME_SETTING_EXTRA_CHANNEL_RESAMPLING, 2); PackedPixelFile ppf_out; - EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 33571, 400); - EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(1.49)); + EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 32000, 1000); + EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.52); } TEST(JxlTest, RoundtripAlphaNonMultipleOf8) { @@ -893,13 +949,14 @@ TEST(JxlTest, RoundtripAlphaNonMultipleOf8) { PackedPixelFile ppf_out; EXPECT_NEAR(Roundtrip(t.ppf(), {}, {}, pool, &ppf_out), 107, 10); - EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(0.95)); + EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.006); } TEST(JxlTest, RoundtripAlpha16) { ThreadPoolForTests pool(4); // The image is wider than 512 pixels to ensure multiple groups are tested. - size_t xsize = 1200, ysize = 160; + size_t xsize = 1200; + size_t ysize = 160; TestImage t; t.SetDimensions(xsize, ysize).SetChannels(4).SetAllBitDepths(16); TestImage::Frame frame = t.AddFrame(); @@ -923,12 +980,13 @@ TEST(JxlTest, RoundtripAlpha16) { JXLCompressParams cparams; cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 6); // kWombat cparams.distance = 0.5; + cparams.alpha_distance = 0.5; PackedPixelFile ppf_out; // TODO(szabadka) Investigate big size difference on i686 // This still keeps happening (2023-04-18). EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 3666, 120); - EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(0.65)); + EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.65); } namespace { @@ -990,8 +1048,8 @@ TEST(JxlTest, JXL_SLOW_TEST(RoundtripLossless8LightningGradient)) { PackedPixelFile ppf_out; // Lax comparison because different SIMD will cause different compression. - EXPECT_THAT(Roundtrip(t.ppf(), cparams, dparams, &pool, &ppf_out), - IsSlightlyBelow(286848u)); + EXPECT_SLIGHTLY_BELOW(Roundtrip(t.ppf(), cparams, dparams, &pool, &ppf_out), + 286848u); EXPECT_EQ(ComputeDistance2(t.ppf(), ppf_out), 0.0); } @@ -1035,7 +1093,8 @@ TEST(JxlTest, RoundtripLossless8Alpha) { TEST(JxlTest, RoundtripLossless16Alpha) { ThreadPool* pool = nullptr; - size_t xsize = 1200, ysize = 160; + size_t xsize = 1200; + size_t ysize = 160; TestImage t; t.SetDimensions(xsize, ysize).SetChannels(4).SetAllBitDepths(16); TestImage::Frame frame = t.AddFrame(); @@ -1062,7 +1121,7 @@ TEST(JxlTest, RoundtripLossless16Alpha) { PackedPixelFile ppf_out; // TODO(szabadka) Investigate big size difference on i686 - EXPECT_NEAR(Roundtrip(t.ppf(), cparams, dparams, pool, &ppf_out), 4884, 100); + EXPECT_NEAR(Roundtrip(t.ppf(), cparams, dparams, pool, &ppf_out), 4665, 100); EXPECT_EQ(ComputeDistance2(t.ppf(), ppf_out), 0.0); EXPECT_EQ(ppf_out.info.alpha_bits, 16); EXPECT_TRUE(test::SameAlpha(t.ppf(), ppf_out)); @@ -1070,7 +1129,8 @@ TEST(JxlTest, RoundtripLossless16Alpha) { TEST(JxlTest, RoundtripLossless16AlphaNotMisdetectedAs8Bit) { ThreadPool* pool = nullptr; - size_t xsize = 128, ysize = 128; + size_t xsize = 128; + size_t ysize = 128; TestImage t; t.SetDimensions(xsize, ysize).SetChannels(4).SetAllBitDepths(16); TestImage::Frame frame = t.AddFrame(); @@ -1098,7 +1158,7 @@ TEST(JxlTest, RoundtripLossless16AlphaNotMisdetectedAs8Bit) { dparams.accepted_formats.push_back(t.ppf().frames[0].color.format); PackedPixelFile ppf_out; - EXPECT_NEAR(Roundtrip(t.ppf(), cparams, dparams, pool, &ppf_out), 591, 50); + EXPECT_NEAR(Roundtrip(t.ppf(), cparams, dparams, pool, &ppf_out), 280, 50); EXPECT_EQ(ComputeDistance2(t.ppf(), ppf_out), 0.0); EXPECT_EQ(ppf_out.info.bits_per_sample, 16); EXPECT_EQ(ppf_out.info.alpha_bits, 16); @@ -1123,7 +1183,7 @@ TEST(JxlTest, RoundtripDots) { PackedPixelFile ppf_out; EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 280333, 4000); - EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(0.35)); + EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 0.35); } TEST(JxlTest, RoundtripNoise) { @@ -1143,7 +1203,7 @@ TEST(JxlTest, RoundtripNoise) { PackedPixelFile ppf_out; EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, pool, &ppf_out), 41009, 750); - EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(1.42)); + EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.42); } TEST(JxlTest, RoundtripLossless8Gray) { @@ -1182,17 +1242,17 @@ TEST(JxlTest, RoundtripAnimation) { dparams.accepted_formats.push_back(t.ppf().frames[0].color.format); PackedPixelFile ppf_out; - EXPECT_THAT(Roundtrip(t.ppf(), {}, dparams, pool, &ppf_out), - IsSlightlyBelow(2888)); + EXPECT_SLIGHTLY_BELOW(Roundtrip(t.ppf(), {}, dparams, pool, &ppf_out), 3350); t.CoalesceGIFAnimationWithAlpha(); ASSERT_EQ(ppf_out.frames.size(), t.ppf().frames.size()); - EXPECT_LE(ButteraugliDistance(t.ppf(), ppf_out), + static constexpr double kMaxButteraugli = #if JXL_HIGH_PRECISION - 1.55); + 1.55; #else - 1.75); + 1.75; #endif + EXPECT_LE(ButteraugliDistance(t.ppf(), ppf_out), kMaxButteraugli); } TEST(JxlTest, RoundtripLosslessAnimation) { @@ -1212,8 +1272,8 @@ TEST(JxlTest, RoundtripLosslessAnimation) { dparams.accepted_formats.push_back(t.ppf().frames[0].color.format); PackedPixelFile ppf_out; - EXPECT_THAT(Roundtrip(t.ppf(), cparams, dparams, pool, &ppf_out), - IsSlightlyBelow(958)); + EXPECT_SLIGHTLY_BELOW(Roundtrip(t.ppf(), cparams, dparams, pool, &ppf_out), + 958); t.CoalesceGIFAnimationWithAlpha(); ASSERT_EQ(ppf_out.frames.size(), t.ppf().frames.size()); @@ -1240,11 +1300,11 @@ TEST(JxlTest, RoundtripAnimationPatches) { PackedPixelFile ppf_out; // 40k with no patches, 27k with patch frames encoded multiple times. - EXPECT_THAT(Roundtrip(t.ppf(), cparams, dparams, pool, &ppf_out), - IsSlightlyBelow(19300)); + EXPECT_SLIGHTLY_BELOW(Roundtrip(t.ppf(), cparams, dparams, pool, &ppf_out), + 19300); EXPECT_EQ(ppf_out.frames.size(), t.ppf().frames.size()); // >10 with broken patches; not all patches are detected on borders. - EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(1.9)); + EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.9); } size_t RoundtripJpeg(const std::vector<uint8_t>& jpeg_in, ThreadPool* pool) { @@ -1293,7 +1353,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression444)) { const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png.im_q85_444.jpg"); // JPEG size is 696,659 bytes. - EXPECT_NEAR(RoundtripJpeg(orig, &pool), 568940u, 20); + EXPECT_NEAR(RoundtripJpeg(orig, &pool), 568891u, 20); } TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels)) { @@ -1306,7 +1366,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels)) { PackedPixelFile ppf_out; RoundtripJpegToPixels(orig, {}, &pool, &ppf_out); - EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(12)); + EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 12); } TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels420)) { @@ -1319,7 +1379,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionToPixels420)) { PackedPixelFile ppf_out; RoundtripJpegToPixels(orig, {}, &pool, &ppf_out); - EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(11)); + EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 11); } TEST(JxlTest, @@ -1336,7 +1396,7 @@ TEST(JxlTest, PackedPixelFile ppf_out; RoundtripJpegToPixels(orig, dparams, &pool, &ppf_out); - EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(4410)); + EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 4410); } TEST(JxlTest, @@ -1350,7 +1410,7 @@ TEST(JxlTest, PackedPixelFile ppf_out; RoundtripJpegToPixels(orig, {}, &pool, &ppf_out); - EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(4)); + EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 4); } TEST(JxlTest, @@ -1364,7 +1424,7 @@ TEST(JxlTest, PackedPixelFile ppf_out; RoundtripJpegToPixels(orig, {}, &pool, &ppf_out); - EXPECT_THAT(ComputeDistance2(t.ppf(), ppf_out), IsSlightlyBelow(10)); + EXPECT_SLIGHTLY_BELOW(ComputeDistance2(t.ppf(), ppf_out), 10); } TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionGray)) { @@ -1380,7 +1440,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression420)) { const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png.im_q85_420.jpg"); // JPEG size is 546,797 bytes. - EXPECT_NEAR(RoundtripJpeg(orig, &pool), 455560u, 10); + EXPECT_NEAR(RoundtripJpeg(orig, &pool), 455510u, 20); } TEST(JxlTest, @@ -1389,7 +1449,7 @@ TEST(JxlTest, const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png.im_q85_luma_subsample.jpg"); // JPEG size is 400,724 bytes. - EXPECT_NEAR(RoundtripJpeg(orig, &pool), 325354u, 15); + EXPECT_NEAR(RoundtripJpeg(orig, &pool), 325310u, 20); } TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression444_12)) { @@ -1398,7 +1458,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression444_12)) { const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png.im_q85_444_1x2.jpg"); // JPEG size is 703,874 bytes. - EXPECT_NEAR(RoundtripJpeg(orig, &pool), 569679u, 10); + EXPECT_NEAR(RoundtripJpeg(orig, &pool), 569630u, 20); } TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression422)) { @@ -1406,7 +1466,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression422)) { const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png.im_q85_422.jpg"); // JPEG size is 522,057 bytes. - EXPECT_NEAR(RoundtripJpeg(orig, &pool), 499282u, 10); + EXPECT_NEAR(RoundtripJpeg(orig, &pool), 499236u, 20); } TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression440)) { @@ -1414,7 +1474,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression440)) { const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png.im_q85_440.jpg"); // JPEG size is 603,623 bytes. - EXPECT_NEAR(RoundtripJpeg(orig, &pool), 501151u, 10); + EXPECT_NEAR(RoundtripJpeg(orig, &pool), 501101u, 20); } TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression_asymmetric)) { @@ -1424,7 +1484,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression_asymmetric)) { const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png.im_q85_asymmetric.jpg"); // JPEG size is 604,601 bytes. - EXPECT_NEAR(RoundtripJpeg(orig, &pool), 500602u, 10); + EXPECT_NEAR(RoundtripJpeg(orig, &pool), 500548u, 20); } TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression420Progr)) { @@ -1432,7 +1492,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompression420Progr)) { const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png.im_q85_420_progr.jpg"); // JPEG size is 522,057 bytes. - EXPECT_NEAR(RoundtripJpeg(orig, &pool), 455499u, 10); + EXPECT_NEAR(RoundtripJpeg(orig, &pool), 455454u, 20); } TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionMetadata)) { @@ -1440,7 +1500,8 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionMetadata)) { const std::vector<uint8_t> orig = ReadTestData("jxl/jpeg_reconstruction/1x1_exif_xmp.jpg"); // JPEG size is 4290 bytes - EXPECT_NEAR(RoundtripJpeg(orig, &pool), 1400u, 30); + // 1370 on 386, so higher margin. + EXPECT_NEAR(RoundtripJpeg(orig, &pool), 1334u, 100); } TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionRestarts)) { @@ -1448,7 +1509,7 @@ TEST(JxlTest, JXL_TRANSCODE_JPEG_TEST(RoundtripJpegRecompressionRestarts)) { const std::vector<uint8_t> orig = ReadTestData("jxl/jpeg_reconstruction/bicycles_restarts.jpg"); // JPEG size is 87478 bytes - EXPECT_NEAR(RoundtripJpeg(orig, &pool), 76125u, 30); + EXPECT_NEAR(RoundtripJpeg(orig, &pool), 76054u, 30); } TEST(JxlTest, @@ -1475,7 +1536,7 @@ TEST(JxlTest, RoundtripProgressive) { PackedPixelFile ppf_out; EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 70544, 750); - EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(1.4)); + EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.4); } TEST(JxlTest, RoundtripProgressiveLevel2Slow) { @@ -1492,7 +1553,7 @@ TEST(JxlTest, RoundtripProgressiveLevel2Slow) { PackedPixelFile ppf_out; EXPECT_NEAR(Roundtrip(t.ppf(), cparams, {}, &pool, &ppf_out), 76666, 1000); - EXPECT_THAT(ButteraugliDistance(t.ppf(), ppf_out), IsSlightlyBelow(1.17)); + EXPECT_SLIGHTLY_BELOW(ButteraugliDistance(t.ppf(), ppf_out), 1.17); } TEST(JxlTest, RoundtripUnsignedCustomBitdepthLossless) { @@ -1509,9 +1570,9 @@ TEST(JxlTest, RoundtripUnsignedCustomBitdepthLossless) { t.SetAllBitDepths(bitdepth).SetEndianness(endianness); TestImage::Frame frame = t.AddFrame(); frame.RandomFill(); + t.ppf().input_bitdepth.type = JXL_BIT_DEPTH_FROM_CODESTREAM; JXLCompressParams cparams = CompressParamsForLossless(); - cparams.input_bitdepth.type = JXL_BIT_DEPTH_FROM_CODESTREAM; JXLDecompressParams dparams; dparams.accepted_formats.push_back(t.ppf().frames[0].color.format); @@ -1543,7 +1604,6 @@ TEST(JxlTest, LosslessPNMRoundtrip) { JXLCompressParams cparams = CompressParamsForLossless(); cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 1); // kLightning - cparams.input_bitdepth.type = JXL_BIT_DEPTH_FROM_CODESTREAM; JXLDecompressParams dparams; dparams.accepted_formats.push_back(t.ppf().frames[0].color.format); @@ -1592,10 +1652,13 @@ struct StreamingTestParam { size_t xsize; size_t ysize; bool is_grey; + bool has_alpha; int effort; bool progressive; - size_t num_channels() const { return is_grey ? 1 : 3; } + size_t num_channels() const { + return (is_grey ? 1 : 3) + (has_alpha ? 1 : 0); + } float max_psnr() const { return is_grey ? 90 : 50; } @@ -1603,11 +1666,13 @@ struct StreamingTestParam { std::vector<StreamingTestParam> params; for (int e : {1, 3, 4, 7}) { for (bool g : {false, true}) { - params.push_back(StreamingTestParam{357, 517, g, e, false}); - params.push_back(StreamingTestParam{2247, 2357, g, e, false}); + params.push_back(StreamingTestParam{357, 517, g, false, e, false}); + params.push_back(StreamingTestParam{2247, 2357, g, false, e, false}); } } - params.push_back(StreamingTestParam{2247, 2357, false, 1, true}); + params.push_back(StreamingTestParam{2247, 2357, false, false, 1, true}); + params.push_back(StreamingTestParam{2247, 2157, false, false, 5, false}); + params.push_back(StreamingTestParam{2247, 2157, false, true, 5, false}); return params; } }; @@ -1651,15 +1716,66 @@ JXL_GTEST_INSTANTIATE_TEST_SUITE_P( JxlStreamingTest, JxlStreamingTest, testing::ValuesIn(StreamingTestParam::All())); +struct StreamingEncodingTestParam { + std::string file; + int effort; + float distance; + int group_size; + float palette_percent; + + static std::vector<StreamingEncodingTestParam> All() { + std::vector<StreamingEncodingTestParam> params; + for (const auto* file : + {"jxl/flower/flower.png", "jxl/flower/flower_alpha.png"}) { + for (int effort : {1, 3, 5, 6}) { + if (effort != 1) { + params.push_back( + StreamingEncodingTestParam{file, effort, 1.0, 1, -1}); + params.push_back( + StreamingEncodingTestParam{file, effort, 4.0, 1, -1}); + } + for (auto group_size : {-1, 0}) { + for (float palette_percent : {-1, 50, 100}) { + params.push_back(StreamingEncodingTestParam{ + file, effort, 0.0, group_size, palette_percent}); + } + } + } + } + return params; + } +}; + +std::ostream& operator<<(std::ostream& out, + const StreamingEncodingTestParam& p) { + out << p.file << "-"; + out << "e" << p.effort; + if (p.distance == 0) { + out << "Lossless"; + out << "G" << p.group_size << "P" << p.palette_percent; + } else { + out << "D" << p.distance; + } + return out; +} + +class JxlStreamingEncodingTest + : public ::testing::TestWithParam<StreamingEncodingTestParam> {}; + // This is broken on mingw32, so we only enable it for x86_64 now. -TEST(JxlTest, JXL_X86_64_TEST(StreamingSamePixels)) { - const std::vector<uint8_t> orig = ReadTestData("jxl/flower/flower.png"); +TEST_P(JxlStreamingEncodingTest, JXL_X86_64_TEST(StreamingSamePixels)) { + const auto param = GetParam(); + const std::vector<uint8_t> orig = ReadTestData(param.file); jxl::test::TestImage image; image.DecodeFromBytes(orig); + JXLCompressParams cparams; - cparams.distance = 1.0; - cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, 6); + cparams.distance = param.distance; + cparams.AddOption(JXL_ENC_FRAME_SETTING_EFFORT, param.effort); + cparams.AddOption(JXL_ENC_FRAME_SETTING_MODULAR_GROUP_SIZE, param.group_size); + cparams.AddFloatOption(JXL_ENC_FRAME_SETTING_CHANNEL_COLORS_GROUP_PERCENT, + param.palette_percent); cparams.AddOption(JXL_ENC_FRAME_SETTING_USE_FULL_IMAGE_HEURISTICS, 0); ThreadPoolForTests pool(8); @@ -1673,5 +1789,9 @@ TEST(JxlTest, JXL_X86_64_TEST(StreamingSamePixels)) { EXPECT_TRUE(jxl::test::SamePixels(ppf_out, ppf_out_streaming)); } +JXL_GTEST_INSTANTIATE_TEST_SUITE_P( + JxlStreamingTest, JxlStreamingEncodingTest, + testing::ValuesIn(StreamingEncodingTestParam::All())); + } // namespace } // namespace jxl |