fabric-pure-browser
Version:
Fabric.js package with no node-specific dependencies (node-canvas, jsdom). The project is published once a day (in case if a new version appears) from 'master' branch of https://github.com/fabricjs/fabric.js repository. You can keep original imports in
216 lines (196 loc) • 7.9 kB
JavaScript
(function(global) {
'use strict';
var fabric = global.fabric || (global.fabric = { }),
filters = fabric.Image.filters,
createClass = fabric.util.createClass;
/**
* Blur filter class
* @class fabric.Image.filters.Blur
* @memberOf fabric.Image.filters
* @extends fabric.Image.filters.BaseFilter
* @see {@link fabric.Image.filters.Blur#initialize} for constructor definition
* @see {@link http://fabricjs.com/image-filters|ImageFilters demo}
* @example
* var filter = new fabric.Image.filters.Blur({
* blur: 0.5
* });
* object.filters.push(filter);
* object.applyFilters();
* canvas.renderAll();
*/
filters.Blur = createClass(filters.BaseFilter, /** @lends fabric.Image.filters.Blur.prototype */ {
type: 'Blur',
/*
'gl_FragColor = vec4(0.0);',
'gl_FragColor += texture2D(texture, vTexCoord + -7 * uDelta)*0.0044299121055113265;',
'gl_FragColor += texture2D(texture, vTexCoord + -6 * uDelta)*0.00895781211794;',
'gl_FragColor += texture2D(texture, vTexCoord + -5 * uDelta)*0.0215963866053;',
'gl_FragColor += texture2D(texture, vTexCoord + -4 * uDelta)*0.0443683338718;',
'gl_FragColor += texture2D(texture, vTexCoord + -3 * uDelta)*0.0776744219933;',
'gl_FragColor += texture2D(texture, vTexCoord + -2 * uDelta)*0.115876621105;',
'gl_FragColor += texture2D(texture, vTexCoord + -1 * uDelta)*0.147308056121;',
'gl_FragColor += texture2D(texture, vTexCoord )*0.159576912161;',
'gl_FragColor += texture2D(texture, vTexCoord + 1 * uDelta)*0.147308056121;',
'gl_FragColor += texture2D(texture, vTexCoord + 2 * uDelta)*0.115876621105;',
'gl_FragColor += texture2D(texture, vTexCoord + 3 * uDelta)*0.0776744219933;',
'gl_FragColor += texture2D(texture, vTexCoord + 4 * uDelta)*0.0443683338718;',
'gl_FragColor += texture2D(texture, vTexCoord + 5 * uDelta)*0.0215963866053;',
'gl_FragColor += texture2D(texture, vTexCoord + 6 * uDelta)*0.00895781211794;',
'gl_FragColor += texture2D(texture, vTexCoord + 7 * uDelta)*0.0044299121055113265;',
*/
/* eslint-disable max-len */
fragmentSource: 'precision highp float;\n' +
'uniform sampler2D uTexture;\n' +
'uniform vec2 uDelta;\n' +
'varying vec2 vTexCoord;\n' +
'const float nSamples = 15.0;\n' +
'vec3 v3offset = vec3(12.9898, 78.233, 151.7182);\n' +
'float random(vec3 scale) {\n' +
/* use the fragment position for a different seed per-pixel */
'return fract(sin(dot(gl_FragCoord.xyz, scale)) * 43758.5453);\n' +
'}\n' +
'void main() {\n' +
'vec4 color = vec4(0.0);\n' +
'float total = 0.0;\n' +
'float offset = random(v3offset);\n' +
'for (float t = -nSamples; t <= nSamples; t++) {\n' +
'float percent = (t + offset - 0.5) / nSamples;\n' +
'float weight = 1.0 - abs(percent);\n' +
'color += texture2D(uTexture, vTexCoord + uDelta * percent) * weight;\n' +
'total += weight;\n' +
'}\n' +
'gl_FragColor = color / total;\n' +
'}',
/* eslint-enable max-len */
/**
* blur value, in percentage of image dimensions.
* specific to keep the image blur constant at different resolutions
* range bewteen 0 and 1.
*/
blur: 0,
mainParameter: 'blur',
applyTo: function(options) {
if (options.webgl) {
// this aspectRatio is used to give the same blur to vertical and horizontal
this.aspectRatio = options.sourceWidth / options.sourceHeight;
options.passes++;
this._setupFrameBuffer(options);
this.horizontal = true;
this.applyToWebGL(options);
this._swapTextures(options);
this._setupFrameBuffer(options);
this.horizontal = false;
this.applyToWebGL(options);
this._swapTextures(options);
}
else {
this.applyTo2d(options);
}
},
applyTo2d: function(options) {
// paint canvasEl with current image data.
//options.ctx.putImageData(options.imageData, 0, 0);
options.imageData = this.simpleBlur(options);
},
simpleBlur: function(options) {
var resources = options.filterBackend.resources, canvas1, canvas2,
width = options.imageData.width,
height = options.imageData.height;
if (!resources.blurLayer1) {
resources.blurLayer1 = fabric.util.createCanvasElement();
resources.blurLayer2 = fabric.util.createCanvasElement();
}
canvas1 = resources.blurLayer1;
canvas2 = resources.blurLayer2;
if (canvas1.width !== width || canvas1.height !== height) {
canvas2.width = canvas1.width = width;
canvas2.height = canvas1.height = height;
}
var ctx1 = canvas1.getContext('2d'),
ctx2 = canvas2.getContext('2d'),
nSamples = 15,
random, percent, j, i,
blur = this.blur * 0.06 * 0.5;
// load first canvas
ctx1.putImageData(options.imageData, 0, 0);
ctx2.clearRect(0, 0, width, height);
for (i = -nSamples; i <= nSamples; i++) {
random = (Math.random() - 0.5) / 4;
percent = i / nSamples;
j = blur * percent * width + random;
ctx2.globalAlpha = 1 - Math.abs(percent);
ctx2.drawImage(canvas1, j, random);
ctx1.drawImage(canvas2, 0, 0);
ctx2.globalAlpha = 1;
ctx2.clearRect(0, 0, canvas2.width, canvas2.height);
}
for (i = -nSamples; i <= nSamples; i++) {
random = (Math.random() - 0.5) / 4;
percent = i / nSamples;
j = blur * percent * height + random;
ctx2.globalAlpha = 1 - Math.abs(percent);
ctx2.drawImage(canvas1, random, j);
ctx1.drawImage(canvas2, 0, 0);
ctx2.globalAlpha = 1;
ctx2.clearRect(0, 0, canvas2.width, canvas2.height);
}
options.ctx.drawImage(canvas1, 0, 0);
var newImageData = options.ctx.getImageData(0, 0, canvas1.width, canvas1.height);
ctx1.globalAlpha = 1;
ctx1.clearRect(0, 0, canvas1.width, canvas1.height);
return newImageData;
},
/**
* 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 {
delta: gl.getUniformLocation(program, 'uDelta'),
};
},
/**
* 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) {
var delta = this.chooseRightDelta();
gl.uniform2fv(uniformLocations.delta, delta);
},
/**
* choose right value of image percentage to blur with
* @returns {Array} a numeric array with delta values
*/
chooseRightDelta: function() {
var blurScale = 1, delta = [0, 0], blur;
if (this.horizontal) {
if (this.aspectRatio > 1) {
// image is wide, i want to shrink radius horizontal
blurScale = 1 / this.aspectRatio;
}
}
else {
if (this.aspectRatio < 1) {
// image is tall, i want to shrink radius vertical
blurScale = this.aspectRatio;
}
}
blur = blurScale * this.blur * 0.12;
if (this.horizontal) {
delta[0] = blur;
}
else {
delta[1] = blur;
}
return delta;
},
});
/**
* Deserialize a JSON definition of a BlurFilter into a concrete instance.
*/
filters.Blur.fromObject = fabric.Image.filters.BaseFilter.fromObject;
})(typeof exports !== 'undefined' ? exports : this);