SVG-фильтры. Часть 1. Основные понятия и типы. Применение к изображениям для создания графических эффектов.

svg-filters

SVG-фильтры – это воистину мощный, но при этом очень редко используемый инструмент. A все потому, что многие до сих пор испытывают страх перед SVG в целом, а уж фильтрация и эффекты кажутся чем-то специфическим и трудным для изучения.

В этой статье я попытаюсь убедить Вас в обратном, расскажу о возможностях и типах SVG-фильтров и, в частности, о том, как применить их к изображениям на веб-страницах.

SVG-фильтры поддерживаются почти всеми современными браузерами, включая мобильные. Исключение составляют IE9 и Android native browser версии ниже 4.4.

svg-filters поддержка браузерами

Чтобы понять, что представляет из себя фильтр в SVG, давайте разберем простой пример. Для начала мы нарисуем круг:

<svg width="400" height="300" viewbox="0 0 400 300">
    <circle cx="200" cy="200" fill="#3498db" r="80" />
</svg>

Если Вы вообще не знакомы с SVG, то сейчас самое время познакомиться :)

Вкратце:

  • тег <circle> – это круг
  • аттрибуты cx, cy – задают положение центра круга, fill – заливку, r – радиус.

То, что мы написали, будет выглядеть в браузере вот так:

Да, круто. Настоящий, большой и синий SVG-круг. А теперь давайте опишем простейший SVG-фильтр, задающий гаусовское размытие, и применим этот фильтр к нашей незамысловатой фигуре.

<svg width="400" height="300" viewbox="0 0 400 300">
  <defs>
    <filter id="myFilter1">
      <feGaussianBlur stdDeviation="10"/>
    </filter>
  </defs>
  <circle cx="200" cy="150" fill="#3498db" filter="url(#myFilter1)" r="80" />
</svg>

Сам фильтр определяется в секции <defs> с помощью тега <filter>. Ему необходимо задать id (уникальный в контексте всего документа). У нас это id="myFilter1".

Внутри описываются типы применяемой фильтрации. В нашем примере это <feGaussianBlur>, где атрибут stdDeviation регулирует уровень размытия.

Забегая вперед, скажем, что спецификация определяет несколько типов фильтрации с большим количеством возможных атрибутов для настройки их параметров.

Далее к той части SVG, которая должна быть обработана фильтром, нужно добавить атрибут filter="url(#myFilter1)" с указанием id фильтра.

И вот что получится:

Да! Вот он – наш первый SVG-фильтр. Не так сложно, как казалось, не правда ли? Идем дальше. Давайте применим такой же фильтр к растровой картинке. Для этого поместим изображение красивой девушки в наушниках внутрь SVG:

<svg width="400" height="300" viewbox="0 0 400 300">
  <image width="100%" height="100%" xlink:href="/blogdemo/img/girl.jpg" />
</svg>

И применим к изображению фильтр, описанный выше:

<svg class="cover" width="1024" height="768">
  <defs>
    <filter id="myFilter2">
      <feGaussianBlur stddeviation="5" />
    </filter>
  </defs>
  <image filter="url(#myFilter2)" xlink:href="/blogdemo/img/girl.jpg" width="100%" height="100%" />
</svg>

Получилась “разблюренная” девушка, как мы и ожидали. И это только начало. Продолжаем!

Комплексные SVG-фильтры. Применяем несколько эффектов последовательно.

Еще одним неотъемлемым достоинством SVG-фильтров является возможность сочетания нескольких типов фильтров. Т.е. результат, полученный после применения одного фильтра, может являться источником изображения для другого фильтра и т.д.

Чтобы было понятнее, давайте добавим еще один тип фильтрации для “разблюренной” девушки. Например, сделаем изображение черно-белым.

