Fabric.js manipulate Image object pixel by pixel to change color

生来就可爱ヽ(ⅴ<●) 提交于 2021-01-20 13:33:12

问题


I want to get the data of an image of a fabric.Image object to loop through each pixel and change its color if it's a given color to another given color. But I don't want to get the data of the entire canvas, only of that specific object. Something like this -

changeColor = (object, targetColor, replacementColor) => {
  data = object.getData();

  for(var i = 0, n = data.length; i<n; i+=4){
    let r = data[i];
    let g = data[i + 1];
    let b = data[i + 2];
    
    if(r === targetColor.r && g === targetColor.g && b === targetColor.b){
      imgd[i] = replacementColor.r;
      imgd[i + 1] = replacementColor.g;
      imgd[i + 2] = replacementColor.b;
      imgd[i + 3] = replacementColor.a;
    }
  }
}

But I do not know how to get the data of an object (I know getData() is not a real function).

TL;DR: I want a way to get the data of an image of a Fabric object (not the entire canvas) and then be able to manipulate its pixels and put the modified image back in.


回答1:


The best way to do this is with an image filter, I'd say. Fortunately, Fabric provides an image filter with a very similar functionality - RemoveColor (http://fabricjs.com/docs/fabric.js.html#line23120). We can take that implementation, tweak it a little to replace with a configurable color instead of removing, and that should do the trick.

There are three main changes we make to the RemoveColor class to create our ReplaceColor class:

  • Adding a replacementColor field that takes a 4 wide array of the color to replace with
  • Modifying the webGL to take in an extra parameter for the replacement color:
        fragmentSource: 'precision highp float;\n' +
            'uniform sampler2D uTexture;\n' +
            'uniform vec4 uLow;\n' +
            'uniform vec4 uHigh;\n' +
            'uniform vec4 uRep;\n' + // New variable for replacement color
            'varying vec2 vTexCoord;\n' +
            'void main() {\n' +
            'gl_FragColor = texture2D(uTexture, vTexCoord);\n' +
            'if(all(greaterThan(gl_FragColor.rgb,uLow.rgb)) && all(greaterThan(uHigh.rgb,gl_FragColor.rgb))) {\n' +
            'gl_FragColor.rgb = uRep.rgb;\n' + // Here we set the color instead of 0-ing out the alpha
            'gl_FragColor.a = uRep.a;\n' +
            '}\n' +
            '}',
  • Updating the applyTo2d method to also use the replacement color:
        applyTo2d: function (options) {
            var imageData = options.imageData,
                data = imageData.data, i,
                distance = this.distance * 255,
                r, g, b,
                source = new fabric.Color(this.color).getSource(),
                lowC = [
                    source[0] - distance,
                    source[1] - distance,
                    source[2] - distance,
                ],
                highC = [
                    source[0] + distance,
                    source[1] + distance,
                    source[2] + distance,
                ];

            for (i = 0; i < data.length; i += 4) {
                r = data[i];
                g = data[i + 1];
                b = data[i + 2];
                if (r > lowC[0] &&
                    g > lowC[1] &&
                    b > lowC[2] &&
                    r < highC[0] &&
                    g < highC[1] &&
                    b < highC[2]) {
                    data[i] = this.replacementColor[0]; // Here we also modify the color directly instead of 0-ing out the alpha
                    data[i + 1] = this.replacementColor[1];
                    data[i + 2] = this.replacementColor[2];
                    data[i + 3] = this.replacementColor[3];
                }
            }
        }

JSFiddle: https://jsfiddle.net/8coka6yv/

Note that on the JSFiddle I cranked up the distance field, so it's a pretty drastic modification. The default value is normally 0.02.



来源:https://stackoverflow.com/questions/65608195/fabric-js-manipulate-image-object-pixel-by-pixel-to-change-color

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!