Image Distortion Effects with SVG Filters

In our recent articles series on SVG Filter Effects, Sara has shown how powerful and versatile SVG filters can be. They allow for a plethora of unique effects. Today we would like to share three animated distortion effects that we apply to an image when hovering a text link. We use feTurbulence and feDisplacementMap to create different kinds of fragment and wave-like distortions. These kind of effects have become quite popular and there are many variations. Menu hover animations showing an image in the background have also been around for a while and you can see an example that we’re based upon on Sara Marandi’s website.

Attention: Note that this is highly experimental and that we use modern CSS properties that might not be supported in older browsers.

If you’d like to understand how SVG filters work and learn how to create your own effects, we highly recommend you read Sara’s series:

Have a look at the effects we’ve created for the demos:

SVGFilterHover01.2019-03-12 17_25_08

SVGFilterHover02

SVGFilterHover03

We hope you like these effects and find them useful!

References and Credits

Image Distortion Effects with SVG Filters was written by Mary Lou and published on Codrops.

Grid Reveal Effects with Anime.js

Recently, a new version of anime.js was released. One of the great new features is its staggering system that makes complex follow through and overlapping animations really simple. We wanted to give it a try and experiment with this new feature on an image grid with many thumbnails. We’ve created four demos, each with a different staggering effect that hides and shows small images to reveal some content underneath.

Attention: Note that this is highly experimental and that we use modern CSS properties that might not be supported in older browsers.

If you want to learn more about staggering in anime, you can check out the great documentation: Staggering in anime.js

In the first demo, we make the thumbnails disappear from the point where we clicked and then reverse this animation when closing the full view.

GridRevealEffects_00

GridRevealEffects_01

In the second demo, we fade and scale the thumbnails down. Not from the center though but from the edges. We also make the thumbnails appear again in the same way when closing the full view.

GridRevealEffects_02

The third demo shows how to make the items disappear towards the bottom right corner.

GridRevealEffects_06

The last demo is a more playful example: here we let the thumbnails “fall down”. When closing the view, we make them show again by moving them upwards.

GridRevealEffects_04

We hope you like these effects and find them useful!

References and Credits

Grid Reveal Effects with Anime.js was written by Mary Lou and published on Codrops.

SVG Filter Effects: Duotone Images with <feComponentTransfer>

SVGFilterEffects_feComponent2_featured

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

A Quick Recap

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

The RGBA components are modified by running different kinds of functions on these components. To do that, each component has its own element. These component elements are nested within feComponentTransfer. The RGBA component elements are: feFuncR, feFuncG, feFuncB, and feFuncA.

The type attribute is used on a component element to define the type of function you want to use to modify this component. There are currently five available function types: identity, table, discrete, linear, and gamma. These function types are used to modify the RGBA components (the colors and alpha channel) of a source graphic. We mentioned that you can modify one or more component at a time and that you can modify channels independently, applying a different function 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 demystified 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 Duotone Effect in Photoshop

I’m not a designer, and I don’t know my way around graphics editors like Photoshop. When I wanted to create a duotone effect in SVG, I looked for the way to create this effect in graphics editor first to see if I can replicate it using the filter operations available in SVG. As it turns out, the steps to create duotone images in SVG turned out to be same as those used in Photoshop.

The following video is a sped-up version of this tutorial I found on YouTube.

In the video, the designer creates the duotone effect following these steps:

  1. Desaturate the image, making it grayscale.
  2. Map the grayscale range into a new range that, instead of having black and white on either end, it has two different colors that you want to use in the duotone effect. In other words, you will need to create and use a gradient map that the grayscale is mapped to.

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

Creating a Duotone Effect in SVG

To recreate this effect in SVG, we will need to desaturate the image first. This is possible using the <feColorMatrix> filter primitive.

Then, we need to be able to create and provide a gradient map for the browser to map the new grayscale image to.

Converting an image to grayscale using feColorMatrix

Using feColorMatrix you can provide a color matrix that specifies the amount of red, green, and blue in your image. By providing equal amounts of these three components, we are creating a matrix that converts our image into a grayscale version of itself:

<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 image, the image on the right is the result of applying the above filter to the image on the left:

Screen Shot 2019-01-12 at 18.50.21
The result (on the right) of converting the image on the left to grayscale using the feColorMatrix filter operation.

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

Now that our image is essentially made of a gray gradient, we need to create a duotone gradient map to map the gray gradient to.

Creating a Gradient Map using the table component transfer function

In SVG, to create the gradient map, we can use feComponentTransfer primitive with the type table.

In the previous article, we saw how you can map the colors in an image to a list of colors that you provide in the tableValues attribute using the discrete function. The browser used our list of tableValues to generate ranges that are then used to map the colors to the values we provided.

