Как пользовательский фильтр изображений fabricjs возвращается к webgl и canvas2d соответственно - PullRequest
0 голосов
/ 06 ноября 2019

Я хочу реализовать пользовательский фильтр, но не могу получить объект canvas2d, потому что мне нужно изменить imageData. Изменение imageData в соответствии с методом документа applyTo2d не имеет реального эффекта. Даже если я удалю его, ошибки не будет, независимо от того, можно ли настроить фрагментSource. Я написал этот метод, applyTo и applyToWebGl возвращают trafficgl, возвращенный canvasEl: true, есть ли способ вернуть canvas2d, можно напрямую получить imageData, я видел почти похожую проблему, не нашел, кто мне может помочь?

fabric3.4.0

fabric.Image.filters.HSL = fabric.util.createClass(fabric.Image.filters.BaseFilter, {
                type: 'HSL',

                initialize: function(options) {
                    console.log(options);
                    options || (options = {});
                    this.rotation = options.rotation || 0;
                    this.saturation = options.saturation || 0;
                    this.lightness = options.lightness || 0;
                    this.brightness = options.brightness || 0;
                    this.contrast = options.contrast || 0;
                    this.img = options.img;
                },

                changeImageDate: function(imgData, H, S, L, B, C) {
                    let data = imgData.data;
                    for (let i = 0; i < data.length / 4; i++) {
                        let rgb = [ data[i * 4], data[i * 4 + 1], data[i * 4 + 2] ];
                        if (H || S || L) {
                            rgb = this.changeHSL(rgb, H, S, L);
                        }
                        if (B || C) {
                            rgb = this.changeBC(rgb, B, C);
                        }
                        data[i * 4] = rgb[0];
                        data[i * 4 + 1] = rgb[1];
                        data[i * 4 + 2] = rgb[2];
                    }
                    return imgData;
                },

                changeHSL: function(rgb, H1, S1, L1) {
                    let hsl = this.rgb2Hsl(rgb[0], rgb[1], rgb[2]);
                    let H = (hsl[0] + 1 + H1 / 360) % 1;
                    let S = Math.min(Math.max(hsl[1] + S1 / 100, 0), 1);
                    let L = Math.min(Math.max(hsl[2] + L1 / 100, 0), 1);
                    let RGB = this.hsl2Rgb(H, S, L);
                    return RGB;
                },

                changeBC: function(rgb, B1, C1) {
                    let k = Math.tan((45 + 44 * (C1 / 100)) / 180 * Math.PI);
                    let R = [ rgb[0] - 127.5 * (1 - B1 / 100) ] * k + 127.5 * (1 + C1 / 100);
                    let G = [ rgb[1] - 127.5 * (1 - B1 / 100) ] * k + 127.5 * (1 + C1 / 100);
                    let B = [ rgb[2] - 127.5 * (1 - B1 / 100) ] * k + 127.5 * (1 + C1 / 100);
                    let RGB = [ R, G, B ];
                    RGB.forEach((it, i) => {
                        it = Math.min(Math.max(it, 0), 255);
                    });

                    return RGB;
                },

                rgb2Hsl: function(r, g, b) {
                    r = r / 255;
                    g = g / 255;
                    b = b / 255;
                    let max = Math.max(r, g, b),
                        min = Math.min(r, g, b);
                    let h,
                        s,
                        l = (max + min) / 2;

                    if (max == min) {
                        h = s = 0; // achromatic
                    } else {
                        let d = max - min;
                        s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
                        switch (max) {
                            case r:
                                h = (g - b) / d + (g < b ? 6 : 0);
                                break;
                            case g:
                                h = (b - r) / d + 2;
                                break;
                            case b:
                                h = (r - g) / d + 4;
                                break;
                        }
                        h /= 6;
                    }
                    return [ Math.round(h * 100) / 100, Math.round(s * 100) / 100, Math.round(l * 100) / 100 ];
                },

                hsl2Rgb: function(h, s, l) {
                    let r, g, b;

                    if (s == 0) {
                        r = g = b = l; // achromatic
                    } else {
                        let q = l < 0.5 ? l * (1 + s) : l + s - l * s;
                        let p = 2 * l - q;
                        r = this.hue2(p, q, h + 1 / 3);
                        g = this.hue2(p, q, h);
                        b = this.hue2(p, q, h - 1 / 3);
                    }

                    return [ Math.round(r * 255), Math.round(g * 255), Math.round(b * 255) ];
                },

                hue2: function(p, q, t) {
                    if (t < 0) t += 1;
                    if (t > 1) t -= 1;
                    if (t < 1 / 6) return p + (q - p) * 6 * t;
                    if (t < 1 / 2) return q;
                    if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
                    return p;
                },

                applyToWebGL: function(canvasEl) {
                    console.log(canvasEl);
                    let origin = this.img;
                    let index = canvas.getObjects().indexOf(origin);
                    let originalElement = origin._originalElement;
                    let width = origin.width * origin.scaleX;
                    let height = origin.height * origin.scaleY;
                    let d = Math.sqrt(width * width + height * height);
                    let element = fabric.util.createCanvasElement();
                    element.width = d;
                    element.height = d;
                    let context = element.getContext('2d');
                    context.drawImage(originalElement, 0, 0, width, height);
                    let imageData = context.getImageData(0, 0, width, height);
                    let data = this.changeImageDate(imageData, this.rotation, this.saturation, this.lightness, this.brightness, this.contrast);
                    context.putImageData(data,0,0)


                },

                toObject: function() {
                    return fabric.util.object.extend(this.callSuper('toObject'), {
                        rotation: this.rotation,
                        saturation: this.saturation,
                        lightness: this.lightness
                    });
                }
            });

            fabric.Image.filters.HSL.fromObject = fabric.Image.filters.BaseFilter.fromObject;

var filterHSL = new fabric.Image.filters.HSL({
        img: origin,
        rotation,
        saturation,
        lightness,
        brightness,
        contrast
    });

    origin.filters = [ filterHSL ];

    origin.applyFilters();

Элемент, который нужно изменить, исчез

...