<svg width="400" height="300" viewbox="0 0 400 300">
  <defs>
    <filter id="myFilter3">
      <feGaussianBlur in="SourceGraphic" result="a1" stddeviation="3" />
      <feColorMatrix in="a1" type="saturate" values="0"></feColorMatrix>
    </filter>
  </defs>
  <image filter="url(#myFilter3)" xlink:href="/blogdemo/img/girl.jpg" width="100%" height="100%" />
</svg>

Графически эту схему фильтрации можно представить как:

svg-filter-multiple

Как Вы видите, для каждого типа фильтров можно указать атрибуты in и result. Если они не указаны, фильтры будут применяться последовательно в порядке их записи.

В качестве in для первого типа фильтра по умолчанию используется предопределенное значение SourceGraphic (в нашем случае оно является псевдонимом <image>)

Типы SVG-фильтров

Как мы уже говорили, существует несколько возможных типов фильтров. Давайте разберем каждый из них подробнее. Для простоты восприятия мы будем рассматривать только код, находящийся внутри тега filter. Все остальное остается таким же, как в предыдущих примерах.


feComponentTransfer

Фильтр <fecomponenttransfer> позволяет производить линейные, табличные, дискретные операции над каналами изображения, а также изменять гамму каждого канала.

Давайте рассмотрим примеры:

<!--1-й пример -->
...
<fecomponenttransfer>
  <feFuncR type="linear" slope="5" intercept="-0.5" />
  <feFuncG type="linear" slope="0.2" />
  <feFuncB type="linear" slope="0.2" />
  <feFuncA type="identity" />
</fecomponenttransfer>
...

Здесь feFuncR, feFuncG, feFuncB, feFuncA – красный, зеленый, синий и канал прозрачности соответственно. type – тип преобразования, slope – множитель, intercept – добавляемое (отнимаемое) значение. T.е. <feFuncR type="linear" slope="5" intercept="-0.5" /> значит: red = red * 5 - 0.5

Вот так, например, можно сделать изображение полупрозрачным:

<!--2-й пример -->
...
<fecomponenttransfer>
  <fefunca type="linear" slope="0.5" />
</fecomponenttransfer>
...

A вот так выделить только синий канал:

<!--3-й пример -->
...
<fecomponenttransfer>
  <fefuncr type="linear" slope="0" />
  <fefuncg type="linear" slope="0" />
  <fefuncb type="linear" slope="1" />
</fecomponenttransfer>
...

Или просто заполнить значения атрибутов случайными значениями и получить интересный эффект.

<!--4-й пример -->
...
<fecomponenttransfer>
  <fefuncr type="linear" slope="10" intercept="-4" />
  <fefuncg type="linear" slope="1.5" intercept="1" />
  <fefuncb type="linear" slope="2" intercept="-1" />
</fecomponenttransfer>
...

Вот демо всех примеров, приведенных выше.

Фильтр <fecomponenttransfer> поддерживает не только линейные преобразования. Тип преобразований задается атрибутом type и может принимать значения identity | table | discrete | linear | gamma. Давайте бегло взглянем, что из себя представляет каждый из типов.

fecomponenttransfer с type="table"

В случае fecomponenttransfer с типом table функция преобразования для канала будет определена путем линейной интерполяции между значениями, указанными в атрибуте tablevalues. А вот так, например, можно добиться эффекта “негатива”, используя табличные значения:

...
<fecomponenttransfer>
  <fefuncr type="table" tablevalues="1 0" />
  <fefuncg type="table" tablevalues="1 0" />
  <fefuncb type="table" tablevalues="1 0" />
</fecomponenttransfer>
...    

fecomponenttransfer с type="discrete"

Для типа discrete функция будет ступенчатой, в соответствии со значениями, указанными в атрибуте tablevalues. Вот несколько примеров:

<!-- 1-й пример -->
...
<fecomponenttransfer>
  <fefuncr type="discrete" tablevalues="1 0" />
  <fefuncg type="discrete" tablevalues="0 0" />
  <fefuncb type="discrete" tablevalues="0 0" />
</fecomponenttransfer>
...

