Smooth radial gradient on HTML Canvas

When I create a radial gradient on HTML Canvas, it doesn’t look totally smooth, you can see the visible circles (Firefox 96.0.3):

I want the gradient to be totally smooth (Shouldn’t the gradient look smooth by default? Why does it look stepped?).

Here is the code I use:

// HTML
<canvas width="1000" height="1000"></canvas>

// JS
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');

var grd = ctx.createRadialGradient(500, 500, 0, 500, 500, 1000);
grd.addColorStop(0, '#444444');
grd.addColorStop(1, '#000000');
ctx.fillStyle = grd;
ctx.fillRect(0, 0, canvas.width, canvas.height);

I tried adding more color stops (as much as 10,000) but it made no difference. I also tried adding blur, it didn’t make much difference either. Is there a way to make the gradient totaly smooth?

Thanks for any opinions.

What you are seeing are quantisation artefacts.

Windows computers use 256 levels of red green and blue, so there are only 256 levels of pure grey available. To reduce the quantization artefacts, the sRGB standard for Windows computers includes a non-linear transfer function so the light level from a monitor screen is not proportional to the digital values of red, green and blue. Although originally done to allow for the characteristics of CRT displays, it has the effect of significantly reducing quantisation artefacts of near-black dark colours.

The introduction of dither can be surprisingly effective at reducing quantisation artefacts. In this image there are only 8 levels of grey but error diffusion dither has been applied. If you don’t believe me that there are no more than 8 levels of grey, try clicking on the image to enlarge it and then zoom in :grinning:

NOTE: this forum is compressing images so to see my image it’s necesary to click on the image.

Unfortunately, dither does not seem to be available for <canvas> elements. In any case you would probably still be limited by the 256 quantisation levels.

3 Likes

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.