skip to Main Content

It’s the first time I’m going to use SVG graphics and I’m a bit confused… I’ve researched extensively but I cannot seem to find an answer to what I’m trying to do.

I want to give an image the following appearance, given the source image is a color image.

color image with gradient map and pattern overlay

The main reason behind this effect is to overcome bad quality images (both in terms of aesthetics and resolution) my clients might upload to their websites.

In Photoshop this is a Gradient Map and a transparent grid in Mode Multiply.

I’ve managed to apply a filter for the grayscale and “gradient map” but I cannot add the grid/pattern.

This is my code so far:

SVG file gradient-map.svg

<svg xmlns="http://www.w3.org/2000/svg">
   <filter id="duotone_filter">
      <feColorMatrix type="matrix" result="grayscale"
         values="1 0 0 0 0
                 1 0 0 0 0
                 1 0 0 0 0
                 0 0 0 1 0" >
      </feColorMatrix>
      <feComponentTransfer color-interpolation-filters="sRGB" result="duotone">
        <feFuncR type="table" tableValues="0.0039525691 0.5764705882"></feFuncR>
        <feFuncG type="table" tableValues="0.0123456790 0.8431372549"></feFuncG>
        <feFuncB type="table" tableValues="0.0123456790 0.9803921569"></feFuncB>
        <feFuncA type="table" tableValues="0 1"></feFuncA>
     </feComponentTransfer>
  </filter>        
</svg>

HTML

<div class="image">
    <img src="link/to/file" />
</div>

CSS

.image {
   filter: url('../images/gradient-map.svg#duotone_filter');
}

And the SVG file for the pattern/fill

<svg xmlns="http://www.w3.org/2000/svg" x="0" y="0" width="6px" height="6px" viewBox="0 0 6 6">
   <circle cx="3" cy="3" r="2" />
</svg>

Is this the way things should be done? How should I proceed to achieve this effect?

If you could also link me to useful resources I would much appreciate. I haven’t found any recent guides or articles.

Thanks.

2

Answers


  1. You’re on the right track. Here’s a demo I put together (and on Codepen). And the output:

    enter image description here

    There’s a helpful question to Overlay grid on responsive image, but I opted for simply overlaying and scaling a large transparent PNG. You’ll likely end up with better results if you use a small, repeating grid section. Of course you’ll have to choose what color, size, etc. to make the grid overlay.

    As a side note, you cannot use the :after or :before pseudo-elements with img elements, so you need to wrap them in a container. You could also accomplish this with an additional element, like:

    <div class="img-container">
        <img src="..." />
        <div class="grid-overlay"></div>
    </div>
    

    But I prefer pseudo-elements so I don’t have to repeat <div class="grid-overlay"></div> every time I want the grid overlay.

    img {
      filter: url(#duotone_filter)
    }
    
    .img-container {
      display: inline-block;
      overflow: hidden;
      position: relative;
      height: 375px;
    }
    
    .img-container::after {
      content: '';
      display: block;
      position: absolute;
      background-image: url('http://www.freeiconspng.com/uploads/grid-png-31.png');
      background-size: 100%;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
    }
    <div class="img-container"><img src="http://kb4images.com/images/random-image/37670495-random-image.jpg" /></div>
    
    <svg xmlns="http://www.w3.org/2000/svg">
       <filter id="duotone_filter">
          <feColorMatrix type="matrix" result="grayscale"
             values="1 0 0 0 0
                     1 0 0 0 0
                     1 0 0 0 0
                     0 0 0 1 0" >
          </feColorMatrix>
          <feComponentTransfer color-interpolation-filters="sRGB" result="duotone">
            <feFuncR type="table" tableValues="0.0039525691 0.5764705882"></feFuncR>
            <feFuncG type="table" tableValues="0.0123456790 0.8431372549"></feFuncG>
            <feFuncB type="table" tableValues="0.0123456790 0.9803921569"></feFuncB>
            <feFuncA type="table" tableValues="0 1"></feFuncA>
         </feComponentTransfer>
      </filter>        
    </svg>

    Also an example using only SVGs (symbols):

    SVG symbol grid overlay

    One final example that also works in Firefox and uses two SVG filters. The key to this example is that it uses another filter to create a composite image. I took another SVG from the web but you could use an inline SVG and reference it by ID as well.

    <filter id="overlay">
        <feImage result="sourceTwo" xlink:href="http://www.vectorstash.com/vectors/vectorstash-grid.svg" width="500" height="375" preserveAspectRatio="none" x="0" y="0" />
        <feComposite in="SourceGraphic" in2="sourceTwo" operator="out" x="0" y="0" />
      </filter>
    
    Login or Signup to reply.
  2. A handy way to do this is to combine the grid overlay with the filter by putting inline SVG for the grid into an feImage primitive.

    (I also changed your greyscale matrix because it was only using the red channel as source which is going to create weird results on blue/green heavy photos.)

    .filterclass {
        filter: url(#duotone_filter);
    }
    <svg xmlns="http://www.w3.org/2000/svg">
       <filter id="duotone_filter" color-interpolation-filters="sRGB" x="0%" y="0%" width="100%" height="100%">
          <feImage width="6" height="6" xlink:href= "data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20x%3D%220%22%20y%3D%220%22%20width%3D%226px%22%20height%3D%226px%22%20viewBox%3D%220%200%206%206%22%3E%0A%20%20%20%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%226%22%20height%3D%226%22%20fill%3D%22none%22%20stroke%3D%22grey%22/%3E%0A%3C/svg%3E"/>
          <feTile result="overlay"/>
    
    
          <feColorMatrix in="SourceGraphic" type="matrix" result="grayscale"
             values=".33 .33 .33 0 0
                     .33 .33 .33 0 0
                     .33 .33 .33 0 0
                     0 0 0 1 0" />
    
          <feComponentTransfer result="duotone">
            <feFuncR type="table" tableValues="0.0039525691 0.5764705882"></feFuncR>
            <feFuncG type="table" tableValues="0.0123456790 0.8431372549"></feFuncG>
            <feFuncB type="table" tableValues="0.0123456790 0.9803921569"></feFuncB>
            <feFuncA type="table" tableValues="0 1"></feFuncA>
         </feComponentTransfer>
        <feBlend mode="multiply" in="overlay"/>
      </filter>        
    </svg>
    
    <div >
    <img class="filterclass" src="http://kb4images.com/images/random-image/37670495-random-image.jpg" />
    </div>

    The source SVG for the inlined data uri is

        <svg xmlns="http://www.w3.org/2000/svg" x="0" y="0" width="6px" height="6px" viewBox="0 0 6 6">
       <rect x="0" y="0" width="6" height="6" fill="none" stroke="grey"/>
    </svg>
    

    If you want to tweak it – I use this converter for svg+xml – which is pretty useful https://codepen.io/yoksel/details/JDqvs

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search