mirror of
https://github.com/korenkonder/ReDIVA.git
synced 2026-10-02 11:47:56 +03:00
125 lines
4.1 KiB
C++
125 lines
4.1 KiB
C++
/*
|
|
by korenkonder
|
|
GitHub/GitLab: korenkonder
|
|
*/
|
|
|
|
#include "image.hpp"
|
|
;
|
|
static rgb565 rgb565_apply_color_tone(rgb565 col, color_tone* col_tone);
|
|
static void rgb_to_ycc(vec3& rgb, vec3& ycc);
|
|
static void ycc_apply_col_tone_hue(vec3& ycc, color_tone* col_tone);
|
|
static void ycc_to_rgb(vec3& ycc, vec3& rgb);
|
|
|
|
void dxt1_image_apply_color_tone(int32_t width, int32_t height,
|
|
int32_t size, dxt1_block* data, 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, 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, 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, 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;
|
|
}
|
|
|
|
vec3_mult(rgb, inv_scale, rgb);
|
|
vec3_mult(rgb, col_tone->blend, rgb);
|
|
vec3_add(rgb, col_tone->offset, rgb);
|
|
vec3_clamp_scalar(rgb, 0.0f, 1.0f, rgb);
|
|
|
|
vec3 ycc;
|
|
rgb_to_ycc(rgb, ycc);
|
|
|
|
vec2_mult_scalar(*(vec2*)&ycc.y, col_tone->saturation, *(vec2*)&ycc.y);
|
|
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(ycc.x, 0.0f, 1.0f);
|
|
vec2_clamp_scalar(*(vec2*)&ycc.y, -0.5f, 0.5f, *(vec2*)&ycc.y);
|
|
|
|
ycc_to_rgb(ycc, rgb);
|
|
|
|
vec3_clamp_scalar(rgb, 0.0f, 1.0f, rgb);
|
|
vec3_mult(rgb, scale, rgb);
|
|
|
|
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 };
|
|
|
|
vec3_dot(rgb, _y_coef_601, ycc.x);
|
|
vec3_dot(rgb, _cb_coef_601, ycc.y);
|
|
vec3_dot(rgb, _cr_coef_601, ycc.z);
|
|
}
|
|
|
|
inline static void ycc_apply_col_tone_hue(vec3& ycc, 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 };
|
|
|
|
vec3_dot(ycc, _red_coef_601, rgb.x);
|
|
vec3_dot(ycc, _grn_coef_601, rgb.y);
|
|
vec3_dot(ycc, _blu_coef_601, rgb.z);
|
|
} |