Mar*_*uto 2 html css hsl css-filters
我想知道是否可以使用 css/svg 滤镜执行色相/饱和度颜色转换,就像 Photoshop 色相/饱和度的工作方式一样。
本质上,根据我所读到的内容,Photoshop 在内部将所有像素从 RGB 表示转换为 HSL 表示,并根据用户使用定义的值基本上增加色调 (H)、饱和度 (S) 或亮度 (L) 值。滑块,如下图所示:

在这里,我选择了默认范围 ( Master),这意味着将考虑所有色调值。
使用 CSShue-rotate过滤器,我们可以得到一个近似结果:

由于另一个问题的答案中指出的问题,某些颜色并不完全相同:/sf/answers/1352779221/。(这对我来说没关系,我不需要它像 Photoshop 一样准确。)
因此,本质上,这两种方法的内部程序似乎大致相同。
现在,Photoshop 还允许我定义要考虑调整的颜色范围,如下图所示:

本质上,这个值范围意味着任何值hue超出范围限制的颜色都将被忽略。因此,在我的示例中,颜色 #1、#2 和 #5 保持不变。
我正在尝试使用 CSS os SVG 过滤器做同样的事情,但我找不到方法。我正在阅读滤镜效果文档(https://drafts.fxtf.org/filter-effects/),看看是否有任何东西可以用来定义范围,但我找不到任何东西。
有谁知道是否有办法做我想做的事?也许有 CSS 过滤器的有效替代品吗?
编辑:此片段显示了我得到的内容filter: hue-rotate(45deg)以及我想要获得的结果。
.block-wrapper {
width: 100%;
height: 50px;
display: flex;
margin-bottom: 10px;
}
.block {
width: 20%;
height: 100%;
}
.b1 {
background-color: rgb(29 85 34);
}
.b1-goal {
background-color: rgb(29 85 34);
}
.b2 {
background-color: rgb(32 53 79);
}
.b2-goal {
background-color: rgb(32 53 79);
}
.b3 {
background-color: rgb(175 43 52);
}
.b3-goal {
background-color: rgb(173 75 51);
}
.b4 {
background-color: rgb(172 94 50);
}
.b4-goal {
background-color: rgb(166 160 44);
}
.b5 {
background-color: rgb(96 230 33);
}
.b5-goal {
background-color: rgb(96 230 33);
}
.hue-45 {
filter: hue-rotate(45deg);
}Run Code Online (Sandbox Code Playgroud)
<h3>Original</h3>
<div class="block-wrapper">
<div class="block b1"></div>
<div class="block b2"></div>
<div class="block b3"></div>
<div class="block b4"></div>
<div class="block b5"></div>
</div>
<h3>With <code>hue-rotate: 45deg;</code></h3>
<div class="block-wrapper hue-45">
<div class="block b1"></div>
<div class="block b2"></div>
<div class="block b3"></div>
<div class="block b4"></div>
<div class="block b5"></div>
</div>
<h3>What I want: update hue only for red colors</h3>
<div class="block-wrapper">
<div class="block b1-goal"></div>
<div class="block b2-goal"></div>
<div class="block b3-goal"></div>
<div class="block b4-goal"></div>
<div class="block b5-goal"></div>
</div>Run Code Online (Sandbox Code Playgroud)
这实际上很难立即完成,因为feColorMatrix处理 RGB 中的颜色,而在 HSL 中还没有办法做到这一点。(如我错了请纠正我。)
所以我找到了一个接近您想要的解决方案。这个想法是首先掩盖掉你不想进行色调旋转的颜色。然后对剩余部分进行色调旋转并将其粘贴到原始部分的顶部。
带过滤器的 SVG 代码如下所示:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<filter id="partial-hue-rotation">
<!--
1) Mask away the colors that shouldn't be hue-rotated.
This is done based on the R-channel value only.
The R-channel value comes in at [0-1],
so multiply it by 255 to get the original value (as in rgb()).
Then subtract (lowest R-channel value of color range - 1)
to leave all color with a R-channel value higher than that.
-->
<feColorMatrix
color-interpolation-filters="sRGB"
type="matrix"
in="SourceGraphic"
result="only-red-visible"
values="1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
255 0 0 0 -171"
/><!-- Colors with R-channel > 171 will be left (and thus effected). -->
<!--
2) Apply hue rotation to remaining colors.
-->
<feColorMatrix
type="hueRotate"
values="45"
in="only-red-visible"
result="rotated-part"
/>
<!--
3) Now paste the rotated part on top of the original.
-->
<feMerge>
<feMergeNode in="SourceGraphic" />
<feMergeNode in="rotated-part" />
</feMerge>
</filter>
<!--
This filter is to check if the right range is hue-rotated.
All white areas will be rotated.
The bottom row of values can be copied over the bottom row
of the filter above.
-->
<filter id="test-partial-hue-rotation">
<feColorMatrix
color-interpolation-filters="sRGB"
type="matrix"
in="SourceGraphic"
result="marked-range"
values="0 0 0 0 1
0 0 0 0 1
0 0 0 0 1
255 0 0 0 -171"
/><!-- Colors with R-channel > 171 will be white. -->
<feMerge>
<feMergeNode in="marked-range" />
</feMerge>
</filter>
</svg>
Run Code Online (Sandbox Code Playgroud)
要应用过滤器,只需添加filter: url(#partial-hue-rotation)到元素的 CSS 中即可。
要测试是否实现了正确的颜色/部分,您可以添加filter: url(#test-partial-hue-rotation);到元素的 CSS。所有白色部分都将进行色调旋转。(您可能需要将父级的背景颜色设置为黑色才能看到它。)
注意事项和限制:
255第一列和-X最后一列中。(255第二列用于 B 值选择等)hue-rotate显然 CSS和feColorMatix's 的hueRotate计算方式也存在差异(来源)。这可以通过添加color-interpolation-filters="sRGB"到hueRotate feColorMatrix标签来消除(不确定)。不管怎样,这是第一次尝试,也许这种方法可以帮助你。:)
更多信息:
有关如何计算色调旋转的颜色矩阵的更多信息,请参阅Chrome 浏览器的 C++ 实现。
另请参见速记过滤器的矩阵等价。
还有这个帖子。
因此,经过一番阅读和思考后,我想到了使用混合模式difference为过滤器提供有关哪些颜色在“范围内”并且应该受到影响的信息。其工作原理如下:
<feBlend>在与原始模式和洪水模式不同的情况下使用。(最暗的部分与中间颜色的重叠最多,例如在色轮上最接近它。)feColorMatrix将此灰度转换为 alpha 值,同时将这些值映射到最低的 2/3 是透明的(将被删除)。feComposite遮盖原始图像并将效果(色调旋转)仅应用于该部分。可以选择要影响的颜色范围的中点和宽度:
flood-color的feFlood。(使用完全饱和和 50% 亮度的颜色以获得最佳效果,所以#ff0000、#00ff00等)feColorMatrixwith中的偏移量选择result="alpha-mask"。示例:保留色轮的 1/3 给出偏移值(2/3) * -255。在这里更新了工作中的 JSFiddle。(底部的一个,过滤#partial-hue-rotation。)
注意:
色调旋转效果做得很糟糕,所以不确定那里出了什么问题,但生成的颜色与CSS的过滤器相同hue-rotate()..所以,是的..
不幸的是,上面的过滤器并不适用于所有颜色。SourceGraphic对于正确将 转换为灰度色调值(其中0deg = black和)的 SVG 滤镜360deg = white,请查看#hue-values我在此 JSFiddle中制作的滤镜。
如果您只想对所有红色/绿色/蓝色/青色/洋红色/黄色应用滤镜效果,则可以使用#tonegroup-select同一JSFiddle中的滤镜。
该过滤器的代码为:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="tonegroup-select"
x="0%" y="0%"
width="100%" height="100%"
primitiveUnits="objectBoundingBox"
color-interpolation-filters="sRGB"
>
<!-- Compare RGB channel values -->
<feColorMatrix type="matrix" in="SourceGraphic" result="test-r-gte-g"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 -255 0 0 1"
/>
<feColorMatrix type="matrix" in="SourceGraphic" result="test-r-gte-b"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 0 -255 0 1"
/>
<feColorMatrix type="matrix" in="SourceGraphic" result="test-g-gte-r"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -255 255 0 0 1"
/>
<feColorMatrix type="matrix" in="SourceGraphic" result="test-g-gte-b"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 -255 0 1"
/>
<feColorMatrix type="matrix" in="SourceGraphic" result="test-b-gte-r"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -255 0 255 0 1"
/>
<feColorMatrix type="matrix" in="SourceGraphic" result="test-b-gte-g"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -255 255 0 1"
/>
<!-- Logic masks for tone groups -->
<!-- For example: all red colors have red channel values greater than or equal to the green and blue values -->
<feComposite operator="in" in="test-r-gte-g" in2="test-r-gte-b" result="red-mask" />
<feComposite operator="in" in="test-g-gte-r" in2="test-g-gte-b" result="green-mask" />
<feComposite operator="in" in="test-b-gte-r" in2="test-b-gte-g" result="blue-mask" />
<feComposite operator="in" in="test-g-gte-r" in2="test-b-gte-r" result="cyan-mask" />
<feComposite operator="in" in="test-b-gte-g" in2="test-r-gte-g" result="magenta-mask" />
<feComposite operator="in" in="test-r-gte-b" in2="test-g-gte-b" result="yellow-mask" />
<!-- Select all colors in tone group -->
<!-- Note: uncomment the right tone group selection here -->
<!-- Note: greyscale colors will always be selected -->
<feComposite operator="in" in="SourceGraphic" in2="red-mask" result="selection" />
<!-- <feComposite operator="in" in="SourceGraphic" in2="green-mask" result="selection" /> -->
<!-- <feComposite operator="in" in="SourceGraphic" in2="blue-mask" result="selection" /> -->
<!-- <feComposite operator="in" in="SourceGraphic" in2="cyan-mask" result="selection" /> -->
<!-- <feComposite operator="in" in="SourceGraphic" in2="magenta-mask" result="selection" /> -->
<!-- <feComposite operator="in" in="SourceGraphic" in2="yellow-mask" result="selection" /> -->
<!-- Cut selection from original image -->
<!-- Note: use same mask for `in2` attribute as with selection -->
<feComposite operator="out" in="SourceGraphic" in2="red-mask" result="not-selected-source" />
<!-- Apply effects to `selection` only -->
<feColorMatrix
type="saturate"
values="0"
in="selection"
result="edited-selection"
/>
<!-- After all effects, adjustments, etc -->
<!-- the last `result` output name should be "edited-selection" -->
<!-- Bring it all together -->
<feMerge>
<!-- <feMergeNode in="selection" /> --><!-- Uncomment to check selection -->
<feMergeNode in="not-selected-source" />
<feMergeNode in="edited-selection" />
</feMerge>
</filter>
</defs>
</svg>
Run Code Online (Sandbox Code Playgroud)
在代码内的注释中,您可以找到有关工作原理的更多信息以及如何使用它的说明。
欲了解更多信息和参考,请查看: