new file mode 100644
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Lens shading correction
+ */
+
+#include "lsc.h"
+
+#include <libcamera/base/log.h>
+
+namespace libcamera {
+
+namespace ipa::soft::algorithms {
+
+LOG_DEFINE_CATEGORY(IPASoftLsc)
+
+int Lsc::init(IPAContext &context, const ValueNode &tuningData)
+{
+ static constexpr unsigned int kGridSize = DebayerParams::kLscGridSize;
+
+ for (unsigned int i = 0; i < kGridSize; i++)
+ gridPos_.push_back(static_cast<double>(i) / (kGridSize - 1));
+
+ return lscAlgo_.init(tuningData, context.ctrlMap,
+ { .keys = { "r", "g", "b" },
+ .numHCells = kGridSize,
+ .numVCells = kGridSize,
+ .sensorSize = context.sensorInfo.activeAreaSize });
+}
+
+int Lsc::configure(IPAContext &context,
+ [[maybe_unused]] const IPAConfigInfo &configInfo)
+{
+ return lscAlgo_.configure(context.activeState.lsc,
+ context.sensorInfo.analogCrop,
+ gridPos_, gridPos_);
+}
+
+void Lsc::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,
+ IPAFrameContext &frameContext, DebayerParams *params)
+{
+ unsigned int ct = context.activeState.awb.automatic.temperatureK;
+
+ params->lscEnabled = frameContext.lsc.enabled;
+
+ if (!frameContext.lsc.enabled ||
+ utils::abs_diff(ct, lastAppliedCt_) < 100)
+ return;
+
+ const lsc::Components<uint8_t> &set = lscAlgo_.interpolateComponents(ct);
+
+ const auto &red = set.at("r");
+ const auto &green = set.at("g");
+ const auto &blue = set.at("b");
+
+ DebayerParams::LscLookupTable lut;
+ constexpr unsigned int gridSize = DebayerParams::kLscGridSize;
+ for (unsigned int i = 0, j = 0; i < gridSize * gridSize; i++) {
+ lut[j++] = red[i] / 64.0;
+ lut[j++] = green[i] / 64.0;
+ lut[j++] = blue[i] / 64.0;
+ }
+ params->lscLut = lut;
+
+ lastAppliedCt_ = ct;
+}
+
+void Lsc::queueRequest(IPAContext &context, [[maybe_unused]] const uint32_t frame,
+ IPAFrameContext &frameContext, const ControlList &controls)
+{
+ lscAlgo_.queueRequest(context.activeState.lsc, frameContext.lsc,
+ controls);
+}
+
+void Lsc::process([[maybe_unused]] IPAContext &context,
+ [[maybe_unused]] const uint32_t frame,
+ IPAFrameContext &frameContext,
+ [[maybe_unused]] const SwIspStats *stats,
+ ControlList &metadata)
+{
+ lscAlgo_.process(frameContext.lsc, metadata);
+}
+
+REGISTER_IPA_ALGORITHM(Lsc, "Lsc")
+
+} /* namespace ipa::soft::algorithms */
+
+} /* namespace libcamera */
new file mode 100644
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Lens shading correction
+ */
+
+#pragma once
+
+#include <libipa/interpolator.h>
+
+#include "libipa/fixedpoint.h"
+#include "libipa/lsc.h"
+
+#include "algorithm.h"
+#include "ipa_context.h"
+
+namespace libcamera {
+
+namespace ipa::soft::algorithms {
+
+class Lsc : public Algorithm
+{
+public:
+ Lsc() = default;
+ ~Lsc() = default;
+
+ int init(IPAContext &context, const ValueNode &tuningData) override;
+ int configure(IPAContext &context,
+ const IPAConfigInfo &configInfo) override;
+ void queueRequest(IPAContext &context, [[maybe_unused]] const uint32_t frame,
+ IPAFrameContext &frameContext, const ControlList &controls) override;
+ void prepare(IPAContext &context,
+ const uint32_t frame,
+ IPAFrameContext &frameContext,
+ DebayerParams *params) override;
+ void process([[maybe_unused]] IPAContext &context,
+ [[maybe_unused]] const uint32_t frame,
+ IPAFrameContext &frameContext,
+ [[maybe_unused]] const SwIspStats *stats,
+ ControlList &metadata) override;
+
+private:
+ LscAlgorithm<UQ<2, 6>> lscAlgo_;
+ std::vector<double> gridPos_;
+
+ unsigned int lastAppliedCt_ = 0;
+};
+
+} /* namespace ipa::soft::algorithms */
+
+} /* namespace libcamera */
@@ -6,4 +6,5 @@ soft_simple_ipa_algorithms = files([
'agc.cpp',
'blc.cpp',
'ccm.cpp',
+ 'lsc.cpp',
])
@@ -19,6 +19,7 @@
#include <libipa/awb.h>
#include <libipa/ccm.h>
#include <libipa/fc_queue.h>
+#include "libipa/lsc.h"
#include "core_ipa_interface.h"
@@ -61,6 +62,8 @@ struct IPAActiveState {
std::optional<float> contrast;
std::optional<float> saturation;
} knobs;
+
+ ipa::lsc::ActiveState lsc;
};
struct IPAFrameContext : public FrameContext {
@@ -75,6 +78,7 @@ struct IPAFrameContext : public FrameContext {
float gamma;
std::optional<float> contrast;
std::optional<float> saturation;
+ ipa::lsc::FrameContext lsc;
};
struct IPAContext {
@@ -89,6 +93,7 @@ struct IPAContext {
FCQueue<IPAFrameContext> frameContexts;
ControlInfoMap::Map ctrlMap;
bool ccmEnabled = false;
+ ipa::lsc::ActiveState lsc;
};
} /* namespace ipa::soft */