1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "lib/jxl/enc_butteraugli_comparator.h"
#include <algorithm>
#include <vector>
#include "lib/jxl/color_management.h"
#include "lib/jxl/enc_image_bundle.h"
namespace jxl {
JxlButteraugliComparator::JxlButteraugliComparator(
const ButteraugliParams& params, const JxlCmsInterface& cms)
: params_(params), cms_(cms) {}
Status JxlButteraugliComparator::SetReferenceImage(const ImageBundle& ref) {
const ImageBundle* ref_linear_srgb;
ImageMetadata metadata = *ref.metadata();
ImageBundle store(&metadata);
if (!TransformIfNeeded(ref, ColorEncoding::LinearSRGB(ref.IsGray()), cms_,
/*pool=*/nullptr, &store, &ref_linear_srgb)) {
return false;
}
comparator_.reset(
new ButteraugliComparator(ref_linear_srgb->color(), params_));
xsize_ = ref.xsize();
ysize_ = ref.ysize();
return true;
}
Status JxlButteraugliComparator::CompareWith(const ImageBundle& actual,
ImageF* diffmap, float* score) {
if (!comparator_) {
return JXL_FAILURE("Must set reference image first");
}
if (xsize_ != actual.xsize() || ysize_ != actual.ysize()) {
return JXL_FAILURE("Images must have same size");
}
const ImageBundle* actual_linear_srgb;
ImageMetadata metadata = *actual.metadata();
ImageBundle store(&metadata);
if (!TransformIfNeeded(actual, ColorEncoding::LinearSRGB(actual.IsGray()),
cms_,
/*pool=*/nullptr, &store, &actual_linear_srgb)) {
return false;
}
ImageF temp_diffmap(xsize_, ysize_);
comparator_->Diffmap(actual_linear_srgb->color(), temp_diffmap);
if (score != nullptr) {
*score = ButteraugliScoreFromDiffmap(temp_diffmap, ¶ms_);
}
if (diffmap != nullptr) {
diffmap->Swap(temp_diffmap);
}
return true;
}
float JxlButteraugliComparator::GoodQualityScore() const {
return ButteraugliFuzzyInverse(1.5);
}
float JxlButteraugliComparator::BadQualityScore() const {
return ButteraugliFuzzyInverse(0.5);
}
float ButteraugliDistance(const ImageBundle& rgb0, const ImageBundle& rgb1,
const ButteraugliParams& params,
const JxlCmsInterface& cms, ImageF* distmap,
ThreadPool* pool) {
JxlButteraugliComparator comparator(params, cms);
return ComputeScore(rgb0, rgb1, &comparator, cms, distmap, pool);
}
float ButteraugliDistance(const std::vector<ImageBundle>& frames0,
const std::vector<ImageBundle>& frames1,
const ButteraugliParams& params,
const JxlCmsInterface& cms, ImageF* distmap,
ThreadPool* pool) {
JxlButteraugliComparator comparator(params, cms);
JXL_ASSERT(frames0.size() == frames1.size());
float max_dist = 0.0f;
for (size_t i = 0; i < frames0.size(); ++i) {
max_dist = std::max(
max_dist,
ComputeScore(frames0[i], frames1[i], &comparator, cms, distmap, pool));
}
return max_dist;
}
} // namespace jxl
|