Mesh gradients are great for creating life-like illustrations. Long asked for, they were one of the first things we added to the SVG 2 specification. I added mesh support to Inkscape (behind a compiler flag) for testing. There was one problem that was immediately apparent: as mesh gradients use bilinear interpolation between corner colors, there were non-smooth color transitions between the mesh patches leading to unwanted visual artifacts. See my blog post from a few years ago for more details about this problem.
A little bit of investigation showed that Adobe Illustrator and CoralDRAW use some sort of smoothing algorithm to get rid of the artifacts. We asked Adobe if they would give us the algorithm but they replied no. I did a little research and found that using bicubic interpolation would be a good solution. After adding a trial implementation in Inkscape and demonstrating it at last year’s Sydney SVG working group meeting, I got the group’s approval to add this to the SVG 2 specification.
The discussion in the Wikipedia of bicubic interpolation has some nice heat map illustrations showing the effects of bilinear vs. bicubic interpolation. I thought it would be interesting to duplicate these illustrations using SVG. Here is how I did it.
The first step is to create a mesh. It is rather easy to do this in Inkscape with the mesh tool. I created a raw mesh with a 3×3 array of patches to match the one in the Wikipedia article. The tricky part is then to set each patch corner to a gray level based on the data. I estimated the data values from looking at the color chart in the Wikipedia illustrations. I then converted each gray level into an appropriate RGB hex color value. Here is the result with bilinear interpolation:
A mesh gradient with a 3×3 array of patches using bilinear interpolation (i.e. without smoothing). The gray levels at the patch corners represent the input data.
One can clearly see the visual artifacts at the mesh boundaries (enhanced by Mach Banding). Switching to bicubic interpolation produces a smoother mesh as seen next:
A mesh gradient using bicubic interpolation (i.e. with smoothing). The gray levels of the patch corners represent the input data.
The next step is to transform the gray levels into a color scale. For this I turned to SVG filters. I used a filter consisting of a single Component Transfer filter primitive. I created a table to map gray level to color by inverting the estimation I used to convert the colors into gray values. Here are the results for both bilinear and bicubic interpolation:
A mesh gradient using bilinear interpolation (i.e. without smoothing) with a simple SVG filter to convert gray levels to color values.
A mesh gradient using bicubic interpolation (i.e. with smoothing) with a simple SVG filter to convert gray levels to color values.
The match between these images (generated with Inkscape) and those in the Wikipedia article are pretty good.
Convincing the SVG working group to add meshes to SVG and then to adding the auto-smoothing option would not of been possible without attending the SVG working group meetings in person. It is much easier to lobby for things when one can provide live demonstrations. At these meetings I’ve been able to get auto-flowed text, text on a shape, font-features support, hatch fills, the arcs and clipped miter line joins, etc. into the SVG 2 specification. The Inkscape board has been allocating funds for my travel (thanks Inkscape donors!). To enable travel to future working group meetings, a designated fund for SVG specification work has been set up. The SVG working group holds about three face-to-face meetings each year (in addition to weekly teleconferences). If you are interested in supporting SVG development from an end-user perspective, please consider donating. More information on the work I’ve done as well a donations link can be found at the Inkscape website on the SVG Standards Work page. (Donations are tax deductible in the US.)