同时使用CSS灰度滤镜和background-blend-mode是否可行?

15

我试图以与Photoshop文件相同的方式处理图像-将图像去色为灰度,然后使用乘法混合模式应用颜色叠加。为此,我正在使用CSS背景图像进行样式设置...

.someclass
{
    /* grayscale */
    -webkit-filter: grayscale(1); 
    filter: gray; 
    filter: grayscale(1);
    filter: url(desaturate.svg#greyscale);

    /* multiply */
    background-color: rgba(190, 50, 50, 0.65);
    background-blend-mode: multiply;
}
这个问题在于灰度滤镜最终会使混合模式的红色变得不饱和。换句话说,先进行了乘法混合,然后才是灰度处理。我该如何调整顺序,以便先应用灰度,然后再应用混合模式呢?
我已经为代码创建了一个调试页面(http://jsfiddle.net/g54LcoL1/1/),以及一个 Photoshop 的截图,展示预期的结果。最底部的图像 div.grayscale.multiply 应该呈现为红色。 enter image description here

据我所知,使用CSS是不可能做到这一点的。这是因为CSS在矩阵中完成所有操作,所以对于所有属性设置的顺序已经确定。可以选择的替代方案是事先将图像保存为灰度图像,或者使用类似画布(canvas)的东西来依次进行处理。 - Zach Saucier
作为 CSS 的“用户”,我认为这应该按照在代码中声明的顺序进行。我相信它之所以是这样的有原因,但随着 background-blend-mode 获得越来越广泛的支持,人们将要求更多地控制混合/过滤器的顺序。我想 canvas 应该是解决这个问题的方法。我会试一试。 - Jeff
CSS 是自下而上的语言,也许这就是你的问题所在,我不确定。无论如何,请尝试使用 Pleeeease Playground,它可以转换过滤器。 - DifferentPseudonym
从来没有-moz前缀的filter属性。已将其从问题中删除... - Volker E.
4个回答

12

不能使用过滤器来实现,但可以在混合模式下保持一致来实现。

在混合模式下灰度图像的等效方式是亮度,源图像为图片,纯白色为背景

所以,从底部到顶部的背景图片依次为:

  1. 白色(作为背景颜色)
  2. 您的图片
  3. 固体红色(现在必须指定为渐变)

混合模式分别为亮度和乘法。

.test {
  width: 400px;
  height: 400px;
  background-image: linear-gradient(0deg, red, red), url("https://istack.dev59.com/WIMBV.webp");
  background-color: white;
  background-blend-mode: multiply, luminosity;
  background-size: cover;
}
<div class="test"></div>


1
这是一个非常棒的解决方案。如果Safari支持明度背景混合模式,我现在就会感觉像置身天堂。 - Joel Farris
3
жҲ‘з”ҡиҮіеңЁSafariдёӯдҪҝз”ЁдәҶmix-blend-modeеұһжҖ§е’Ңfilter: grayscale(100%)еҜ№з…§зүҮиҝӣиЎҢдәҶеӨ„зҗҶпјҢе®һзҺ°дәҶиҜҘж•ҲжһңгҖӮжЈ’жһҒдәҶпјҒ - Joel Farris
猫咪图片的链接无法使用,我找到了另一个链接,但是不知道如何添加:http://4.bp.blogspot.com/_BSmKs8FzkfI/SCi18Kth3oI/AAAAAAAAACA/BzWFAOZXu3U/s1600/kitteh_puddle.jpg - oceanGermanique
1
@Oceangermanique,已将您的照片添加到代码片段中。谢谢! - vals
@vals,你的解决方案启发了我去找到另一种仅使用 mix_blend_mode 的方法。 - oceanGermanique

3

正如Joel在接受的答案下评论中提到的那样,可以使用mix-blend-mode来实现这一点。

在我的示例中,我将使用实际图像而不是背景图像,因为这对于无障碍性更好。如果必须是背景图像,则仍然可以使用相同的技术。将图像替换为具有背景图像样式的空div,如下所示:

<!-- Not the recommended HTML, see the other examples for better HTML -->
<div class="image-wrapper">
    <div class="image" style="background: url('https://static.decalgirl.com/assets/designs/large/clrkit.jpg') no-repeat; height: 100px; width: 100px;"></div>
</div>

我将使用“屏幕”混合模式而不是“正片叠底”混合模式,因为它能更清晰地展示颜色去除效果。
带有颜色去除的效果:

.image-wrapper {
    background: red;
    display: inline-block;
}

.image-wrapper .image {
    mix-blend-mode: screen;
    filter: grayscale(100%);
}
<div class="image-wrapper">
    <img class="image" src="https://static.decalgirl.com/assets/designs/large/clrkit.jpg" alt="Colorful cats"/>
</div>

不去除颜色:

.image-wrapper {
    background: red;
    display: inline-block;
}

.image-wrapper .image {
    mix-blend-mode: screen;
}
<div class="image-wrapper">
    <img class="image" src="https://static.decalgirl.com/assets/designs/large/clrkit.jpg" alt="Colorful cats"/>
</div>

更多信息可在此处找到:

https://css-tricks.com/almanac/properties/m/mix-blend-mode/

此链接是关于CSS属性mix-blend-mode的详细介绍。

只需将图像替换为具有背景图像样式的空div即可。你能加上一个带有background-image的例子吗? - oceanGermanique
1
@Oceangermanique,我已经更新了我的答案,并附上了一个HTML示例,以说明我的意思。 - Daniel Tonon

3
混合模式应用于背景层,然后过滤器应用于整个元素,所以它们可以处理两个不同的东西:在计算背景时(包括红色外观),通过过滤器将整个元素转换为灰度。
有一个针对图像引用的提议的 filter() 函数,因此理论上,您应该能够在加载任何图像时应用过滤器。我认为这就是想法。
.someclass {
    background-image: filter(cat.jpg, grayscale(100%));
    background-color: red;
    background-blend-mode: multiply;
}

很遗憾,我认为这个功能还没有实现,它只存在于过滤器规范的草案版本中。
通常,在这些“后处理”CSS效果方面的操作顺序与SVG相同: 首先进行过滤,然后是裁剪、遮罩和混合。
(请参见混合和合成规范)所以,恐怕您不能改变这一点。

1

100%混合模式

  red  =========================================
                                                |
   cat     =======                              ==== Blending (luminosity)
                  |                             |
                  ==== Blending (multiply) ===
                  |
   white =========

<div style="
  position:relative;
  background-color: rgb(255,255,255);
  height: 316px;
  width: 450px;">
  
  <div style="
    background-image:  url('http://4.bp.blogspot.com/_BSmKs8FzkfI/SCi18Kth3oI/AAAAAAAAACA/BzWFAOZXu3U/s1600/kitteh_puddle.jpg');
    height: 316px;
    width: 450px;
    position:relative;
    left:0px;
    top:0px;
    mix-blend-mode: luminosity;">
  </div>

  <div style="
    background: rgba(190, 50, 50, 0.65);
    height: 316px;
    width: 450px;
    position:absolute;
    left:0px;
    top:0px;
    mix-blend-mode: multiply;">
  </div>
</div>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接