繁体   English   中英

Fabric.js逐像素操作Image object来改变颜色

[英]Fabric.js manipulate Image object pixel by pixel to change color

我想获取织物图像的数据。图像 object 循环遍历每个像素,如果它是给定颜色,则将其颜色更改为另一种给定颜色。 但我不想获取整个 canvas 的数据,只获取特定 object 的数据。 像这样的东西-

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;
    }
  }
}

但我不知道如何获取 object 的数据(我知道getData()不是真正的函数)。

TL;DR:我想要一种方法来获取 Fabric object(不是整个画布)的图像数据,然后能够操纵其像素并将修改后的图像放回原处。

我会说,最好的方法是使用图像过滤器。 幸运的是,Fabric 提供了一个具有非常相似功能的图像过滤器 - RemoveColor ( http://fabricjs.com/docs/fabric.js.html#line23120 )。 我们可以采用该实现,稍微调整一下以替换为可配置的颜色而不是删除,这应该可以解决问题。

我们对RemoveColor class 进行了三个主要更改,以创建我们的ReplaceColor class:

  • 添加一个replacementColor字段,该字段需要 4 个宽的颜色数组来替换
  • 修改 webGL 以获取替换颜色的额外参数:
        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' +
            '}',
  • 更新applyTo2d方法也使用替换颜色:
        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/

请注意,在 JSFiddle 上,我提高了距离场,所以这是一个非常激烈的修改。 默认值通常为0.02

暂无
暂无

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

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