CSS滤色镜将黑白图像转换为双色块

时间:2022-08-10 00:21:09

I need to create a custom CSS filter that would convert black and white image to two-color image with two custom colors.

我需要创建一个自定义的CSS过滤器,它可以将黑白图像转换为两色的图像。

I want to apply filter in something like this way (not sure if this syntax is possible, maybe 6 arguments have to be passed separately):

我想以这种方式应用filter(不确定这种语法是否可行,可能需要分别传递6个参数):

.duotone {
    -webkit-filter: custom(none url(/filters/duotone.fs),
        black_color [255, 0, 0] white_color [255, 192, 203]);
}

so that black color is replaced with Red in this case, both the white and transparent colours (background) are replaced with Pink and all the shades of grey are replaced with colour in between (using straight-line curve).

在这种情况下,黑色的颜色被红色代替,白色和透明的颜色(背景)被粉红色取代,所有灰色的阴影被替换为颜色(使用直线曲线)。

Maybe it is even possible to define filter in CSS without an external file?

也许甚至可以在CSS中定义过滤器而不用外部文件?

The application of this filter is to convert black/white icons to colored icons at run-time.

这个过滤器的应用程序是在运行时将黑白图标转换为彩色图标。

There are very few examples on how to do it, this one is very generic covering much wider range of filters and the specification is also not so easy to understand.

关于如何实现它的示例很少,这个示例非常通用,涉及范围更广的过滤器,而且规范也不太容易理解。

Could somebody post a working filter doing this or something similar? Or at least maybe you could point me to some more focused examples of application of ColorMatrix that will be relevant to my situation.

有人能发布一个工作过滤器来做这个或类似的事情吗?或者至少你可以给我指出一些关于ColorMatrix应用的更集中的例子,这些例子与我的情况相关。

2 个解决方案

#1


3  

UPDATE:

更新:

In order to do that you will need to use -webkit-mask-image on CSS. This used to be a webkit only but it's now w3c css3.

要做到这一点,您需要在CSS中使用-webkit-mask-image。这曾经是一个webkit,但现在是w3c css3。

The support is just present on webkit tho. In order to keep backward compatibility and display a regular black icon you will need to identify if the browser has this capabilities. I'v archived that using modernizr.

支持只是出现在webkit tho上。为了保持向后兼容性并显示常规的黑色图标,您需要确定浏览器是否具有这种功能。我用modernizr保存下来。

http://jsfiddle.net/kkobold/Zq5FZ/5/

http://jsfiddle.net/kkobold/Zq5FZ/5/

old answer:

旧的回答:

I believe thats the result you are looking for:

我相信这就是你要找的结果:

http://s7.postimage.org/vo5v33tuj/Screen_Shot_2013_02_03_at_11_28_46_PM.png

http://s7.postimage.org/vo5v33tuj/Screen_Shot_2013_02_03_at_11_28_46_PM.png

you can archive it by filtering to sepia and then changing hue degree. different combinations will give different results. But a simple color picker can be made for the hue and a slide for sepia to increase or decrease intensity of the color change.

您可以通过过滤到深褐色,然后改变色调程度来存档它。不同的组合会产生不同的结果。但是,可以为色相制作一个简单的颜色选择器,为深褐色制作一个幻灯片,以增加或减少颜色变化的强度。

and CSS3 only.

只和CSS3。

