sundway / blog

oh~~
110 stars 6 forks source link

SVG滤镜对图片调色 #14

Open sundway opened 6 years ago

sundway commented 6 years ago

色彩基础

色彩学是一门综合学科,春节利用闲暇时间看过几本相关书籍,本打算写一篇文章的,但是发现自己知道的东西太少,所以这里会做一些简单的讲解。首先,是大家都耳熟能详的一个概念三原色。这里主要针对色光三原色,如图:

也就是说屏幕上的任何一个像素点都是有红绿蓝三原色组成。在写CSS时,通常会碰到rgb(0, 0, 0)之类的,其中值的范围0-255,也就是说将红绿蓝各分成256进行混合,表现出来的颜色足够了,很多颜色人的肉眼也分不清楚。

伊顿色环

伊顿色环是色彩学家伊顿设计出来的一套色环,除此之外还有蒙塞尔色环等。

如图所示,伊顿色环是由颜料的三原色以及三原色的复色组成的12色色环。这里有一些概念,相近色:相差30度范围内的色彩可以称为相近色,在配色中一般可以用户过渡协调。互补色:色环上相差180度颜色可以就叫做互补色,运算上和255进行位操作。一般用户强烈的对比,谷歌微软的品牌Logo都用双互补色。有些人可能会奇怪,为什么图中的色环没有黑白?这里多提一句,因为黑白不属于颜色,而是明度。将黑白分为12阶,图片分属暗调、明调等。

调色的原理

调色的原理很简单,就可以根据上面的色环进行观察,当我们想要将图片的绿色变为黄色是,我们只需要加入等量的红色即可。当我们减少图片中的红色时,红色的互补色绿色的视觉效果就会变强。对应到色光三原色中,就是减少红色,红色的互补色青色就会增强。

PS图片调色

PS 颜色相关的工具很多:色阶、曲线、色相饱和度、色彩平衡、通道混合器、颜色查找等。这里主要介绍两个工具进行色彩调节:通道混合器、曲线。

通道混合器

下图是通道混合器控制面板。通道混合器和其它色彩调节工具不太一样:色相饱和度,色彩平衡的调色都是往里面加减颜色,但是通道混合器是通过借用其他通道的亮度来改变它的颜色,所以其它通道的颜色是不会被影响的。

下面可以通过一个列子说明这个问题,输出通道为红色时,红色的亮度为100%,绿色和蓝色分别为0%。当我们把红色滑动到50%,绿色和蓝色保持不变时,一张图片中所有包含红色的像素的红色通道亮度都会减少50%,像素rgb整体的r的亮度会减少50%。

如下图所示,我们输出通道为红色中的红色减少到50%,可以看到上面红色部分的亮度变低了一倍,其他包含红色的部分色块的红色减少50%,色相会向红色的互补色青色进行偏移。

同时由于rab中的亮度变为了50%,100%, 100%,色彩的整体亮度失去平衡,所以无色系的部分也会向红色的互补色青色进行偏移,图片整体看起来很怪,感觉像是有一个青色的蒙层。解决这个问题也很简单,只需要将红色输出通道的整体亮度保持100%不变即可,这里直接增加50%的绿色如下图。

这样,上图的操作就是把图片中所有色块中的红色部分降低50%,绿色部分加50%的红色,上图中明显变化的色块有红色的亮度降低了50%。颜色由rgb(255, 0, 0)变为rgb(125, 0, 0),相当于明度降低一半,将rgb模式转化为hsl模式可以明显的看出倍数关系。绿色部分红色降低50%,绿色中加50%的红色,颜色由rgb(0, 255, 0)变为rgb(125, 255, 0),相当于绿色中加50%的红色,其他颜色以此次类推。

通道混合器处理图片

通过上面的例子,我们知道了通道混合器的原理,结合前面所讲的色光的基础知识,就可以对一张真实的图片进行颜色处理了。比如我们可以快速的将一张夏天拍摄的照片转换成秋天的场景。

上图是团队夏天outing时在张家界拍摄的一张图片。简单分析下,图片基本是由绿色和蓝色组成。秋天和夏天色彩上的差别主要就是绿色的树叶会变为黄色。我们希望图片中的绿色可以变成黄色,其他色彩保持不变(PS中有其他工具可以直接将绿色色相转化成黄色),这个用上面介绍的知识,绿色中加入红色可以让绿色变为黄色,也就是说我们在红色输出通道中将绿色向右移动,红色和蓝色向做左移动保持总量为100%即可实现。这里将输出通道为红色中的红色由100%变为-30%,绿色由0%变为200%,蓝色由0%变为-70%,总量保持100% 不变。如下图:

曲线处理图片

下面是曲线控制面板。曲线和通道混合器类似,对rgb通道亮度进行调节。曲线的横轴是原图的亮度分布,从左到右依次是0值纯黑,1-254的中间灰色值,以及最右边255的纯白最亮值。横轴上叠加着一个直方图,显示出原图各个亮度上,分别存在着多少像素。

当我们在曲线上任意取一个点,它的“输入值”就是它横轴对应的值,即原图中的亮度,它的“输出值”就是它纵轴中的数值,也就是调整后它的亮度值。那么下图中横轴128位置原来的rgb亮度为128,通过曲线调整后,现在的亮度变成了178。同时,PS中的曲线采用的是spine曲线,曲线其他位置进行了平滑调整。所以,添加完这个曲线之后,图片的整体亮度会有一个提亮的效果。

