📜 ⬆️ ⬇️

Effects of filtering SVG. Part 4. Two-color images with feComponentTransfer

This fourth article in the series is about SVG filters in which Sara Soueidan shows you how to use feComponentTransfer to create a two-tone filter effect.



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 consists of the following articles:


Effects of filtering SVG


  1. Effects of filtering SVG. Part 1. SVG filters 101
  2. Effects of filtering SVG. Part 2. Outline text with feMorphology
  3. Effects of filtering SVG. Part 3. Image posterization effect using feComponentTransfer
  4. Effects of filtering SVG. Part 4. Two-color images with feComponentTransfer .

Not yet translated

SVG Filter Effects: Conforming Text to Surface Texture with


In the previous article in this series, I introduced you to the primitive feComponentTransfer , and we used it to limit the number of colors in an image to create a posterization effect. In this article we will look at how this primitive can be used to create the duotone effect, like Photoshop. We will also learn how to use it to control the intensity and contrast of colors in an image.


Short review


A little repeat.


Primitive feComponentTransfer allows you to modify each of the components R, G, B and A, present in the pixel. In other words, feComponentTransfer provides independent manipulation of each color channel, as well as the alpha channel, in the input element.


RGBA components are modified by performing various kinds of functions on these components. For this, each component has its own element. These component elements are nested in feComponentTransfer . For RGBA, these are the component elements 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. Currently, five types of functions are available: identity , table , discrete , linear and gamma . These types of functions are used to change the RGBA components (colors and alpha channel) of the graphics source. We mentioned that you can change one or more components at the same time and that you can change channels independently by applying different functions to each component element.


<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>"> 

In the previous article, we clarified the discrete function and saw how it can be used to posterize images. In this article, we will start by using the table function to create a duotone effect, similar to what you can create in Photoshop.


Creating a two-color effect in Photoshop


I am not a designer and I don’t understand graphic editors such as Photoshop . When I wanted to create a two-color effect in SVG, I first looked for a way to create this effect in a graphic editor to see if I can replicate it using filtering operations available in SVG. As it turned out, the steps to create two-color images in SVG are the same as in Photoshop.


The following video is an accelerated version of this lesson that I found on YouTube.


In this video, the designer creates a two-color effect by following these steps:


  • Decolorize the image by making it shades of gray.
  • Match the range of shades of gray with the new range, which instead of black and white at both ends has two different colors that you want to use in a two-color effect. In other words, you must create and use a gradient map with which shades of gray are matched.

Let's see how these steps can be replicated in the SVG.


Creating a two-color effect in SVG


To recreate this effect in SVG, we need to first discolor the image. This can be done using the feColorMatrix filter primitive .


Then, we need to be able to create and transmit a gradient map to the browser in order to display a new image in grayscale.


Convert image to grayscale with feColorMatrix


With feColorMatrix, you can set a color matrix that determines the amount of red, green, and blue in your image. By providing an equal amount of these three components, we create a matrix that converts our image into a version of itself in shades of gray:


 <svg viewBox="0 0 266 400"> <filter id="duotone"> <feColorMatrix type="matrix" values=".33 .33 .33 0 0 .33 .33 .33 0 0 .33 .33 .33 0 0 0 0 0 1 0"> </feColorMatrix> <!-- ... --> </filter> <image xlink:href="..." width="100%" x="0" y="0" height="100%" filter="url(#duotone)"></image> </svg> 

In the following figure, the image on the right is the result of applying the above filter to the image on the left:


Result (on the right) of converting the image to the left in grayscale using the filter operation feColorMatrix
Fig_1. The result (on the right) of converting the image to the left in grayscale using the feColorMatrix filter operation


You can learn everything about feColorMatrix and how to use it in this article by Una Kravets.


Now that our image is essentially composed of a gray gradient, we need to create a two-color gradient map to display the gray gradient.


Creating a gradient map using the table component transfer feature


In SVG, you can use a feComponentTransfer primitive with a type table to create a gradient map.