<div class="pull-left span4" >
<img src="/img/bw.jpg" style="-webkit-filter: sepia(0.0) hue-rotate(0deg);" width="300"/><br />
-webkit-filter: sepia(0) hue-rotate(0deg);
</div>
<div class="pull-left span4" >
<img src="/img/bw.jpg" style="-webkit-filter: sepia(0.8) hue-rotate(50deg);" width="300"/><br />
-webkit-filter: sepia(0.8) hue-rotate(50deg);
</div>
<div class="pull-left span4" >
<img src="/img/bw.jpg" style="-webkit-filter: sepia(0.8) hue-rotate(100deg);" width="300"/><br />
-webkit-filter: sepia(0.8) hue-rotate(100deg);
</div>
<div class="pull-left span4" >
<img src="/img/bw.jpg" style="-webkit-filter: sepia(0.8) hue-rotate(150deg);" width="300"/><br />
-webkit-filter: sepia(0.8) hue-rotate(150deg);
</div>
<div class="pull-left span4" >
<img src="/img/bw.jpg" style="-webkit-filter: sepia(0.8) hue-rotate(200deg);" width="300"/><br />
-webkit-filter: sepia(0.8) hue-rotate(200deg);
</div>
<div class="pull-left span4" >
<img src="/img/bw.jpg" style="-webkit-filter: sepia(0.8) hue-rotate(250deg);" width="300"/><br />
-webkit-filter: sepia(0.8) hue-rotate(250deg);
</div>
<div class="pull-left span4" >
<img src="/img/bw.jpg" style="-webkit-filter: sepia(0.8) hue-rotate(300deg);" width="300"/><br />
-webkit-filter: sepia(0.8) hue-rotate(300deg);
</div>
<div class="pull-left span4" >
<img src="/img/bw.jpg" style="-webkit-filter: sepia(0.8) hue-rotate(350deg);" width="300"/><br />
-webkit-filter: sepia(0.8) hue-rotate(350deg);
</div>

#2


3  

A little late to the party here, but I've built you a CSS custom filter that does exactly what you're looking for. All the code can be found on GitHub here: https://github.com/awgreenblatt/css-custom-filters/tree/master/duotone

虽然有点晚了,但是我已经为您构建了一个CSS自定义过滤器,它可以完全满足您的需求。所有代码都可以在GitHub上找到:https://github.com/awgreenblatt/css-custom-filters/tree/master/duotone

Because of security restrictions, custom filters can't read pixels; they can only apply transformations to them. So for instance, the filter can't say, if the pixel is black, change it to red. However, there is still a way to do it.

由于安全限制,自定义过滤器不能读取像素;它们只能对它们应用变换。例如,过滤器不能说,如果像素是黑色,把它改成红色。然而,仍然有办法做到这一点。

Each color component ranges from [0,1]: All white pixels in the source image will be (1, 1, 1, 1) and all black pixels in the source image will be (0, 0, 0, 1)

每个颜色分量范围为[0,1]:源图像中的所有白像素都为(1,1,1,1,1,1),源图像中的所有黑像素都为(0,0,0,0,1)

Let's call the color you want to map black to: (br, bg, bb, 1) and the color you want to map white to: (wr, wg, wb, 1)

我们把要映射黑色的颜色命名为:(br, bg, bb, 1),把要映射白色的颜色命名为:(wr, wg, wb, 1)

You can define in a fragment shader a css_ColorMatrix which will apply a transformation on the source image. If we set the blend mode to 'multiply' then the css_ColorMatrix will be pre-multiplied by the current source image's color.

您可以在片段着色器中定义一个css_ColorMatrix,它将对源映像应用一个转换。如果我们将混合模式设置为“相乘”,那么css_ColorMatrix将被当前源图像的颜色预先相乘。

So, we set the css_ColorMatrix to:

因此,我们将css_ColorMatrix设为:

wr - br,       0,       0,     0,
      0, wg - bg,       0,     0,
      0,       0, wb - bb,     0,
     br,      bg,      bb,     1

If the source pixel is black, (0, 0, 0, 1) then the result of the multiplication will be (br, bg, bb, 1) If the source pixel is white (1, 1, 1, 1) then the result of the multiplication will be

如果源像素为黑色(0,0,0,0,0,1),则乘法的结果为(br, bg, bb, 1)如果源像素为白色(1,1,1,1,1,1,1,1,1,1,1),则乘法的结果为

((wr - br + br), (wg - bg + bg), (wb - bb + bb), 1) or (wr, wg, wb, 1)

((wr - br + br),(wg - bg + bg),(wb - bb + bb),1)或(wr,wg、白平衡、1)

Here's the fragment shader source:

这是碎片着色源:

precision mediump float;

uniform vec3 black;
uniform vec3 white;

