all repos — fluxbox @ e7bfc639323bf5d4b207323b6e2fd275dcb5d825

custom fork of the fluxbox windowmanager

Improve calculation of brighter colors

The old code did not brighten up "pure" colors like "red", "green" and "blue"
at all. The new code use a different precomputed LUT which is based upon
simplified vector math, see the comments in FbTk/ColorLUT.cc
Mathias Gumz akira at fluxbox dot org
commit

e7bfc639323bf5d4b207323b6e2fd275dcb5d825

parent

c67743d010cd0346ef145b98bd1caec189e09dfd

4 files changed, 209 insertions(+), 22 deletions(-)

jump to
M src/FbTk/ColorLUT.ccsrc/FbTk/ColorLUT.cc

@@ -1,4 +1,4 @@

-// ColorLUT.cc for Fluxbox Window Manager +// ColorLUT.cc for Fluxbox Window Manager // Copyright (c) 2013 - Mathias Gumz <akira at fluxbox dot org> // // Permission is hereby granted, free of charge, to any person obtaining a

@@ -22,6 +22,7 @@

#include "ColorLUT.hh" +namespace FbTk { // created by: //

@@ -52,8 +53,7 @@

// ./a.out 1.5 | xxd -i -c 8 # value + (value >> 1)) // -namespace FbTk { - +#if 0 // unused const unsigned char ColorLUT::PRE_MULTIPLY_1_5[256] = { 0x00, 0x01, 0x03, 0x04, 0x06, 0x07, 0x09, 0x0a, 0x0c, 0x0d, 0x0f, 0x10, 0x12, 0x13, 0x15, 0x16,

@@ -125,6 +125,7 @@ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,

0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +#endif // ./a.out 0.75 | xxd -i -c 8 # (value >> 1) + (value >> 2)) const unsigned char ColorLUT::PRE_MULTIPLY_0_75[256] = {

@@ -161,6 +162,186 @@ 0xae, 0xae, 0xaf, 0xb0, 0xb1, 0xb1, 0xb2, 0xb3,

