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