可以使用 SVG 滤镜对图像进行像素化吗?

问题描述 投票:0回答:3

注意: 我无法使用 JavaScript,因为这是针对 CSS Zen Garden 之类的挑战。请不要推荐 JS 库。

我有 2 个想法尚未取得进展:

  1. 使用 SVG 滤镜对图像进行像素化;我一直在玩

    <feMorphology operator="erode"/>
    并在之后提高对比度,但看起来很糟糕。

  2. 将图像过滤得更小,然后使用 CSS 和

    image-rendering
    将其放大为块状。最困难的部分是步骤A;我找不到任何缩放输入的过滤操作。

我错过了什么吗?如何使用 SVG 滤镜获得“像素化”效果?

css svg svg-filters
3个回答
16
投票

如果您有正确的“神奇”位移贴图,您可以对图像进行像素化。请随意使用下面引用的一个(由 Zoltan Fegyver 提供)。

更新:更改了示例代码以将位移贴图图像内联为数据:URI(感谢代码 IllidanS4。)

最初的答案将displacementMap图像托管在不同的域上。这曾经有效 - 但浏览器实施了新的过滤器安全措施,不允许这样做。对于今天的生产代码,您需要从与源图形文件相同的域提供置换贴图图像,或者您需要内联置换贴图。

更新2: 您可能需要调整 feImage 和 feGaussianBlur 的大小,以避免 feTile 中出现添加伪影的错误。例如 - 这似乎效果更好:

<feGaussianBlur stdDeviation="8" in="SourceGraphic" result="smoothed" />
 <feImage width="15.4" height="15.4" 

<svg x="0px" y="0px" width="810px" height="600px" viewBox="0 0 810 600" color-interpolation-filters="sRGB">
  <defs>
<filter id="pixelate" x="0%" y="0%" width="100%" height="100%">
  <!--Thanks to Zoltan Fegyver for figuring out pixelation and producing the awesome pixelation map. -->
  <feGaussianBlur stdDeviation="2" in="SourceGraphic" result="smoothed" />
  <feImage width="15" height="15" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAIAAAACDbGyAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAWSURBVAgdY1ywgOEDAwKxgJhIgFQ+AP/vCNK2s+8LAAAAAElFTkSuQmCC" result="displacement-map" />
  <feTile in="displacement-map" result="pixelate-map" />
  <feDisplacementMap in="smoothed" in2="pixelate-map" xChannelSelector="R" yChannelSelector="G" scale="50" result="pre-final"/>
  <feComposite operator="in" in2="SourceGraphic"/>
</filter>
  </defs>

  <image filter="url(#pixelate)" width="810" height="600" preserveAspectRatio="xMidYMid meet" xlink:href="http://uploads2.wikiart.org/images/vincent-van-gogh/the-starry-night-1889(1).jpg"/>
</svg>


5
投票

Michael Mullany 的答案中的过滤器对我不起作用,相反,我找到了 Taylor Hunt 的这个过滤器:

<svg>
  <filter id="pixelate" x="0" y="0">
    <feFlood x="4" y="4" height="2" width="2"/>
    <feComposite width="10" height="10"/>
    <feTile result="a"/>
    <feComposite in="SourceGraphic" in2="a" operator="in"/>
    <feMorphology operator="dilate" radius="5"/>
  </filter>
</svg>

