gogoend / blog

blogs, ideas, etc.
MIT License
9 stars 2 forks source link

看!我用SVG滤镜P完照片,发了条朋友圈,发了个沸点🖼 #70

Open gogoend opened 3 years ago

gogoend commented 3 years ago

前言

前段时间写了两篇文章,是关于SVG滤镜相关内容的,总觉得干看看好像没什么意思,还是应该输出一些结果 —— 毕竟SVG是一种可视化技术,只有文字、公式、代码的描述,是完全无法领略到它的魅力所在的。因此最近在发朋友圈时,我尝试着使用SVG滤镜来对拍的照片进行调色。

其实我是个挺爱在朋友圈里发照片的人,不过日常拍的都是景色,通过各种修图软件,为照片调色,调出别样的情调。手机端P图软件有很多,类似Adobe旗下的Lightroom、Google旗下的Snapseed,在不使用预设的情况下,我们通过更改饱和度、对比度、曝光等参数,来对照片颜色进行校正或是加入一些额外氛围。

在SVG滤镜的世界里,这些参数变成了另一种方式存在,即SVG滤镜原语中用于进行图像处理的原语(你可以点击# ✨让网页 Bling-Bling 的SVG滤镜 - 总览篇进行了解)。

image

这类原语可谓是滤镜的魅力与精髓所在。它们具有对通过in属性输入的图像源进行处理能力,可以将处理结果交给下一个原语进行处理,或直接作为结果展示到页面。其中就包括了例如像素位移滤镜、高斯模糊、颜色调整、卷积等等图像操作,提供了比CSS Filter 10个滤镜属性更加底层一些的图像操作。

下一篇我的文章将会开启SVG滤镜的图像处理原语之旅,因此这篇文章也算是个先导篇吧。不得不说,这里东西真心太多,一篇文章显然是没法写完的(而且前两篇文章中出现的SVG滤镜构建工具也仅仅是个半成品,还得慢慢编写),而且其实很多东西在没把这一系列文章写完之前我应该是不了解的,因此下面如有问题还请各位勘误。

下面就来通过几个例子,介绍一下我最近搭建出来的滤镜。当然滤镜效果是和源图像内容强相关的,下列滤镜可能不通用,同样, 和其它后期处理流程一样,素材的质量很重要,如果太糟糕可能是救不回来的

【例1】胶片效果

原图:

IMG_20210817_190406_2.jpg

可以看到这张图仅仅是十分单纯的一张景色照片(北京市海淀区中关村软件园一期旁的一个电线杆),看起来似乎可以直接发朋友圈,但有时候还是能发出照片里的一些问题以及想到一些创意:

  1. 感觉天空中的被夕阳所照射的云朵不是那么的鲜艳
  2. 希望图片可以朦胧一些
  3. 还希望照片能够有一些偏绿的老照片的感觉
  4. 希望天空可以稍微暗一些

因此通过以下滤镜来对图片的颜色进行了调整:

<svg style="width: 0;height: 0">
    <filter id="filter" x="0" y="0" width="100%" height="100%">
        <feFlood flood-color="#089" flood-opacity="0.5" result="98FF3FAE-0126-490C-A82F-8E16FB2FEFE7"></feFlood>
        <feColorMatrix in="SourceGraphic" type="matrix" values="
        1 0 0 0 0
        0 0.5 0.2 0 0
        0 0 0 0 0
        0 0 0 1 0" result="C7942AE9-423F-436F-B9C9-DA5AE285B6C4"></feColorMatrix>
        <feBlend in="SourceGraphic" in2="98FF3FAE-0126-490C-A82F-8E16FB2FEFE7" mode="lighten" result="A9D208EF-CC5A-4C72-B87F-9701CDEAC015"></feBlend>
        <feGaussianBlur in="A9D208EF-CC5A-4C72-B87F-9701CDEAC015" stdDeviation="2" result="07D9C1F0-6E6B-4F23-8CF8-E0D5FE822789"></feGaussianBlur>
        <feBlend in="C7942AE9-423F-436F-B9C9-DA5AE285B6C4" in2="07D9C1F0-6E6B-4F23-8CF8-E0D5FE822789" mode="soft-light" result="44BA7ABB-E248-431F-9DB0-D3EBF4FF160E"></feBlend>
        <feConvolveMatrix in="44BA7ABB-E248-431F-9DB0-D3EBF4FF160E" kernelMatrix="
        0 0 0,
        0 1.6 0,
        0 0 0" order="3, 3" divisor="1" edgeMode="none" kernelUnitLength="2" preserveAlpha="true" result="5DED114B-C12E-4B25-8021-2FEE5AC7BE66"></feConvolveMatrix>
    </filter>
</svg>

这是滤镜代码对应的节点导图:

image.png

注意导图和代码不同的地方。代码中的源图像是使用SourceGraphic关键字引入的,而导图是使用<feImage>引入的。因此图中<feImage>的输出相当于SourceGraphic

我们通过看这个导图来讲解一下此处图像处理的处理流程。笔者为各连线标了号,可以参照这一标号分步骤阅读

  1. 引入源图像,将源图像SourceGraphic连入feColorMatrix颜色矩阵节点来得到一个与源图像相比较黄的图像 —— 实际上是让原图中蓝色通道的亮度变为0,无任何蓝色成分,同时绿色通道也稍微变暗一些
  2. 填充一个绿色色块,将色块连入feBlend混合模式节点的in2输入端口,以便接下来参与混合
  3. 将源图像SourceGraphic连入feBlend混合模式节点的in输入端口,让源图像与色块以lighten(变亮)模式进行混合,这就让图像暗部有了一种偏绿的感觉
  4. 将经过feBlend混合模式节点处理的图像连入feGaussianBlur高斯模糊节点,得到一张经过模糊的照片,有了一些朦胧感
  5. 将经过feColorMatrix颜色矩阵节点处理过后的图像连入一个feBlend混合模式节点,以供接下来混合
  6. 将经过feGaussianBlur高斯模糊节点处理过的图像连入该feBlend混合模式节点,将高斯模糊节点的结果与颜色矩阵节点的结果以soft-light进行混合
  7. 经过上一步feBlend混合模式节点,看起来图像偏暗,因此接下来连入feConvolveMatrix卷积矩阵节点,卷积核中心设为一个比1大的值,让中心像素变亮一些。

得到:

image.png

【例2】灯光增强

原图:

IMG_20210816_215833.png

可以看到这张图是一张普通的雨天照片(北京市海淀区后厂村路的一个路口,某天暴雨路都给淹了),突然想到一些创意:

  1. 期望让灯光能够更亮一些,让水面倒影更有观感
  2. 多一些蓝色或紫色的灯光,这样对比感更强

因此经过各种调整与试错得到了如下滤镜:

<svg style="width: 0;height: 0">
    <filter id="filter" x="0" y="0" width="100%" height="100%">
        <feColorMatrix in="SourceGraphic" type="matrix" values="
        1 0 0 0 0
        0 0 0 0 0
        0 0 1 0 0
        0 0 0 1 0" result="15321EE7-E850-46DA-9DDF-119265E917FB"/>
        <feConvolveMatrix in="15321EE7-E850-46DA-9DDF-119265E917FB" kernelMatrix="
        0 1 0,
        1 1 1,
        0 1 0" order="3, 3" divisor="1.5" bias="0" edgeMode="none" kernelUnitLength="2" preserveAlpha="true" result="F12F0C6B-3D13-4F7A-A0B0-502118EA4557"/>
        <feBlend in="SourceGraphic" in2="F12F0C6B-3D13-4F7A-A0B0-502118EA4557" mode="lighten" result="4CE67E24-8ABA-4B72-97E8-737AD96949E5"/>
    </filter>
</svg>

这是滤镜代码对应的节点导图:

image.png

同样我们根据标号分步骤来进行阅读:

  1. 引入源图像,将源图像SourceGraphic连入feColorMatrix颜色矩阵节点来提取出源图像中的红、蓝、Alpha通道,让结果看起来没有任何绿色成分 —— 实际上是将绿色通道的亮度调为了0
  2. feColorMatrix颜色矩阵节点结果连入feConvolveMatrix卷积矩阵节点,卷积核中心及上下所有四个数值均设为1,看起来让中心像素和上下左右四个像素有种发光效果,我们可以在结果中看到原来的光都产生了一些扩散
  3. feConvolveMatrix卷积矩阵节点处理结果连入feBlend混合模式节点的in2输入端口,以供接下来混合
  4. 将源图像SourceGraphic连入feBlend混合模式节点的in输入端口,将卷积矩阵节点的结果与源图像lighten(变亮)模式进行混合。混合后最终图像将保留两个混合对象之间亮度最亮的部分。

得到:

image.png


以上就是本文的全部内容了。本文主要通过两个例子,向你展示了SVG滤镜的魅力。在这里,没有用Canvas、WebGL甚至也没有用JavaScript,唯一使用的,最纯的HTML/SVG元素。

不得不说,每一个元素(标签)的背后应该都有一段极其有趣的故事,弄懂各种标签的作用,有时候可以帮助我们以原生的方式以及较低的代价实现可能较为复杂的需求,甚至发现更大的世界。


总目录:

  1. CSS滤镜篇
  2. 总览篇
  3. 图像引入篇