还原过滤器invert()CSS规则 [英] Revert a filter invert() CSS rule

查看:130
本文介绍了还原过滤器invert()CSS规则的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一整段代码,其中应用了CSS规则filter: invert(0.85).

I have a whole block of code where the CSS rule filter: invert(0.85) is applied.

在此块中,我有一个图像,该图像当然也遵循此CSS规则,并且被反转了.

Inside this block, I have an image, which of course also follows this CSS rule, and is inverted.

我需要还原该图像的invert().

有可能吗?我尝试了invert(1),但是图像并不完全像以前那样,它还是有点倒置了(由于第一个invert仅是0.85而不是1)

Is it possible? I tried invert(1), but the image isn't fully like it was before, it's still a little inverted (due to the first invert being only 0.85 and not 1)

请参见以下示例:

body{
  font-size: 0;
}

div{
  display: inline-block;
  width: 50%;
}

.filter{
  filter: invert(0.85);
}

.filter img{
  filter: invert(1);
}

<div class="initial">
  <img src="https://s7d1.scene7.com/is/image/PETCO/cat-category-090617-369w-269h-hero-cutout-d?fmt=png-alpha" alt="">
</div>
<div class="filter">
  <img src="https://s7d1.scene7.com/is/image/PETCO/cat-category-090617-369w-269h-hero-cutout-d?fmt=png-alpha" alt="">
</div>

推荐答案

TL; DR

您不能通过应用其他invert()或其他过滤器的组合来还原invert()过滤器.

TL;DR

You cannot revert the invert() filter by applying another invert() or a combination of other filters.

首先,我将以一个基本示例和一个解释开始:invert()过滤器用于通过指定反转百分比(或从01的值)来反转颜色.如果我们使用值1,我们会完全反转颜色,因此很容易回到初始状态,因为我们只需要再次应用相同的反转:

First, I am going to start with a basic example and an explanation: the invert() filter is used to invert the colors by specifying the percentage of the inversion (or a value from 0 to 1). If we use the value 1 we invert completely the colors thus it's easy to get back to initial state as we simply have to apply the same invert again:

.container {
 display:flex;
 justify-content:space-around;
}

.inner {
  height: 200px;
  width: 200px;
  background: 
  linear-gradient(to right, rgb(255,0,0) 50%, rgb(0,255,255) 0) 0 0/100% 50% no-repeat, 
  
  linear-gradient(to right, rgb(50,0,60) 50%, rgb(205,255,195) 0) 0 100%/100% 50% no-repeat;
}

<div class="container" style="filter:invert(1)">
  <div class="inner"></div>
  <div class="inner" style="filter:invert(1)"></div>
</div>

从此示例中,我们还可以了解反转如何处理颜色.我们只需对 RGB 的每个值进行(255 - x).

From this example we can also understand how the invert is working with colors. We simply do (255 - x) for each value of the RGB.

现在让我们考虑另一个值的取反,让我们使用0.85:

Now let's consider the invert with another value, let's take the 0.85:

.container {
  display: inline-block;
}

.inner {
  display: inline-block;
  height: 200px;
  width: 200px;
  background: linear-gradient(to right, rgb(255, 0, 0) 50%, rgb(0, 255, 255) 0) 0 0/100% 50% no-repeat, linear-gradient(to right, rgb(50, 0, 60) 50%, rgb(205, 255, 195) 0) 0 100%/100% 50% no-repeat;
}

<div class="container" style="filter:invert(0.85)">
  <div class="inner"></div>
</div>
<div class="inner"></div>

它如何工作?

对于第一种颜色(rgb(255,0,0)),我们获得此(rgb(38, 217, 217)),因此计算如下:

For the first color (rgb(255,0,0)) we obtain this (rgb(38, 217, 217)) so the calculation is done as follow:

255 - [255*(1-0.85) + x*(2*0.85-1)]

所以我们的目标是反转这个公式:

So our goal is to invert this formula:

f(x) = 255 - [255*(1-p) + x*(2*p-1)] , p a value in the range [0,1]

您可能会清楚地注意到,当p=0时我们很容易拥有f(x)=x,而当p=1时我们将会很容易地拥有f(x)=255-x.现在,让我们使用 f(x) (在这里将其用作y)来表达x的值:

You may clearly notice that it's pretty easy when p=0 as we will have f(x)=x and when p=1 we will have f(x)=255-x. Now let's express the value of x using f(x) (I will use it as y here):

x = 1/(2*p-1) * [255 - (255*(1-p) +y)]

让我们尝试使其类似于反转函数.我们有y=(2*p-1)*y',我们将获得:

Let's try to make it similar to an invert function. Let's havey=(2*p-1)*y' and We will obtain:

x = 1/(2*p-1) * [255 - (255*(1-p) +(2*p-1)*y')]

等效于

x = 1/(2*p-1) * f(y') ---> x = K * f(K*y) with K = 1/(2*p-1)

此处f是使用相同值p的求反函数,并且K是基于值p计算的常数.我们可以区分3种情况:

Here f is an invert function using the same value of p and K is a constant calculated based on the value p. We can distinguish 3 situations:

  1. p的值等于0.5时,该函数未定义,因此无法反转inem(您可以尝试应用invert(0.5)来查看结果)
  2. 当p的值大于0.5时,K为[1,+infinity]范围内的值.
  3. 当p的值小于0.5时,K为值,范围为[-infinity,-1].
  1. When the value of p is equal to 0.5 the function is no defined and thus the invert cannot be inverted (you can by the way try to apply invert(0.5) to see the result)
  2. When the value of p is greater than 0.5 K is a positive value in the range [1,+infinity].
  3. When the value of p is smaller than 0.5 K is a negative value in the range [-infinity,-1].

因此,如果我们忽略第一种情况,则可以用K=1/K'的方式设置K,其中K'是在[-1,1]/{0}范围内的值,而abs(K')]0,1]范围内.然后我们的函数可以写成如下:

So if we omit the first case, K can be set in this way K=1/K' where K' is a value in the range [-1,1]/{0} and abs(K') is in the range of ]0,1]. Then our function can be written as follow:

x = (1/K') * f(y/K') where K' in the range [-1,1] define by (2*p - 1)


在这一点上,我们用invert函数和具有易于计算的值的乘法/除法表示了我们的函数.


At this point we expressed our function with an invert function and a multiplication/division with a value that we can easily compute.

现在,我们需要找到应用乘法/除法的滤波器.我知道有使用线性变换的brightnesscontrast过滤器.

Now we need to find which filter apply a multiplication/division. I know there is the brightness and the contrast filter that uses linear transformation.

如果我们使用brightness(p),则论坛如下:

If we use brightness(p) the forumla is as follow:

f(x) = x*p;

如果使用contrast(p),则公式将如下所示:

And if we use contrast(p) the formula will look like this:

f(x) = p*(x - 255/2) + 255/2

这将在这里结束...

This will end up here ...

正如最初所说,我们无法使用其他过滤器还原invert().对于某些值,我们可能可以近似此值,但对于其他值,则不可能(例如0.5).换句话说,当应用invert()时,我们丢失了一些我们无法获取的信息.例如,当您获得彩色图像并转换为黑白图像时,就像白色版本.您无法还原初始颜色.

As said intially we cannot revert invert() using other filters. We can probably approximate this for some values but for other it will impossible (like with 0.5). In other words, when applying the invert() we lose some information that we cannot get back. It's like when, for example, you get a coloured image that you transform into a black & white version. You have no way to put back the initial colors.

更新

这里有一些JS代码可以证明上面的计算是正确的,并且可以看到一些结果.我使用画布是为了在应用我的功能时再次绘制图像:

Here is some JS code to proove that the above calculation is correct and to see some results. I used canvas in order to draw the image again while applying my function:

很遗憾,出于安全性和跨浏览器起源的问题,我无法在代码段中使用图片,因此我考虑使用渐变

var canvas = document.querySelector('canvas');
var img = document.querySelector('img');
var ctx = canvas.getContext('2d');
//we draw the same image on the canvas (here I will draw the same gradient )
//canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height);
var grd = ctx.createLinearGradient(0, 0, 150, 0);
grd.addColorStop(0, "blue");
grd.addColorStop(1, "red");
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 150, 150);

//we get the data of the image
var imgData = canvas.getContext('2d').getImageData(0, 0, 150, 150);
var pix = imgData.data;
var p = 0.85;
// Loop over each pixel and apply the function
for (var i = 0, n = pix.length; i < n; i += 4) {
  pix[i + 0] = Math.round((1 / (2 * p - 1)) * (255 - (255 * (1 - p) + pix[i + 0])));
  pix[i + 1] = Math.round((1 / (2 * p - 1)) * (255 - (255 * (1 - p) + pix[i + 1])))
  pix[i + 2] = Math.round((1 / (2 * p - 1)) * (255 - (255 * (1 - p) + pix[i + 2])))
  // i+3 is alpha (the fourth element)
}
//Draw the image again
imgData.data = pix;
canvas.getContext('2d').putImageData(imgData, 0, 0);

body {
  font-size: 0;
}

div,
canvas {
  display: inline-block;
}

.grad {
  height: 150px;
  width: 150px;
  background: linear-gradient(to right, blue, red);
}

.filter {
  filter: invert(0.85);
}

<div class="grad"></div>
<div class="filter">
  <div class="grad"></div>
  <canvas></canvas>
</div>

我们看到有3张图片:原始图片倒置图片以及应用功能将其恢复为原始图片的那张图片

As we can see we have 3 images: the original one, the inverted one and the one on where we applied our function to make it back to the original one.

我们在这里取得了很好的结果,因为该值接近1.如果我们使用另一个更接近0.5的值,则会导致不良结果,因为我们已接近该函数定义的位置的限制:

We are having a good result here because the value is close to 1. If we use another value more close to 0.5 will have a bad result because we are close to the limit of where the function is defined:

var canvas = document.querySelector('canvas');
var img = document.querySelector('img');
var ctx = canvas.getContext('2d');
//we draw the same image on the canvas (here I will draw the same gradient )
//canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height);
var grd = ctx.createLinearGradient(0, 0, 150, 0);
grd.addColorStop(0, "blue");
grd.addColorStop(1, "red");
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 150, 150);

//we get the data of the image
var imgData = canvas.getContext('2d').getImageData(0, 0, 150, 150);
var pix = imgData.data;
var p = 0.6;
// Loop over each pixel and apply the function
for (var i = 0, n = pix.length; i < n; i += 4) {
  pix[i + 0] = Math.round((1 / (2 * p - 1)) * (255 - (255 * (1 - p) + pix[i + 0])));
  pix[i + 1] = Math.round((1 / (2 * p - 1)) * (255 - (255 * (1 - p) + pix[i + 1])))
  pix[i + 2] = Math.round((1 / (2 * p - 1)) * (255 - (255 * (1 - p) + pix[i + 2])))
  // i+3 is alpha (the fourth element)
}
//Draw the image again
imgData.data = pix;
canvas.getContext('2d').putImageData(imgData, 0, 0);

body {
  font-size: 0;
}

div,
canvas {
  display: inline-block;
}

.grad {
  height: 150px;
  width: 150px;
  background: linear-gradient(to right, blue, red);
}

.filter {
  filter: invert(0.6);
}

<div class="grad"></div>
<div class="filter">
  <div class="grad"></div>
  <canvas></canvas>
</div>

您可以使用以下代码来创建通用函数,该函数将允许您部分还原invert()过滤器:

You can use this code in order to create a generic function that will allow you to partially revert the invert() filter:

  1. 使用一些JS,您可以轻松找到过滤器中使用的p的值.
  2. 您可以使用特定的选择器将特定图像仅定位到要应用此逻辑的位置.
  3. 如您所见,我创建了一个canvas,因此其想法是先创建它,然后隐藏图像以仅保留画布.
  1. Using some JS you can easily find the value of p used in the filter.
  2. You can use a specific selector to target only specific images on where you want to apply this logic.
  3. As you can see I created a canvas so the idea is to create it and then hide the image to keep only the canvas.

这是一个更具交互性的演示:

Here is a more interactive demo:

var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
var init = function() {
  var grd = ctx.createLinearGradient(0, 0, 150, 0);
  grd.addColorStop(0, "blue");
  grd.addColorStop(1, "red");
  ctx.fillStyle = grd;
  ctx.fillRect(0, 0, 150, 100);
  var grd2 = ctx.createLinearGradient(0, 0, 0, 150);
  grd2.addColorStop(0, "green");
  grd2.addColorStop(1, "yellow");
  ctx.fillStyle = grd2;
  ctx.fillRect(40, 0, 70, 100);
}
var invert = function(p) {
  //we get the data of the image
  var imgData = canvas.getContext('2d').getImageData(0, 0, 150, 100);
  var pix = imgData.data;
  // Loop over each pixel and apply the function
  for (var i = 0, n = pix.length; i < n; i += 4) {
    pix[i + 0] = Math.round((1 / (2 * p - 1)) * (255 - (255 * (1 - p) + pix[i + 0])));
    pix[i + 1] = Math.round((1 / (2 * p - 1)) * (255 - (255 * (1 - p) + pix[i + 1])))
    pix[i + 2] = Math.round((1 / (2 * p - 1)) * (255 - (255 * (1 - p) + pix[i + 2])))
    // i+3 is alpha (the fourth element)
  }
  //Draw the image again
  imgData.data = pix;
  canvas.getContext('2d').putImageData(imgData, 0, 0);
}
init();
$('input').change(function() {
  var v = $(this).val();
  $('.filter').css('filter', 'invert(' + v + ')');
  init();
  invert(v);
})

p {
  margin: 0;
}

div,
canvas {
  display: inline-block;
}

.grad {
  height: 100px;
  width: 150px;
  background: linear-gradient(to bottom, green, yellow)40px 0/70px 100% no-repeat, linear-gradient(to right, blue, red);
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="grad"></div>
<div class="filter">
  <div class="grad"></div>
  <canvas height="100" width="150"></canvas>
</div>
<p>Adjust the value of the invert filter</p>
<input type="range" value="0" min=0 max=1 step=0.05>

在此演示中,我们还可以注意到,当我们接近值0.5时,仅由于无法在0.5处将滤光片取反,我们就不会获得良好的结果,并且如果我们参考先前的计算,则该值K的很大,因此K'太小.

From this demo we can also notice that when we are close to the value 0.5 we don't have a good result simply because the filter cannot be inverted at 0.5 and if we refer to previous calculation, the value of K become very big and thus K' is too small .

这篇关于还原过滤器invert()CSS规则的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