aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2021-06-15 04:35:41 +0200
committerPřemysl Eric Janouch <p@janouch.name>2021-06-15 07:09:23 +0200
commitb4dd0052ffc60fbd642729a3e05bcadbd6edd6e1 (patch)
tree68676dbb46fc9d1bb1e214ea9116f6ecaca8754b
parente3c47c33fa3a1fb9412198413962ac35f4483240 (diff)
downloaduirc3-b4dd0052ffc60fbd642729a3e05bcadbd6edd6e1.tar.gz
uirc3-b4dd0052ffc60fbd642729a3e05bcadbd6edd6e1.tar.xz
uirc3-b4dd0052ffc60fbd642729a3e05bcadbd6edd6e1.zip
degesch: pick colours based on relative luminance
Replaces the inaccurate Rec. 709 luma we used to use before. This is the first feature here that requires libm, which doesn't seem to be a particularly great sacrifice. Moreover, I've rectified that the input isn't linear in sRGB, and then was even normalized wrong for the luma formula.
-rw-r--r--CMakeLists.txt3
-rw-r--r--degesch.c19
-rwxr-xr-xtest-nick-colors23
3 files changed, 38 insertions, 7 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e3dbb7c..acbfb72 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -61,7 +61,8 @@ endif ()
# -lrt is only for glibc < 2.17
# -liconv may or may not be a part of libc
-foreach (extra iconv rt)
+# -lm may or may not be a part of libc
+foreach (extra iconv rt m)
find_library (extra_lib_${extra} ${extra})
if (extra_lib_${extra})
list (APPEND project_libraries ${extra_lib_${extra}})
diff --git a/degesch.c b/degesch.c
index 3262691..0e70813 100644
--- a/degesch.c
+++ b/degesch.c
@@ -51,6 +51,7 @@ enum
#include "common.c"
#include "kike-replies.c"
+#include <math.h>
#include <langinfo.h>
#include <locale.h>
#include <pwd.h>
@@ -2108,17 +2109,23 @@ filter_color_cube_for_acceptable_nick_colors (size_t *len)
// This is a pure function and we don't use threads, static storage is fine
static int table[6 * 6 * 6];
size_t len_counter = 0;
- for (int x = 0; x < 6 * 6 * 6; x++)
+ for (int x = 0; x < N_ELEMENTS (table); x++)
{
- // FIXME this isn't exactly right, the values aren't linear
int r = x / 36;
int g = (x / 6) % 6;
int b = (x % 6);
- // Use the luma value of colours within the cube to filter colours that
- // look okay-ish on terminals with both black and white backgrounds
- double luma = 0.2126 * r / 6. + 0.7152 * g / 6. + 0.0722 * b / 6.;
- if (luma >= .3 && luma <= .5)
+ // The first step is 95/255, the rest are 40/255,
+ // as an approximation we can double the first step
+ double linear_R = pow ((r + !!r) / 6., 2.2);
+ double linear_G = pow ((g + !!g) / 6., 2.2);
+ double linear_B = pow ((b + !!b) / 6., 2.2);
+
+ // Use the relative luminance of colours within the cube to filter
+ // colours that look okay-ish on terminals with both black and white
+ // backgrounds (use the test-nick-colors script to calibrate)
+ double Y = 0.2126 * linear_R + 0.7152 * linear_G + 0.0722 * linear_B;
+ if (Y >= .25 && Y <= .4)
table[len_counter++] = 16 + x;
}
*len = len_counter;
diff --git a/test-nick-colors b/test-nick-colors
new file mode 100755
index 0000000..a09f74a
--- /dev/null
+++ b/test-nick-colors
@@ -0,0 +1,23 @@
+#!/bin/sh
+# Check whether the terminal colours filtered by our algorithm are legible
+export example=$(
+ tcc "-run -lm" - <<-EOF
+ #include <stddef.h>
+ #include <stdio.h>
+ #include <math.h>
+
+ $(perl -0777 -ne 'print $& if /^.*?\nfilter_color(?s:.*?)^}$/m' degesch.c)
+
+ void main () {
+ size_t len = 0;
+ int *table = filter_color_cube_for_acceptable_nick_colors (&len);
+ for (size_t i = 0; i < len; i++)
+ printf ("<@\\x1b[38;5;%dmIRCuser\\x1b[m> I'm typing!\n", table[i]);
+ }
+ EOF
+)
+
+# Both should give acceptable results,
+# which results in a bad compromise that the main author himself needs
+xterm -bg black -fg white -e 'echo $example; cat' &
+xterm -bg white -fg black -e 'echo $example; cat' &