diff options
Diffstat (limited to 'src/ipa/ipu3/algorithms/tone_mapping.cpp')
-rw-r--r-- | src/ipa/ipu3/algorithms/tone_mapping.cpp | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/src/ipa/ipu3/algorithms/tone_mapping.cpp b/src/ipa/ipu3/algorithms/tone_mapping.cpp new file mode 100644 index 00000000..160338c1 --- /dev/null +++ b/src/ipa/ipu3/algorithms/tone_mapping.cpp @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2021, Google inc. + * + * IPU3 ToneMapping and Gamma control + */ + +#include "tone_mapping.h" + +#include <cmath> +#include <string.h> + +/** + * \file tone_mapping.h + */ + +namespace libcamera { + +namespace ipa::ipu3::algorithms { + +/** + * \class ToneMapping + * \brief A class to handle tone mapping based on gamma + * + * This algorithm improves the image dynamic using a look-up table which is + * generated based on a gamma parameter. + */ + +ToneMapping::ToneMapping() + : gamma_(1.0) +{ +} + +/** + * \brief Configure the tone mapping given a configInfo + * \param[in] context The shared IPA context + * \param[in] configInfo The IPA configuration data + * + * \return 0 + */ +int ToneMapping::configure(IPAContext &context, + [[maybe_unused]] const IPAConfigInfo &configInfo) +{ + /* Initialise tone mapping gamma value. */ + context.activeState.toneMapping.gamma = 0.0; + + return 0; +} + +/** + * \brief Fill in the parameter structure, and enable gamma control + * \param[in] context The shared IPA context + * \param[in] frame The frame context sequence number + * \param[in] frameContext The FrameContext for this frame + * \param[out] params The IPU3 parameters + * + * Populate the IPU3 parameter structure with our tone mapping look up table and + * enable the gamma control module in the processing blocks. + */ +void ToneMapping::prepare([[maybe_unused]] IPAContext &context, + [[maybe_unused]] const uint32_t frame, + [[maybe_unused]] IPAFrameContext &frameContext, + ipu3_uapi_params *params) +{ + /* Copy the calculated LUT into the parameters buffer. */ + memcpy(params->acc_param.gamma.gc_lut.lut, + context.activeState.toneMapping.gammaCorrection.lut, + IPU3_UAPI_GAMMA_CORR_LUT_ENTRIES * + sizeof(params->acc_param.gamma.gc_lut.lut[0])); + + /* Enable the custom gamma table. */ + params->use.acc_gamma = 1; + params->acc_param.gamma.gc_ctrl.enable = 1; +} + +/** + * \brief Calculate the tone mapping look up table + * \param[in] context The shared IPA context + * \param[in] frame The current frame sequence number + * \param[in] frameContext The current frame context + * \param[in] stats The IPU3 statistics and ISP results + * \param[out] metadata Metadata for the frame, to be filled by the algorithm + * + * The tone mapping look up table is generated as an inverse power curve from + * our gamma setting. + */ +void ToneMapping::process(IPAContext &context, [[maybe_unused]] const uint32_t frame, + [[maybe_unused]] IPAFrameContext &frameContext, + [[maybe_unused]] const ipu3_uapi_stats_3a *stats, + [[maybe_unused]] ControlList &metadata) +{ + /* + * Hardcode gamma to 1.1 as a default for now. + * + * \todo Expose gamma control setting through the libcamera control API + */ + gamma_ = 1.1; + + if (context.activeState.toneMapping.gamma == gamma_) + return; + + struct ipu3_uapi_gamma_corr_lut &lut = + context.activeState.toneMapping.gammaCorrection; + + for (uint32_t i = 0; i < std::size(lut.lut); i++) { + double j = static_cast<double>(i) / (std::size(lut.lut) - 1); + double gamma = std::pow(j, 1.0 / gamma_); + + /* The output value is expressed on 13 bits. */ + lut.lut[i] = gamma * 8191; + } + + context.activeState.toneMapping.gamma = gamma_; +} + +REGISTER_IPA_ALGORITHM(ToneMapping, "ToneMapping") + +} /* namespace ipa::ipu3::algorithms */ + +} /* namespace libcamera */ |