/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, ¶ms_); |
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 |