blob: b1dd9756e3214ff58c4e3d90566c8e0e5aa20e91 [file] [log] [blame]
/*
* Copyright 2022 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "samples/risp4ml/common/utils.h"
#include "samples/risp4ml/isp_stages/gamma.h"
#define kRgbColorChannels 3
static const uint16_t kRgbPipelineBpp = 16;
static const uint32_t kRgbPipelineMaxVal = (1 << kRgbPipelineBpp) - 1;
// Fixed HW Parameters
static const uint8_t kGammaNumberSegments = 4;
static const uint8_t kGammaLogSegmentOffsets[] = {0, 3, 2, 1};
static const uint8_t kGammaLogSegmentSpacing[] = {8, 9, 10, 11};
static const uint16_t kGammaLogNumberPoints[] = {5, 4, 4, 4};
static const uint16_t kGammaSegmentLutOffset[] = {0, 32, 48, 64};
static GammaParams gamma_params = {
.enable = true,
.lut = {0, 3255, 5552, 7237, 8618, 9809, 10868, 11828, 12710,
13531, 14300, 15026, 15713, 16368, 16995, 17596, 18173, 18731,
19269, 19790, 20295, 20786, 21264, 21728, 22182, 22624, 23056,
23479, 23892, 24297, 24694, 25083, 25466, 26209, 26928, 27623,
28298, 28953, 29590, 30211, 30816, 31406, 31983, 32547, 33099,
33640, 34170, 34689, 35199, 36192, 37151, 38080, 38980, 39855,
40705, 41534, 42341, 43129, 43899, 44652, 45389, 46111, 46818,
47512, 48192, 49517, 50798, 52037, 53239, 54407, 55542, 56648,
57726, 58778, 59806, 60811, 61794, 62757, 63702, 64627, 65535}};
void set_gamma_params(GammaParams* params) { gamma_params = *params; }
void gamma_process(Image* img) {
if (!gamma_params.enable) return;
pixel_type_t* line[kRgbColorChannels];
for (uint16_t y = 0; y < img->height; ++y) {
for (uint16_t c = 0; c < kRgbColorChannels; ++c) {
line[c] = image_row(img, c, y);
}
for (uint16_t x = 0; x < img->width; ++x) {
for (uint16_t c = 0; c < kRgbColorChannels; ++c) {
pixel_type_t pixel_val =
(pixel_type_t)Clamp(line[c][x], 0, kRgbPipelineMaxVal);
// Determine segment
int segment_index =
(kGammaNumberSegments - 1) -
ClzMsb(pixel_val, kRgbPipelineBpp, kGammaNumberSegments - 1);
uint16_t segment_left =
segment_index ? 1 << (kRgbPipelineBpp -
kGammaLogSegmentOffsets[segment_index])
: 0;
// Bin index
int bin_index = ((pixel_val - segment_left) >>
kGammaLogSegmentSpacing[segment_index]) +
kGammaSegmentLutOffset[segment_index];
int offset_within_bin =
(pixel_val - segment_left) &
((1 << kGammaLogSegmentSpacing[segment_index]) - 1);
uint16_t l_val = gamma_params.lut[bin_index];
uint16_t r_val = gamma_params.lut[bin_index + 1];
uint16_t bin_size = 1 << kGammaLogSegmentSpacing[segment_index];
uint32_t lerp_val = (l_val * (bin_size - offset_within_bin) +
r_val * offset_within_bin + (bin_size >> 1)) >>
kGammaLogSegmentSpacing[segment_index];
// Clamping is not requied
// TODO(alexkaplan): The comment above is from gChips source.
// this calc needs to be checked carefully:
//
line[c][x] = (pixel_type_t)lerp_val;
}
}
}
}