// Main

void main()
{
  vec3 b = black / 255.0;
  vec3 w = white / 255.0;

  css_ColorMatrix = mat4(w.r-b.r, 0.0, 0.0, 0.0,
                         0.0, w.g - b.g, 0.0, 0.0,
                         0.0, 0.0, w.b - b.b, 0.0,
                         b.r, b.g, b.b, 1.0);
}

The vertex shader is just the default:

顶点着色器只是默认值:

precision mediump float;

// Built-in attributes

attribute vec4 a_position;

// Built-in uniforms

uniform mat4 u_projectionMatrix;

// Main

void main()
{
  gl_Position = u_projectionMatrix * a_position;
}

And you apply the filter as follows:

应用过滤器如下:

-webkit-filter: custom(url(duotone.vs) mix(url(duotone.fs) normal source-atop), 
             1 1 border-box, black 255 0 0, white 255 192 203);

#1


3  

UPDATE:

更新:

In order to do that you will need to use -webkit-mask-image on CSS. This used to be a webkit only but it's now w3c css3.

要做到这一点,您需要在CSS中使用-webkit-mask-image。这曾经是一个webkit,但现在是w3c css3。

The support is just present on webkit tho. In order to keep backward compatibility and display a regular black icon you will need to identify if the browser has this capabilities. I'v archived that using modernizr.

支持只是出现在webkit tho上。为了保持向后兼容性并显示常规的黑色图标,您需要确定浏览器是否具有这种功能。我用modernizr保存下来。

http://jsfiddle.net/kkobold/Zq5FZ/5/

http://jsfiddle.net/kkobold/Zq5FZ/5/

old answer:

旧的回答:

I believe thats the result you are looking for:

我相信这就是你要找的结果:

http://s7.postimage.org/vo5v33tuj/Screen_Shot_2013_02_03_at_11_28_46_PM.png

http://s7.postimage.org/vo5v33tuj/Screen_Shot_2013_02_03_at_11_28_46_PM.png

you can archive it by filtering to sepia and then changing hue degree. different combinations will give different results. But a simple color picker can be made for the hue and a slide for sepia to increase or decrease intensity of the color change.

您可以通过过滤到深褐色,然后改变色调程度来存档它。不同的组合会产生不同的结果。但是,可以为色相制作一个简单的颜色选择器,为深褐色制作一个幻灯片,以增加或减少颜色变化的强度。

and CSS3 only.

只和CSS3。

<div class="pull-left span4" >
<img src="/img/bw.jpg" style="-webkit-filter: sepia(0.0) hue-rotate(0deg);" width="300"/><br />
-webkit-filter: sepia(0) hue-rotate(0deg);
</div>
<div class="pull-left span4" >
<img src="/img/bw.jpg" style="-webkit-filter: sepia(0.8) hue-rotate(50deg);" width="300"/><br />
-webkit-filter: sepia(0.8) hue-rotate(50deg);
</div>
<div class="pull-left span4" >
<img src="/img/bw.jpg" style="-webkit-filter: sepia(0.8) hue-rotate(100deg);" width="300"/><br />
-webkit-filter: sepia(0.8) hue-rotate(100deg);
</div>
<div class="pull-left span4" >
<img src="/img/bw.jpg" style="-webkit-filter: sepia(0.8) hue-rotate(150deg);" width="300"/><br />
-webkit-filter: sepia(0.8) hue-rotate(150deg);
</div>
<div class="pull-left span4" >
<img src="/img/bw.jpg" style="-webkit-filter: sepia(0.8) hue-rotate(200deg);" width="300"/><br />
-webkit-filter: sepia(0.8) hue-rotate(200deg);
</div>
<div class="pull-left span4" >
<img src="/img/bw.jpg" style="-webkit-filter: sepia(0.8) hue-rotate(250deg);" width="300"/><br />
-webkit-filter: sepia(0.8) hue-rotate(250deg);
</div>
<div class="pull-left span4" >
<img src="/img/bw.jpg" style="-webkit-filter: sepia(0.8) hue-rotate(300deg);" width="300"/><br />
-webkit-filter: sepia(0.8) hue-rotate(300deg);
</div>
<div class="pull-left span4" >
<img src="/img/bw.jpg" style="-webkit-filter: sepia(0.8) hue-rotate(350deg);" width="300"/><br />
-webkit-filter: sepia(0.8) hue-rotate(350deg);
</div>

