Skip to main content
added documentation link to feComponentTransfer
Source Link
dotnetCarpenter
  • 10.9k
  • 7
  • 35
  • 58

UPDATE

Doing step 2 might be better with feComponentTransfer. Below is my experiment with adjusting the tableValues for all channels by 20%.

.hero-200__img {
    filter: url(#halftone);
}
<img class="hero-200__img" width="1920" height="660" src="https://firefund-assets.s3.amazonaws.com/hero-200/hero-img-1920x660.jpg">

<svg viewBox="0 0 1000 1000" width="1920" height="660">
    <filter id="halftone">
        <!-- black/white -->
        <feColorMatrix in="SourceGraphic" type="saturate" values="0"/>

        <!-- 45deg  -->
        <feComponentTransfer>
            <feFuncR type="discrete" tableValues="0 0.2 0.4 0.6 0.8 1"/>
            <feFuncG type="discrete" tableValues="0 0.2 0.4 0.6 0.8 1"/>
            <feFuncB type="discrete" tableValues="0 0.2 0.4 0.6 0.8 1"/>
            <feFuncA type="discrete" tableValues="0 0.2 0.4 0.6 0.8 1"/>
        </feComponentTransfer>

        <!-- dots -->
        <feMorphology operator="dilate" radius="2"/>
    </filter>
</svg>

UPDATE

Doing step 2 might be better with feComponentTransfer. Below is my experiment with adjusting the tableValues for all channels by 20%.

.hero-200__img {
    filter: url(#halftone);
}
<img class="hero-200__img" width="1920" height="660" src="https://firefund-assets.s3.amazonaws.com/hero-200/hero-img-1920x660.jpg">

<svg viewBox="0 0 1000 1000" width="1920" height="660">
    <filter id="halftone">
        <!-- black/white -->
        <feColorMatrix in="SourceGraphic" type="saturate" values="0"/>

        <!-- 45deg  -->
        <feComponentTransfer>
            <feFuncR type="discrete" tableValues="0 0.2 0.4 0.6 0.8 1"/>
            <feFuncG type="discrete" tableValues="0 0.2 0.4 0.6 0.8 1"/>
            <feFuncB type="discrete" tableValues="0 0.2 0.4 0.6 0.8 1"/>
            <feFuncA type="discrete" tableValues="0 0.2 0.4 0.6 0.8 1"/>
        </feComponentTransfer>

        <!-- dots -->
        <feMorphology operator="dilate" radius="2"/>
    </filter>
</svg>

added missing sentences
Source Link
dotnetCarpenter
  • 10.9k
  • 7
  • 35
  • 58

TheI got the before- and after image-image (only the after-image, looks horrible when scaled):

I have also found this Portuguese recipe1 that looks like it could be translated to feConvolveMatrix but because I am not sure how to use feConvolveMatrix and kernelMatrix, then I can not.

The before and after image (only the after-image, looks horrible when scaled):

I have also found this Portuguese recipe1 that looks like it could be translated to feConvolveMatrix but

I got the before- and after-image (only the after-image, looks horrible when scaled):

I have also found this Portuguese recipe1 that looks like it could be translated to feConvolveMatrix but because I am not sure how to use feConvolveMatrix and kernelMatrix, then I can not.

Source Link
dotnetCarpenter
  • 10.9k
  • 7
  • 35
  • 58

Halftone image effect with SVG filters

I am trying to translate specifications from Photoshop to svg filters.

The recipe is:

  1. Filter > Pixelate > Color Halftone
  2. All 4 channels 45 degrees
  3. Radius of the dots between 5-8

The process, in Photoshop, is illustrated here: http://www.photoshopsupport.com/tutorials/cb/halftone.html

The before and after image (only the after-image, looks horrible when scaled):

  1. Before: https://firefund-assets.s3.amazonaws.com/hero-200/hero-img-1920x660.jpg
  2. After: https://firefund-assets.s3.amazonaws.com/hero-200/hero-200-1920x660.jpg

I have found a complete list of SVG filters and I have found several recipes on SO that explains steps to create a halftone image effect but not with SVG filters.

Single-level halftone: Input: Pixels from your image; preconstructed "screen" containing threshold values. At runtime: For each color channel, for each pixel, select one threshold value (index into threshold array modulo the array dimensions). One comparison between the pixel and the threshold determines whether the output value is on or off

feConvolveMatrix seems to be able to set a threshold to turn off/on pixels but I don't understand the MDN documentation. It might even be the wrong filter to use.

I have also found this Portuguese recipe1 that looks like it could be translated to feConvolveMatrix but

My initially attempt has failed, as seen below.

.hero-200__img {
    filter: url(#halftone);
}
<img class="hero-200__img" alt="Hero" width="1920" height="660" src="https://firefund-assets.s3.amazonaws.com/hero-200/hero-img-1920x660.jpg">

    <!--
    1. Color Halftone
    2. All 4 channels 45degrees
    3. Radius of the dots between 5-8
    -->
<svg viewBox="0 0 100 100" width="1920" height="660">
    <filter id="halftone">
        <!-- black/white -->
        <feColorMatrix in="SourceGraphic" type="saturate" values="0"/>
        <!-- 45deg -->
        <feConvolveMatrix kernelMatrix="0.125 0 0
                                        0 0.125 0
                                        0 0 0.125"/>
        <!-- dots -->
        <feMorphology operator="dilate" radius="5"/>
    </filter>
</svg>

The input image (SourceGraphic) is already black/white but I've added it here in case the input image will change.

I'm happy to pull in svg.js, especially svg.filter.js, in case I need to do some of these calculations in JS.

1: English translation: https://www-inf-pucrs-br.translate.goog/~pinho/CG/Aulas/Img/IMG.htm?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=en&_x_tr_pto=wapp