Effects of filtering SVG. Part 3. Image posterization effect using feComponentTransfer
In the third part of the series, you will learn how feComponentTransfer works and how you can posterize images with this powerful SVG filter primitive.
Sara Soueidan, a freelance UI / UX developer of the interface and author of many technical articles living in Lebanon, offers a series of articles on the SVG filters and includes the following articles:
Effects of filtering SVG
- Effects of filtering SVG. Part 1. SVG filters 101
- Effects of filtering SVG. Part 2. Outline text with feMorphology
- Effects of filtering SVG. Part 3. Image posterization effect using feComponentTransfer
- Not yet translated
This article assumes that you are already familiar with the basics of SVG filters or have read the first article in this series - "SVG Filters 101". If you have not done so, please feel free to spend a few minutes to replenish your knowledge.
feComponentTransfer is one of the most powerful SVG filter primitives. It gives us control over the individual RGBA channels of our graphics source, allowing us to create effects like Photoshop in SVG. In this article, which is the first part of an article on feComponentTransfer , we will get acquainted with this primitive and see how it can be used to posterize images.
Posterization or coarsening of the image implies the transformation of a continuous color transition into several ranges of a smaller number of colors, with abrupt transitions from one color to another. Initially, this was done using photographic processes to create posters. - Wikipedia .
Posterization occurs throughout the image, but is most evident in the area of subtle change in color.
Fig_1. Example of a JPEG photo (24-bit color or 16.7 million colors) before posterization, which contrasts with the result of saving it in GIF format (256 colors). (Source: Wikipedia)
In this article, we will use feComponentTransfer to reduce the number of colors in an image, which in turn will create a pleasant poster effect, similar to the ones we see in commercial or graphic design posters.
Pic_2. Applying the posterization effect to the image on the left with feComponentTransfer reduces the number of colors in this image (on the right).
But first consider the technical basics ...
FeComponentTransfer Short Review
Primitive feComponentTransfer allows you to modify each of the R , G , B and A components present in a pixel. In other words, feComponentTransfer allows you to independently manipulate each color channel in the same way as the alpha channel of the input graphics. It allows you to precisely control the brightness adjustment, contrast adjustment, color balance or setting the threshold.
RGBA components are modified by performing the transfer functions of these components. To do this, each component has its own element, called the Transfer Function Element . Throughout the article I will call these elements as “ component elements ” - i.e. elements that relate to individual components of RGBA. These elements are nested in feComponentTransfer . So feComponentTransfer does nothing except to place individual RGB component elements. The component elements of RGBA are: feFuncR , feFuncG , feFuncB and feFuncA .
The type attribute is used in the component element to determine the type of function that you want to use to change this component. There are currently five types of functions: identity , table , discrete , linear, and gamma . These types of functions are used to modify the R / G / B / A components of the graphics source. We will look at most of them in this series and see how they can be used.
<feComponentTransfer> <!-- The RED component --> <feFuncR type="identity | table | discrete | linear | gamma"></feFuncR> <!-- The GREEN component --> <feFuncG type="identity | table | discrete | linear | gamma"></feFuncG> <!-- The BLUE component --> <feFuncB type="identity | table | discrete | linear | gamma"></feFuncB> <!-- The ALPHA component --> <feFuncA type="identity | table | discrete | linear | gamma"></feFuncA> </feComponentTransfer>">
For each type of function, there are one or more attributes that allow you to specify additional information about the function being used. For example, the linear function has a slope attribute that is used to indicate the slope of the linear function that will be used to change the component to which it is applied.
You can change one or more components at the same time . This means that feComponentTransfer can contain one, two, three or all component elements at the same time. You can also change channels independently of one another by applying different functions to each component element.
The ability to use different functions on different component elements means that you have very large control over the colors of the graphics source at the lowest pixel level. For example, you can change the red and blue channels by matching them with two new colors and leave the green unchanged or just increase its intensity. This low-level component management means that you can apply functions like Photoshop to images in the browser using a few lines of code. I do not know about you, but the (beginner) designer in me thinks that it is super interesting!
Example: Using Alpha Components to Reduce Object Opacity
A simple real-life example is the use of the feFuncA component element to reduce the opacity of the graphics source. In the first article of this series, we saw how you can use feColorMatrix to reduce the element opacity by changing the Alpha channel value in the color matrix. I personally prefer to use feComponentTransfer for this kind of work.
Applying the following filter to the source reduces the opacity of this source to 0.5:
<filter id="redOp"> <feComponentTransfer> <feFuncA type="table" tableValues="0 0.5"></feFuncA> </feComponentTransfer> </filter>
We mentioned above that we have five different functions that we can use to control RGBA components. The type of the table function works by matching the values of the component, which is the alpha channel in our example, with the series of values provided by the tableValues attribute .
So what does this mean?
The alpha channel of an element usually lies in the range [0, 1]. Using the table function and providing two values: 0 and 0.5, we essentially tell the browser to match the alpha range [0, 1] with the new range: [0, 0.5]. In this case, the opacity is reduced by half.
A more detailed example of the table function will be discussed in the next article. Now I want to shed light on the discrete function type . So let's see how it works and what we can do with it.
The effect of posterization of the image: reducing the number of colors in the image using the function discrete
The discrete function is used to reduce the number of colors in an image or component if only one component is used. Reducing the number of colors in an image means that instead of a smooth linear color change, you will see sharper color transitions that make the image look like stripes or color clusters, which leads to a poster-like effect.
Fig_3. The image on the right is a copy of the image on the left, to which a discrete function has been applied to reduce the number of colors in it to 5 per component.
In the image above, you can see that instead of smooth transitions, colors change dramatically, creating color bars and clusters, and the image looks more “posterized.”
Personally, the discrete function reminds me of the steps () synchronization function in CSS. Compared to a linear function, the step-by-step function moves from one value to another, rather than linearly moving between them.
Like the table function , the discrete function accepts a number of values specified in the tableValues attribute . The discrete function differs from table in how it uses these values.
Using tableValues , you provide the browser with a finite list of values with which it must match the color component. And since you provide a finite list of values, you get a finite number of colors, thus creating color bands and clusters that would otherwise be linear color transitions.
This function is defined by the function steps specified in the tableValues attribute , which provides a list of n values to identify the step function consisting of n steps.— SVG Filters specification
Let's see what this means in simple language. Suppose we have the following code snippet:
<svg width="500" height="335" viewBox="0 0 500 335"> <filter id="posterize"> <feComponentTransfer> <feFuncR type="discrete" tableValues="0 .5 1" /> </feComponentTransfer> </filter> <image xlink:href="..."cwidth="100%" height="100%" x="0" y="0" filter="url(#posterize)"></image> </svg>
In the above code snippet, we use a discrete function to change the red channel in the image source. We provide 3 different values for the browser to match the red values. In the SVG filter, the values of the components are represented as fractions in the range [0, 1]. This means that the value of the red component in any pixel can be 0 (0% red / fully black), 1 (100% red), or any value (shade of red) between them. The same goes for the green, blue and alpha channels.
For any number of values you enter ( n ), the browser will create n ranges. More specifically, it will divide the [0, 1] into n ranges. It will then display the color values that lie within these ranges by n values. Apply this logic to our code snippet:
- the browser sees three different red values in tableValues ;
- it divides the red values in the range [0, 1] into three equal parts. So our three ranges are as follows:
- [0, 0.33]
- [0.33, 0.66]
- [0.66, 1]
- Further, the browser checks the red value of each pixel of the image and determines which range it is in;
- then all the red values of the same range are displayed with the new value associated with that range from the ones you provided. The display is as follows:
- colors in the range [0, 0.33] are displayed as 0;
- colors in the range [0.33, 0.66] are displayed as 0.5;
- colors in the range [0.66, 1] are displayed as 1.
You can also think of this process as turning colors on or off. When you provide discrete values for a color, you tell the browser that only these values will be included, and if a pixel contains a value that is not one of them, then it should be disabled and replaced with one of the allowed ones. For example, a color value of 0.8 is considered off and will be replaced by 1 (because this value lies in the third range).
The following is a hand-drawn illustration of this color mapping that I painted when I reasoned about it. Perhaps you need it.
Fig_4. Displays color values in a color range.
By the time the browser goes through all the pixels in the image, you will replace the large number of red values with the small number you selected in tableValues , thus replacing smooth color changes with abrupt transitions, and the image looks as if it is made of clusters or stripes of color.
Below is a demo of applying the above code snippet to an image with a large amount of red. By limiting the number of red in image pixels and zeroing red in some of them, the image shows a generally noticeable decrease in red, especially at the bottom of the image:
Changing the number of discrete values and / or changing the values themselves will change the overall result. You may not want to give a color value of 0 to get rid of some black areas of the image. For example, there probably should not be any clusters or black stripes in the posterization version of the image above, because it is still the image of the sky. To do this, you need to have more than two or three colors, otherwise the image will lose most of its visual ability.
To create this effect, I limited the number of RGB colors to five, starting with the lowest value of 0.25:
<filter id="posterize"> <feComponentTransfer> <feFuncR type="discrete" tableValues=".25 .4 .5 .75 1" /> <feFuncG type="discrete" tableValues=".25 .4 .5 .75 1" /> <feFuncB type="discrete" tableValues=".25 .4 .5 .75 1" /> </feComponentTransfer> </filter>
You can play with the effect in the following demo:
I hope that this article helped clarify a bit the feComponentTransfer and showed you how powerful color control at the level of pixels and components can be.
In the next article, we will look at two more powerful types of the transfer function feComponentTransfer . We will look at how you can simulate the effect of a two-tone image in Photoshop , and how you can control the brightness, contrast, and intensity of the image colors using feComponentTransfer . Stay with us.