(以与其他过滤器相同的方式使用它:通过给图像赋予属性

filter="url(#pixelate)"

在此 CodePen 中的操作:https://codepen.io/tigt/pen/aZYqrg

但是,这两个过滤器似乎都无法处理绘图不占据整个 viewBox 的 SVG。


0
投票

我扩展了 Jlubberger 和 Tigt 的解决方案。

改进:

  • 多种尺寸
  • 动画
  • 如果你不能 svg 平铺,边缘就不再有空白

  .imgAni {
    animation: pixelAni 5s;
  }
  @keyframes pixelAni {
    99.9% {
      filter: url("#pixelateAni");
    }
  }
  
  img {
    width: 100%;
    height: 100%;
  }
<img class="imgAni" src="https://www.hartz.com/wp-content/uploads/2022/04/small-dog-owners-1.jpg"/>

<svg>
  <filter id="pixelateAni" x="0" y="0" width="100%" height="100%">

    <!-- First layer: Normal pixelation effect-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="composite" in2="SourceGraphic" operator="in" width="2" height="2"></fecomposite>
    <fetile result="tiled"></fetile>
    <fecomposite in="SourceGraphic" in2="tiled" operator="in"></fecomposite>
    <femorphology id="morphology" operator="dilate" radius="1" result="dilatedPixelation"></femorphology>

    <!-- Second layer: Fallback with full-width tiling-->
    <feflood x="1" y="1" height="1" width="1" result="floodFallbackX"></feflood>
    <fecomposite id="compositeX" in2="SourceGraphic" operator="in" width="1" height="2"></fecomposite>
    <fetile result="fullTileX"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileX" operator="in"></fecomposite>
    <femorphology id="morphologyX" operator="dilate" radius="1" result="dilatedFallbackX"></femorphology>

    <!-- Third layer: Fallback with full-height tiling-->
    <feflood x="1" y="1" height="1" width="1"></feflood>
    <fecomposite id="compositeY" in2="SourceGraphic" operator="in" width="2" height="1"></fecomposite>
    <fetile result="fullTileY"></fetile>
    <fecomposite in="SourceGraphic" in2="fullTileY" operator="in"></fecomposite>
    <femorphology id="morphologyY" operator="dilate" radius="1" result="dilatedFallbackY"></femorphology>

    <!-- Lets animate them -->
    <animate calcmode="discrete" xlink:href="#composite" attributename="width" values="128; 64; 32; 16; 8; 4; 2" dur="5s" fill="freeze" repeatcount="once"></animate>
    <animate calcmode="discrete" xlink:href="#composite" attributename="height" values="128; 64; 32; 16; 8; 4; 2" dur="5s" fill="freeze" repeatcount="once"></animate>
    <animate calcmode="discrete" xlink:href="#morphology" attributename="radius" values="64; 32; 16; 8; 4; 2; 1" dur="5s" fill="freeze" repeatcount="once"></animate>
    
    <animate calcmode="discrete" xlink:href="#compositeX" attributename="width" values="64; 32; 16; 8; 4; 2; 1" dur="5s" fill="freeze" repeatcount="once"></animate>
    <animate calcmode="discrete" xlink:href="#compositeX" attributename="height" values="128; 64; 32; 16; 8; 4; 2" dur="5s" fill="freeze" repeatcount="once"></animate>
    <animate calcmode="discrete" xlink:href="#morphologyX" attributename="radius" values="64; 32; 16; 8; 4; 2; 1" dur="5s" fill="freeze" repeatcount="once"></animate>
    
    <animate calcmode="discrete" xlink:href="#compositeY" attributename="width" values="128; 64; 32; 16; 8; 4; 2" dur="5s" fill="freeze" repeatcount="once"></animate>
    <animate calcmode="discrete" xlink:href="#compositeY" attributename="height" values="64; 32; 16; 8; 4; 2; 1" dur="5s" fill="freeze" repeatcount="once"></animate>
    <animate calcmode="discrete" xlink:href="#morphologyY" attributename="radius" values="64; 32; 16; 8; 4; 2; 1" dur="5s" fill="freeze" repeatcount="once"></animate>
    
    <!-- Combine all three layers-->
    <femerge>
      <femergenode in="dilatedFallbackX"></femergenode>
      <femergenode in="dilatedFallbackY"></femergenode>
      <femergenode in="dilatedPixelation"></femergenode>
    </femerge>
  </filter>
</svg>

查看更多变体:https://codepen.io/QuiteQuinn/pen/qBeWaEW

© www.soinside.com 2019 - 2024. All rights reserved.