In the previous article, we saw how you can match the colors of an image with the list of colors provided in the tableValues attribute using the discrete function. The browser uses our tableValues list to create ranges, which are then used to match colors with the values ​​we provide.


When using the table function, we will also provide color values ​​in the tableValues attribute. Again, the browser will use these values ​​to match the colors of the image with them. However, how the browser will display these colors is different. Instead of matching color ranges to a discrete color value, it will create a color range from the provided values, and then match the input range to this new range.


Suppose we want to use two colors for our two-tone effect:


Original two colors
Pic_2. Original two colors.


These two colors will be used to create a gradient display:


Gradient created by two color values
Fig_3. Gradient created by two color values.


... which we are going to map our grayscale map.


Display of a two-tone card to a two-color gradient
Fig_4. Displays a dual-tone card to a two-color gradient.


To use these colors in feComponentTransfer , we need to get the values ​​of the R, G and B channels of each color. Since tableValues contains fractional values, we need to convert RGB values ​​to fractions. Color values ​​are usually in the range [0,255]. To convert them into fractions, divide them by 255.


For example, pink has the following RGB values:


 R: 254 G: 32 B: 141 

Converting them into a fraction, we get:


 R: 254/255 = .996078431 G: 32/255 = .125490196 B: 141/255 = .552941176 

Similarly, for values ​​of yellow, we obtain:


 R: .984313725 G: .941176471 B: .478431373 

Now that we have color values, it's time to create our gradient map. We mentioned earlier that when we provide tableValues for use in the table function, the browser will use tableValues to create a range. Therefore, we will start by providing two color RGB values ​​as RGB values ​​for component elements:


 <feComponentTransfer color-interpolation-filters="sRGB"> <feFuncR type="table" tableValues=".996078431 .984313725"></feFuncR> <feFuncG type="table" tableValues=".125490196 .941176471"></feFuncG> <feFuncB type="table" tableValues=".552941176 .478431373"></feFuncB> </feComponentTransfer> 


In the previous article, we saw that when using the discrete function, the browser creates n ranges for n values ​​in tableValues . When we use the table function, the browser creates an n-1 range for n values. Since we provided two tableValues for each component, which means that we get one range ([pink, yellow]) for each.


Now feComponentTransfer will do its thing: the browser will view each pixel of the image source sequentially. For each pixel, it will get the value of the red, green, and blue components. Since our image has shades of gray, the R / G / B values ​​will be in the range [0, 1] = [black, white] (0 is completely black, 1 is completely white and shades of gray between them). Then the value of each component will be matched with the new range specified in tableValues .


So:


  • the value of the red component will be mapped to the range [.996078431, .984313725];
  • the blue value of the component will be assigned to the range [.1249490196, .941176471];
  • the green value of the component will match the range [.552941176, .478431373].

Thus, by the time the browser passes through all the pixels in the image, you will replace all the RGB values ​​in the gradient of shades of gray with the RGB values ​​of the two-color gradient display. As a result, the image will become two-color.


The result (on the right) is the display of a grayscale image (left) in our gradient map.
Fig_6. The result (on the right) is the display of the grayscale image (on the left) in our gradient map.


Our full code now looks like this:


 <svg viewBox="0 0 266 400"> <filter id="duotone"> <!-- Grab the SourceGraphic (implicit) and convert it to grayscale --> <feColorMatrix type="matrix" values=".33 .33 .33 0 0 .33 .33 .33 0 0 .33 .33 .33 0 0 0 0 0 1 0"> </feColorMatrix> <!-- Map the grayscale result to the gradient map provided in tableValues --> <feComponentTransfer color-interpolation-filters="sRGB"> <feFuncR type="table" tableValues=".996078431 .984313725"></feFuncR> <feFuncG type="table" tableValues=".125490196 .941176471"></feFuncG> <feFuncB type="table" tableValues=".552941176 .478431373"></feFuncB> </feComponentTransfer> </filter> <image xlink:href=".." width="100%" x="0" y="0" height="100%" filter="url(#duotone)"></image> </svg> 

