libjxl

FORK: libjxl patches used on blog
git clone https://git.neptards.moe/blog/libjxl.git
Log | Files | Refs | Submodules | README | LICENSE

opsin_image_test.cc (4173B)


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