#2


3  

A little late to the party here, but I've built you a CSS custom filter that does exactly what you're looking for. All the code can be found on GitHub here: https://github.com/awgreenblatt/css-custom-filters/tree/master/duotone

虽然有点晚了,但是我已经为您构建了一个CSS自定义过滤器,它可以完全满足您的需求。所有代码都可以在GitHub上找到:https://github.com/awgreenblatt/css-custom-filters/tree/master/duotone

Because of security restrictions, custom filters can't read pixels; they can only apply transformations to them. So for instance, the filter can't say, if the pixel is black, change it to red. However, there is still a way to do it.

由于安全限制,自定义过滤器不能读取像素;它们只能对它们应用变换。例如,过滤器不能说,如果像素是黑色,把它改成红色。然而,仍然有办法做到这一点。

Each color component ranges from [0,1]: All white pixels in the source image will be (1, 1, 1, 1) and all black pixels in the source image will be (0, 0, 0, 1)

每个颜色分量范围为[0,1]:源图像中的所有白像素都为(1,1,1,1,1,1),源图像中的所有黑像素都为(0,0,0,0,1)

Let's call the color you want to map black to: (br, bg, bb, 1) and the color you want to map white to: (wr, wg, wb, 1)

我们把要映射黑色的颜色命名为:(br, bg, bb, 1),把要映射白色的颜色命名为:(wr, wg, wb, 1)

You can define in a fragment shader a css_ColorMatrix which will apply a transformation on the source image. If we set the blend mode to 'multiply' then the css_ColorMatrix will be pre-multiplied by the current source image's color.

您可以在片段着色器中定义一个css_ColorMatrix,它将对源映像应用一个转换。如果我们将混合模式设置为“相乘”,那么css_ColorMatrix将被当前源图像的颜色预先相乘。

So, we set the css_ColorMatrix to:

因此,我们将css_ColorMatrix设为:

wr - br,       0,       0,     0,
      0, wg - bg,       0,     0,
      0,       0, wb - bb,     0,
     br,      bg,      bb,     1

If the source pixel is black, (0, 0, 0, 1) then the result of the multiplication will be (br, bg, bb, 1) If the source pixel is white (1, 1, 1, 1) then the result of the multiplication will be

如果源像素为黑色(0,0,0,0,0,1),则乘法的结果为(br, bg, bb, 1)如果源像素为白色(1,1,1,1,1,1,1,1,1,1,1),则乘法的结果为

((wr - br + br), (wg - bg + bg), (wb - bb + bb), 1) or (wr, wg, wb, 1)

((wr - br + br),(wg - bg + bg),(wb - bb + bb),1)或(wr,wg、白平衡、1)

Here's the fragment shader source:

这是碎片着色源:

precision mediump float;

uniform vec3 black;
uniform vec3 white;

// Main

void main()
{
  vec3 b = black / 255.0;
  vec3 w = white / 255.0;

  css_ColorMatrix = mat4(w.r-b.r, 0.0, 0.0, 0.0,
                         0.0, w.g - b.g, 0.0, 0.0,
                         0.0, 0.0, w.b - b.b, 0.0,
                         b.r, b.g, b.b, 1.0);
}

The vertex shader is just the default:

顶点着色器只是默认值:

precision mediump float;

// Built-in attributes

attribute vec4 a_position;

// Built-in uniforms

uniform mat4 u_projectionMatrix;

// Main

void main()
{
  gl_Position = u_projectionMatrix * a_position;
}

And you apply the filter as follows:

应用过滤器如下:

-webkit-filter: custom(url(duotone.vs) mix(url(duotone.fs) normal source-atop), 
             1 1 border-box, black 255 0 0, white 255 192 203);