How do you avoid bands of prominent color in gradients?

So this is more scientific visualization than graphic design, but I think the theory is the same. In colormaps used for visualizing data, there are often bands of color that stick out when they shouldn’t. I believe they’re a form of Mach bands?

For instance, I used this bipolar colormap and it produces images like this:

enter image description here

It’s almost like a ring of neon orange around 0.2, and a similar one for blue around -0.2. Here’s a plot of the RGB components, and a calculation of relative luminance in black:

enter image description here

I manually tweaked it to try to get rid of the bands, and somewhat succeeded, but I don’t really understand the theory behind it:

enter image description here

enter image description here

It’s better, but I still see bands in it.

For another example, for the hot colormap, I thought maybe I had to linearize the luminance plot to prevent banding, but it didn’t really work:

enter image description here
enter image description here

The yellow and orange bands are still there, they’re just moved and smeared out a little. So discontinuities in the luminance plot are not the cause of the problem.

How do I smoothly transition through colors without banding? Are there rules for making smooth curves through Lab color space or something? (Edit: Ooh, I found an example for this: “The color scale is computed using the Lab* color space. It follows a uniform ramp along the L* direction, and it follows a semicircular path in the a*-b* plane.”)

Update: Here’s a plot of this colormap in the RGB cube, showing the sharp angles user568458 is talking about:

enter image description here


Don’t forget that, even if you’re working with LAB colour values, RGB values have to be output to show it on a screen. At some point, it has to tell the red, green and blue pixels of a screen what to do.

Look at it in RGB terms, and the cause of the bands is actually pretty simple.

Grab a colour picker and look at the gradients, and you’ll notice that the bands are around the points where the nature of the gradient changes:

  • In the red, it’s around where it turns from smoothly increasing the R in the RGB to adding G to become yellow – around #FF0000 to #FF2500
  • In the blue, it’s around where it turns from smoothly increasing the B in the RGB to adding G to become cyan – around #0000FF to #0025FF

And likewise with the bottom plots, adding yellow to white: they’re essentially three gradients joined together. Using the red gradient as an example:

  • it’s #000000 to #FF0000 (increasing Brightness in HSB terms, increasing Red channel in RGB)
  • then #FF0000 to #FFFF00 (changing Hue in HSB terms, increasing Green channel in RGB)
  • then #FFFF00 to #FFFFFF (changing Saturation in HSB terms, increasing Blue channel in RGB)

enter image description here

So there’s always going to be a visible join, if that’s how it’s set up. As a general rule, where accuracy and linearity are the main aim, it’s best to keep a gradient simple, varying one feature constantly (unless you want banding, e.g. on some types of brain scan).

That said, if you’re determined to run through the wider spectrum (it does look good), I’d look into either beginning to add the second channel before the first is complete, forming a bridging section between the gradients, or having a slight reverse S shape curve to the rate at which the second channel is added (probably both).

So instead of:

  • 000000 to #FF0000, 100% black to 100% red

  • FF0000 to #FFFF00, 100% red to 100% yellow

  • FFFF00 to #FFFFFF, 100% yellow to 100% white

…it might be (just guesses off the top of my head, will need adjustment):

  • 000000 to #E90000, 100% black to bright red

  • E90000 to #FF2500, (SHORT BRIDGE) bright red (dark) to bright red (slightly orange)

  • FF2500 to #FFE900, bright red (slightly orange) to bright yellow (slightly orange)

  • FFE900 to #FFFF25, (SHORT BRIDGE) bright yellow (slightly orange) to bright yellow (light)

  • FFFF25 to #FFFFFF, bright yellow (light) to 100% white

…then adjust the curves of each section according to taste 🙂

Edit: Here’s a demonstration of the ‘cutting the corners’ suggestion. It’s not perfect – it’s fairly unrefined, just something I put together by eye in a few minutes using the Illustrator blend tool (unblended objects at the bottom to show the colour points). Each segment of the gradient between each colour point is 100% linear, whereas you’d probably want something more rounded – and as a result, if you look carefully you can spot bands.

Results naturally vary between monitors: on my ‘good’ monitor, it’s smooth; on the ‘bad’ monitor I use for checking the resilience of web images (where the original bands don’t show very clearly), oranges always appear subdued making the red and yellow ares seem brighter than the joining orange, over-emphasising the red and yellow areas – but you can still see that the ‘edge’ of the original bands has largely gone.

Either way, compared with the original gradients, you can clearly see the difference. (as for the maths behind this – no idea, I’m no mathematician, but hopefully this helps identify the problem and solution)

enter image description here

The other advantage is, you’re free to use the clearer black > one channel transition more.

Or the same idea on an RGB colour cube (forgive the crudeness, it’s intended to be demonstrative not accurate…):

enter image description here

This shows probably more clearly what I meant when I said the example gradient can be improved by making the transitions from main segments to corner-cutting segments smooth rather than angular.

Source : Link , Question Author : endolith , Answer Author : Community

Leave a Comment