- Contemporary messages sorted: [ by date ] [ by thread ] [ by subject ] [ by author ] [ by messages with attachments ]

From: Alexander S. <alex0player_AT_gmail.com>

Date: Mon, 26 May 2014 06:25:12 +0400

2014-05-22 1:57 GMT+04:00 Roberto E. Vargas Caballero <k0ga_AT_shike2.com>:

*>> Read this: http://www.4p8.com/eric.brasseur/gamma.html
*

*>>
*

*>> We need to generally re-think the algorithm used here. I hate the idea
*

*>> of being conformant to this or that terminal emulator and instead
*

*>> prefer an implementation according to how it's defined (!).
*

*>
*

*> I like this idea, but I don't know how it could be implemented.
*

The obvious idea is to convert a colour to HSV/HSL, increase

brightness, and convert it back

(One cannot help but notice that such a calculation is a matter of

initialization, since appropriate bright colours may be calculated for

all built-in colours in advance. Therefore, one possible solution may

be to modify dc.col (also xloadcols and xsetcolorname) to have

structures, containing normal and bold variants for a colour.)

After this point, dragons lie.

In HSV model, there are notions of Value, which is equal to maximum

among colors, and Saturation, which is 1 - Max/Min. Thus, Max = V, Min

= V (1 - S).

Then,

R = r * Max + (1 - r) * Min = V * (r + (1 - r) * (1 - S)),

G = g * Max + (1 - g) * Min = ..., and so on, and r, g, b depend only

on Hue. It is then trivial to see that a change in Brightness is a

trivial rescale: R_{new} = V_{new} * R_{old}/V_{old}. (In linear

space, not gamma space.) It's a simple calculation indeed, but, as

XTerm cube contains a lot of colours close to pure, it may not look

appropriate.

In HSL model, there are notions of Saturation and Lightness.

Saturation is calculated as (Max - Min)/(1 - |1 - (Max + Min)|), and

Lightness as (Max + Min)/2. Thus, reverse calculations of Max and Min

are a little more involved, but the general truth remains the same:

all colour components are convex combinations between Max and Min,

whose coefficients depend only on Hue.

Thus, for R coordinate for example, R_{new} = (R_{old} - Min_{old}) /

(Max_{old} - Min_{old}) * (Max_{new} - Min_{new}) + Min_{new}. It's

the same rescaling but with two points instead of one.

(I cannot emphanise enough that we DO NOT need luminance or perceived

brightness here. These define the brightness of all colours to come

common reference point, whereas lightness/value define brightness

relative to a reference color of the same hue. Which is exactly what

we need. Default colors are of different brightnesses, and this is not

our concern.)

Let us now estimate how precise should we be in our tables of sRGB <->

linear conversion. Let's say that, for the simplicity, we use the

evenly-spaced table and linear interpolation. (Dreadful.) The error is

estimated thus by h^2 * 1/8 max(f''(x)). for sRGB->linear, the

constant is 3.429/8 = 0.428. Let's say we want the precision of 2e-16,

which is totally reasonable considering that we use 16-bit color

model. And I might say, is ain't so bad! We merely need ~170 data

points. Let's go big and make it 257. (Then, the index for a 16-bit

integer is just number>>8.)

As for the reverse transofrmation, there we experience a big uprise

around zero. In fact, the second derivative peaks at ~-2300, which is

indeed true: the function curves a lot there, and interpolating it is

the world of trouble, requiring ~4300 points, which is distressingly

only slightly more than 4096. Makes things even worse.

Fortunately, we happen to know the reverse function for this one,

which is not only pretty smooth - but we also have a table for it! So

