summaryrefslogtreecommitdiff
path: root/tools/generate_cc_lut.c
diff options
context:
space:
mode:
authorjdgleaver2020-09-21 17:50:21 +0100
committerjdgleaver2020-09-21 18:03:58 +0100
commitaa7feb70ca6157e1aa83f1e19062c9a6a85773fb (patch)
tree271b7068c4023fa5750911c5385c03fcf4673274 /tools/generate_cc_lut.c
parent4a2848af48359a6c06ceb0f38da2051088536f04 (diff)
downloadpicogpsp-aa7feb70ca6157e1aa83f1e19062c9a6a85773fb.tar.gz
picogpsp-aa7feb70ca6157e1aa83f1e19062c9a6a85773fb.tar.bz2
picogpsp-aa7feb70ca6157e1aa83f1e19062c9a6a85773fb.zip
Add optional colour correction + interframe blending
Diffstat (limited to 'tools/generate_cc_lut.c')
-rw-r--r--tools/generate_cc_lut.c135
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;
+}