diff options
-rw-r--r-- | src/ipa/simple/algorithms/awb.cpp | 4 | ||||
-rw-r--r-- | src/ipa/simple/algorithms/ccm.cpp | 74 | ||||
-rw-r--r-- | src/ipa/simple/algorithms/ccm.h | 43 | ||||
-rw-r--r-- | src/ipa/simple/algorithms/lut.cpp | 2 | ||||
-rw-r--r-- | src/ipa/simple/algorithms/meson.build | 1 | ||||
-rw-r--r-- | src/ipa/simple/ipa_context.h | 13 |
6 files changed, 133 insertions, 4 deletions
diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp index 4e31e386..ec77c6e5 100644 --- a/src/ipa/simple/algorithms/awb.cpp +++ b/src/ipa/simple/algorithms/awb.cpp @@ -59,9 +59,9 @@ void Awb::process(IPAContext &context, */ auto &gains = context.activeState.awb.gains; gains = { { - sumR <= sumG / 4 ? 4.0 : static_cast<double>(sumG) / sumR, + sumR <= sumG / 4 ? 4.0f : static_cast<float>(sumG) / sumR, 1.0, - sumB <= sumG / 4 ? 4.0 : static_cast<double>(sumG) / sumB, + sumB <= sumG / 4 ? 4.0f : static_cast<float>(sumG) / sumB, } }; RGB<double> rgbGains{ { 1 / gains.r(), 1 / gains.g(), 1 / gains.b() } }; diff --git a/src/ipa/simple/algorithms/ccm.cpp b/src/ipa/simple/algorithms/ccm.cpp new file mode 100644 index 00000000..86e0395c --- /dev/null +++ b/src/ipa/simple/algorithms/ccm.cpp @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024, Ideas On Board + * Copyright (C) 2024-2025, Red Hat Inc. + * + * Color correction matrix + */ + +#include "ccm.h" + +#include <libcamera/base/log.h> +#include <libcamera/base/utils.h> + +#include <libcamera/control_ids.h> + +namespace { + +constexpr unsigned int kTemperatureThreshold = 100; + +} + +namespace libcamera { + +namespace ipa::soft::algorithms { + +LOG_DEFINE_CATEGORY(IPASoftCcm) + +int Ccm::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData) +{ + int ret = ccm_.readYaml(tuningData["ccms"], "ct", "ccm"); + if (ret < 0) { + LOG(IPASoftCcm, Error) + << "Failed to parse 'ccm' parameter from tuning file."; + return ret; + } + + return 0; +} + +void Ccm::prepare(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, [[maybe_unused]] DebayerParams *params) +{ + const unsigned int ct = context.activeState.awb.temperatureK; + + /* Change CCM only on bigger temperature changes. */ + if (frame > 0 && + utils::abs_diff(ct, lastCt_) < kTemperatureThreshold) { + frameContext.ccm.ccm = context.activeState.ccm.ccm; + context.activeState.ccm.changed = false; + return; + } + + lastCt_ = ct; + Matrix<float, 3, 3> ccm = ccm_.getInterpolated(ct); + + context.activeState.ccm.ccm = ccm; + frameContext.ccm.ccm = ccm; + context.activeState.ccm.changed = true; +} + +void Ccm::process([[maybe_unused]] IPAContext &context, + [[maybe_unused]] const uint32_t frame, + IPAFrameContext &frameContext, + [[maybe_unused]] const SwIspStats *stats, + ControlList &metadata) +{ + metadata.set(controls::ColourCorrectionMatrix, frameContext.ccm.ccm.data()); +} + +REGISTER_IPA_ALGORITHM(Ccm, "Ccm") + +} /* namespace ipa::soft::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/simple/algorithms/ccm.h b/src/ipa/simple/algorithms/ccm.h new file mode 100644 index 00000000..f4e2b85b --- /dev/null +++ b/src/ipa/simple/algorithms/ccm.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2024-2025, Red Hat Inc. + * + * Color correction matrix + */ + +#pragma once + +#include "libcamera/internal/matrix.h" + +#include <libipa/interpolator.h> + +#include "algorithm.h" + +namespace libcamera { + +namespace ipa::soft::algorithms { + +class Ccm : public Algorithm +{ +public: + Ccm() = default; + ~Ccm() = default; + + int init(IPAContext &context, const YamlObject &tuningData) override; + void prepare(IPAContext &context, + const uint32_t frame, + IPAFrameContext &frameContext, + DebayerParams *params) override; + void process(IPAContext &context, const uint32_t frame, + IPAFrameContext &frameContext, + const SwIspStats *stats, + ControlList &metadata) override; + +private: + unsigned int lastCt_; + Interpolator<Matrix<float, 3, 3>> ccm_; +}; + +} /* namespace ipa::soft::algorithms */ + +} /* namespace libcamera */ diff --git a/src/ipa/simple/algorithms/lut.cpp b/src/ipa/simple/algorithms/lut.cpp index 063bec73..3a3daed7 100644 --- a/src/ipa/simple/algorithms/lut.cpp +++ b/src/ipa/simple/algorithms/lut.cpp @@ -103,7 +103,7 @@ void Lut::prepare(IPAContext &context, const double div = static_cast<double>(DebayerParams::kRGBLookupSize) / gammaTableSize; /* Apply gamma after gain! */ - const RGB<double> lutGains = (gains * i / div).min(gammaTableSize - 1); + const RGB<float> lutGains = (gains * i / div).min(gammaTableSize - 1); params->red[i] = gammaTable[static_cast<unsigned int>(lutGains.r())]; params->green[i] = gammaTable[static_cast<unsigned int>(lutGains.g())]; params->blue[i] = gammaTable[static_cast<unsigned int>(lutGains.b())]; diff --git a/src/ipa/simple/algorithms/meson.build b/src/ipa/simple/algorithms/meson.build index 37a2eb53..2d0adb05 100644 --- a/src/ipa/simple/algorithms/meson.build +++ b/src/ipa/simple/algorithms/meson.build @@ -4,5 +4,6 @@ soft_simple_ipa_algorithms = files([ 'awb.cpp', 'agc.cpp', 'blc.cpp', + 'ccm.cpp', 'lut.cpp', ]) diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h index 6a285414..67183b3e 100644 --- a/src/ipa/simple/ipa_context.h +++ b/src/ipa/simple/ipa_context.h @@ -13,6 +13,7 @@ #include <libcamera/controls.h> +#include "libcamera/internal/matrix.h" #include "libcamera/internal/vector.h" #include <libipa/fc_queue.h> @@ -38,7 +39,7 @@ struct IPAActiveState { } blc; struct { - RGB<double> gains; + RGB<float> gains; unsigned int temperatureK; } awb; @@ -48,6 +49,12 @@ struct IPAActiveState { uint8_t blackLevel; double contrast; } gamma; + + struct { + Matrix<float, 3, 3> ccm; + bool changed; + } ccm; + struct { /* 0..2 range, 1.0 = normal */ std::optional<double> contrast; @@ -56,6 +63,10 @@ struct IPAActiveState { struct IPAFrameContext : public FrameContext { struct { + Matrix<float, 3, 3> ccm; + } ccm; + + struct { int32_t exposure; double gain; } sensor; |