tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

opsin_image_test.cc (4577B)


      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 <jxl/cms.h>
      7 #include <jxl/memory_manager.h>
      8 
      9 #include <cstddef>
     10 #include <utility>
     11 
     12 #include "lib/jxl/base/compiler_specific.h"
     13 #include "lib/jxl/base/matrix_ops.h"
     14 #include "lib/jxl/base/rect.h"
     15 #include "lib/jxl/cms/opsin_params.h"
     16 #include "lib/jxl/dec_xyb.h"
     17 #include "lib/jxl/enc_xyb.h"
     18 #include "lib/jxl/image.h"
     19 #include "lib/jxl/image_bundle.h"
     20 #include "lib/jxl/image_metadata.h"
     21 #include "lib/jxl/opsin_params.h"
     22 #include "lib/jxl/test_memory_manager.h"
     23 #include "lib/jxl/test_utils.h"
     24 #include "lib/jxl/testing.h"
     25 
     26 namespace jxl {
     27 namespace {
     28 
     29 // Convert a single linear sRGB color to xyb, using the exact image conversion
     30 // procedure that jpeg xl uses.
     31 void LinearSrgbToOpsin(float rgb_r, float rgb_g, float rgb_b,
     32                       float* JXL_RESTRICT xyb_x, float* JXL_RESTRICT xyb_y,
     33                       float* JXL_RESTRICT xyb_b) {
     34  JxlMemoryManager* memory_manager = jxl::test::MemoryManager();
     35  JXL_TEST_ASSIGN_OR_DIE(Image3F linear, Image3F::Create(memory_manager, 1, 1));
     36  linear.PlaneRow(0, 0)[0] = rgb_r;
     37  linear.PlaneRow(1, 0)[0] = rgb_g;
     38  linear.PlaneRow(2, 0)[0] = rgb_b;
     39 
     40  ImageMetadata metadata;
     41  metadata.SetFloat32Samples();
     42  metadata.color_encoding = ColorEncoding::LinearSRGB();
     43  ImageBundle ib(memory_manager, &metadata);
     44  ASSERT_TRUE(ib.SetFromImage(std::move(linear), metadata.color_encoding));
     45  JXL_TEST_ASSIGN_OR_DIE(Image3F opsin, Image3F::Create(memory_manager, 1, 1));
     46  (void)ToXYB(ib, /*pool=*/nullptr, &opsin, *JxlGetDefaultCms());
     47 
     48  *xyb_x = opsin.PlaneRow(0, 0)[0];
     49  *xyb_y = opsin.PlaneRow(1, 0)[0];
     50  *xyb_b = opsin.PlaneRow(2, 0)[0];
     51 }
     52 
     53 // Convert a single XYB color to linear sRGB, using the exact image conversion
     54 // procedure that jpeg xl uses.
     55 void OpsinToLinearSrgb(float xyb_x, float xyb_y, float xyb_b,
     56                       float* JXL_RESTRICT rgb_r, float* JXL_RESTRICT rgb_g,
     57                       float* JXL_RESTRICT rgb_b) {
     58  JxlMemoryManager* memory_manager = jxl::test::MemoryManager();
     59  JXL_TEST_ASSIGN_OR_DIE(Image3F opsin, Image3F::Create(memory_manager, 1, 1));
     60  opsin.PlaneRow(0, 0)[0] = xyb_x;
     61  opsin.PlaneRow(1, 0)[0] = xyb_y;
     62  opsin.PlaneRow(2, 0)[0] = xyb_b;
     63  JXL_TEST_ASSIGN_OR_DIE(Image3F linear, Image3F::Create(memory_manager, 1, 1));
     64  OpsinParams opsin_params;
     65  opsin_params.Init(/*intensity_target=*/255.0f);
     66  ASSERT_TRUE(
     67      OpsinToLinear(opsin, Rect(opsin), nullptr, &linear, opsin_params));
     68  *rgb_r = linear.PlaneRow(0, 0)[0];
     69  *rgb_g = linear.PlaneRow(1, 0)[0];
     70  *rgb_b = linear.PlaneRow(2, 0)[0];
     71 }
     72 
     73 void OpsinRoundtripTestRGB(float r, float g, float b) {
     74  float xyb_x;
     75  float xyb_y;
     76  float xyb_b;
     77  LinearSrgbToOpsin(r, g, b, &xyb_x, &xyb_y, &xyb_b);
     78  float r2;
     79  float g2;
     80  float b2;
     81  OpsinToLinearSrgb(xyb_x, xyb_y, xyb_b, &r2, &g2, &b2);
     82  EXPECT_NEAR(r, r2, 1e-3);
     83  EXPECT_NEAR(g, g2, 1e-3);
     84  EXPECT_NEAR(b, b2, 1e-3);
     85 }
     86 
     87 TEST(OpsinImageTest, VerifyOpsinAbsorbanceInverseMatrix) {
     88  Matrix3x3 matrix;  // writable copy
     89  matrix = GetOpsinAbsorbanceInverseMatrix();
     90  EXPECT_TRUE(Inv3x3Matrix(matrix));
     91  for (int j = 0; j < 3; j++) {
     92    for (int i = 0; i < 3; i++) {
     93      EXPECT_NEAR(matrix[j][i], jxl::cms::kOpsinAbsorbanceMatrix[j][i], 1e-6);
     94    }
     95  }
     96 }
     97 
     98 TEST(OpsinImageTest, OpsinRoundtrip) {
     99  OpsinRoundtripTestRGB(0, 0, 0);
    100  OpsinRoundtripTestRGB(1. / 255, 1. / 255, 1. / 255);
    101  OpsinRoundtripTestRGB(128. / 255, 128. / 255, 128. / 255);
    102  OpsinRoundtripTestRGB(1, 1, 1);
    103 
    104  OpsinRoundtripTestRGB(0, 0, 1. / 255);
    105  OpsinRoundtripTestRGB(0, 0, 128. / 255);
    106  OpsinRoundtripTestRGB(0, 0, 1);
    107 
    108  OpsinRoundtripTestRGB(0, 1. / 255, 0);
    109  OpsinRoundtripTestRGB(0, 128. / 255, 0);
    110  OpsinRoundtripTestRGB(0, 1, 0);
    111 
    112  OpsinRoundtripTestRGB(1. / 255, 0, 0);
    113  OpsinRoundtripTestRGB(128. / 255, 0, 0);
    114  OpsinRoundtripTestRGB(1, 0, 0);
    115 }
    116 
    117 TEST(OpsinImageTest, VerifyZero) {
    118  // Test that black color (zero energy) is 0,0,0 in xyb.
    119  float x;
    120  float y;
    121  float b;
    122  LinearSrgbToOpsin(0, 0, 0, &x, &y, &b);
    123  EXPECT_NEAR(0, x, 1e-9);
    124  EXPECT_NEAR(0, y, 1e-7);
    125  EXPECT_NEAR(0, b, 1e-7);
    126 }
    127 
    128 TEST(OpsinImageTest, VerifyGray) {
    129  // Test that grayscale colors have a fixed y/b ratio and x==0.
    130  for (size_t i = 1; i < 255; i++) {
    131    float x;
    132    float y;
    133    float b;
    134    LinearSrgbToOpsin(i / 255., i / 255., i / 255., &x, &y, &b);
    135    EXPECT_NEAR(0, x, 1e-6);
    136    EXPECT_NEAR(jxl::cms::kYToBRatio, b / y, 3e-5);
    137  }
    138 }
    139 
    140 }  // namespace
    141 }  // namespace jxl