@@ -6,10 +6,11 @@
*/
#include "goc.h"
+#include <array>
#include <cmath>
#include <libcamera/base/log.h>
-#include <libcamera/base/utils.h>
+#include <libcamera/base/span.h>
#include <libcamera/control_ids.h>
@@ -29,21 +30,13 @@ namespace ipa::rkisp1::algorithms {
* \class GammaOutCorrection
* \brief RkISP1 Gamma out correction
*
- * This algorithm implements the gamma out curve for the RkISP1. It defaults to
- * a gamma value of 2.2.
- *
- * As gamma is internally represented as a piecewise linear function with only
- * 17 knots, the difference between gamma=2.2 and sRGB gamma is minimal.
- * Therefore sRGB gamma was not implemented as special case.
- *
- * Useful links:
- * - https://www.cambridgeincolour.com/tutorials/gamma-correction.htm
- * - https://en.wikipedia.org/wiki/SRGB
+ * This algorithm implements the gamma out curve for the RkISP1 using the
+ * libipa GammaAlgorithm class.
*/
LOG_DEFINE_CATEGORY(RkISP1Gamma)
-const float kDefaultGamma = 2.2f;
+static constexpr unsigned int kNumLutSegments = RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10 - 1;
/**
* \copydoc libcamera::ipa::Algorithm::init
@@ -57,10 +50,12 @@ int GammaOutCorrection::init(IPAContext &context, const ValueNode &tuningData)
return -EINVAL;
}
- defaultGamma_ = tuningData["gamma"].get<double>(kDefaultGamma);
- context.ctrlMap[&controls::Gamma] = ControlInfo(0.1f, 10.0f, defaultGamma_);
+ std::array<unsigned int, kNumLutSegments> segments = {
+ 64, 64, 64, 64, 128, 128, 128, 128,
+ 256, 256, 256, 512, 512, 512, 512, 512
+ };
- return 0;
+ return gammaAlgo_.init(context.ctrlMap, tuningData, segments);
}
/**
@@ -69,7 +64,7 @@ int GammaOutCorrection::init(IPAContext &context, const ValueNode &tuningData)
int GammaOutCorrection::configure(IPAContext &context,
[[maybe_unused]] const IPACameraSensorInfo &configInfo)
{
- context.activeState.goc.gamma = defaultGamma_;
+ gammaAlgo_.configure(context.activeState.gamma);
return 0;
}
@@ -80,17 +75,8 @@ void GammaOutCorrection::queueRequest(IPAContext &context, const uint32_t frame,
IPAFrameContext &frameContext,
const ControlList &controls)
{
- if (frame == 0)
- frameContext.goc.update = true;
-
- const auto &gamma = controls.get(controls::Gamma);
- if (gamma) {
- context.activeState.goc.gamma = *gamma;
- frameContext.goc.update = true;
- LOG(RkISP1Gamma, Debug) << "Set gamma to " << *gamma;
- }
-
- frameContext.goc.gamma = context.activeState.goc.gamma;
+ gammaAlgo_.queueRequest(context.activeState.gamma, frame,
+ frameContext.gamma, controls);
}
/**
@@ -104,29 +90,14 @@ void GammaOutCorrection::prepare(IPAContext &context,
ASSERT(context.hw.numGammaOutSamples ==
RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10);
- if (!frameContext.goc.update)
+ if (!frameContext.gamma.update)
return;
- /*
- * The logarithmic segments as specified in the reference.
- * Plus an additional 0 to make the loop easier
- */
- static constexpr std::array<unsigned int, RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10> segments = {
- 64, 64, 64, 64, 128, 128, 128, 128, 256,
- 256, 256, 512, 512, 512, 512, 512, 0
- };
-
auto config = params->block<BlockType::Goc>();
config.setEnabled(true);
- __u16 *gamma_y = config->gamma_y;
-
- unsigned x = 0;
- for (const auto [i, size] : utils::enumerate(segments)) {
- gamma_y[i] = std::pow(x / 4096.0, 1.0 / frameContext.goc.gamma) * 1023.0;
- x += size;
- }
-
+ Span<uint16_t> lut{ config->gamma_y };
+ gammaAlgo_.prepare(frameContext.gamma, lut);
config->mode = RKISP1_CIF_ISP_GOC_MODE_LOGARITHMIC;
}
@@ -139,7 +110,7 @@ void GammaOutCorrection::process([[maybe_unused]] IPAContext &context,
[[maybe_unused]] const rkisp1_stat_buffer *stats,
ControlList &metadata)
{
- metadata.set(controls::Gamma, frameContext.goc.gamma);
+ gammaAlgo_.process(frameContext.gamma, metadata);
}
REGISTER_IPA_ALGORITHM(GammaOutCorrection, "GammaOutCorrection")
@@ -9,6 +9,11 @@
#include "algorithm.h"
+#include <linux/rkisp1-config.h>
+
+#include <libipa/fixedpoint.h>
+#include <libipa/gamma.h>
+
namespace libcamera {
namespace ipa::rkisp1::algorithms {
@@ -35,7 +40,7 @@ public:
ControlList &metadata) override;
private:
- float defaultGamma_;
+ GammaAlgorithm<RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10, UQ<0, 10>> gammaAlgo_;
};
} /* namespace ipa::rkisp1::algorithms */
@@ -30,6 +30,7 @@
#include "libipa/ccm.h"
#include "libipa/fc_queue.h"
#include "libipa/fixedpoint.h"
+#include "libipa/gamma.h"
#include "libipa/lsc.h"
namespace libcamera {
@@ -127,9 +128,7 @@ struct IPAActiveState {
uint8_t sharpness;
} filter;
- struct {
- double gamma;
- } goc;
+ ipa::gamma::ActiveState gamma;
struct {
double lux;
@@ -194,10 +193,7 @@ struct IPAFrameContext : public FrameContext {
bool update;
} filter;
- struct {
- double gamma;
- bool update;
- } goc;
+ ipa::gamma::FrameContext gamma;
struct {
uint32_t exposure;