简体   繁体   中英

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 is a smart-tool which cleverly increases the intensity of the more muted colors and leaves the already well-saturated colors alone. It's sort of like fill light, but for colors. Vibrance also prevents skin tones from becoming overly saturated and unnatural.

Source: 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. 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?

在此处输入图片说明

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.

I've built a version of Vibrance for Fabric.js using that same formula and it seems to do the trick. You should find performance quite a bit better than with Caman.js as well since Fabric.js filters support 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. 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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