Files
korenkonder_ReDIVA/src/KKdLib/image.cpp
T

125 lines
4.1 KiB
C++

/*
by korenkonder
GitHub/GitLab: korenkonder
*/
#include "image.hpp"
static rgb565 rgb565_apply_color_tone(rgb565 col, const color_tone* col_tone);
static void rgb_to_ycc(vec3& rgb, vec3& ycc);
static void ycc_apply_col_tone_hue(vec3& ycc, const color_tone* col_tone);
static void ycc_to_rgb(vec3& ycc, vec3& rgb);
color_tone::color_tone() : hue(), saturation(), value(), contrast(), inverse() {
}
void dxt1_image_apply_color_tone(int32_t width, int32_t height,
int32_t size, dxt1_block* data, const color_tone* col_tone) {
if (size <= 0)
return;
for (size_t i = (size - 1ULL) / sizeof(dxt1_block) + 1; i; i--, data++) {
data->color0 = rgb565_apply_color_tone(data->color0, col_tone);
data->color1 = rgb565_apply_color_tone(data->color1, col_tone);
if (*(uint16_t*)&data->color0 <= *(uint16_t*)&data->color1) {
data->indices[0] &= ~((data->indices[0] >> 1) & 0x5555);
data->indices[1] &= ~((data->indices[1] >> 1) & 0x5555);
}
}
}
void dxt5_image_apply_color_tone(int32_t width, int32_t height,
int32_t size, dxt5_block* data, const color_tone* col_tone) {
if (size <= 0)
return;
for (size_t i = (size - 1ULL) / sizeof(dxt5_block) + 1; i; i--, data++) {
data->color0 = rgb565_apply_color_tone(data->color0, col_tone);
data->color1 = rgb565_apply_color_tone(data->color1, col_tone);
if (*(uint16_t*)&data->color0 <= *(uint16_t*)&data->color1) {
data->color_indices[0] &= ~((data->color_indices[0] >> 1) & 0x5555);
data->color_indices[1] &= ~((data->color_indices[1] >> 1) & 0x5555);
}
}
}
void rgb565_image_apply_color_tone(int32_t width, int32_t height,
int32_t size, rgb565* data, const color_tone* col_tone) {
for (size_t i = (size - 1ULL) / sizeof(uint16_t) + 1; i; i--, data++)
*data = rgb565_apply_color_tone(*data, col_tone);
}
static rgb565 rgb565_apply_color_tone(rgb565 col, const color_tone* col_tone) {
const vec3 scale = {
(float_t)((1 << 5) - 1),
(float_t)((1 << 6) - 1),
(float_t)((1 << 5) - 1),
};
const vec3 inv_scale = {
(float_t)(1.0 / (double_t)((1 << 5) - 1)),
(float_t)(1.0 / (double_t)((1 << 6) - 1)),
(float_t)(1.0 / (double_t)((1 << 5) - 1)),
};
vec3 rgb;
if (col_tone->inverse) {
rgb.x = (float_t)((1 << 5) - 1 - col.r);
rgb.y = (float_t)((1 << 5) - 1 - col.g);
rgb.z = (float_t)((1 << 5) - 1 - col.b);
}
else {
rgb.x = (float_t)col.r;
rgb.y = (float_t)col.g;
rgb.z = (float_t)col.b;
}
rgb = vec3::clamp(rgb * inv_scale * col_tone->blend + col_tone->offset, 0.0f, 1.0f);
vec3 ycc;
rgb_to_ycc(rgb, ycc);
*(vec2*)&ycc.y = *(vec2*)&ycc.y * col_tone->saturation;
ycc_apply_col_tone_hue(ycc, col_tone);
ycc.x = (ycc.x + col_tone->value - 0.5f) * col_tone->contrast + 0.5f;
ycc.x = clamp_def(ycc.x, 0.0f, 1.0f);
*(vec2*)&ycc.y = vec2::clamp(*(vec2*)&ycc.y, -0.5f, 0.5f);
ycc_to_rgb(ycc, rgb);
rgb = vec3::clamp(rgb, 0.0f, 1.0f) * scale;
col.r = (uint8_t)rgb.x;
col.g = (uint8_t)rgb.y;
col.b = (uint8_t)rgb.z;
return col;
}
inline static void rgb_to_ycc(vec3& rgb, vec3& ycc) {
const vec3 _y_coef_601 = { 0.29891f, 0.58661f, 0.11448f };
const vec3 _cb_coef_601 = { -0.16874f, -0.33126f, 0.5f };
const vec3 _cr_coef_601 = { 0.5f, -0.41869f, -0.08131f };
ycc.x = vec3::dot(rgb, _y_coef_601);
ycc.y = vec3::dot(rgb, _cb_coef_601);
ycc.z = vec3::dot(rgb, _cr_coef_601);
}
inline static void ycc_apply_col_tone_hue(vec3& ycc, const color_tone* col_tone) {
float_t hue = col_tone->hue * DEG_TO_RAD_FLOAT;
float_t cos = cosf(hue);
float_t sin = sinf(hue);
ycc.y = ycc.y * cos + ycc.z * sin;
ycc.z = ycc.z * cos - ycc.y * sin;
}
inline static void ycc_to_rgb(vec3& ycc, vec3& rgb) {
const vec3 _red_coef_601 = { 1.0f, 0.0f, 1.402f };
const vec3 _grn_coef_601 = { 1.0f, -0.34414f, -0.71414f };
const vec3 _blu_coef_601 = { 1.0f, 1.772f, 0.0f };
rgb.x = vec3::dot(ycc, _red_coef_601);
rgb.y = vec3::dot(ycc, _grn_coef_601);
rgb.z = vec3::dot(ycc, _blu_coef_601);
}