<!--2-й пример -->
...
<fecomponenttransfer>
  <fefuncr type="discrete" tablevalues="1 0" />
  <fefuncg type="discrete" tablevalues="0 0" />
  <fefuncb type="discrete" tablevalues="0 0" />
</fecomponenttransfer>
...

<!-- 3-й пример -->
...
<fecomponenttransfer>
  <fefuncr type="discrete" tablevalues="1 1 1" />
  <fefuncg type="discrete" tablevalues="0 0.8 1" />
  <fefuncb type="discrete" tablevalues="0 0.5 1" />
</fecomponenttransfer>
...

<!-- 4-й пример -->
...
<fecomponenttransfer>
  <fefuncr type="discrete" tablevalues="0 0" />
  <fefuncg type="discrete" tablevalues="0.1 0.6" />
  <fefuncb type="discrete" tablevalues="0.3 0.9" />
</fecomponenttransfer>
...

Имеется также возможность задавать значения гаммы каждого канала при помощи типа фильтра type="gamma" и атрибутов amplitude, exponent и offset для каждого из каналов.

Например, <fefuncg type="gamma" amplitude="1.2" exponent="0.5" offset="0.2" /> значит: green = 1.2 * pow(green, 0.5) + 0.2

Демо:

<!-- 1-й пример -->
...
<fecomponenttransfer>
  <fefuncr type="gamma" amplitude="1.1" exponent="1" offset="0" />
  <fefuncg type="gamma" amplitude="1.1" exponent="1" offset="0" />
  <fefuncB type="gamma" amplitude="1.3" exponent="0.9" offset="0.5" />
</fecomponenttransfer>
...

<!-- 2-й пример -->
...
<fecomponenttransfer>
  <fefuncr type="gamma" amplitude="2" exponent="1" offset="0.1" />
  <fefuncg type="gamma" amplitude="1" exponent="1.2" offset="0.1" />
  <fefuncB type="gamma" amplitude="1.4" exponent="1" offset="0.1" />
</fecomponenttransfer>
...

<!-- 3-й пример -->
...
<fecomponenttransfer>
  <fefuncr type="gamma" amplitude="0.1" exponent="1" offset="0.1" />
  <fefuncg type="gamma" amplitude="1" exponent="3" offset="0.1" />
  <fefuncB type="gamma" amplitude="0.1" exponent="1" offset="0.1" />
</fecomponenttransfer>
...

<!-- 4-й пример -->
...
<fecomponenttransfer>
  <fefuncr type="gamma" amplitude="0.4" exponent="1" offset="0.4" />
  <fefuncg type="gamma" amplitude="1" exponent="0.33" offset="0.33" />
  <fefuncB type="gamma" amplitude="0.1" exponent="1" offset="0.1" />
</fecomponenttransfer>
...


feColorMatrix

Фильтр позволяет умножить каждый пиксель исходного изображения в виде вектора, образованного каналами R, G, B, A и дополненного до размерности 5, на матрицу 5×5. В результате мы получим вектор, представляющий из себя каналы R', G', B', A' каждого пикселя результирующего изображения.

  | R' |     | a00 a01 a02 a03 a04 |   | R |
  | G' |     | a10 a11 a12 a13 a14 |   | G |
  | B' |  =  | a20 a21 a22 a23 a24 | * | B |
  | A' |     | a30 a31 a32 a33 a34 |   | A |
  | 1  |     |  0   0   0   0   1  |   | 1 |

Давайте сразу перейдем к примеру. Знакомый всем эффект “сепия” можно получить с помощью вот такой матрицы:

  0.343 0.669 0.119 0 0
  0.249 0.626 0.130 0 0
  0.172 0.334 0.111 0 0
  0     0     0     1 0
  0     0     0     0 1

Матрица записывается в атрибут values фильтра <fecolormatrix> с типом matrix в виде значений, разделенных пробелом.

Последнюю строку не нужно указывать, т.к. она всегда равна | 0 0 0 0 1 |.