the task results in binary search in aforementioned table (of size

257, I might remind you, so it's more or less instant) and doing a

linear interpolation afterwards. Slower, but saves us a lot of

trouble!

Thus, the proposal requires addition of:

- the table of 16-bit integers of size 257;

- the function of interpolating y given x1, x2, y1, y2 and x;

- the function of increasing a given color's brightness;

- possibly changes to dc.col, depending on how costly it will be to do

such calculations on the fly vs in the initialization.

Date: Mon, 26 May 2014 06:25:12 +0400

2014-05-22 1:57 GMT+04:00 Roberto E. Vargas Caballero <k0ga_AT_shike2.com>:

The obvious idea is to convert a colour to HSV/HSL, increase

brightness, and convert it back

(One cannot help but notice that such a calculation is a matter of

initialization, since appropriate bright colours may be calculated for

all built-in colours in advance. Therefore, one possible solution may

be to modify dc.col (also xloadcols and xsetcolorname) to have

structures, containing normal and bold variants for a colour.)

After this point, dragons lie.

In HSV model, there are notions of Value, which is equal to maximum

among colors, and Saturation, which is 1 - Max/Min. Thus, Max = V, Min

= V (1 - S).

Then,

R = r * Max + (1 - r) * Min = V * (r + (1 - r) * (1 - S)),

G = g * Max + (1 - g) * Min = ..., and so on, and r, g, b depend only

on Hue. It is then trivial to see that a change in Brightness is a

trivial rescale: R_{new} = V_{new} * R_{old}/V_{old}. (In linear

space, not gamma space.) It's a simple calculation indeed, but, as

XTerm cube contains a lot of colours close to pure, it may not look

appropriate.

In HSL model, there are notions of Saturation and Lightness.

Saturation is calculated as (Max - Min)/(1 - |1 - (Max + Min)|), and

Lightness as (Max + Min)/2. Thus, reverse calculations of Max and Min

are a little more involved, but the general truth remains the same:

all colour components are convex combinations between Max and Min,

whose coefficients depend only on Hue.

Thus, for R coordinate for example, R_{new} = (R_{old} - Min_{old}) /

(Max_{old} - Min_{old}) * (Max_{new} - Min_{new}) + Min_{new}. It's

the same rescaling but with two points instead of one.

(I cannot emphanise enough that we DO NOT need luminance or perceived

brightness here. These define the brightness of all colours to come

common reference point, whereas lightness/value define brightness

relative to a reference color of the same hue. Which is exactly what

we need. Default colors are of different brightnesses, and this is not

our concern.)

Let us now estimate how precise should we be in our tables of sRGB <->

linear conversion. Let's say that, for the simplicity, we use the

evenly-spaced table and linear interpolation. (Dreadful.) The error is

estimated thus by h^2 * 1/8 max(f''(x)). for sRGB->linear, the

constant is 3.429/8 = 0.428. Let's say we want the precision of 2e-16,

which is totally reasonable considering that we use 16-bit color

model. And I might say, is ain't so bad! We merely need ~170 data

points. Let's go big and make it 257. (Then, the index for a 16-bit

integer is just number>>8.)

As for the reverse transofrmation, there we experience a big uprise

around zero. In fact, the second derivative peaks at ~-2300, which is

indeed true: the function curves a lot there, and interpolating it is

the world of trouble, requiring ~4300 points, which is distressingly

only slightly more than 4096. Makes things even worse.

Fortunately, we happen to know the reverse function for this one,

which is not only pretty smooth - but we also have a table for it! So

the task results in binary search in aforementioned table (of size

257, I might remind you, so it's more or less instant) and doing a

linear interpolation afterwards. Slower, but saves us a lot of

trouble!

Thus, the proposal requires addition of:

- the table of 16-bit integers of size 257;

- the function of interpolating y given x1, x2, y1, y2 and x;

- the function of increasing a given color's brightness;

- possibly changes to dc.col, depending on how costly it will be to do

such calculations on the fly vs in the initialization.

-- Best regards, Alexander Sedov.Received on Mon May 26 2014 - 04:25:12 CEST

*
This archive was generated by hypermail 2.3.0
: Mon May 26 2014 - 04:36:07 CEST
*