2016-03-18 3 views
0

Я пытаюсь создать собственный фильтр, он должен принять цветовой код.Как создать пользовательский фильтр, передав цветовой код в ткани js

Вот мой код.

Он отлично работает.

fabric.Image.fromURL('pug.jpg', function(img) { 
    img.filters.push(
    new fabric.Image.filters.Sepia(), 
    new fabric.Image.filters.Brightness({ brightness: 100 })); 

    img.applyFilters(canvas.renderAll.bind(canvas)); 
    canvas.add(img); 
}); 

Теперь мне нужно создать фильтр с определенным цветовым кодом. Что я нашел это

fabric.Image.filters.Redify = fabric.util.createClass({ 

    type: 'Redify', 

    applyTo: function(canvasEl) { 
    var context = canvasEl.getContext('2d'), 
     imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), 
     data = imageData.data; 

    for (var i = 0, len = data.length; i < len; i += 4) { 
     data[i + 1] = 0; 
     data[i + 2] = 0; 
    } 

    context.putImageData(imageData, 0, 0); 
    } 
}); 

fabric.Image.filters.Redify.fromObject = function(object) { 
    return new fabric.Image.filters.Redify(object); 
}; 

мне нужно объяснить, что за цикл делает ... также, пожалуйста, объяснить, как я могу передать код цвета.

+0

Вы хотите пройти цвет и что вы хотите сделать с этим цветом? – AndreaBogazzi

+0

@AndreaBogazzi, я создам новый цветовой фильтр – gambler

+0

@AndreaBogazzi, у меня есть требование как создать настраиваемый фильтр на основе цветового кода – gambler

ответ

3

Фильтр очистки, который вы нашли, на самом деле не является фильтром для очистки. Как видно из кода, он убивает зеленый и синий канал и оставляет вас только с красными изображениями. Это не тот эффект, который вы могли бы применить к красному красителю.

Вы можете создать bluify и greenify фильтр таким же образом, только изменяя выжившего Channell:

fabric.Image.filters.Greenify= fabric.util.createClass({ 

    type: 'greenify', 

    applyTo: function(canvasEl) { 
    var context = canvasEl.getContext('2d'), 
     imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), 
     data = imageData.data; 

    for (var i = 0, len = data.length; i < len; i += 4) { 
     //kill red 
     data[i] = 0; 
     //kill blue 
     data[i + 2] = 0; 
    } 

    context.putImageData(imageData, 0, 0); 
    } 
}); 

Чтобы создать colorify фильтр, сначала вы должны знать, как это сделать. Я лично проверил, как colorify фильтр из GIMP работает:

https://docs.gimp.org/en/plug-in-colorify.html

1) сделать черно-белое изображение, основанное на светимость

2) умножить уровень серого для цвета вы хотите

Это будет быть более или менее равным применять существующие фильтры fabricjs в порядке оттенков серого и Multiply.

var canvas = new fabric.Canvas("c"); 
 

 
fabric.Image.filters.Luminosity = fabric.util.createClass(fabric.Image.filters.BaseFilter, /** @lends fabric.Image.filters.Luminosity.prototype */ { 
 

 
    /** 
 
    * Filter type 
 
    * @param {String} type 
 
    * @default 
 
    */ 
 
    type: 'Luminosity', 
 

 
    /** 
 
    * Applies filter to canvas element 
 
    * @memberOf fabric.Image.filters.Grayscale.prototype 
 
    * @param {Object} canvasEl Canvas element to apply filter to 
 
    */ 
 
    applyTo: function(canvasEl) { 
 
     var context = canvasEl.getContext('2d'), 
 
      imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height), 
 
      data = imageData.data, 
 
      len = imageData.width * imageData.height * 4, 
 
      index = 0, 
 
      average; 
 

 
     while (index < len) { 
 
     //Luminosity = 0.21 × R + 0.72 × G + 0.07 × B 
 
     average = (0.21 * data[index] + 0.72 * data[index + 1] + 0.07 * data[index + 2]); 
 
     data[index]  = average; 
 
     data[index + 1] = average; 
 
     data[index + 2] = average; 
 
     index += 4; 
 
     } 
 

 
     context.putImageData(imageData, 0, 0); 
 
    } 
 
    }); 
 

 
    /** 
 
    * Returns filter instance from an object representation 
 
    * @static 
 
    * @return {fabric.Image.filters.Grayscale} Instance of fabric.Image.filters.Grayscale 
 
    */ 
 
    fabric.Image.filters.Grayscale.fromObject = function() { 
 
    return new fabric.Image.filters.Grayscale(); 
 
    }; 
 

 

 
fabric.Image.fromURL("http://fabricjs.com/assets/pug.jpg", function(img) { 
 
    img.filters.push(new fabric.Image.filters.Grayscale()); 
 
    img.filters.push(new fabric.Image.filters.Multiply({color: '#F0F'})); 
 
    img.scale(0.3); 
 
    img.applyFilters(function() { 
 
    canvas.add(img); 
 
    }); 
 
}, {crossOrigin: 'Anonymous'}); 
 

 

 

 

 
fabric.Image.fromURL("http://fabricjs.com/assets/pug.jpg", function(img) { 
 
    img.filters.push(new fabric.Image.filters.Luminosity()); 
 
    img.filters.push(new fabric.Image.filters.Multiply({color: '#F0F'})); 
 
    img.applyFilters(function() { 
 
    img.scale(0.3); 
 
    img.left = img.getWidth(); 
 
    canvas.add(img); 
 
    }); 
 
}, {crossOrigin: 'Anonymous'});
<script src="http://www.deltalink.it/andreab/fabric/fabric.js"></script> 
 
<canvas width="500" height="400" id="c" ></canvas>
Для сравнения встроенных функций fabricjs с примером из садомазо, я создал Luminosity фильтр, чтобы использовать вместо градаций серого фильтра, который основан на «Среднее значение» метода. Как вы видите, результаты довольно похожи, но они зависят от изображения.

Проверьте исходный код фильтра Multiply, чтобы узнать, как обрабатывается параметр в фильтре, если вы хотите создать собственный фильтр.

+0

спасибо за обновление. Есть ли другой способ передать цветовой код непосредственно в ткань js – gambler

+0

Проверьте исходный код фильтра Multiply рядом с моим примером, чтобы узнать, как передать параметр. – AndreaBogazzi

1

Чтобы иметь возможность использовать фильтр, который вы должны изменить код фильтра ниже в соответствии с Fabricjs filter boilerplate

(function(global) { 

'use strict'; 

var fabric = global.fabric || (global.fabric = { }), 
    filters = fabric.Image.filters, 
    createClass = fabric.util.createClass; 

/** 
* Redify filter class 
* @class fabric.Image.filters.Redify 
* @memberOf fabric.Image.filters 
* @extends fabric.Image.filters.BaseFilter 
* @see {@link fabric.Image.filters.Redify#initialize} for constructor definition 
* @see {@link http://fabricjs.com/image-filters|ImageFilters demo} 
* @example 
* var filter = new fabric.Image.filters.Redify({ 
* add here an example of how to use your filter 
* }); 
* object.filters.push(filter); 
* object.applyFilters(); 
*/ 
filters.Redify = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Redify.prototype */ { 

    /** 
    * Filter type 
    * @param {String} type 
    * @default 
    */ 
    type: 'Redify', 

    /** 
    * Fragment source for the threshold program 
    */ 
    fragmentSource: 'precision highp float;\n' + 
    'uniform sampler2D uTexture;\n' + 
    'uniform float uthreshold;\n' + 
    'varying vec2 vTexCoord;\n' + 
    'void main() {\n' + 
    'vec4 color = texture2D(uTexture, vTexCoord);\n' + 
    // add your gl code here 
    'gl_FragColor = color;\n' + 
    '}', 

    /** 
    * Redify value, from -1 to 1. 
    * translated to -255 to 255 for 2d 
    * 0.0039215686 is the part of 1 that get translated to 1 in 2d 
    * @param {Number} threshold 
    * @default 
    */ 
    threshold: 5, 

    /** 
    * Describe the property that is the filter parameter 
    * @param {String} m 
    * @default 
    */ 
    mainParameter: 'threshold', 

    /** 
    * Apply the Redify operation to a Uint8ClampedArray representing the pixels of an image. 
    * 
    * @param {Object} options 
    * @param {ImageData} options.imageData The Uint8ClampedArray to be filtered. 
    */ 
    applyTo2d: function(options) { 
     var imageData = options.imageData, 
      data = imageData.data, i, len = data.length,sublim = 255-this.threshold; 
     for (i = 0; i < len; i += 4) { 
      if (data[i] < sublim && data[i + 1] < sublim && data[i + 2] < sublim) { 
       data[i + 1] = 0; 
       data[i + 2] = 0; 
      } 
     } 
    }, 

    /** 
    * Return WebGL uniform locations for this filter's shader. 
    * 
    * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader. 
    * @param {WebGLShaderProgram} program This filter's compiled shader program. 
    */ 
    getUniformLocations: function(gl, program) { 
     return { 
      uMyParameter: gl.getUniformLocation(program, 'uMyParameter'), 
     }; 
    }, 

    /** 
    * Send data from this filter to its shader program's uniforms. 
    * 
    * @param {WebGLRenderingContext} gl The GL canvas context used to compile this filter's shader. 
    * @param {Object} uniformLocations A map of string uniform names to WebGLUniformLocation objects 
    */ 
    sendUniformData: function(gl, uniformLocations) { 
     gl.uniform1f(uniformLocations.uMyParameter, this.threshold); 
    }, 
}); 

/** 
* Returns filter instance from an object representation 
* @static 
* @param {Object} object Object to create an instance from 
* @param {function} [callback] to be invoked after filter creation 
* @return {fabric.Image.filters.Redify} Instance of fabric.Image.filters.Redify 
*/ 
fabric.Image.filters.Redify.fromObject = fabric.Image.filters.BaseFilter.fromObject; 

})(typeof exports !== 'undefined' ? exports : this); 

После того, как вы сделали, что вы можете просто использовать его, как показано ниже, чтобы передать переменную

fabric.Image.fromURL('pug.jpg', function(img) { 
    img.filters.push(
    new fabric.Image.filters.Redify({ threshold: 10 })); 

    img.applyFilters(); 
    canvas.add(img); 
});