0xb4, 0xb4, 0xb5, 0xb6, 0xb7, 0xb7, 0xb8, 0xb9, 0xba, 0xba, 0xbb, 0xbc, 0xbd, 0xbd, 0xbe, 0xbf }; + + + +// created by: +// +// #include <math.h> +// #include <stdlib.h> +// #include <unistd.h> +// +// int main(int argc, char const *argv[]) { +// +// size_t i; +// unsigned char c; +// unsigned int v; +// unsigned int s = 4; +// +// if (argc > 1) { +// s = atoi(argv[1]); +// } +// +// for (i = 0; i < 256; ++i) { +// v = i + ((0xff - i) / s); +// c = (unsigned char)v; +// write(1, &c, 1); +// } +// +// return 0; +// } +// +// math behind: +// +// rgb-color-space forms a cube. to make +// something "brighter" one has to nudge a +// given color towards "white" (255, 255, 255). +// we use simple vector math to do this: +// +// (nred ) (red ) ((255) (red )) +// (ngreen) = (green) + s * ((255) - (green)) +// (nblue ) (blue ) ((255) (blue )) +// +// this approach is better than just multiplying +// a given color by a factor (ColorLUT::PRE_MULTIPLY*) +// example: +// +// brighten_via_premultiply_*(#ff0000) = #ff0000 +// brighten_via_brighter_4(#ff0000) = #ffef3f +// +// right now the calculation of 's' is pretty +// straightforward: it is just 1/nth of the length +// of the vector-component. a more precise approach +// would calculate the length of the vector via +// sqrt(red * red + green * green + blue * blue) and +// scale that value down, allthough this would +// need either adhoc-computation or a more advanced +// lookup-table. right now the simple approach is +// sufficient. +// +// to make a color "darker" one has to nudge the +// color towards "black" (0, 0, 0). the formula +// from above changes to +// +// (nred) = (0) + s * ((red) - 0) +// ... +// +// which simplifies down to (s * red) .. which is +// covered by PRE_MULTIPLY_0_75 already. + + +// ./a.out 4 | xxd -i -c 8 +const unsigned char ColorLUT::BRIGHTER_4[256] = { + 0x3f, 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x45, + 0x45, 0x46, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b, + 0x4b, 0x4c, 0x4d, 0x4e, 0x4e, 0x4f, 0x50, 0x51, + 0x51, 0x52, 0x53, 0x54, 0x54, 0x55, 0x56, 0x57, + 0x57, 0x58, 0x59, 0x5a, 0x5a, 0x5b, 0x5c, 0x5d, + 0x5d, 0x5e, 0x5f, 0x60, 0x60, 0x61, 0x62, 0x63, + 0x63, 0x64, 0x65, 0x66, 0x66, 0x67, 0x68, 0x69, + 0x69, 0x6a, 0x6b, 0x6c, 0x6c, 0x6d, 0x6e, 0x6f, + 0x6f, 0x70, 0x71, 0x72, 0x72, 0x73, 0x74, 0x75, + 0x75, 0x76, 0x77, 0x78, 0x78, 0x79, 0x7a, 0x7b, + 0x7b, 0x7c, 0x7d, 0x7e, 0x7e, 0x7f, 0x80, 0x81, + 0x81, 0x82, 0x83, 0x84, 0x84, 0x85, 0x86, 0x87, + 0x87, 0x88, 0x89, 0x8a, 0x8a, 0x8b, 0x8c, 0x8d, + 0x8d, 0x8e, 0x8f, 0x90, 0x90, 0x91, 0x92, 0x93, + 0x93, 0x94, 0x95, 0x96, 0x96, 0x97, 0x98, 0x99, + 0x99, 0x9a, 0x9b, 0x9c, 0x9c, 0x9d, 0x9e, 0x9f, + 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xab, + 0xab, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb1, + 0xb1, 0xb2, 0xb3, 0xb4, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb7, 0xb8, 0xb9, 0xba, 0xba, 0xbb, 0xbc, 0xbd, + 0xbd, 0xbe, 0xbf, 0xc0, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc3, 0xc4, 0xc5, 0xc6, 0xc6, 0xc7, 0xc8, 0xc9, + 0xc9, 0xca, 0xcb, 0xcc, 0xcc, 0xcd, 0xce, 0xcf, + 0xcf, 0xd0, 0xd1, 0xd2, 0xd2, 0xd3, 0xd4, 0xd5, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd8, 0xd9, 0xda, 0xdb, + 0xdb, 0xdc, 0xdd, 0xde, 0xde, 0xdf, 0xe0, 0xe1, + 0xe1, 0xe2, 0xe3, 0xe4, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe7, 0xe8, 0xe9, 0xea, 0xea, 0xeb, 0xec, 0xed, + 0xed, 0xee, 0xef, 0xf0, 0xf0, 0xf1, 0xf2, 0xf3, + 0xf3, 0xf4, 0xf5, 0xf6, 0xf6, 0xf7, 0xf8, 0xf9, + 0xf9, 0xfa, 0xfb, 0xfc, 0xfc, 0xfd, 0xfe, 0xff +}; + +// ./a.out 8 | xxd -i -c 8 +const unsigned char ColorLUT::BRIGHTER_8[256] = { + 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, + 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, + 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, + 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, + 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, + 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, + 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, + 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, + 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, + 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, + 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, + 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, + 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, + 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, + 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, + 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, + 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, + 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, + 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, + 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + +#if 0 // unused + +// ./a.out 4 | xxd -i -c 8 +const unsigned char ColorLUT::BRIGHTER_16[256] = { + 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, + 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, + 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, + 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, + 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, + 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, + 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, + 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, + 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, + 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, + 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, + 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, + 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, + 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, + 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, + 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, + 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, + 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, + 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, + 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, + 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, + 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff +}; + +#endif + }
M src/FbTk/ColorLUT.hhsrc/FbTk/ColorLUT.hh

