butteraugli_test.cc (3756B)
1 // Copyright (c) the JPEG XL Project Authors. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 #include "lib/jxl/butteraugli/butteraugli.h" 7 8 #include <jxl/types.h> 9 #include <stddef.h> 10 11 #include <algorithm> 12 #include <cstdint> 13 #include <utility> 14 15 #include "lib/extras/metrics.h" 16 #include "lib/extras/packed_image.h" 17 #include "lib/jxl/base/random.h" 18 #include "lib/jxl/base/status.h" 19 #include "lib/jxl/enc_external_image.h" 20 #include "lib/jxl/image.h" 21 #include "lib/jxl/image_ops.h" 22 #include "lib/jxl/test_image.h" 23 #include "lib/jxl/testing.h" 24 25 namespace jxl { 26 namespace { 27 28 using extras::PackedImage; 29 using extras::PackedPixelFile; 30 using test::TestImage; 31 32 Image3F SinglePixelImage(float red, float green, float blue) { 33 JXL_ASSIGN_OR_DIE(Image3F img, Image3F::Create(1, 1)); 34 img.PlaneRow(0, 0)[0] = red; 35 img.PlaneRow(1, 0)[0] = green; 36 img.PlaneRow(2, 0)[0] = blue; 37 return img; 38 } 39 40 Image3F GetColorImage(const PackedPixelFile& ppf) { 41 JXL_CHECK(!ppf.frames.empty()); 42 const PackedImage& image = ppf.frames[0].color; 43 const JxlPixelFormat& format = image.format; 44 const uint8_t* pixels = reinterpret_cast<const uint8_t*>(image.pixels()); 45 JXL_ASSIGN_OR_DIE(Image3F color, Image3F::Create(image.xsize, image.ysize)); 46 for (size_t c = 0; c < format.num_channels; ++c) { 47 JXL_CHECK(ConvertFromExternal(pixels, image.pixels_size, image.xsize, 48 image.ysize, ppf.info.bits_per_sample, format, 49 c, nullptr, &color.Plane(c))); 50 } 51 return color; 52 } 53 54 void AddUniformNoise(Image3F* img, float d, size_t seed) { 55 Rng generator(seed); 56 for (size_t y = 0; y < img->ysize(); ++y) { 57 for (int c = 0; c < 3; ++c) { 58 for (size_t x = 0; x < img->xsize(); ++x) { 59 img->PlaneRow(c, y)[x] += generator.UniformF(-d, d); 60 } 61 } 62 } 63 } 64 65 void AddEdge(Image3F* img, float d, size_t x0, size_t y0) { 66 const size_t h = std::min<size_t>(img->ysize() - y0, 100); 67 const size_t w = std::min<size_t>(img->xsize() - x0, 5); 68 for (size_t dy = 0; dy < h; ++dy) { 69 for (size_t dx = 0; dx < w; ++dx) { 70 img->PlaneRow(1, y0 + dy)[x0 + dx] += d; 71 } 72 } 73 } 74 75 TEST(ButteraugliInPlaceTest, SinglePixel) { 76 Image3F rgb0 = SinglePixelImage(0.5f, 0.5f, 0.5f); 77 Image3F rgb1 = SinglePixelImage(0.5f, 0.49f, 0.5f); 78 ButteraugliParams ba; 79 ImageF diffmap; 80 double diffval; 81 EXPECT_TRUE(ButteraugliInterface(rgb0, rgb1, ba, diffmap, diffval)); 82 EXPECT_NEAR(diffval, 2.5, 0.5); 83 ImageF diffmap2; 84 double diffval2; 85 EXPECT_TRUE(ButteraugliInterfaceInPlace(std::move(rgb0), std::move(rgb1), ba, 86 diffmap2, diffval2)); 87 EXPECT_NEAR(diffval, diffval2, 1e-10); 88 } 89 90 TEST(ButteraugliInPlaceTest, LargeImage) { 91 const size_t xsize = 1024; 92 const size_t ysize = 1024; 93 TestImage img; 94 img.SetDimensions(xsize, ysize).AddFrame().RandomFill(777); 95 Image3F rgb0 = GetColorImage(img.ppf()); 96 JXL_ASSIGN_OR_DIE(Image3F rgb1, Image3F::Create(xsize, ysize)); 97 CopyImageTo(rgb0, &rgb1); 98 AddUniformNoise(&rgb1, 0.02f, 7777); 99 AddEdge(&rgb1, 0.1f, xsize / 2, xsize / 2); 100 ButteraugliParams ba; 101 ImageF diffmap; 102 double diffval; 103 EXPECT_TRUE(ButteraugliInterface(rgb0, rgb1, ba, diffmap, diffval)); 104 double distp = ComputeDistanceP(diffmap, ba, 3.0); 105 EXPECT_NEAR(diffval, 4.0, 0.5); 106 EXPECT_NEAR(distp, 1.5, 0.5); 107 ImageF diffmap2; 108 double diffval2; 109 EXPECT_TRUE(ButteraugliInterfaceInPlace(std::move(rgb0), std::move(rgb1), ba, 110 diffmap2, diffval2)); 111 double distp2 = ComputeDistanceP(diffmap2, ba, 3.0); 112 EXPECT_NEAR(diffval, diffval2, 5e-7); 113 EXPECT_NEAR(distp, distp2, 1e-7); 114 } 115 116 } // namespace 117 } // namespace jxl