<fecolormatrix type="matrix" values="0.343 0.669 0.119 0 0 0.249 0.626 0.130 0 0 0.172 0.334 0.111 0 0 0 0 0 1 0" />

Для удобства чтения матрицу можно записать в таком виде:

<!-- 1-й пример -->
...
<fecolormatrix type="matrix"
  values="0.343 0.669 0.119 0 0
          0.249 0.626 0.130 0 0
          0.172 0.334 0.111 0 0
          0     0     0     1 0" />
...

Давайте посмотрим еще на несколько примеров с различными матрицами:

  <!-- 2-й пример -->
  ...
  <fecolormatrix type="matrix"
    values="0.788 -0.262  0.474  0   0
            0.1    1.032 -0.132 -0.1 0
            -1     2.1    0.912 -2.8 0
            0      0      0      1   0" />
  ...    

  <!-- 3-й пример -->
  ...
  <fecolormatrix in="SourceGraphic" type="matrix"
    values="5   0   0 0 -0.2
            0 1.2   0 0 -0.2
            0   5 1.2 0 -0.2
            5   0   0 1    0 "/>
  ...    

  <!-- 4-й пример -->
  ...
  <fecolormatrix type="matrix"
    values="1.2 0   0 0 -0.2
            2   0   2 2 -0.2
            2   2 1.2 0 -0.2
            2   0   0 1    0"/>
  ...    

Вот результат:

Частные случаи цветовых матриц – это поворот изображения по цветовому кругу, изменение цветности и т.п. Чтобы упростить жизнь разработчикам и не требовать умножения на матрицы для типовых операций в спецификации для фильтров , определены вспомогательные типы type=saturate, type=hueRotate, type=luminanceToAlpha. Давайте рассмотрим примеры их использования:

Обесцвечивание с type="saturate", а также примеры, где цветность увеличена в 0, 0.5, 2, 5 раз, используя type="saturate":

<fecolormatrix type="saturate" values="0"   /> <!-- 1-й пример -->
...
<fecolormatrix type="saturate" values="0.5" /> <!-- 2-й пример -->
...
<fecolormatrix type="saturate" values="2"   /> <!-- 3-й пример -->
...
<fecolormatrix type="saturate" values="5"   /> <!-- 4-й пример -->

Поворот по цветовому кругу на 40, 120, 240, 320 градусов, используя type="hueRotate":

<fecolormatrix type="hueRotate" values="40"  /> <!-- 1-й пример -->
...
<fecolormatrix type="hueRotate" values="120" /> <!-- 2-й пример -->
...
<fecolormatrix type="hueRotate" values="240" /> <!-- 3-й пример -->
...
<fecolormatrix type="hueRotate" values="360" /> <!-- 4-й пример -->


Свертка feConvolveMatrix

В процессе свертки матрица коэффициентов «умножается» на значения каналов пикселей изображения. Будет намного проще представить это графически:

matrix-cnvolution

Действие над изображением (или фильтрование изображения) определяется матрицей свертки m. Матрица свертки определяет то, как конкретный пиксель зависит от соседних пикселей в процессе свертки. Пиксель у в результирующем изображении зависит от пикселей x0 … x8 исходя из следующей формулы:

y = x0×m0 + x1×m1 + ... + x8×m8

Свертка используется в цифровой обработке изображений для различных целей. Это размытие, искусственное увеличение резкости и другие интересные эффекты.

Давайте посмотрим, как можно немного «подтянуть» резкость классического нечеткого #duckface изображения при помощи вот такого фильтра свертки с размерностью 3:

...
<feConvolveMatrix 
  order="3" 
  kernelMatrix=" 1  -1   1 
                -1  -1  -1 
                 1  -1   1">
</feConvolveMatrix>
...

Оригинальное изображение (слева) и результат фильтрации (справа)

Далее представлены еще несколько примеров для различных фильтров свертки:

