diff options
author | Ron Yorston <rmy@pobox.com> | 2021-02-07 14:27:48 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2021-02-07 14:27:48 +0000 |
commit | 15286a04d8ae24530380d92d302f839b056e7a6e (patch) | |
tree | b99380ad9b5c7c74a6d9115bc2729363a932fe11 | |
parent | 96cc886097812dfeb3f1096492ff0c601e38b17f (diff) | |
download | busybox-w32-15286a04d8ae24530380d92d302f839b056e7a6e.tar.gz busybox-w32-15286a04d8ae24530380d92d302f839b056e7a6e.tar.bz2 busybox-w32-15286a04d8ae24530380d92d302f839b056e7a6e.zip |
winansi: more accurate colour mapping
Use a more accurate technique to map RGB colours to standard
Windows console colours. Since this costs 648 bytes it's
configurable but is enabled by default.
-rw-r--r-- | Config.in | 8 | ||||
-rw-r--r-- | configs/mingw32_defconfig | 3 | ||||
-rw-r--r-- | configs/mingw64_defconfig | 3 | ||||
-rw-r--r-- | win32/winansi.c | 119 |
4 files changed, 111 insertions, 22 deletions
@@ -472,6 +472,14 @@ config SKIP_ANSI_EMULATION_DEFAULT | |||
472 | Setting the environment variable BB_SKIP_ANSI_EMULATION overrides | 472 | Setting the environment variable BB_SKIP_ANSI_EMULATION overrides |
473 | this default. | 473 | this default. |
474 | 474 | ||
475 | config FEATURE_IMPROVED_COLOUR_MAPPING | ||
476 | bool "More accurate colour mapping for ANSI emulation (0.6 kb)" | ||
477 | default y | ||
478 | depends on PLATFORM_MINGW32 | ||
479 | help | ||
480 | Use a more accurate technique to map RGB colours to the standard | ||
481 | Windows console colours. | ||
482 | |||
475 | config FEATURE_EXTRA_FILE_DATA | 483 | config FEATURE_EXTRA_FILE_DATA |
476 | bool "Read additional file metadata (2.1 kb)" | 484 | bool "Read additional file metadata (2.1 kb)" |
477 | default y | 485 | default y |
diff --git a/configs/mingw32_defconfig b/configs/mingw32_defconfig index 51b27f366..f245141f3 100644 --- a/configs/mingw32_defconfig +++ b/configs/mingw32_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Busybox version: 1.34.0.git | 3 | # Busybox version: 1.34.0.git |
4 | # Wed Feb 3 13:41:09 2021 | 4 | # Sun Feb 7 13:53:22 2021 |
5 | # | 5 | # |
6 | CONFIG_HAVE_DOT_CONFIG=y | 6 | CONFIG_HAVE_DOT_CONFIG=y |
7 | # CONFIG_PLATFORM_POSIX is not set | 7 | # CONFIG_PLATFORM_POSIX is not set |
@@ -53,6 +53,7 @@ CONFIG_FEATURE_ICON=y | |||
53 | CONFIG_FEATURE_ICON_ALL=y | 53 | CONFIG_FEATURE_ICON_ALL=y |
54 | CONFIG_FEATURE_EURO=y | 54 | CONFIG_FEATURE_EURO=y |
55 | CONFIG_SKIP_ANSI_EMULATION_DEFAULT=2 | 55 | CONFIG_SKIP_ANSI_EMULATION_DEFAULT=2 |
56 | CONFIG_FEATURE_IMPROVED_COLOUR_MAPPING=y | ||
56 | CONFIG_FEATURE_EXTRA_FILE_DATA=y | 57 | CONFIG_FEATURE_EXTRA_FILE_DATA=y |
57 | CONFIG_FEATURE_READLINK2=y | 58 | CONFIG_FEATURE_READLINK2=y |
58 | 59 | ||
diff --git a/configs/mingw64_defconfig b/configs/mingw64_defconfig index a8cb75215..3ac1f7703 100644 --- a/configs/mingw64_defconfig +++ b/configs/mingw64_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Busybox version: 1.34.0.git | 3 | # Busybox version: 1.34.0.git |
4 | # Wed Feb 3 13:41:09 2021 | 4 | # Sun Feb 7 13:53:22 2021 |
5 | # | 5 | # |
6 | CONFIG_HAVE_DOT_CONFIG=y | 6 | CONFIG_HAVE_DOT_CONFIG=y |
7 | # CONFIG_PLATFORM_POSIX is not set | 7 | # CONFIG_PLATFORM_POSIX is not set |
@@ -53,6 +53,7 @@ CONFIG_FEATURE_ICON=y | |||
53 | CONFIG_FEATURE_ICON_ALL=y | 53 | CONFIG_FEATURE_ICON_ALL=y |
54 | CONFIG_FEATURE_EURO=y | 54 | CONFIG_FEATURE_EURO=y |
55 | CONFIG_SKIP_ANSI_EMULATION_DEFAULT=2 | 55 | CONFIG_SKIP_ANSI_EMULATION_DEFAULT=2 |
56 | CONFIG_FEATURE_IMPROVED_COLOUR_MAPPING=y | ||
56 | CONFIG_FEATURE_EXTRA_FILE_DATA=y | 57 | CONFIG_FEATURE_EXTRA_FILE_DATA=y |
57 | CONFIG_FEATURE_READLINK2=y | 58 | CONFIG_FEATURE_READLINK2=y |
58 | 59 | ||
diff --git a/win32/winansi.c b/win32/winansi.c index efb6efeb7..6120d5c28 100644 --- a/win32/winansi.c +++ b/win32/winansi.c | |||
@@ -262,6 +262,27 @@ static void move_cursor(int x, int y) | |||
262 | SetConsoleCursorPosition(console, pos); | 262 | SetConsoleCursorPosition(console, pos); |
263 | } | 263 | } |
264 | 264 | ||
265 | static const unsigned char colour_1bit[16] = { | ||
266 | /* Black */ 0, | ||
267 | /* Red */ FOREGROUND_RED, | ||
268 | /* Green */ FOREGROUND_GREEN, | ||
269 | /* Yellow */ FOREGROUND_RED | FOREGROUND_GREEN, | ||
270 | /* Blue */ FOREGROUND_BLUE, | ||
271 | /* Magenta */ FOREGROUND_RED | FOREGROUND_BLUE, | ||
272 | /* Cyan */ FOREGROUND_GREEN | FOREGROUND_BLUE, | ||
273 | /* White */ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, | ||
274 | /* ... and again but brighter */ | ||
275 | FOREGROUND_INTENSITY, | ||
276 | FOREGROUND_RED | FOREGROUND_INTENSITY, | ||
277 | FOREGROUND_GREEN | FOREGROUND_INTENSITY, | ||
278 | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, | ||
279 | FOREGROUND_BLUE | FOREGROUND_INTENSITY, | ||
280 | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY, | ||
281 | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY, | ||
282 | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY | ||
283 | }; | ||
284 | |||
285 | #if !ENABLE_FEATURE_IMPROVED_COLOUR_MAPPING | ||
265 | static WORD rgb_to_console(int *rgb) | 286 | static WORD rgb_to_console(int *rgb) |
266 | { | 287 | { |
267 | int dark = 0, bright; | 288 | int dark = 0, bright; |
@@ -291,6 +312,84 @@ static WORD rgb_to_console(int *rgb) | |||
291 | 312 | ||
292 | return attr; | 313 | return attr; |
293 | } | 314 | } |
315 | #else | ||
316 | #include <math.h> | ||
317 | |||
318 | /* Standard console colours in LAB colour space */ | ||
319 | static float colour_lab[16][3] = { | ||
320 | {-0.000000, 0.000000, 0.000000}, | ||
321 | {25.530788, 48.055233, 38.059635}, | ||
322 | {46.228817, -51.699638, 49.897949}, | ||
323 | {51.868336, -12.930751, 56.677288}, | ||
324 | {12.975313, 47.507763, -64.704285}, | ||
325 | {29.782101, 58.939846, -36.497940}, | ||
326 | {48.256081, -28.841570, -8.481050}, | ||
327 | {77.704361, 0.004262, -0.008416}, | ||
328 | {53.585018, 0.003129, -0.006235}, | ||
329 | {53.232883, 80.109299, 67.220078}, | ||
330 | {87.737038, -86.184654, 83.181168}, | ||
331 | {97.138245, -21.555901, 94.482483}, | ||
332 | {32.302586, 79.196678, -107.863686}, | ||
333 | {60.319931, 98.254234, -60.842991}, | ||
334 | {91.116524, -48.079609, -14.138126}, | ||
335 | {100.000000, 0.005245, -0.010419}, | ||
336 | }; | ||
337 | |||
338 | /* Convert RGB to XYZ and XYZ to LAB. See: | ||
339 | * http://www.easyrgb.com/en/math.php#text1 */ | ||
340 | static void rgb2lab(const int *rgb, float *lab) | ||
341 | { | ||
342 | float var_RGB[3], var_XYZ[3]; | ||
343 | int i; | ||
344 | |||
345 | for (i = 0; i < 3; ++i) { | ||
346 | var_RGB[i] = rgb[i]/255.0; | ||
347 | if (var_RGB[i] > 0.04045) | ||
348 | var_RGB[i] = pow(((var_RGB[i] + 0.055) / 1.055), 2.4); | ||
349 | else | ||
350 | var_RGB[i] /= 12.92; | ||
351 | } | ||
352 | |||
353 | /* use equal energy reference values */ | ||
354 | var_XYZ[0] = var_RGB[0]*0.4124 + var_RGB[1]*0.3576 + var_RGB[2]*0.1805; | ||
355 | var_XYZ[1] = var_RGB[0]*0.2126 + var_RGB[1]*0.7152 + var_RGB[2]*0.0722; | ||
356 | var_XYZ[2] = var_RGB[0]*0.0193 + var_RGB[1]*0.1192 + var_RGB[2]*0.9505; | ||
357 | |||
358 | for (i = 0; i < 3; ++i) { | ||
359 | if (var_XYZ[i] > 0.008856) | ||
360 | var_XYZ[i] = pow(var_XYZ[i], 1.0 / 3.0); | ||
361 | else | ||
362 | var_XYZ[i] = 7.787 * var_XYZ[i] + 16.0 / 116.0; | ||
363 | } | ||
364 | |||
365 | lab[0] = 116.0 * var_XYZ[1] - 16.0; | ||
366 | lab[1] = 500.0 * (var_XYZ[0] - var_XYZ[1]); | ||
367 | lab[2] = 200.0 * (var_XYZ[1] - var_XYZ[2]); | ||
368 | } | ||
369 | |||
370 | static WORD rgb_to_console(int *rgb) | ||
371 | { | ||
372 | int i, imin = 0; | ||
373 | float deltamin = 1.0e20; | ||
374 | |||
375 | /* Use 1976 CIE deltaE to find closest console colour. See: | ||
376 | * https://zschuessler.github.io/DeltaE/learn */ | ||
377 | for (i = 0; i < 16; ++i) { | ||
378 | float lab[3], dl, da, db, delta; | ||
379 | |||
380 | rgb2lab(rgb, lab); | ||
381 | dl = colour_lab[i][0] - lab[0]; | ||
382 | da = colour_lab[i][1] - lab[1]; | ||
383 | db = colour_lab[i][2] - lab[2]; | ||
384 | delta = dl * dl + da * da + db *db; | ||
385 | if (delta < deltamin) { | ||
386 | imin = i; | ||
387 | deltamin = delta; | ||
388 | } | ||
389 | } | ||
390 | return colour_1bit[imin]; | ||
391 | } | ||
392 | #endif | ||
294 | 393 | ||
295 | /* 24-bit colour */ | 394 | /* 24-bit colour */ |
296 | static char *process_24bit(char *str, WORD *attr) | 395 | static char *process_24bit(char *str, WORD *attr) |
@@ -308,26 +407,6 @@ static char *process_24bit(char *str, WORD *attr) | |||
308 | return str; | 407 | return str; |
309 | } | 408 | } |
310 | 409 | ||
311 | static const unsigned char colour_1bit[16] = { | ||
312 | /* Black */ 0, | ||
313 | /* Red */ FOREGROUND_RED, | ||
314 | /* Green */ FOREGROUND_GREEN, | ||
315 | /* Yellow */ FOREGROUND_RED | FOREGROUND_GREEN, | ||
316 | /* Blue */ FOREGROUND_BLUE, | ||
317 | /* Magenta */ FOREGROUND_RED | FOREGROUND_BLUE, | ||
318 | /* Cyan */ FOREGROUND_GREEN | FOREGROUND_BLUE, | ||
319 | /* White */ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, | ||
320 | /* ... and again but brighter */ | ||
321 | FOREGROUND_INTENSITY, | ||
322 | FOREGROUND_RED | FOREGROUND_INTENSITY, | ||
323 | FOREGROUND_GREEN | FOREGROUND_INTENSITY, | ||
324 | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, | ||
325 | FOREGROUND_BLUE | FOREGROUND_INTENSITY, | ||
326 | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY, | ||
327 | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY, | ||
328 | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY | ||
329 | }; | ||
330 | |||
331 | /* 8-bit colour */ | 410 | /* 8-bit colour */ |
332 | static char *process_8bit(char *str, WORD *attr) | 411 | static char *process_8bit(char *str, WORD *attr) |
333 | { | 412 | { |