# 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:

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:

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:

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:

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 L*a*b* 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:

-
note, i made a comment about perceptual bands (below), but this was before I really looked at the question. I see that you are speaking about how two particular color ranges stand out. – horatio Feb 26 '13 at 22:27
Nice diagram! That's exactly what I mean by sharp corners, I was imagining a colour cube like this one or like this. I've added a crude but hopefully useful illustration of the kind of thing I mean to my answer. (of course there's also the second pair of sharp corners at the points where the red path adds green to reach white, and where the blue path adds red to reach white) – user568458 Mar 1 '13 at 12:42

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)

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).

• #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)

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...):

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.

-
so tldr; avoid values of 255 for R,G,B channels (?) – horatio Feb 27 '13 at 18:14
@horatio not really no, more like tldr; avoid sharp corners between sections of a gradient – user568458 Feb 27 '13 at 18:20
It all depends on the colour space used for output - you'd see the same bands in print design if you had a gradient that went for example from pure white to pure magenta to pure violet (100% magenta and cyan) to pure black (made of 100% C,m,k) – user568458 Feb 27 '13 at 18:27
More like "avoid sharp corners while moving through HSB space"? But if I try to do cubic interpolation or something, I end up going outside of HSB space, which then clips the values and causes bad things anyway. In my second example, I'm kind of doing what you recommend about adding bridging sections, but it's not working perfectly. It still looks like a blob of yellow inside a blob of reddish-orange with a halo around it, instead of a smoothly-varying color change. – endolith Feb 27 '13 at 19:56
Here's an attempt using a bezier curve instead: flic.kr/p/e1bcFf flic.kr/p/e15wik – endolith Mar 6 '13 at 16:26

Maybe this could help you, it works for me, but I don't know a manual way to accomplish it.

http://nomorebanding.com/

-
That's not the same kind of banding, and dithering isn't possible in this context, anyway. I guess I'm talking more about perceptual bands in what should be a smooth gradient, while your link is about banding due to quantization of the colors? – endolith Feb 26 '13 at 15:07
the perceptual bands are from color quantization. It is a problem with 8-bit per pixel representation. I don't know anything about the plug-in, but using 16bpp RGB when producing gradients and then down-sampling to 8bpp will produce far better results with far less banding than building them in 8bpp. – horatio Feb 26 '13 at 15:36
@horatio: No, the bands are from the curve taking sharp corners as it moves through perceptual color space. Specifically, in my example, it's the chroma that's reaching a peak at those corners. – endolith Oct 23 '14 at 1:36