/* 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 */