mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-16 08:55:06 +03:00
It's more natural to represent color gains 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. Black level still uses pixel (integer) values, for consistency with other libcamera parts. Signed-off-by: Milan Zamazal <mzamazal@redhat.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Umang Jain <umang.jain@ideasonboard.com> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
86 lines
2.5 KiB
C++
86 lines
2.5 KiB
C++
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
|
/*
|
|
* Copyright (C) 2024, Red Hat Inc.
|
|
*
|
|
* Color lookup tables construction
|
|
*/
|
|
|
|
#include "lut.h"
|
|
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
#include <stdint.h>
|
|
|
|
#include <libcamera/base/log.h>
|
|
|
|
#include "simple/ipa_context.h"
|
|
|
|
namespace libcamera {
|
|
|
|
namespace ipa::soft::algorithms {
|
|
|
|
int Lut::configure(IPAContext &context,
|
|
[[maybe_unused]] const IPAConfigInfo &configInfo)
|
|
{
|
|
/* Gamma value is fixed */
|
|
context.configuration.gamma = 0.5;
|
|
updateGammaTable(context);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void Lut::updateGammaTable(IPAContext &context)
|
|
{
|
|
auto &gammaTable = context.activeState.gamma.gammaTable;
|
|
auto blackLevel = context.activeState.blc.level;
|
|
const unsigned int blackIndex = blackLevel * gammaTable.size() / 256;
|
|
|
|
std::fill(gammaTable.begin(), gammaTable.begin() + blackIndex, 0);
|
|
const float divisor = gammaTable.size() - blackIndex - 1.0;
|
|
for (unsigned int i = blackIndex; i < gammaTable.size(); i++)
|
|
gammaTable[i] = UINT8_MAX * std::pow((i - blackIndex) / divisor,
|
|
context.configuration.gamma);
|
|
|
|
context.activeState.gamma.blackLevel = blackLevel;
|
|
}
|
|
|
|
void Lut::prepare(IPAContext &context,
|
|
[[maybe_unused]] const uint32_t frame,
|
|
[[maybe_unused]] IPAFrameContext &frameContext,
|
|
[[maybe_unused]] DebayerParams *params)
|
|
{
|
|
/*
|
|
* Update the gamma table if needed. This means if black level changes
|
|
* and since the black level gets updated only if a lower value is
|
|
* observed, it's not permanently prone to minor fluctuations or
|
|
* rounding errors.
|
|
*/
|
|
if (context.activeState.gamma.blackLevel != context.activeState.blc.level)
|
|
updateGammaTable(context);
|
|
|
|
auto &gains = context.activeState.gains;
|
|
auto &gammaTable = context.activeState.gamma.gammaTable;
|
|
const unsigned int gammaTableSize = gammaTable.size();
|
|
|
|
for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) {
|
|
const double div = static_cast<double>(DebayerParams::kRGBLookupSize) /
|
|
gammaTableSize;
|
|
/* Apply gamma after gain! */
|
|
unsigned int idx;
|
|
idx = std::min({ static_cast<unsigned int>(i * gains.red / div),
|
|
gammaTableSize - 1 });
|
|
params->red[i] = gammaTable[idx];
|
|
idx = std::min({ static_cast<unsigned int>(i * gains.green / div),
|
|
gammaTableSize - 1 });
|
|
params->green[i] = gammaTable[idx];
|
|
idx = std::min({ static_cast<unsigned int>(i * gains.blue / div),
|
|
gammaTableSize - 1 });
|
|
params->blue[i] = gammaTable[idx];
|
|
}
|
|
}
|
|
|
|
REGISTER_IPA_ALGORITHM(Lut, "Lut")
|
|
|
|
} /* namespace ipa::soft::algorithms */
|
|
|
|
} /* namespace libcamera */
|