Артефакты края фильтра размытия SVG

#svg #svg-filters

#svg #svg-фильтры

Вопрос:

Когда я применяю фильтр размытия к изображению svg, он размывает края, поэтому они становятся немного прозрачными (см. Левый пример). Я хочу размыть его без такого артефакта (см. Правый пример). Я решил это с помощью взлома: просто скопировал одно и то же перевернутое изображение и разместил их на 4 стороны.

Есть ли лучший способ?

Обратите внимание, что я не могу просто увеличить изображение на 5-10%; размер должен быть таким же, как у исходного изображения.

Вот мой svg:

 ...
<filter id="blur">
 <feGaussianBlur in="SourceGraphic" stdDeviation="4"></feGaussianBlur>
</filter>
...
<g filter="url(#blur)">
  <image xlink:href="cathedral.jpg"></image>
</g>
 

введите описание изображения здесь

Ответ №1:

Это хороший способ создания четкой границы, который использует feComponentTransfer для увеличения непрозрачности краев до 1.0, но также требует, чтобы вы обрезали фильтр до размера фильтруемого элемента (используя атрибуты filter sizing в filter element) — если вы этого не сделаете, выпосмотрите, как переполнение нового непрозрачного размытия и черного фона выходит за пределы исходного изображения.

 <filter id="blur" x="0%"
 y="0%" width="100%" height="100%">
 <feGaussianBlur in="SourceGraphic" stdDeviation="4"/>
  <feComponentTransfer>
      <feFuncA type="discrete" tableValues="1 1"/>
   </feComponentTransfer>
</filter>
...
<g filter="url(#blur)">
  <image xlink:href="cathedral.jpg"></image>
</g>
 

Если у вас нет квадратного ввода (допустим, ваша фотография круглая), то вам нужно использовать feComposite «in», чтобы обрезать выходные данные до области ввода, а не использовать размеры фильтра. Но feComposites сейчас работают немного медленно и пока не могут использоваться как часть CSS-фильтра, поэтому приведенный выше метод предпочтительнее для квадратных входов.

Обратите внимание, что это не будет работать на изображениях с переменной непрозрачностью / альфа-каналом — все будет преобразовано в 100% непрозрачность.

Другой вариант — использовать feColorMatrix для выполнения того же самого, в некоторых браузерах, похоже, GPU ускоряет эту операцию, поэтому она может быть быстрее, чем feComponentTransfer

 <filter id="blur" x="0%"
 y="0%" width="100%" height="100%">
 <feGaussianBlur in="SourceGraphic" stdDeviation="4"/>
 <feColorMatrix type="matrix"  values="1 0 0 0 0
                                       0 1 0 0 0 
                                       0 0 1 0 0 
                                       0 0 0 0 1"/>
</filter>
...
<g filter="url(#blur)">
  <image xlink:href="cathedral.jpg"></image>
</g>
 

Комментарии:

1. Похоже, это не работает. Смотрите здесь: jsbin.com/vugojiju/1/edit Я поместил то же изображение на обороте, чтобы проиллюстрировать проблему — прозрачные края размытого изображения.

2. Перед добавлением componentTransfer необходимо закрыть тег feGaussianBlur. В моем коде я использую самозакрывающийся <feGaussianBlur/> В вашей версии вы помещаете componenttransfer в набор тегов open и close feGaussian. Таким образом, он игнорирует передачу компонентов

3. Здесь опечатка: в первой строке x=»0% должно содержать закрывающую двойную кавычку. Кроме этого, потрясающий хак!