<!-- 1-й пример -->
...
<feConvolveMatrix order="3" kernelMatrix="1 -1 1 -1 -0.1 -1 1 -1 1"></feConvolveMatrix>
...

<!-- 2-й пример -->
...
<feConvolveMatrix order="3" kernelMatrix="9 0 0 0 1 0 0 0 -9"></feConvolveMatrix>
...

<!-- 3-й пример -->
...
<feConvolveMatrix order="3" kernelMatrix="-1 -1 -1 -1 7 -1 -1 -1 -1"></feConvolveMatrix>
...

<!-- 4-й пример -->
...
<feConvolveMatrix order="5" kernelMatrix="1 1 1 1 1 1 -2 -2 -2 1 1 -2 .01 -2 1 1 -2 -2 -2 1 1 1 1 1 1"></feConvolveMatrix>
...

Композитные операции c feComposite

При помощи feComposite можно осуществлять арифметические и логические операции над слоями в svg.

<feComposite
    in="source1"
    in2="source2"
    operator="xor"/>

Давайте рассмотрим возможные значения на примерах:

Режимы смешивания слоев с feBlend

При помощи feBlend можно осуществлять смешивание слоев в svg.

<feBlend
    in="source1"
    in2="source2"
    mode="lighten"/>

Давайте рассмотрим возможные значения на примерах. Их не так много, как в photoshop и подобных редакторах, но все же есть наиболее часто используемые:

Текстура (повторяющееся изображение) с feTile

feTile позволяет сделать в svg текстуру. Это очень похоже на background-repeat: repeat; в html

<feTile in="source" />

Демо c svg-фильтрами:

В качестве демо посмотрите, что мы делали на halloween

Еще несколько примеров будут опубликованы в ближайшее время отдельными статьями.

В заключение:

Это первая статья с основами SVG фильтров. Продолжение седует…

Подписывайтесь на наши группы в Ваших любимых соц. сетях.

Метки: , ,
11 комментариев на “SVG-фильтры. Часть 1. Основные понятия и типы. Применение к изображениям для создания графических эффектов.
  1. Temy пишет:

    Полезнейшая статья, спасибо автору за работу!
    Не нашел на сайте подписки на rss. Где-то есть?

  2. enovot пишет:

    Добрый вечер! Я автор этого вопроса.
    Как быть, если очень хочется сохранить изображение отфильтрованное с помощью svg filter? И чтобы было яснее для чего это мне нужно, отмечу что я хочу использовать это в js приложении собранным с использованием Phonegap. Одно из составляющих приложения, это как раз съемка фотографий и применение к ним фильтров, аля мини инстаграм.

    • Привет! Вы можете использовать консольный браузер на сервере (например PhantomJS)
      Те процесс примерно такой:

      1. Вы даете юзеру поиграть с картинкой в Phonegap и применить фильтры, посмотреть как оно будет
      2. Отправляете на сервер оригинал картинки и параметры фильтра, который пользователь выбрал
      3. В консольном браузере на стороне сервера моделируете тот же svg-фильтр и делаете скриншот в jpg или png, который сохраняете. Например для nodejs есть удобная обертка https://github.com/brenden/node-webshot

      Скажите понятно ли я рассказал :) ?

  3. Александр пишет:

    Здравствуйте, подскажите пожалуйста визуальный редактор в котором можно “поиграться” с фильтрами

  4. Денис пишет:

    годнейший материал, спасибо!

  5. Вячеслав пишет:

    Офигенная статья, автору уважуха. Очень полезная статья, рад, что такую нашёл! СПАСИБО!

Оставить комментарий

Ваш email не будет опубликован. Обязательные поля отмечены *

*

* Copy This Password *

* Type Or Paste Password Here *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

Вы можете использовать это HTMLтеги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Узнавай о новых статьях первым!

Спасибо за лайк в FACEBOOK
Подписывайтесь на новости вконтакте
Последние статьи от html5.by