aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-02-07 14:27:48 +0000
committerRon Yorston <rmy@pobox.com>2021-02-07 14:27:48 +0000
commit15286a04d8ae24530380d92d302f839b056e7a6e (patch)
treeb99380ad9b5c7c74a6d9115bc2729363a932fe11
parent96cc886097812dfeb3f1096492ff0c601e38b17f (diff)
downloadbusybox-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.in8
-rw-r--r--configs/mingw32_defconfig3
-rw-r--r--configs/mingw64_defconfig3
-rw-r--r--win32/winansi.c119
4 files changed, 111 insertions, 22 deletions
diff --git a/Config.in b/Config.in
index 6d91ad248..356bc6d5a 100644
--- a/Config.in
+++ b/Config.in
@@ -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
475config 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
475config FEATURE_EXTRA_FILE_DATA 483config 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#
6CONFIG_HAVE_DOT_CONFIG=y 6CONFIG_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
53CONFIG_FEATURE_ICON_ALL=y 53CONFIG_FEATURE_ICON_ALL=y
54CONFIG_FEATURE_EURO=y 54CONFIG_FEATURE_EURO=y
55CONFIG_SKIP_ANSI_EMULATION_DEFAULT=2 55CONFIG_SKIP_ANSI_EMULATION_DEFAULT=2
56CONFIG_FEATURE_IMPROVED_COLOUR_MAPPING=y
56CONFIG_FEATURE_EXTRA_FILE_DATA=y 57CONFIG_FEATURE_EXTRA_FILE_DATA=y
57CONFIG_FEATURE_READLINK2=y 58CONFIG_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#
6CONFIG_HAVE_DOT_CONFIG=y 6CONFIG_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
53CONFIG_FEATURE_ICON_ALL=y 53CONFIG_FEATURE_ICON_ALL=y
54CONFIG_FEATURE_EURO=y 54CONFIG_FEATURE_EURO=y
55CONFIG_SKIP_ANSI_EMULATION_DEFAULT=2 55CONFIG_SKIP_ANSI_EMULATION_DEFAULT=2
56CONFIG_FEATURE_IMPROVED_COLOUR_MAPPING=y
56CONFIG_FEATURE_EXTRA_FILE_DATA=y 57CONFIG_FEATURE_EXTRA_FILE_DATA=y
57CONFIG_FEATURE_READLINK2=y 58CONFIG_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
265static 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
265static WORD rgb_to_console(int *rgb) 286static 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 */
319static 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 */
340static 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
370static 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 */
296static char *process_24bit(char *str, WORD *attr) 395static 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
311static 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 */
332static char *process_8bit(char *str, WORD *attr) 411static char *process_8bit(char *str, WORD *attr)
333{ 412{