我正在使用libvips在后端上转换图像,并在前端上使用css / svg预览来节省资源。
我正在努力实现对比css / svg过滤器功能。
The specification将对比度显示为线性变换,形式为:
out = slope * in + intercept
其中intercept
应该是:
intercept = - (0.5 * slope) + 0.5
这样,我可以在图像修改的CSS预览中使用contrast(1.25)
。
但是,通过JS库Sharp在libvips中实现此线性函数:
sharp.linear(contrast, - (0.5 * contrast) + 0.5)
更深入地观察图像的对比度变化,预期结果是高点被放置得更高而低点被降低到更低。这看起来像是与规范的矛盾,因为该规范应用了线性变换,因此它应始终是多个并相加,使得高点更高,但低点也更高。
使用线性锐化(在libvips中也是如此)来改变对比度,输出实际上看起来像一个亮度滤镜,在css / svg滤镜的规范中,它是形式线性变换而无需加法
out = slope * in
在我看来,这可能是我误解了SVG线性函数中的截距。同样,比较svg和css也显示出差异。在CSS中使用contrast(2)
应该可以在svg中模仿slope = 2
和intercept = -(0.5 * 2) + 0.5 = -0.5
,在这种提琴中不是这样的:
.svg {
filter: url(#contrast);
}
.css {
filter: contrast(2);
}
<img src="https://dev-cdn.swbpg.com/o/g/1515254671.jpeg" width="300">
<img class="svg" src="https://dev-cdn.swbpg.com/o/g/1515254671.jpeg" width="300">
<img class="css" src="https://dev-cdn.swbpg.com/o/g/1515254671.jpeg" width="300">
<svg>
<filter id="contrast">
<feComponentTransfer>
<feFuncR type="linear" slope="2" intercept="-0.5"/>
<feFuncG type="linear" slope="2" intercept="-0.5"/>
<feFuncB type="linear" slope="2" intercept="-0.5"/>
</feComponentTransfer>
</filter>
</svg>
您可以清楚地看到带有svg滤镜的第二张图像看起来与使用css滤镜的第三幅图像不同。
我对过滤器的理解完全错误吗?我希望应该在某个地方有某个阈值,以将乘法转换为低位除法。
如何在不同的环境中将CSS对比度实现为具有相同结果的线性函数?
答案 0 :(得分:1)
您的直觉是不正确的:)对于小于0.5的输入值-公式会降低亮度-为什么?对比值为2,输入值为0.4
输出= 2 * 0.4-(0.5 * 2)+ 0.5
输出= 0.8-1 + 0.5
输出= 0.3
如您所见,当输入低于0.5时,输出将始终小于输入,因为斜率分量与截距的第一个(负)分量之和等于对比度乘以通过输入与0.5之差
这是单位值上的公式结果(以0/1为上限和上限)。
默认情况下,CSS滤镜也使用sRGB颜色空间。 SVG滤镜使用linearRGB。您需要通过向svg元素添加属性:color-interpolation-filters =“ sRGB”来将SVG滤镜颜色空间设置为sRGB。当您执行此操作时-您的图像看起来一样。
.svg {
filter: url(#contrast);
}
.css {
filter: contrast(2);
}
<img src="https://dev-cdn.swbpg.com/o/g/1515254671.jpeg" width="300">
<img class="svg" src="https://dev-cdn.swbpg.com/o/g/1515254671.jpeg" width="300">
<img class="css" src="https://dev-cdn.swbpg.com/o/g/1515254671.jpeg" width="300">
<svg color-interpolation-filters="sRGB">
<filter id="contrast">
<feComponentTransfer>
<feFuncR type="linear" slope="2" intercept="-0.5"/>
<feFuncG type="linear" slope="2" intercept="-0.5"/>
<feFuncB type="linear" slope="2" intercept="-0.5"/>
</feComponentTransfer>
</filter>
</svg>
答案 1 :(得分:0)
https://github.com/lovell/sharp/issues/1958
这里有一个来自 css 的工作公式:
filter: `contrast(${contrast})`
锐化:
brightness = 1;
image.linear(brightness * constrast, brightness * (-(128 * contrast) + 128));
虽然,我还没有弄清楚如何将 brightness
合并到这个中