[PATCH v4 15/18] libcamera: software_isp: Use floating point for color parameters
Milan Zamazal
mzamazal at redhat.com
Thu Aug 15 10:16:19 CEST 2024
It's more natural to represent color gains and black level as floating
point numbers rather than using a particular pixel-related
representation.
double is used rather than float because it's a more common floating
point type in libcamera algorithms. Otherwise there is no obvious
reason to select one over the other here.
The constructed color tables still use integer representation for
efficiency.
Signed-off-by: Milan Zamazal <mzamazal at redhat.com>
---
src/ipa/simple/algorithms/awb.cpp | 24 +++++++++++++-----------
src/ipa/simple/algorithms/blc.cpp | 8 ++++----
src/ipa/simple/algorithms/gamma.cpp | 2 +-
src/ipa/simple/ipa_context.h | 11 +++++------
4 files changed, 23 insertions(+), 22 deletions(-)
diff --git a/src/ipa/simple/algorithms/awb.cpp b/src/ipa/simple/algorithms/awb.cpp
index 1e43f3fd..ff6591de 100644
--- a/src/ipa/simple/algorithms/awb.cpp
+++ b/src/ipa/simple/algorithms/awb.cpp
@@ -27,7 +27,7 @@ int Awb::init(IPAContext &context,
[[maybe_unused]] const YamlObject &tuningData)
{
auto &gains = context.activeState.gains;
- gains.red = gains.green = gains.blue = 256;
+ gains.red = gains.green = gains.blue = 1.0;
return 0;
}
@@ -40,15 +40,18 @@ void Awb::prepare(IPAContext &context,
auto &gains = context.activeState.gains;
auto &gammaTable = context.activeState.gamma.gammaTable;
for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) {
- constexpr unsigned int div =
- static_cast<double>(DebayerParams::kRGBLookupSize) * 256 / kGammaLookupSize;
+ constexpr double div =
+ static_cast<double>(DebayerParams::kRGBLookupSize) / kGammaLookupSize;
/* Apply gamma after gain! */
unsigned int idx;
- idx = std::min({ i * gains.red / div, kGammaLookupSize - 1 });
+ idx = std::min({ static_cast<unsigned int>(i * gains.red / div),
+ kGammaLookupSize - 1 });
params->red[i] = gammaTable[idx];
- idx = std::min({ i * gains.green / div, kGammaLookupSize - 1 });
+ idx = std::min({ static_cast<unsigned int>(i * gains.green / div),
+ kGammaLookupSize - 1 });
params->green[i] = gammaTable[idx];
- idx = std::min({ i * gains.blue / div, kGammaLookupSize - 1 });
+ idx = std::min({ static_cast<unsigned int>(i * gains.blue / div),
+ kGammaLookupSize - 1 });
params->blue[i] = gammaTable[idx];
}
}
@@ -60,7 +63,7 @@ void Awb::process(IPAContext &context,
[[maybe_unused]] ControlList &metadata)
{
const SwIspStats::Histogram &histogram = stats->yHistogram;
- const uint8_t blackLevel = context.activeState.black.level;
+ const double blackLevel = context.activeState.black.level;
/*
* Black level must be subtracted to get the correct AWB ratios, they
@@ -77,12 +80,11 @@ void Awb::process(IPAContext &context,
/*
* Calculate red and blue gains for AWB.
* Clamp max gain at 4.0, this also avoids 0 division.
- * Gain: 128 = 0.5, 256 = 1.0, 512 = 2.0, etc.
*/
auto &gains = context.activeState.gains;
- gains.red = sumR <= sumG / 4 ? 1024 : 256 * sumG / sumR;
- gains.blue = sumB <= sumG / 4 ? 1024 : 256 * sumG / sumB;
- /* Green gain is fixed to 256 */
+ gains.red = sumR <= sumG / 4 ? 4.0 : static_cast<double>(sumG) / sumR;
+ gains.blue = sumB <= sumG / 4 ? 4.0 : static_cast<double>(sumG) / sumB;
+ /* Green gain is fixed to 1.0 */
LOG(IPASoftAwb, Debug) << "gain R/B " << gains.red << "/" << gains.blue;
}
diff --git a/src/ipa/simple/algorithms/blc.cpp b/src/ipa/simple/algorithms/blc.cpp
index 3b73d830..ab7e7dd9 100644
--- a/src/ipa/simple/algorithms/blc.cpp
+++ b/src/ipa/simple/algorithms/blc.cpp
@@ -24,7 +24,7 @@ BlackLevel::BlackLevel()
int BlackLevel::init(IPAContext &context,
[[maybe_unused]] const YamlObject &tuningData)
{
- context.activeState.black.level = 255;
+ context.activeState.black.level = 1.0;
return 0;
}
@@ -44,16 +44,16 @@ void BlackLevel::process(IPAContext &context,
const unsigned int total =
std::accumulate(begin(histogram), end(histogram), 0);
const unsigned int pixelThreshold = ignoredPercentage_ * total;
- const unsigned int histogramRatio = 256 / SwIspStats::kYHistogramSize;
const unsigned int currentBlackIdx =
- context.activeState.black.level / histogramRatio;
+ context.activeState.black.level * SwIspStats::kYHistogramSize;
for (unsigned int i = 0, seen = 0;
i < currentBlackIdx && i < SwIspStats::kYHistogramSize;
i++) {
seen += histogram[i];
if (seen >= pixelThreshold) {
- context.activeState.black.level = i * histogramRatio;
+ context.activeState.black.level =
+ static_cast<double>(i) / SwIspStats::kYHistogramSize;
LOG(IPASoftBL, Debug)
<< "Auto-set black level: "
<< i << "/" << SwIspStats::kYHistogramSize
diff --git a/src/ipa/simple/algorithms/gamma.cpp b/src/ipa/simple/algorithms/gamma.cpp
index 0b8ec5ee..b03dff25 100644
--- a/src/ipa/simple/algorithms/gamma.cpp
+++ b/src/ipa/simple/algorithms/gamma.cpp
@@ -34,7 +34,7 @@ void Gamma::updateGammaTable(IPAContext &context)
auto &gammaTable = context.activeState.gamma.gammaTable;
auto blackLevel = context.activeState.black.level;
const unsigned int blackIndex =
- blackLevel * IPAActiveState::kGammaLookupSize / 256;
+ blackLevel * IPAActiveState::kGammaLookupSize;
std::fill(gammaTable.begin(), gammaTable.begin() + blackIndex, 0);
const float divisor = kGammaLookupSize - blackIndex - 1.0;
for (unsigned int i = blackIndex; i < kGammaLookupSize; i++)
diff --git a/src/ipa/simple/ipa_context.h b/src/ipa/simple/ipa_context.h
index f8b8834d..28a02475 100644
--- a/src/ipa/simple/ipa_context.h
+++ b/src/ipa/simple/ipa_context.h
@@ -8,7 +8,6 @@
#pragma once
#include <array>
-#include <stdint.h>
#include <libipa/fc_queue.h>
@@ -22,17 +21,17 @@ struct IPASessionConfiguration {
struct IPAActiveState {
struct {
- uint8_t level;
+ double level;
} black;
struct {
- unsigned int red;
- unsigned int green;
- unsigned int blue;
+ double red;
+ double green;
+ double blue;
} gains;
static constexpr unsigned int kGammaLookupSize = 1024;
struct {
std::array<double, kGammaLookupSize> gammaTable;
- uint8_t blackLevel;
+ double blackLevel;
} gamma;
};
--
2.44.1
More information about the libcamera-devel
mailing list