diff options
Diffstat (limited to 'tools/generate_cc_lut.c')
-rw-r--r-- | tools/generate_cc_lut.c | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/tools/generate_cc_lut.c b/tools/generate_cc_lut.c new file mode 100644 index 0000000..33b4cef --- /dev/null +++ b/tools/generate_cc_lut.c @@ -0,0 +1,135 @@ +#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; +} |