3
$\begingroup$

Red, Green and Blue apparently contribute differently to the luminosity perceived by humans:

https://en.wikipedia.org/wiki/Relative_luminance

I am trying to find an algorithm to map unsigned 16 bit integers into RGB values such that the relative luminance of the RGB values to which the integers map respects their order (with integer 0 being black, integer 2^16-1 white and all other integers mapped to some RGB color).

I don't really care about how the colors evolve as one walks up from 0 to 2^16-1 as long as luminosity always increases and a reasonably large swathe of the RGB space is used.

Apparently I am missing the right words to describe what I am trying to accomplish as I've failed to google anything pertinent. A couple of weeks ago I had stumbled upon a paper that described such an algorithm in the form of a helix that is arranged diagonally in the three dimensional RGB space such that when one starts at the base of the helix and works his way towards the other end, luminosity always increases and a large variety of color is used. Alas, I can't find it any more.

update

Found the algorithm I was looking for. It is known as the 'cubehelix' color scheme by Dave Green and is described here: http://www.mrao.cam.ac.uk/~dag/CUBEHELIX/. The original paper is here: http://astron-soc.in/bulletin/11June/289392011.pdf

$\endgroup$
  • 1
    $\begingroup$ There are infinitely many solutions to your problem, you may want to impose extra constraints. $\endgroup$ – lightxbulb Sep 5 '19 at 15:01
3
$\begingroup$

Since you want monotonically increasing luminance, it's probably best to work in a color space that separates luma from chroma, such as a Y'UV space. You can assign values in Y'UV and then convert it to RGB using the matrix at that link.

Start by setting $Y' = N / (2^{16} - 1)$, where N is your input 16-bit integer. Now you just need to make up some function to use for the U and V components.

It wasn't clear to me if you want the chroma part of the color to vary continuously with the input N, or be pseudo-random. For a continuous curve, you could just have it be a circle in UV space: $$ U = 0.5 \cos(2\pi N/2^{16}) \\ V = 0.5 \sin(2\pi N/2^{16}) $$ or whatever other curve you feel like coming up with. For a pseudo-random chroma, you could use a hash function, or a Halton sequence or another low-discrepancy sequence.

| improve this answer | |
$\endgroup$
  • 1
    $\begingroup$ The above, together with a modified version of the YUV to RGB formula found here: fourcc.org/fccyvrgb.php (which seems to assume that Y, U and V are in the 0-255 range so I had to scale the numbers your answer produces) produced an acceptable result. $\endgroup$ – Marcus Junius Brutus Sep 5 '19 at 19:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.