gpsp/tools/generate_cc_lut.c

136 lines
4.0 KiB
C

#include <stdio.h>
#include <stdint.h>
#include <math.h>
/* gpsp targets devices that are too slow to generate
* a colour correction table at runtime. We therefore
* have to pre-generate the lookup table array... */
/* Colour correction defines */
#define CC_TARGET_GAMMA 2.2f
#define CC_RGB_MAX 31.0f
#define CC_LUM 0.94f
#define CC_R 0.82f
#define CC_G 0.665f
#define CC_B 0.73f
#define CC_RG 0.125f
#define CC_RB 0.195f
#define CC_GR 0.24f
#define CC_GB 0.075f
#define CC_BR -0.06f
#define CC_BG 0.21f
#define CC_GAMMA_ADJ 1.0f
/* Output video is RGB565. This is 16bit,
* but only 15 bits are actually used
* (i.e. 'G' is the highest 5 bits of the
* 6bit component). To save memory, we
* only include 15bit compound values
* and convert RGB565 video to 15bit when
* using the lookup table */
#define CC_LUT_SIZE 32768
static uint16_t c_lut[CC_LUT_SIZE] = {0};
void init_lut(void)
{
size_t color;
float display_gamma_inv = 1.0f / CC_TARGET_GAMMA;
float rgb_max_inv = 1.0f / CC_RGB_MAX;
float adjusted_gamma = CC_TARGET_GAMMA + CC_GAMMA_ADJ;
/* Populate colour correction look-up table */
for (color = 0; color < CC_LUT_SIZE; color++)
{
unsigned r_final = 0;
unsigned g_final = 0;
unsigned b_final = 0;
/* Extract values from RGB555 input */
const unsigned r = color >> 10 & 0x1F;
const unsigned g = color >> 5 & 0x1F;
const unsigned b = color & 0x1F;
/* Perform gamma expansion */
float r_float = pow((float)r * rgb_max_inv, adjusted_gamma);
float g_float = pow((float)g * rgb_max_inv, adjusted_gamma);
float b_float = pow((float)b * rgb_max_inv, adjusted_gamma);
/* Perform colour mangling */
float r_correct = CC_LUM * ((CC_R * r_float) + (CC_GR * g_float) + (CC_BR * b_float));
float g_correct = CC_LUM * ((CC_RG * r_float) + (CC_G * g_float) + (CC_BG * b_float));
float b_correct = CC_LUM * ((CC_RB * r_float) + (CC_GB * g_float) + (CC_B * b_float));
/* Range check... */
r_correct = r_correct > 0.0f ? r_correct : 0.0f;
g_correct = g_correct > 0.0f ? g_correct : 0.0f;
b_correct = b_correct > 0.0f ? b_correct : 0.0f;
/* Perform gamma compression */
r_correct = pow(r_correct, display_gamma_inv);
g_correct = pow(g_correct, display_gamma_inv);
b_correct = pow(b_correct, display_gamma_inv);
/* Range check... */
r_correct = r_correct > 1.0f ? 1.0f : r_correct;
g_correct = g_correct > 1.0f ? 1.0f : g_correct;
b_correct = b_correct > 1.0f ? 1.0f : b_correct;
/* Convert to RGB565 */
r_final = (unsigned)((r_correct * CC_RGB_MAX) + 0.5f) & 0x1F;
g_final = (unsigned)((g_correct * CC_RGB_MAX) + 0.5f) & 0x1F;
b_final = (unsigned)((b_correct * CC_RGB_MAX) + 0.5f) & 0x1F;
c_lut[color] = r_final << 11 | g_final << 6 | b_final;
}
}
int main(int argc, char *argv[])
{
FILE *file = NULL;
size_t i;
/* Populate lookup table */
init_lut();
/* Write header file */
file = fopen("../gba_cc_lut.h", "w");
if (!file)
return 1;
fprintf(file,
"#ifndef __CC_LUT_H__\n"
"#define __CC_LUT_H__\n\n"
"#include \"common.h\"\n\n"
"extern const u16 gba_cc_lut[];\n\n"
"#endif /* __CC_LUT_H__ */\n");
fclose(file);
file = NULL;
/* Write source file */
file = fopen("../gba_cc_lut.c", "w");
if (!file)
return 1;
fprintf(file,
"#include \"gba_cc_lut.h\"\n\n"
"const u16 gba_cc_lut[] = {\n");
for (i = 0; i < CC_LUT_SIZE; i++)
{
fprintf(file, " 0x%04x", c_lut[i]);
if (i == CC_LUT_SIZE - 1)
fprintf(file, "\n");
else
{
if ((i + 1) % 5 == 0)
fprintf(file, ",\n");
else
fprintf(file, ",");
}
}
fprintf(file, "};\n");
fclose(file);
file = NULL;
return 0;
}