When using the table function, we will also provide color values in the tableValues attribute. Once again, the browser will use the values we provide to map the colors in the image to them. How the browser will map the colors, though, is different. Instead of mapping color ranges to discrete color values, it will create a color range from the values we provide and then map the input range to this new range.

Suppose we want to use the following two colors for our duotone effect:

Screen Shot 2019-01-12 at 19.05.26

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

Screen Shot 2019-01-12 at 19.11.46

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

IMG_4149

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

For example, the pink color has the following RGB values:

R: 254
G: 32
B: 141

Converted to fractions, these values are now equal to:

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

Similarly, the yellow color values resolve to:

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

Now that we have our color values handy, it’s time to create our gradient map. We mentioned earlier that when we provide values to tableValues with the table function in use, the browser will use the tableValues to create a range. So we start by providing the RGB values of the two colors as values for the RGB 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>

Screen Shot 2019-01-12 at 19.26.35

We saw in the previous article 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 n-1 ranges for n values; and since we provided two tableValues for each component, this means that we will get one range ([pink, yellow]) for each.

Now feComponentTransfer will do its thing: The browser will go over each and every pixel in the source image. For each pixel, it will get the value of the Red, Green, and Blue components. Since our image is grayscale, the R/G/B values will be in the range [0, 1] = [black, white] (0 being fully black, 1 being fully white, and shades of gray in between). Then, the value of each component will be mapped to the new range we provided in tableValues. So:

  • The red component value will be mapped to the range [.996078431, .984313725]
  • The blue component value will be mapped to the range [.125490196, .941176471]
  • The green component value will be mapped to the range [.552941176, .478431373]

So by the time the browser goes over all the pixels in the image, you will have replaced all RGB values in the grayscale gradient with the RGB values of the duotone gradient map. As a result, the image becomes duotone.

Screen Shot 2019-01-12 at 19.40.07
The result (on the right) of mapping the grayscale image (left) to 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>

And you can play with the live demo here:

See the Pen Duotone Image effect by Sara Soueidan (@SaraSoueidan) on CodePen.light

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

Controling color contrast and intensity with the gamma transfer function

Using the gamma component transfer function we are able to perform gamma correction on our source graphic. Gamma correction is the function of controlling an image’s luminance levels.

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. Combined, they make up the following transfer function:

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

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

Tweaking the contrast and dark and light areas of an image can sometimes be useful if you’re not getting the amount of “shine” that you’d like to see in an image.

For example, if I apply the duotone filter from the previous section to the following image, the result is not as “lively” as I’d want it to be:

Screen Shot 2019-01-14 at 18.50.04

The duotone image on the right looks a little pale and the colors slightly washed out. I want to add some contrast to it to make it look more lively. By increasing the amplitude and the exponent a little 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 am able to make the light areas shine more and the darker areas look more intense:

Screen Shot 2019-01-14 at 18.56.11

Of course, this is just an example. You may prefer the paler version of the image, especially that it might look better with text on top. I think gamma correction is most useful in 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 version:

Screen Shot 2019-01-14 at 19.08.34

Of course, you may want to do the opposite: instead of increasing contrast, you may want to lighten the dark areas a bit, in which case you’d decrease the amplitude and/or exponent values instead of increasing them. The default value for both the amplitude and exponent is 1. The default offset value is 0.

Play with the gamma function values in the following live demo to get a better feel of how it affects the brightness and contrast of an image:

See the Pen Duotone Image effect with Contrast Tweak by Sara Soueidan (@SaraSoueidan) on CodePen.light

The SVG Gradient Map Tool

Yoksel has been playing with SVG Filters for a while and has recently created a fantastic visual tool that allows you to upload an image and apply different duotone and even tritone effects, and that generates the SVG filter code for you ready to copy-paste anywhere you need it. It is a great tool to play with to learn more about feComponentTransfer.

Screen Shot 2019-01-14 at 19.13.12
The SVG Gradient Map Filter tool by Yoksel.

The tool even allows you to tweak the grayscale effect created using feColorMatrix. In our code, we used equal amounts of the R, G, and B channels to get a grayscale effect. This is one way to make an image grayscale. But there are other ways, too. For example, you could create a grayscale effect per channel, which would result in a different grayscale result for each:

b7w

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

Final Words

The feComponentTransfer primitive gives us a lot of control over the color and alpha components of images and enables us to create Photoshop-grade effects in the comfort of our code editors.

In the next article in this series, we will look at a couple more primitives that allow us to replicate yet another Photoshop effect using almost exactly the same steps as those you’d take in Photoshop, showing once again how SVG can bring the power of graphic editors into the Web platform. We’ll learn how to blend text with both the color and the texture of a background image, to create some eye-catching results. Stay tuned.

SVG Filter Effects: Duotone Images with <feComponentTransfer> was written by Sara Soueidan and published on Codrops.