Photorealistic images with vector graphics
Visual Math
What are vector graphics and how could we make them better?
Have you ever wondered why you can zoom in on a piece of text in your web browser, PDF viewer, or word processor, and it still retains the smooth look it had at the original scale? In comparison, zooming in on a web image generally yields a pixelated or ragged-looking result. What gives text this resolution-independent property, and is it possible to extend this property to graphics in general?
Understanding Vector Graphics
A discussion of computer graphics should begin with the observation that there are two types of graphics: raster graphics and vector graphics. You're probably quite familiar with raster graphics – rectangular grids composed of individually colored pixels. Zooming in on a pixel-based raster image eventually results in either a blocky picture or a somewhat smoother result that often looks a bit blurred. This blurring or distortion is caused by an interpolation algorithm that generates new pixel data for the magnified version based on the values of neighboring pixels. On the other hand, vector graphics relies on mathematical descriptions of curves. These descriptions are resolution-independent, which means that vector graphics can scale without losing quality. The glyphs of a font that you look at on your screen are examples of vector graphics in daily life. If you're interested in taking a closer look at the curves defining these characters, install FontForge [1] (or alternatively, Birdfont [2]), and open a font you're interested in (commonly stored in /usr/share/fonts
).
For a deeper look at vector graphics, it is very useful to install a dedicated vector graphics editor – the open source Inkscape is an excellent choice. Start by adding a circle, a (rounded) star, and a single character from your favorite font. Set the fill of all objects to none and the stroke to a solid light gray. Then, with all three selected, choose the option Path | Object to Path. Viewing the resulting paths in edit mode (F2) with everything selected should yield a result similar to the images in Figure 1.
The squares (referred to as nodes) and round handles are all it takes to define these composite curves. A single curve segment consists of two of each: a node at each endpoint of the curve segment and a handle connected to each node to define the tangent – that is, the direction – of the curve at those points. These curves are known as (cubic) Bézier curves, and they were discovered in the French car industry in the early sixties by Paul de Casteljau and Pierre Bézier, who at the time were working at Citroën and Renault, respectively. Bézier curves are the fundamental building block of vector graphics. (Press B in Inkscape and click/drag on the canvas to create a new Bézier curve.)
When a curve consists of multiple segments, nodes usually have handles on both sides. If a node and its two handles lie on a single line, the connection between the two segments is smooth (or tangent-continuous in mathematical language), which is often desired in a design. Most nodes in Figure 1 are smooth nodes, with the exception of some nodes defining the outline of the character S from the Linux Libertine font, which are sharp nodes.
Bézier curves facilitate the design of intricate 2D shapes. You can design these shapes manually or obtain them automatically – in Inkscape, a raster graphic can be traced using the option Path | Trace Bitmap.
The fill of paths can be set to a single color, though that probably won't result in something quite lifelike. A linear or radial gradient brings the result a bit closer to life but is still rather limiting.
For something better, consider a rectangular curve network, where each cell is defined by four Bézier curves. Something like the 2x2 curve network in Figure 2 will do for now.
The curves can be moved around freely, though the nodes at path intersections are connected to each other (something which currently cannot be done in Inkscape in edit mode). Take, for example, the central node, which is connected to four curve segments, or in other words, is a corner of four cells.
Next, assign a color to each node, which you could visualize as shown in Figure 3.
Finally, interpolate the assigned colors over the interior of the cells. You can interpolate in a variety of ways – using cubic interpolation (the same type used by the Bézier curves, but now in both directions) is a reasonable choice resulting in a smooth color propagation (Figure 4).
The overall concept is known as a gradient mesh, and it was added to Adobe Illustrator as a new vector graphics primitive in 1998 following the introduction of PostScript 3. Soon after, it also became available in CorelDRAW, and nowadays it is available in Inkscape as well. The gradient mesh feature facilitates the design of lifelike graphics that are fully scalable.
Refinements?
After using the gradient mesh tool for a while, you'll probably become aware of certain shortcomings. For one, if you want to add more detail to your shape, you'll likely need more cells. But because the gradient mesh is inherently stored as a rectangular curve network, you'll end up with an entire new row and/or column of additional cells. These unneeded cells can quickly clutter the workspace and slow down your machine. Instead, a local approach would be much better, though it requires a more sophisticated data structure. The example in Figure 5 shows the difference between a global (standard/traditional) and a local (improved) refinement of a gradient mesh.
Secondly, the network's rectangular nature itself is rather limiting – modeling an arbitrary object as a deformed curved rectangle is not exactly intuitive. Although several gradient meshes can be placed on top of each other to partially remedy this, this approach is not very user-friendly. Instead, letting go of the rectangular nature of the curve network altogether provides much more freedom. Although maintaining a smooth color propagation in such a flexible setting poses a mathematical challenge, it is certainly possible.
Another obstacle is the assignment of sharp transitions in color, which requires a minor modification of the data structure. The examples in Figure 6, 7, 8 and 9 showcase the three improvements I just described.
As of the time of this article, vector graphics editors only support the traditional version of the gradient mesh (the examples in Figures 6-8 were generated using my own software, which was developed as part of my PhD). We hope that graphics developers will add these advanced features to the leading open source vector graphics editors in the near future. Nevertheless, digital artists have created some quite sophisticated digital artwork using gradient meshes – a quick search on DeviantArt [3] shows how realistic you can get with common vector graphics tools.
Other Improvements
Just as shapes composed of curves can be traced automatically, raster graphics can be automatically vectorized into gradient meshes by external tools. This fact makes it possible to create resolution-independent versions of existing art, which can then be displayed and printed at any size without losing quality. An added benefit is that a vector representation can be much smaller than a raster representation of a medium to large image – in other words, vectorization could also be used from the perspective of file compression.
In addition to the gradient mesh, there is a second primitive known as diffusion curves that aims for the same goal – scalable photorealistic images. The necessary steps are as follows. First, the outline and inner detail of a shape are designed using Bézier curves. Then, a color gradient can be assigned to each curve. Finally, these assigned color profiles are then diffused throughout the interior, producing smooth results. In addition to curves, individual color points can be added that also diffuse their color around them. This is evidently much closer to the workflow of an artist, and therefore more intuitive to use than gradient meshes. Although the concept has been around for over a decade, it got introduced as a primitive in Adobe Illustrator only recently under the name freeform gradient – you will find some demonstrations and how-to on YouTube.
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
System76 Refreshes Meerkat Mini PC
If you're looking for a small form factor PC powered by Linux, System76 has exactly what you need in the Meerkat mini PC.
-
Gnome 48 Alpha Ready for Testing
The latest Gnome desktop alpha is now available with plenty of new features and improvements.
-
Wine 10 Includes Plenty to Excite Users
With its latest release, Wine has the usual crop of bug fixes and improvements, along with some exciting new features.
-
Linux Kernel 6.13 Offers Improvements for AMD/Apple Users
The latest Linux kernel is now available, and it includes plenty of improvements, especially for those who use AMD or Apple-based systems.
-
Gnome 48 Debuts New Audio Player
To date, the audio player found within the Gnome desktop has been meh at best, but with the upcoming release that all changes.
-
Plasma 6.3 Ready for Public Beta Testing
Plasma 6.3 will ship with KDE Gear 24.12.1 and KDE Frameworks 6.10, along with some new and exciting features.
-
Budgie 10.10 Scheduled for Q1 2025 with a Surprising Desktop Update
If Budgie is your desktop environment of choice, 2025 is going to be a great year for you.
-
Firefox 134 Offers Improvements for Linux Version
Fans of Linux and Firefox rejoice, as there's a new version available that includes some handy updates.
-
Serpent OS Arrives with a New Alpha Release
After months of silence, Ikey Doherty has released a new alpha for his Serpent OS.
-
HashiCorp Cofounder Unveils Ghostty, a Linux Terminal App
Ghostty is a new Linux terminal app that's fast, feature-rich, and offers a platform-native GUI while remaining cross-platform.