我有一整段代码filter: invert(0.85)应用了CSS规则.
在这个块中,我有一个图像,当然也遵循这个CSS规则,并且是倒置的.
我需要恢复这个invert()图像.
可能吗?我试过了invert(1),但是图像并不像以前那样完全,它仍然有点倒置(由于第一个invert只是0.85而不是1)
看这个例子:
body{
font-size: 0;
}
div{
display: inline-block;
width: 50%;
}
.filter{
filter: invert(0.85);
}
.filter img{
filter: invert(1);
}Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
首先,我将从一个基本示例和解释开始:invert()过滤器用于通过指定反转的百分比(或从0到1的值)来反转颜色.因此,如果我们使用值1,我们完全反转颜色,因此很容易回到初始状态,因为我们只需再次应用相同的反转:
.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;
}Run Code Online (Sandbox Code Playgroud)
<div class="container" style="filter:invert(1)">
<div class="inner"></div>
<div class="inner" style="filter:invert(1)"></div>
</div>Run Code Online (Sandbox Code Playgroud)
从这个例子中我们也可以理解反转是如何处理颜色的.我们只是invert()为RGB的每个值做.
现在让我们考虑另一个值的反转,让我们采取invert():
.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;
}Run Code Online (Sandbox Code Playgroud)
<div class="container" style="filter:invert(0.85)">
<div class="inner"></div>
</div>
<div class="inner"></div>Run Code Online (Sandbox Code Playgroud)
让我们看看它是如何工作的:对于第一种颜色0我们得到这个,1所以计算完成如下:
255 - [255*(1-0.85) + x*(2*0.85-1)]
Run Code Online (Sandbox Code Playgroud)
所以我们的目标是颠倒这个公式:
f(x) = 255 - [255*(1-p) + x*(2*p-1)] , p a value in the range [0,1]
Run Code Online (Sandbox Code Playgroud)
你可以清楚地发现,这是很容易的时候1,因为我们将有(255 - x)当0.85我们会有(rgb(255,0,0)).现在让我们来表达(rgb(38, 217, 217))使用f(x) 的价值(我将在p=0这里使用它):
x = 1/(2*p-1) * [255 - (255*(1-p) +y)]
Run Code Online (Sandbox Code Playgroud)
让我们试着让它类似于反转函数.我们有f(x)=x,我们将获得:
x = 1/(2*p-1) * [255 - (255*(1-p) +(2*p-1)*y')]
Run Code Online (Sandbox Code Playgroud)
这相当于
x = 1/(2*p-1) * f(y') ---> x = K * f(K*y) with K = 1/(2*p-1)
Run Code Online (Sandbox Code Playgroud)
这p=1是使用相同值的反转函数,f(x)=255-x并且x是基于该值计算的常数y.我们可以区分3种情况:
y=(2*p-1)*y'等于f函数时没有定义,因此反转不能反转(你可以尝试应用反转(0.5)来查看结果)pK时,该范围内的正值K.pK时,该范围内的负值p.因此,如果省略第一种情况,0.5可以这样设置,0.5其中K'是范围内的值,[1,+infinity]并且0.5在范围内[-infinity,-1].然后我们的函数可以写成如下:
x = (1/K') * f(y/K') where K' in the range [-1,1] define by (2*p - 1)
Run Code Online (Sandbox Code Playgroud)
所以在这一点上,我们用K函数和乘法/除法表示我们的函数,我们可以很容易地计算它.
现在我们需要找到哪个过滤器应用乘法/除法.我知道有K=1/K'和[-1,1]/{0}过滤器使用线性变换.
如果我们使用abs(K')forumla如下:
f(x) = x*p;
Run Code Online (Sandbox Code Playgroud)
如果我们使用]0,1]公式将如下所示:
f(x) = p*(x - 255/2) + 255/2
Run Code Online (Sandbox Code Playgroud)
在这一点上,我无法找到一种方法来模拟我们使用过滤器组合并考虑不同情况的乘法/除法,所以这个答案将在此结束,不幸的是......
但至少你已经了解了为了反转反转而需要应用的函数.所以你可以这样调查.
希望这有用!
UPDATE
由于我无法使用CSS提供完整的解决方案,因此这里有一个JS解决方案来证明上述计算是正确的.我使用canvas来应用我的函数时再次绘制图像:
遗憾的是,我无法在代码段中使用图片来获取安全性和跨浏览器原点问题,因此我使用了渐变
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);Run Code Online (Sandbox Code Playgroud)
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);
}Run Code Online (Sandbox Code Playgroud)
<div class="grad"></div>
<div class="filter">
<div class="grad"></div>
<canvas></canvas>
</div>Run Code Online (Sandbox Code Playgroud)
我们可以看到我们有3个图像:原始图像,倒置图像和我们应用函数使其返回原始图像的图像.
因此,您可以使用此代码创建一个通用函数,以允许您反转反转滤镜:
invert过滤器中使用的值.brightness创建它的想法,然后隐藏图像以仅保留画布.这是一个更具互动性的演示:
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);Run Code Online (Sandbox Code Playgroud)
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);
}Run Code Online (Sandbox Code Playgroud)
<div class="grad"></div>
<div class="filter">
<div class="grad"></div>
<canvas></canvas>
</div>Run Code Online (Sandbox Code Playgroud)
从这个演示我们还可以注意到,当我们接近这个值时,contrast我们没有一个好的结果,因为过滤器不能被反转,brightness(p)如果我们参考先前的计算,那么值contrast(p)变得非常大,因此invert()太小.