同样,以上面那张图为例,我们发现照片的整体亮度偏低,所以加一个曲线可以迅速的将照片的整体亮度提高。我们平时处理图片时都会根据具体的图片去调整曲线参数,平时较常用的有提亮压暗曲线,黑白场曲线,对比度曲线等。

feColorMatrix处理图片

feColorMatrix 顾名思义是一个色彩矩阵,fe代表的意思是svg滤镜。feColorMatrix则可以完全的类比到上面PS中的通道混合器。下面简单的介绍一下svg feColorMatrix的用法:

<filter id="filterName"> 
    <feColorMatrix
        type="matrix" 
        values="R 0 0 0 0 
                0 G 0 0 0 
                0 0 B 0 0 
                0 0 0 A 0"
    /> 
    </feColorMatrix> 
</filter>

在SVG中,你可以声明一个filter。在大多数情况之下,可以使用SVG的defs来声明你想要的filter,然后可以在CSS这样使用声明的filter。

.filter-me { 
    filter: url('#filterName'); 
}

type设置为matrix(type是其他类型时可以认为内置好的values模版)的时候,values值则可以完全类比PS中的通道混合器。第一行第一列代表的就是红色输出通道,第一行第二列则可以理解为上面的红色输出通道中绿色加入红色的比例。那么我们上图中的最后那张图片由SVG feColorMatrix处理时,只需要简单的修改values就可以达到相同的效果:

<filter id="filterName"> 
    <feColorMatrix
        type="matrix" 
        values="-1 3 -1 0 0 
                0 1 0 0 0 
                0 0 1 0 0 
                0 0 0 1 0"
    /> 
    </feColorMatrix> 
</filter>

效果如下图:

feComponentTransfer处理图片

<feComponentTransfer> SVG滤镜基元对每个像素执行颜色分量的数据重映射.它允许进行像亮度调整,对比度调整,色彩平衡或阈值的操作。其实就可以类比成PS中的曲线,不同的是PS中的曲线是spine曲线,而feComponentTransfer可以通过table或者line模拟出来。feComponentTransfer也可以设置幂曲线,但通常是作为gamma校正用。下面简单介绍下feComponentTransfer的用法:

<filter id="table">
    <feComponentTransfer>
        <feFuncR type="table" tableValues="0.0 0.7 0.9 1.0"/>
        <feFuncG type="table" tableValues=".2 0.7 0.9 1.0"/>
        <feFuncB type="table" tableValues=".2 0.7 0.9 1.0"/>
    </feComponentTransfer>
</filter>
.filter-me { 
    filter: url('#table'); 
}

feComponentTransfer重的type类型有四种,table其中一种。如下图,将 tableValues="0.0 0.7 0.9 1.0" 时,横轴会分为三等份:0.0 0.33 0.66 1,分别对应的纵轴为 0.0 0.7 0.9 1.0。

同样,以曲线那个图片处理为例,我们在PS曲线中增加了一个输入为128,输出为178的点。那么用table表示就是:

<filter id="table">
    <feComponentTransfer>
        <feFuncR type="table" tableValues="0.0 0.7 1.0"/>
        <feFuncG type="table" tableValues="0.0 0.7 1.0"/>
        <feFuncB type="table" tableValues="0.0 0.7 1.0"/>
    </feComponentTransfer>
</filter>

上面那张图是没有加滤镜的效果,下面那张图是加了滤镜的效果,可以明显的看到下面那张图整体亮度提升了。上面的例子中只是feComponentTransfer对rgb整体做了调节,和曲线一样它可以对每个通道进行调节,从而实现和PS曲线一样的各种效果。

CSS filter

CSS中的滤镜效果基本都可以用svg滤镜快速实现,而CSS无法实现的滤镜效果,SVG基本也能快速实现。下面简单的列举几个CSS 滤镜,并且用svg滤镜实现一遍。

filter: brightness(0.5)

上面是对明度的控制,也就是将rgb的总体明度调整到50%,而每个通道的比例保持不变。通过feColorMatrix快速实现:

<filter id="filterName"> 
    <feColorMatrix
        type="matrix" 
        values="0.5 0 0 0 0 
                0 0.5 0 0 0 
                0 0 0.5 0 0 
                0 0 0 1 0"
    /> 
    </feColorMatrix> 
</filter>

对应到PS通道混合通道中的操作就是红色输出通道中的红色降低50%,绿色输出通道中的绿色降低50%,蓝色输出通道中的蓝色降低50%。整体rgb亮度也会降低50%,效果如下:

同样通feComponentTransfer也可以快速实现:

<filter id="brightness">
    <feComponentTransfer>
        <feFuncR type="linear" slope="[amount]"/>
        <feFuncG type="linear" slope="[amount]"/>
        <feFuncB type="linear" slope="[amount]"/>
    </feComponentTransfer>
</filter>

上面调整的是直线的斜率,类比到PS中的效果如下:

结束语

SVG中的滤镜很强大,上面列举的两个滤镜可以轻松的处理图片,但一般对图片的处理还是会借助专业的处理软件。通过类比,我们可以更加容易理解滤镜的原理,也可以通过编程的方式实现对图片的动态处理。CSS filter 是一个中内置了一些常用的滤镜,也通过SVG滤镜可以轻松的实现那些滤镜效果。