You can play with the demo here:



You can go further and instead of providing only two color values ​​for a gradient map, provide three color values ​​in tableValues , creating a gradient map that has three colors instead of two.


Contrast and color management using the gamma transfer function


Using the gamma component transfer function, we can perform gamma correction of our graphics source. Gamma Correction is a function to control the light levels of an image.


The gamma function has three attributes that allow you to control the gamma correction function that will be used to control the luminance: amplitude, exponent, and offset. Together, they constitute the following transfer function:


 C' = amplitude * pow(C, exponent) + offset 

gamma can be used to control the overall image contrast. An increase in the exponent attribute makes dark areas darker, while an increase in the amplitude attribute causes light areas to shine more. And this, in turn, increases the overall contrast of the image. The offset attribute is used to increase the intensity of each component, and also affects the full image: both light and dark areas.


Adjusting the contrast in both dark and light areas of an image can sometimes be useful if you do not get the amount of “shine” you would like to see in the image.


For example, if you apply the duotone filter from the previous section to the next image, the result will not be as “alive” as you would like:


The result of the filter duotone
Fig_7. The result of the filter duotone.


The two-color image on the right looks a little pale, and the colors are slightly blurred. I want to add contrast to make it look more alive. Increase the amplitude and exponent a bit:


 <feComponentTransfer color-interpolation-filters="sRGB"> <feFuncR type="gamma" exponent="1.5" amplitude="1.3" offset="0"></feFuncR> <feFuncG type="gamma" exponent="1.5" amplitude="1.3" offset="0"></feFuncG> <feFuncB type="gamma" exponent="1.5" amplitude="1.3" offset="0"></feFuncB> </feComponentTransfer> 

I was able to make the light areas more luminous, and the dark ones more intense:


The result of the previous code
Fig_8. The result of the gamma correction.


Of course, this is just an example. You may prefer a paler version of the image, especially to make it look better with text on top. I think gamma correction is most useful for controlling the contrast of black and white images. If I apply the same gamma correction operation to the grayscale version of the image, I get a more favorable picture:


Gamma Correction Result for Grayscale Image
Figure_9. The result of the gamma correction for the image in grayscale.


Of course, you can do the opposite and instead of increasing the contrast, you can lighten the dark areas a bit. In this case, you should decrease the values ​​of the amplitude and / or exponent attributes, and not increase them. The default value for both is 1. The default attribute value for offset is 0.


Play with the gamma function values ​​in the following demo to better understand how they affect the brightness and contrast of the image:



SVG-tool Gradient Map


Yoksel has been playing with SVG filters for some time and has recently created a fantastic visual tool that allows you to load an image and apply various two and even three-tone effects, and which generates an SVG filter code for you, ready to copy and paste to any place you want. This is a great tool for further exploring feComponentTransfer .


SVG filter tool ** Gradient Map ** from Yoksel
Figure 10. Gradient Map SVG filter tool from Yoksel.


The tool even allows you to customize the grayscale effect created with feColorMatrix . In our code, we used an equal number of channels R, G and B to get the effect of shades of gray. This is one way to make a grayscale image. But there are other ways. For example, you can create a grayscale effect for each channel, resulting in different shades of gray for each channel:


The result of creating a grayscale image in other ways.
Fig_11. The result of creating a grayscale image in other ways.


I recommend playing with the tool for a bit and checking how your choice of effect changes the base code, as this is one of the best ways to learn more about SVG filters.


Conclusion


Primitive feComponentTransfer gives us a lot of control over the color and alpha components of images and allows you to create Photoshop-class effects in the comfort of our code editors.


In the next article in this series, we will look at a few more primitives that allow us to reproduce another Photoshop effect, using almost the same steps as in Photoshop, and show again how SVG can bring the power of graphic editors to a web platform. We learn how to blend text with the color and texture of the background image to get attractive looking results. Stay with us.



Source: https://habr.com/ru/post/440474/