Program Listing for File GainBias.hpp

Return to documentation for file (include\util\function\halide\GainBias.hpp)

#pragma once

#include "util/common/Result.hpp"
#include "util/function/FunctionContext.hpp"

#include <cstddef>
#include <cstdint>
#include <vector>

namespace PDJE_UTIL::function::halide {

struct GrayImageView {
    const std::uint8_t *data   = nullptr;
    std::size_t         width  = 0;
    std::size_t         height = 0;
    std::size_t         stride = 0;
};

struct GrayImage {
    std::vector<std::uint8_t> pixels;
    std::size_t               width  = 0;
    std::size_t               height = 0;
    std::size_t               stride = 0;
};

struct GainBiasArgs {
    int  gain  = 1;
    int  bias  = 0;
    bool clamp = true;
};

inline common::Result<GrayImage>
apply_gain_bias(GrayImageView input,
                const GainBiasArgs &args,
                function::EvalOptions options = {})
{
    (void)options;

    if (input.data == nullptr) {
        return common::Result<GrayImage>::failure(
            { common::StatusCode::invalid_argument, "GrayImageView.data must not be null." });
    }
    if (input.width == 0 || input.height == 0) {
        return common::Result<GrayImage>::failure(
            { common::StatusCode::invalid_argument,
              "GrayImageView width and height must be greater than zero." });
    }
    if (input.stride < input.width) {
        return common::Result<GrayImage>::failure(
            { common::StatusCode::invalid_argument,
              "GrayImageView.stride must be greater than or equal to width." });
    }

    GrayImage output;
    output.width  = input.width;
    output.height = input.height;
    output.stride = input.width;
    output.pixels.resize(output.width * output.height);

    for (std::size_t y = 0; y < input.height; ++y) {
        for (std::size_t x = 0; x < input.width; ++x) {
            const auto src_index = y * input.stride + x;
            const auto dst_index = y * output.stride + x;
            int value = static_cast<int>(input.data[src_index]) * args.gain + args.bias;
            if (args.clamp) {
                if (value < 0) {
                    value = 0;
                } else if (value > 255) {
                    value = 255;
                }
            }
            output.pixels[dst_index] = static_cast<std::uint8_t>(value);
        }
    }

    return common::Result<GrayImage>::success(std::move(output));
}

} // namespace PDJE_UTIL::function::halide