Coverage Report

Created: 2025-06-16 07:00

/src/libjxl/lib/jxl/enc_butteraugli_comparator.cc
Line
Count
Source (jump to first uncovered line)
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/enc_butteraugli_comparator.h"
7
8
#include <jxl/cms_interface.h>
9
#include <jxl/memory_manager.h>
10
11
#include <cstddef>
12
13
#include "lib/jxl/base/compiler_specific.h"
14
#include "lib/jxl/base/status.h"
15
#include "lib/jxl/butteraugli/butteraugli.h"
16
#include "lib/jxl/color_encoding_internal.h"
17
#include "lib/jxl/enc_image_bundle.h"
18
#include "lib/jxl/image.h"
19
#include "lib/jxl/image_bundle.h"
20
#include "lib/jxl/image_metadata.h"
21
22
namespace jxl {
23
24
JxlButteraugliComparator::JxlButteraugliComparator(
25
    const ButteraugliParams& params, const JxlCmsInterface& cms)
26
0
    : params_(params), cms_(cms) {}
27
28
0
Status JxlButteraugliComparator::SetReferenceImage(const ImageBundle& ref) {
29
0
  const ImageBundle* ref_linear_srgb;
30
0
  JxlMemoryManager* memory_manager = ref.memory_manager();
31
0
  ImageMetadata metadata = *ref.metadata();
32
0
  ImageBundle store(memory_manager, &metadata);
33
0
  if (!TransformIfNeeded(ref, ColorEncoding::LinearSRGB(ref.IsGray()), cms_,
34
0
                         /*pool=*/nullptr, &store, &ref_linear_srgb)) {
35
0
    return false;
36
0
  }
37
0
  JXL_ASSIGN_OR_RETURN(comparator_, ButteraugliComparator::Make(
38
0
                                        ref_linear_srgb->color(), params_));
39
0
  xsize_ = ref.xsize();
40
0
  ysize_ = ref.ysize();
41
0
  intensity_target_ = ref.metadata()->IntensityTarget();
42
0
  return true;
43
0
}
44
45
Status JxlButteraugliComparator::SetLinearReferenceImage(
46
0
    const Image3F& linear) {
47
0
  JXL_ASSIGN_OR_RETURN(comparator_,
48
0
                       ButteraugliComparator::Make(linear, params_));
49
0
  xsize_ = linear.xsize();
50
0
  ysize_ = linear.ysize();
51
0
  return true;
52
0
}
53
54
Status JxlButteraugliComparator::CompareWith(const ImageBundle& actual,
55
0
                                             ImageF* diffmap, float* score) {
56
0
  if (!comparator_) {
57
0
    return JXL_FAILURE("Must set reference image first");
58
0
  }
59
0
  if (xsize_ != actual.xsize() || ysize_ != actual.ysize()) {
60
0
    return JXL_FAILURE("Images must have same size");
61
0
  }
62
0
  JxlMemoryManager* memory_manager = actual.memory_manager();
63
64
0
  const ImageBundle* actual_linear_srgb;
65
0
  ImageMetadata metadata = *actual.metadata();
66
0
  ImageBundle store(memory_manager, &metadata);
67
0
  if (!TransformIfNeeded(actual, ColorEncoding::LinearSRGB(actual.IsGray()),
68
0
                         cms_,
69
0
                         /*pool=*/nullptr, &store, &actual_linear_srgb)) {
70
0
    return false;
71
0
  }
72
73
0
  JXL_ASSIGN_OR_RETURN(ImageF temp_diffmap,
74
0
                       ImageF::Create(memory_manager, xsize_, ysize_));
75
0
  const Image3F* scaled_actual_linear_srgb = &actual_linear_srgb->color();
76
0
  Image3F scaled_actual_linear_srgb_store;
77
0
  if (intensity_target_ != 0 &&
78
0
      actual.metadata()->IntensityTarget() != intensity_target_) {
79
0
    scaled_actual_linear_srgb = &scaled_actual_linear_srgb_store;
80
0
    JXL_ASSIGN_OR_RETURN(scaled_actual_linear_srgb_store,
81
0
                         Image3F::Create(memory_manager, xsize_, ysize_));
82
0
    const float scale =
83
0
        actual.metadata()->IntensityTarget() / intensity_target_;
84
0
    for (size_t c = 0; c < 3; ++c) {
85
0
      for (size_t y = 0; y < ysize_; ++y) {
86
0
        const float* JXL_RESTRICT source_row =
87
0
            actual_linear_srgb->color().ConstPlaneRow(c, y);
88
0
        float* JXL_RESTRICT scaled_row =
89
0
            scaled_actual_linear_srgb_store.PlaneRow(c, y);
90
0
        for (size_t x = 0; x < xsize_; ++x) {
91
0
          scaled_row[x] = scale * source_row[x];
92
0
        }
93
0
      }
94
0
    }
95
0
  }
96
0
  JXL_RETURN_IF_ERROR(
97
0
      comparator_->Diffmap(*scaled_actual_linear_srgb, temp_diffmap));
98
99
0
  if (score != nullptr) {
100
0
    *score = ButteraugliScoreFromDiffmap(temp_diffmap, &params_);
101
0
  }
102
0
  if (diffmap != nullptr) {
103
0
    diffmap->Swap(temp_diffmap);
104
0
  }
105
106
0
  return true;
107
0
}
108
109
0
float JxlButteraugliComparator::GoodQualityScore() const {
110
0
  return ButteraugliFuzzyInverse(1.5);
111
0
}
112
113
0
float JxlButteraugliComparator::BadQualityScore() const {
114
0
  return ButteraugliFuzzyInverse(0.5);
115
0
}
116
117
}  // namespace jxl