@@ -24,9 +24,17 @@ namespace FbTk {

namespace ColorLUT { +#if 0 // unused extern const unsigned char PRE_MULTIPLY_1_5[256]; extern const unsigned char PRE_MULTIPLY_1_125[256]; +#endif extern const unsigned char PRE_MULTIPLY_0_75[256]; + +extern const unsigned char BRIGHTER_4[256]; +extern const unsigned char BRIGHTER_8[256]; +#if 0 // unused +extern const unsigned char BRIGHTER_16[256]; +#endif }
M src/FbTk/Texture.ccsrc/FbTk/Texture.cc

@@ -37,7 +37,7 @@

namespace { unsigned short inline brighten(unsigned short c) { - return 0x101 * FbTk::ColorLUT::PRE_MULTIPLY_1_5[c]; + return 0x101 * FbTk::ColorLUT::BRIGHTER_8[c]; } unsigned short inline darken(unsigned short c) {
M src/FbTk/TextureRender.ccsrc/FbTk/TextureRender.cc

@@ -49,9 +49,9 @@ using std::endl;

using std::string; using std::max; using std::min; -using FbTk::ColorLUT::PRE_MULTIPLY_1_5; -using FbTk::ColorLUT::PRE_MULTIPLY_1_125; using FbTk::ColorLUT::PRE_MULTIPLY_0_75; +using FbTk::ColorLUT::BRIGHTER_4; +using FbTk::ColorLUT::BRIGHTER_8; namespace FbTk {

@@ -65,19 +65,17 @@ // use of 'static void function()' here to have

// simple function-pointers for interlace-code // (and avoid *this 'overhead') - // 1.5 of current value, clamp to ~0 (0xff) - static void brighten_1_5(RGBA& color) { - color.r = PRE_MULTIPLY_1_5[color.r]; - color.g = PRE_MULTIPLY_1_5[color.g]; - color.b = PRE_MULTIPLY_1_5[color.b]; - } + static void brighten_4(RGBA& color) { + color.r = BRIGHTER_4[color.r]; + color.g = BRIGHTER_4[color.g]; + color.b = BRIGHTER_4[color.b]; + } - // 1.125 of current value - static void brighten_1_125(RGBA& color) { - color.r = PRE_MULTIPLY_1_125[color.r]; - color.g = PRE_MULTIPLY_1_125[color.g]; - color.b = PRE_MULTIPLY_1_125[color.b]; + static void brighten_8(RGBA& color) { + color.r = BRIGHTER_8[color.r]; + color.g = BRIGHTER_8[color.g]; + color.b = BRIGHTER_8[color.b]; } // 0.75 of old value

@@ -93,7 +91,7 @@ static const colorFunc pseudoInterlaceFuncs[2];

}; const RGBA::colorFunc RGBA::pseudoInterlaceFuncs[2] = { - RGBA::brighten_1_125, + RGBA::brighten_4, RGBA::darken };

@@ -287,13 +285,13 @@

// brighten top line and first pixel of the // 2nd line for (i = 0; i < width + 1; ++i) { - FbTk::RGBA::brighten_1_5(rgba[i]); + FbTk::RGBA::brighten_4(rgba[i]); } // bright and darken left and right border for (i = 2 * width - 1; i < s - width; i += width) { FbTk::RGBA::darken(rgba[i]); // right border - FbTk::RGBA::brighten_1_5(rgba[i + 1]); // left border on the next line + FbTk::RGBA::brighten_4(rgba[i + 1]); // left border on the next line } // darken bottom line, except the first pixel

@@ -331,14 +329,14 @@ size_t i;

// top line, but stop 2 pixels before right border for (i = (width + 1); i < ((2 * width) - 2); i++) { - FbTk::RGBA::brighten_1_5(rgba[i]); + FbTk::RGBA::brighten_4(rgba[i]); } // first darken the right border, then brighten the // left border for ( ; i < (s - (2 * width) - 1); i += width) { FbTk::RGBA::darken(rgba[i]); - FbTk::RGBA::brighten_1_5(rgba[i + 3]); + FbTk::RGBA::brighten_4(rgba[i + 3]); } // bottom line