aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias Gumz <akira at fluxbox dot org>2013-01-23 08:46:08 (GMT)
committerMathias Gumz <akira at fluxbox dot org>2013-01-23 08:46:08 (GMT)
commite7bfc639323bf5d4b207323b6e2fd275dcb5d825 (patch)
treef88b3e16a21300e3356a93cd3b0eedcf90128773
parentc67743d010cd0346ef145b98bd1caec189e09dfd (diff)
downloadfluxbox-e7bfc639323bf5d4b207323b6e2fd275dcb5d825.zip
fluxbox-e7bfc639323bf5d4b207323b6e2fd275dcb5d825.tar.bz2
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
-rw-r--r--src/FbTk/ColorLUT.cc187
-rw-r--r--src/FbTk/ColorLUT.hh8
-rw-r--r--src/FbTk/Texture.cc2
-rw-r--r--src/FbTk/TextureRender.cc34
4 files changed, 209 insertions, 22 deletions
diff --git a/src/FbTk/ColorLUT.cc b/src/FbTk/ColorLUT.cc
index 97af8aa..9bcabf7 100644
--- a/src/FbTk/ColorLUT.cc
+++ b/src/FbTk/ColorLUT.cc
@@ -1,4 +1,4 @@
1// ColorLUT.cc for Fluxbox Window Manager 1// ColorLUT.cc for Fluxbox Window Manager
2// Copyright (c) 2013 - Mathias Gumz <akira at fluxbox dot org> 2// Copyright (c) 2013 - Mathias Gumz <akira at fluxbox dot org>
3// 3//
4// Permission is hereby granted, free of charge, to any person obtaining a 4// Permission is hereby granted, free of charge, to any person obtaining a
@@ -22,6 +22,7 @@
22 22
23#include "ColorLUT.hh" 23#include "ColorLUT.hh"
24 24
25namespace FbTk {
25 26
26// created by: 27// created by:
27// 28//
@@ -52,8 +53,7 @@
52// ./a.out 1.5 | xxd -i -c 8 # value + (value >> 1)) 53// ./a.out 1.5 | xxd -i -c 8 # value + (value >> 1))
53// 54//
54 55
55namespace FbTk { 56#if 0 // unused
56
57const unsigned char ColorLUT::PRE_MULTIPLY_1_5[256] = { 57const unsigned char ColorLUT::PRE_MULTIPLY_1_5[256] = {
58 0x00, 0x01, 0x03, 0x04, 0x06, 0x07, 0x09, 0x0a, 58 0x00, 0x01, 0x03, 0x04, 0x06, 0x07, 0x09, 0x0a,
59 0x0c, 0x0d, 0x0f, 0x10, 0x12, 0x13, 0x15, 0x16, 59 0x0c, 0x0d, 0x0f, 0x10, 0x12, 0x13, 0x15, 0x16,
@@ -125,6 +125,7 @@ const unsigned char ColorLUT::PRE_MULTIPLY_1_125[256] = {
125 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 125 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
126}; 126};
127 127
128#endif
128 129
129// ./a.out 0.75 | xxd -i -c 8 # (value >> 1) + (value >> 2)) 130// ./a.out 0.75 | xxd -i -c 8 # (value >> 1) + (value >> 2))
130const unsigned char ColorLUT::PRE_MULTIPLY_0_75[256] = { 131const unsigned char ColorLUT::PRE_MULTIPLY_0_75[256] = {
@@ -162,5 +163,185 @@ const unsigned char ColorLUT::PRE_MULTIPLY_0_75[256] = {
162 0xba, 0xba, 0xbb, 0xbc, 0xbd, 0xbd, 0xbe, 0xbf 163 0xba, 0xba, 0xbb, 0xbc, 0xbd, 0xbd, 0xbe, 0xbf
163}; 164};
164 165
166
167
168// created by:
169//
170// #include <math.h>
171// #include <stdlib.h>
172// #include <unistd.h>
173//
174// int main(int argc, char const *argv[]) {
175//
176// size_t i;
177// unsigned char c;
178// unsigned int v;
179// unsigned int s = 4;
180//
181// if (argc > 1) {
182// s = atoi(argv[1]);
183// }
184//
185// for (i = 0; i < 256; ++i) {
186// v = i + ((0xff - i) / s);
187// c = (unsigned char)v;
188// write(1, &c, 1);
189// }
190//
191// return 0;
192// }
193//
194// math behind:
195//
196// rgb-color-space forms a cube. to make
197// something "brighter" one has to nudge a
198// given color towards "white" (255, 255, 255).
199// we use simple vector math to do this:
200//
201// (nred ) (red ) ((255) (red ))
202// (ngreen) = (green) + s * ((255) - (green))
203// (nblue ) (blue ) ((255) (blue ))
204//
205// this approach is better than just multiplying
206// a given color by a factor (ColorLUT::PRE_MULTIPLY*)
207// example:
208//
209// brighten_via_premultiply_*(#ff0000) = #ff0000
210// brighten_via_brighter_4(#ff0000) = #ffef3f
211//
212// right now the calculation of 's' is pretty
213// straightforward: it is just 1/nth of the length
214// of the vector-component. a more precise approach
215// would calculate the length of the vector via
216// sqrt(red * red + green * green + blue * blue) and
217// scale that value down, allthough this would
218// need either adhoc-computation or a more advanced
219// lookup-table. right now the simple approach is
220// sufficient.
221//
222// to make a color "darker" one has to nudge the
223// color towards "black" (0, 0, 0). the formula
224// from above changes to
225//
226// (nred) = (0) + s * ((red) - 0)
227// ...
228//
229// which simplifies down to (s * red) .. which is
230// covered by PRE_MULTIPLY_0_75 already.
231
232
233// ./a.out 4 | xxd -i -c 8
234const unsigned char ColorLUT::BRIGHTER_4[256] = {
235 0x3f, 0x40, 0x41, 0x42, 0x42, 0x43, 0x44, 0x45,
236 0x45, 0x46, 0x47, 0x48, 0x48, 0x49, 0x4a, 0x4b,
237 0x4b, 0x4c, 0x4d, 0x4e, 0x4e, 0x4f, 0x50, 0x51,
238 0x51, 0x52, 0x53, 0x54, 0x54, 0x55, 0x56, 0x57,
239 0x57, 0x58, 0x59, 0x5a, 0x5a, 0x5b, 0x5c, 0x5d,
240 0x5d, 0x5e, 0x5f, 0x60, 0x60, 0x61, 0x62, 0x63,
241 0x63, 0x64, 0x65, 0x66, 0x66, 0x67, 0x68, 0x69,
242 0x69, 0x6a, 0x6b, 0x6c, 0x6c, 0x6d, 0x6e, 0x6f,
243 0x6f, 0x70, 0x71, 0x72, 0x72, 0x73, 0x74, 0x75,
244 0x75, 0x76, 0x77, 0x78, 0x78, 0x79, 0x7a, 0x7b,
245 0x7b, 0x7c, 0x7d, 0x7e, 0x7e, 0x7f, 0x80, 0x81,
246 0x81, 0x82, 0x83, 0x84, 0x84, 0x85, 0x86, 0x87,
247 0x87, 0x88, 0x89, 0x8a, 0x8a, 0x8b, 0x8c, 0x8d,
248 0x8d, 0x8e, 0x8f, 0x90, 0x90, 0x91, 0x92, 0x93,
249 0x93, 0x94, 0x95, 0x96, 0x96, 0x97, 0x98, 0x99,
250 0x99, 0x9a, 0x9b, 0x9c, 0x9c, 0x9d, 0x9e, 0x9f,
251 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5,
252 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xab,
253 0xab, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb1,
254 0xb1, 0xb2, 0xb3, 0xb4, 0xb4, 0xb5, 0xb6, 0xb7,
255 0xb7, 0xb8, 0xb9, 0xba, 0xba, 0xbb, 0xbc, 0xbd,
256 0xbd, 0xbe, 0xbf, 0xc0, 0xc0, 0xc1, 0xc2, 0xc3,
257 0xc3, 0xc4, 0xc5, 0xc6, 0xc6, 0xc7, 0xc8, 0xc9,
258 0xc9, 0xca, 0xcb, 0xcc, 0xcc, 0xcd, 0xce, 0xcf,
259 0xcf, 0xd0, 0xd1, 0xd2, 0xd2, 0xd3, 0xd4, 0xd5,
260 0xd5, 0xd6, 0xd7, 0xd8, 0xd8, 0xd9, 0xda, 0xdb,
261 0xdb, 0xdc, 0xdd, 0xde, 0xde, 0xdf, 0xe0, 0xe1,
262 0xe1, 0xe2, 0xe3, 0xe4, 0xe4, 0xe5, 0xe6, 0xe7,
263 0xe7, 0xe8, 0xe9, 0xea, 0xea, 0xeb, 0xec, 0xed,
264 0xed, 0xee, 0xef, 0xf0, 0xf0, 0xf1, 0xf2, 0xf3,
265 0xf3, 0xf4, 0xf5, 0xf6, 0xf6, 0xf7, 0xf8, 0xf9,
266 0xf9, 0xfa, 0xfb, 0xfc, 0xfc, 0xfd, 0xfe, 0xff
267};
268
269// ./a.out 8 | xxd -i -c 8
270const unsigned char ColorLUT::BRIGHTER_8[256] = {
271 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
272 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
273 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34,
274 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
275 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42,
276 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
277 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
278 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
279 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e,
280 0x5e, 0x5f, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65,
281 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c,
282 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73,
283 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a,
284 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81,
285 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
286 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
287 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
288 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d,
289 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4,
290 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab,
291 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2,
292 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9,
293 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0,
294 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
295 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce,
296 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5,
297 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc,
298 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3,
299 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
300 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1,
301 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
302 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
303};
304
305#if 0 // unused
306
307// ./a.out 4 | xxd -i -c 8
308const unsigned char ColorLUT::BRIGHTER_16[256] = {
309 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
310 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
311 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
312 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
313 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34,
314 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c,
315 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43,
316 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
317 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52,
318 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a,
319 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61,
320 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
321 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
322 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
323 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
324 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
325 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e,
326 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
327 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d,
328 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5,
329 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac,
330 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4,
331 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb,
332 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3,
333 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca,
334 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2,
335 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9,
336 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1,
337 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8,
338 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
339 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
340 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
341};
342
343#endif
344
345
165} 346}
166 347
diff --git a/src/FbTk/ColorLUT.hh b/src/FbTk/ColorLUT.hh
index 66b8493..a9ff410 100644
--- a/src/FbTk/ColorLUT.hh
+++ b/src/FbTk/ColorLUT.hh
@@ -24,10 +24,18 @@ namespace FbTk {
24 24
25namespace ColorLUT { 25namespace ColorLUT {
26 26
27#if 0 // unused
27extern const unsigned char PRE_MULTIPLY_1_5[256]; 28extern const unsigned char PRE_MULTIPLY_1_5[256];
28extern const unsigned char PRE_MULTIPLY_1_125[256]; 29extern const unsigned char PRE_MULTIPLY_1_125[256];
30#endif
29extern const unsigned char PRE_MULTIPLY_0_75[256]; 31extern const unsigned char PRE_MULTIPLY_0_75[256];
30 32
33extern const unsigned char BRIGHTER_4[256];
34extern const unsigned char BRIGHTER_8[256];
35#if 0 // unused
36extern const unsigned char BRIGHTER_16[256];
37#endif
38
31} 39}
32 40
33} 41}
diff --git a/src/FbTk/Texture.cc b/src/FbTk/Texture.cc
index da45bc4..888b3c7 100644
--- a/src/FbTk/Texture.cc
+++ b/src/FbTk/Texture.cc
@@ -37,7 +37,7 @@
37namespace { 37namespace {
38 38
39unsigned short inline brighten(unsigned short c) { 39unsigned short inline brighten(unsigned short c) {
40 return 0x101 * FbTk::ColorLUT::PRE_MULTIPLY_1_5[c]; 40 return 0x101 * FbTk::ColorLUT::BRIGHTER_8[c];
41} 41}
42 42
43unsigned short inline darken(unsigned short c) { 43unsigned short inline darken(unsigned short c) {
diff --git a/src/FbTk/TextureRender.cc b/src/FbTk/TextureRender.cc
index f1addb4..8c7087f 100644
--- a/src/FbTk/TextureRender.cc
+++ b/src/FbTk/TextureRender.cc
@@ -49,9 +49,9 @@ using std::endl;
49using std::string; 49using std::string;
50using std::max; 50using std::max;
51using std::min; 51using std::min;
52using FbTk::ColorLUT::PRE_MULTIPLY_1_5;
53using FbTk::ColorLUT::PRE_MULTIPLY_1_125;
54using FbTk::ColorLUT::PRE_MULTIPLY_0_75; 52using FbTk::ColorLUT::PRE_MULTIPLY_0_75;
53using FbTk::ColorLUT::BRIGHTER_4;
54using FbTk::ColorLUT::BRIGHTER_8;
55 55
56namespace FbTk { 56namespace FbTk {
57 57
@@ -65,19 +65,17 @@ struct RGBA {
65 // simple function-pointers for interlace-code 65 // simple function-pointers for interlace-code
66 // (and avoid *this 'overhead') 66 // (and avoid *this 'overhead')
67 67
68 // 1.5 of current value, clamp to ~0 (0xff)
69 static void brighten_1_5(RGBA& color) {
70 color.r = PRE_MULTIPLY_1_5[color.r];
71 color.g = PRE_MULTIPLY_1_5[color.g];
72 color.b = PRE_MULTIPLY_1_5[color.b];
73 }
74 68
69 static void brighten_4(RGBA& color) {
70 color.r = BRIGHTER_4[color.r];
71 color.g = BRIGHTER_4[color.g];
72 color.b = BRIGHTER_4[color.b];
73 }
75 74
76 // 1.125 of current value 75 static void brighten_8(RGBA& color) {
77 static void brighten_1_125(RGBA& color) { 76 color.r = BRIGHTER_8[color.r];
78 color.r = PRE_MULTIPLY_1_125[color.r]; 77 color.g = BRIGHTER_8[color.g];
79 color.g = PRE_MULTIPLY_1_125[color.g]; 78 color.b = BRIGHTER_8[color.b];
80 color.b = PRE_MULTIPLY_1_125[color.b];
81 } 79 }
82 80
83 // 0.75 of old value 81 // 0.75 of old value
@@ -93,7 +91,7 @@ struct RGBA {
93}; 91};
94 92
95const RGBA::colorFunc RGBA::pseudoInterlaceFuncs[2] = { 93const RGBA::colorFunc RGBA::pseudoInterlaceFuncs[2] = {
96 RGBA::brighten_1_125, 94 RGBA::brighten_4,
97 RGBA::darken 95 RGBA::darken
98}; 96};
99 97
@@ -287,13 +285,13 @@ void renderBevel1(bool interlaced,
287 // brighten top line and first pixel of the 285 // brighten top line and first pixel of the
288 // 2nd line 286 // 2nd line
289 for (i = 0; i < width + 1; ++i) { 287 for (i = 0; i < width + 1; ++i) {
290 FbTk::RGBA::brighten_1_5(rgba[i]); 288 FbTk::RGBA::brighten_4(rgba[i]);
291 } 289 }
292 290
293 // bright and darken left and right border 291 // bright and darken left and right border
294 for (i = 2 * width - 1; i < s - width; i += width) { 292 for (i = 2 * width - 1; i < s - width; i += width) {
295 FbTk::RGBA::darken(rgba[i]); // right border 293 FbTk::RGBA::darken(rgba[i]); // right border
296 FbTk::RGBA::brighten_1_5(rgba[i + 1]); // left border on the next line 294 FbTk::RGBA::brighten_4(rgba[i + 1]); // left border on the next line
297 } 295 }
298 296
299 // darken bottom line, except the first pixel 297 // darken bottom line, except the first pixel
@@ -331,14 +329,14 @@ void renderBevel2(bool interlaced,
331 329
332 // top line, but stop 2 pixels before right border 330 // top line, but stop 2 pixels before right border
333 for (i = (width + 1); i < ((2 * width) - 2); i++) { 331 for (i = (width + 1); i < ((2 * width) - 2); i++) {
334 FbTk::RGBA::brighten_1_5(rgba[i]); 332 FbTk::RGBA::brighten_4(rgba[i]);
335 } 333 }
336 334
337 // first darken the right border, then brighten the 335 // first darken the right border, then brighten the
338 // left border 336 // left border
339 for ( ; i < (s - (2 * width) - 1); i += width) { 337 for ( ; i < (s - (2 * width) - 1); i += width) {
340 FbTk::RGBA::darken(rgba[i]); 338 FbTk::RGBA::darken(rgba[i]);
341 FbTk::RGBA::brighten_1_5(rgba[i + 3]); 339 FbTk::RGBA::brighten_4(rgba[i + 3]);
342 } 340 }
343 341
344 // bottom line 342 // bottom line