简体   繁体   English

如何使用 CSS 滤镜或 colorMatrix 将 VIBRANCE 效果应用于图像

[英]How to use CSS filters or colorMatrix to apply VIBRANCE effect to image

To set the stage for this question, I will be pasting the definition of Vibrance and what makes it differ from regular Saturation .为了为这个问题做准备,我将粘贴Vibrance的定义以及它与常规Saturation不同之处。

Vibrance is a smart-tool which cleverly increases the intensity of the more muted colors and leaves the already well-saturated colors alone. Vibrance 是一种智能工具,它巧妙地增加了更柔和的颜色的强度,而只留下已经饱和的颜色。 It's sort of like fill light, but for colors.它有点像补光灯,但用于颜色。 Vibrance also prevents skin tones from becoming overly saturated and unnatural. Vibrance 还可以防止肤色变得过于饱和和不自然。

Source: https://digital-photography-school.com/vibrance-vs-saturation-in-plain-english/来源: https : //digital-photography-school.com/vibrance-vs-saturation-in-plain-english/

Currently all CSS filters apply homogeneously and equally to every pixel color value on the image.目前,所有 CSS 过滤器都均匀且平等地应用于图像上的每个像素颜色值。 Is there any way and/or package that can apply so called smart filters which applies its filter depending on the current pixel color value that it is applying its filter on?有什么方法和/或包可以应用所谓的smart filters ,它根据应用滤镜的当前像素颜色值应用滤镜?

在此处输入图片说明

The exact formula used in Adobe's vibrance filter appears to be a bit of a mystery, but the Caman.js library actually includes a pretty simple formula for calculating vibrance. Adobe 的振动过滤器中使用的确切公式似乎有点神秘,但 Caman.js 库实际上包含一个非常简单的计算振动的公式。

I've built a version of Vibrance for Fabric.js using that same formula and it seems to do the trick.我使用相同的公式为 Fabric.js 构建了一个 Vibrance 版本,它似乎可以解决问题。 You should find performance quite a bit better than with Caman.js as well since Fabric.js filters support WebGL.您应该会发现性能也比 Caman.js 好很多,因为 Fabric.js 过滤器支持 WebGL。

振动过滤器

 var canvas = new fabric.Canvas("canvas", { backgroundColor: "white" }); fabric.Image.fromURL("https://live.staticflickr.com/65535/51283215722_e949fa76c8_k.jpg", function(img) { img.filters.push(new fabric.Image.filters.Vibrance({ vibrance: 0 })); img.filters.push(new fabric.Image.filters.Saturation({ saturation: 0 })); img.applyFilters() img.scaleToWidth(350) img.set({ left: 20, top: 20 }); canvas.add(img) }, { crossOrigin: 'anonymous' }); function setVibrance(value) { var img = canvas.item(0); img.filters[0].vibrance = value; img.applyFilters(); canvas.renderAll(); } function setSaturation(value) { var img = canvas.item(0); img.filters[1].saturation = value; img.applyFilters(); canvas.renderAll(); } //start vibrance filter code (function(global) { var fabric = global.fabric || (global.fabric = {}), filters = fabric.Image.filters, createClass = fabric.util.createClass; filters.Vibrance = createClass(filters.BaseFilter, { type: 'Vibrance', fragmentSource: 'precision highp float;\\n' + 'uniform sampler2D uTexture;\\n' + 'uniform float uVibrance;\\n' + 'varying vec2 vTexCoord;\\n' + 'void main() {\\n' + 'vec4 color = texture2D(uTexture, vTexCoord);\\n' + 'float max = max(color.r, max(color.g, color.b));\\n' + 'float avg = (color.r + color.g + color.b) / 3.0;\\n' + 'float amt = (abs(max - avg) * 2.0) * uVibrance;\\n' + 'color.r += max != color.r ? (max - color.r) * amt : 0.00;\\n' + 'color.g += max != color.g ? (max - color.g) * amt : 0.00;\\n' + 'color.b += max != color.b ? (max - color.b) * amt : 0.00;\\n' + 'gl_FragColor = color;\\n' + '}', vibrance: 0, mainParameter: 'vibrance', applyTo2d: function(options) { if (this.vibrance === 0) { return; } var imageData = options.imageData, data = imageData.data, len = data.length, adjust = -this.vibrance, i, max, avg, amt; for (i = 0; i < len; i += 4) { max = Math.max(data[i], data[i + 1], data[i + 2]); avg = (data[i] + data[i + 1] + data[i + 2]) / 3; amt = ((Math.abs(max - avg) * 2 / 255) * adjust); data[i] += max !== data[i] ? (max - data[i]) * amt : 0; data[i + 1] += max !== data[i + 1] ? (max - data[i + 1]) * amt : 0; data[i + 2] += max !== data[i + 2] ? (max - data[i + 2]) * amt : 0; } }, getUniformLocations: function(gl, program) { return { uVibrance: gl.getUniformLocation(program, 'uVibrance'), }; }, sendUniformData: function(gl, uniformLocations) { gl.uniform1f(uniformLocations.uVibrance, -this.vibrance); }, }); fabric.Image.filters.Vibrance.fromObject = fabric.Image.filters.BaseFilter.fromObject; })(typeof exports !== 'undefined' ? exports : this);
 <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.5.0/fabric.min.js"></script> <span>Vibrance</span> <input type="range" value="0" min="-1" max="1" step="0.1" onchange="setVibrance(this.value)"/> <span>Saturation</span> <input type="range" value="0" min="-1" max="1" step="0.1" onchange="setSaturation(this.value)"/> <canvas id="canvas" width="400" height="200"></canvas>

According to the Vibrance definition, none of the css filters have this operation.根据 Vibrance 的定义,没有一个 css 过滤器有这个操作。 I think you can simulate that mood by other filters blur() brightness() contrast() opacity() saturate()我认为您可以通过其他过滤器来模拟这种情绪模糊()亮度()对比度()不透明度()饱和度()

img {
  filter: blur(5px) brightness(10%) saturate(10%);
   }

This is just an example这只是一个例子

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM