summaryrefslogtreecommitdiff
path: root/src/ipa
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipa')
-rw-r--r--src/ipa/simple/soft_simple.cpp51
1 files changed, 42 insertions, 9 deletions
diff --git a/src/ipa/simple/soft_simple.cpp b/src/ipa/simple/soft_simple.cpp
index dbbeabbf..92095e59 100644
--- a/src/ipa/simple/soft_simple.cpp
+++ b/src/ipa/simple/soft_simple.cpp
@@ -5,6 +5,7 @@
* Simple Software Image Processing Algorithm module
*/
+#include <cmath>
#include <numeric>
#include <stdint.h>
#include <sys/mman.h>
@@ -84,6 +85,10 @@ private:
ControlInfoMap sensorInfoMap_;
BlackLevel blackLevel_;
+ static constexpr unsigned int kGammaLookupSize = 1024;
+ std::array<uint8_t, kGammaLookupSize> gammaTable_;
+ int lastBlackLevel_ = -1;
+
int32_t exposureMin_, exposureMax_;
int32_t exposure_;
double againMin_, againMax_, againMinStep_;
@@ -246,7 +251,6 @@ void IPASoftSimple::processStats(const ControlList &sensorControls)
if (ignoreUpdates_ > 0)
blackLevel_.update(histogram);
const uint8_t blackLevel = blackLevel_.get();
- params_->blackLevel = blackLevel;
/*
* Black level must be subtracted to get the correct AWB ratios, they
@@ -263,13 +267,42 @@ void IPASoftSimple::processStats(const ControlList &sensorControls)
/*
* 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.
*/
- params_->gainR = sumR <= sumG / 4 ? 1024 : 256 * sumG / sumR;
- params_->gainB = sumB <= sumG / 4 ? 1024 : 256 * sumG / sumB;
-
+ const unsigned int gainR = sumR <= sumG / 4 ? 1024 : 256 * sumG / sumR;
+ const unsigned int gainB = sumB <= sumG / 4 ? 1024 : 256 * sumG / sumB;
/* Green gain and gamma values are fixed */
- params_->gainG = 256;
- params_->gamma = 0.5;
+ constexpr unsigned int gainG = 256;
+
+ /* Update the gamma table if needed */
+ if (blackLevel != lastBlackLevel_) {
+ constexpr float gamma = 0.5;
+ const unsigned int blackIndex = blackLevel * kGammaLookupSize / 256;
+ std::fill(gammaTable_.begin(), gammaTable_.begin() + blackIndex, 0);
+ const float divisor = kGammaLookupSize - blackIndex - 1.0;
+ for (unsigned int i = blackIndex; i < kGammaLookupSize; i++)
+ gammaTable_[i] = UINT8_MAX *
+ std::pow((i - blackIndex) / divisor, gamma);
+
+ lastBlackLevel_ = blackLevel;
+ }
+
+ for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) {
+ constexpr unsigned int div =
+ DebayerParams::kRGBLookupSize * DebayerParams::kGain10 /
+ kGammaLookupSize;
+ unsigned int idx;
+
+ /* Apply gamma after gain! */
+ idx = std::min({ i * gainR / div, (kGammaLookupSize - 1) });
+ params_->red[i] = gammaTable_[idx];
+
+ idx = std::min({ i * gainG / div, (kGammaLookupSize - 1) });
+ params_->green[i] = gammaTable_[idx];
+
+ idx = std::min({ i * gainB / div, (kGammaLookupSize - 1) });
+ params_->blue[i] = gammaTable_[idx];
+ }
setIspParams.emit();
@@ -290,7 +323,7 @@ void IPASoftSimple::processStats(const ControlList &sensorControls)
* https://www.araa.asn.au/acra/acra2007/papers/paper84final.pdf
*/
const unsigned int blackLevelHistIdx =
- params_->blackLevel / (256 / SwIspStats::kYHistogramSize);
+ blackLevel / (256 / SwIspStats::kYHistogramSize);
const unsigned int histogramSize =
SwIspStats::kYHistogramSize - blackLevelHistIdx;
const unsigned int yHistValsPerBin = histogramSize / kExposureBinsCount;
@@ -338,8 +371,8 @@ void IPASoftSimple::processStats(const ControlList &sensorControls)
LOG(IPASoft, Debug) << "exposureMSV " << exposureMSV
<< " exp " << exposure_ << " again " << again_
- << " gain R/B " << params_->gainR << "/" << params_->gainB
- << " black level " << params_->blackLevel;
+ << " gain R/B " << gainR << "/" << gainB
+ << " black level " << static_cast<unsigned int>(blackLevel);
}
void IPASoftSimple::updateExposure(double exposureMSV)