Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

A hierarchy of color (intensity)?

by BrowserUk (Pope)
on Nov 22, 2005 at 06:24 UTC ( #510659=perlquestion: print w/replies, xml ) Need Help??
BrowserUk has asked for the wisdom of the Perl Monks concerning the following question:

I want to represent a range of numerical values (approx: 0 -> 1000) using colors such that there is an visually obvious gradient between low and high values, with similar values being visually similar. Kind of like astronomers use to show differences and similarities on IR or UV photographs.

Should I use a lookup table (and is there one available)?

Or can I get away with a formula to map them (and does anyone know such a formula)?

Update: I finally found a reference for what astronomers use--it's call a Color Ramp, and there is a standard one.

The reference for anyone following along is Color Ramp and there is an implementation in C at C source.

I've translated this into Perl as:

sub colorRamp { my( $v, $vmin, $vmax ) = @_; my( $r, $g, $b ) = (1) x 3; $v = $vmax if $v > $vmax; $v = $vmin if $v < $vmin; ## Uncomment below to invert the color range ## so that small numbers are hot (red) ## and high numbers are cold (blue) ## $v = $vmax + $vmin - $v; my $dv = $vmax - $vmin; if( $v < ( $vmin + 0.25*$dv ) ) { $r = 0; $g = 4 * ($v - $vmin) / $dv; } elsif( $v < ( $vmin + 0.5 * $dv ) ) { $r = 0; $b = 1 + 4 * ($vmin + 0.25 * $dv - $v) / $dv; } elsif( $v < ( $vmin + 0.75 * $dv ) ) { $r = 4 * ($v - $vmin - 0.5 * $dv) / $dv; $b = 0; } else { $g = 1 + 4 * ($vmin + 0.75 * $dv - $v) / $dv; $b = 0; } ## Convert the 0->1 range rgb values to 0->255 ## and output as a web/tk style "#rrggbb" hex string return sprintf "#%02x%02x%02x", $r*255, $g*255, $b*255; }

Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

Replies are listed 'Best First'.
Re: A hierarchy of color (intensity)?
by creamygoodness (Curate) on Nov 22, 2005 at 06:53 UTC

    It seems like Color::Scheme may be of some use here. The effect you want can be realized by varying the hue value in a hue-saturation-brightness color model -- the H in HSB. The only problem is to find an HSB implementation which meets the 1000-discrete-values criteria.

    Marvin Humphrey
    Rectangular Research ―

      Color::Scheme produces sets of complimentary colors, in groups of 4 to 16. Not quite what I need.

      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        Mmm, you're right about Color::Scheme... not what I thought at first glance...

        ( ... time passes ... )

        Aha! Try Graphics::ColorObject.

        If you have access to any graphic app that has an HSB (aka HSV, HSL) color picker with sliders, you can see the desired effect by moving the H slider. That effect can be reproduced using Graphics::ColorObject to build a converter and holding the Saturation and Brightness values constant while varing the Hue.

        Marvin Humphrey
        Rectangular Research ―
Re: A hierarchy of color (intensity)?
by Zaxo (Archbishop) on Nov 22, 2005 at 06:56 UTC

    By default, GD uses an indexed color table.

    One simple mapping is to think of the "color wheel" of red-yellow-green-cyan-blue-magenta-red and all the interpolated colors. Map an arc of, say, red through blue and insert those in order into the GD color table.

    With only eight-bit color channels, you may need to dither the intensity or the third color a bit if you want all thousand to be unique.

    After Compline,

Re: A hierarchy of color (intensity)?
by Perl Mouse (Chaplain) on Nov 22, 2005 at 10:18 UTC
    A way of doing that would be by using the following table:
    Intermediate value are calculated by linear interpolation. This gives you 2040 different colours; nearby values are mapped to nearby numbers; and values far apart will have quite different values (with the caveat that the table above is cyclic). It shouldn't be too hard to turn this table into code.

    If you just have 1000 numbers, multiply the numbers by 2 before consulting the above table, or just use a subset of the colours.

    If you have a lot of numbers, much more numbers than there are different values, it probably pays to make a lookup table.

    Perl --((8:>*
Re: A hierarchy of color (intensity)?
by inman (Curate) on Nov 22, 2005 at 10:01 UTC
    The following code was actually the result of a Perl Monks discussion. The code simply creates an HTML page that contains all the websafe colours. The interesting bit is the luminosity calculation that is used to determine whether the text should be black or white. The colour table produces blocks of 256 colours but this could be extended by increasing the number of starting values.
Re: A hierarchy of color (intensity)?
by YuckFoo (Abbot) on Nov 22, 2005 at 20:55 UTC

    A sine wave can be used to make a good color gradient, see Color Gradient Generator for the idea, sub make_rgb() for the formula. Turn of $WRAPPING for your purpose.


Re: A hierarchy of color (intensity)?
by renodino (Curate) on Nov 22, 2005 at 16:18 UTC
    I've used a fairly simplistic solution for DBD::Chart: a simple linear interpolation of RGB values between 2 endpoint colors. E.g., if "cold" is blue and "hot" is yellow, then simply subdivide the value range between the 2 colors into a fixed number of slots (number of available slots depends on your graphics library and/or the app's environment). Then just interpolate each of the R, G, and B values between the endpoint values of each slot. Works surprisingly well despite its simplicity (e.g., see the quadtree display at the DBIx::Chart homepage. I also used a similar technique to provide 3-D shading for the 3-D barcharts.)

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://510659]
Approved by monkfan
[vrk]: Hope he gets better soon.
[Discipulus]: hdb sorry i profit; is known that a prime number is never a figurate one nor the sumattion of two adjacent figurates of the same order? like 3th triangular+3th tetrahedric
[Discipulus]: if known where i can read about the matter?
[choroba]: he's not really sick, we just got nobody to look after him today
[Discipulus]: create an account for him; we are funny baby sitters ;=) come here child, want to listen the typeglob tale?
[vrk]: choroba Oh, that's good.
[vrk]: Discipulus I don't know much about prime numbers, but wouldn't that kind of an answer be in a graduate-level number theory book?
[Discipulus]: my 8 yo daughter has two weeks of sleep disturbs.. we are gonna be crazy..

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (7)
As of 2017-04-27 07:59 GMT
Find Nodes?
    Voting Booth?
    I'm a fool:

    Results (501 votes). Check out past polls.