gl-image
Version:
image filter utils based on webgl
101 lines (98 loc) • 10 kB
JavaScript
"use strict";
/**
* @filter Brightness / Contrast
* @description Provides additive brightness and multiplicative contrast control.
* @param brightness -1 to 1 (-1 is solid black, 0 is no change, and 1 is solid white)
* @param contrast -1 to 1 (-1 is solid gray, 0 is no change, and 1 is maximum contrast)
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.GLSL_FS_blur = exports.GLSL_FS_pixelate2 = exports.GLSL_FS_pixelate = exports.GLSL_FS_noise = exports.GLSL_FS_vignette = exports.GLSL_FS_vibrance = exports.GLSL_FS_sepia = exports.GLSL_FS_hueSaturation = exports.GLSL_FS_brightnessContrast = void 0;
exports.GLSL_FS_brightnessContrast = "\nprecision highp float;\nuniform sampler2D texture;\nuniform float brightness;\nuniform float contrast;\nvarying vec2 texCoord;\nvoid main() {\n vec4 color = texture2D(texture, texCoord);\n color.rgb += brightness;\n if (contrast > 0.0) {\n color.rgb = (color.rgb - 0.5) / (1.0 - contrast) + 0.5;\n } else {\n color.rgb = (color.rgb - 0.5) * (1.0 + contrast) + 0.5;\n }\n gl_FragColor = color;\n}\n";
/**
* @filter Hue / Saturation
* @description Provides rotational hue and multiplicative saturation control. RGB color space
* can be imagined as a cube where the axes are the red, green, and blue color
* values. Hue changing works by rotating the color vector around the grayscale
* line, which is the straight line from black (0, 0, 0) to white (1, 1, 1).
* Saturation is implemented by scaling all color channel values either toward
* or away from the average color channel value.
* @param hue -1 to 1 (-1 is 180 degree rotation in the negative direction, 0 is no change,
* and 1 is 180 degree rotation in the positive direction)
* @param saturation -1 to 1 (-1 is solid gray, 0 is no change, and 1 is maximum contrast)
*/
exports.GLSL_FS_hueSaturation = "\nprecision highp float;\nuniform sampler2D texture;\nuniform float hue;\nuniform float saturation;\nvarying vec2 texCoord;\nvoid main() {\n vec4 color = texture2D(texture, texCoord);\n \n /* hue adjustment, wolfram alpha: RotationTransform[angle, {1, 1, 1}][{x, y, z}] */\n float angle = hue * 3.14159265;\n float s = sin(angle), c = cos(angle);\n vec3 weights = (vec3(2.0 * c, -sqrt(3.0) * s - c, sqrt(3.0) * s - c) + 1.0) / 3.0;\n float len = length(color.rgb);\n color.rgb = vec3(\n dot(color.rgb, weights.xyz),\n dot(color.rgb, weights.zxy),\n dot(color.rgb, weights.yzx)\n );\n \n /* saturation adjustment */\n float average = (color.r + color.g + color.b) / 3.0;\n if (saturation > 0.0) {\n color.rgb += (average - color.rgb) * (1.0 - 1.0 / (1.001 - saturation));\n } else {\n color.rgb += (average - color.rgb) * (-saturation);\n }\n \n gl_FragColor = color;\n}\n";
/**
* @filter Sepia
* @description Gives the image a reddish-brown monochrome tint that imitates an old photograph.
* @param sepia_amount 0 to 1 (0 for no effect, 1 for full sepia coloring)
*/
exports.GLSL_FS_sepia = "\nprecision highp float;\nuniform sampler2D texture;\nuniform float sepia_amount;\nvarying vec2 texCoord;\nvoid main() {\n vec4 color = texture2D(texture, texCoord);\n float r = color.r;\n float g = color.g;\n float b = color.b;\n \n color.r = min(1.0, (r * (1.0 - (0.607 * sepia_amount))) + (g * (0.769 * sepia_amount)) + (b * (0.189 * sepia_amount)));\n color.g = min(1.0, (r * 0.349 * sepia_amount) + (g * (1.0 - (0.314 * sepia_amount))) + (b * 0.168 * sepia_amount));\n color.b = min(1.0, (r * 0.272 * sepia_amount) + (g * 0.534 * sepia_amount) + (b * (1.0 - (0.869 * sepia_amount))));\n \n gl_FragColor = color;\n} \n";
/**
* @filter Vibrance
* @description Modifies the saturation of desaturated colors, leaving saturated colors unmodified.
* @param vibrance_amount -1 to 1 (-1 is minimum vibrance, 0 is no change, and 1 is maximum vibrance)
*/
exports.GLSL_FS_vibrance = "\nprecision highp float;\nuniform sampler2D texture;\nuniform float vibrance_amount;\nvarying vec2 texCoord;\nvoid main() {\n vec4 color = texture2D(texture, texCoord);\n float average = (color.r + color.g + color.b) / 3.0;\n float mx = max(color.r, max(color.g, color.b));\n float amt = (mx - average) * (-vibrance_amount * 3.0);\n color.rgb = mix(color.rgb, vec3(mx), amt);\n gl_FragColor = color;\n}\n";
/**
* @filter Vignette
* @description Adds a simulated lens edge darkening effect.
* @param vignette_size 0 to 1 (0 for center of frame, 1 for edge of frame)
* @param vignette_amount 0 to 1 (0 for no effect, 1 for maximum lens darkening)
*/
exports.GLSL_FS_vignette = "\nprecision highp float;\nuniform sampler2D texture;\nuniform float vignette_size;\nuniform float vignette_amount;\nvarying vec2 texCoord;\nvoid main() {\n vec4 color = texture2D(texture, texCoord);\n \n float dist = distance(texCoord, vec2(0.5, 0.5));\n color.rgb *= smoothstep(0.8, vignette_size * 0.799, dist * (vignette_amount + vignette_size));\n \n gl_FragColor = color;\n}\n";
/**
* @filter Noise
* @description Adds black and white noise to the image.
* @param noise_amount 0 to 1 (0 for no effect, 1 for maximum noise)
*/
exports.GLSL_FS_noise = "\nprecision highp float;\nuniform sampler2D texture;\nuniform float noise_amount;\nvarying vec2 texCoord;\nfloat rand(vec2 co) {\n return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);\n}\nvoid main() {\n vec4 color = texture2D(texture, texCoord);\n \n float diff = (rand(texCoord) - 0.5) * noise_amount;\n color.r += diff;\n color.g += diff;\n color.b += diff;\n \n gl_FragColor = color;\n}\n";
/**
* @filter pixelate
* @description pixelate the image.
* @param pixelate_block_size 0 to 100 (0 for no effect, 100 for maximum noise)
* @param pixelate_step_w 1 / image Width, fixed value
* @param pixelate_step_h 1 / image Height, fixed value
*/
exports.GLSL_FS_pixelate = "\nprecision highp float;\nuniform sampler2D texture;\nuniform float pixelate_block_size;\nuniform float pixelate_step_w;\nuniform float pixelate_step_h;\nvarying vec2 texCoord;\nvoid main() {\n float blockW = pixelate_block_size * pixelate_step_w;\n float blockH = pixelate_block_size * pixelate_step_h;\n vec4 color;\n \n if (pixelate_block_size <= 0.0 || blockW <= 0.0 || blockH <= 0.0) {\n color = texture2D(texture, texCoord); \n } else {\n int posX = int(texCoord.x / blockW);\n int posY = int(texCoord.y / blockH);\n float fposX = float(posX);\n float fposY = float(posY);\n vec2 squareCoords = vec2(fposX * blockW, fposY * blockH);\n color = texture2D(texture, squareCoords);\n }\n\n gl_FragColor = color;\n}\n";
/**
* @filter Hexagonal Pixelate
* @description Renders the image using a pattern of hexagonal tiles. Tile colors
* are nearest-neighbor sampled from the centers of the tiles.
* @param centerX The x coordinate of the pattern center.
* @param centerY The y coordinate of the pattern center.
* @param scale The width of an individual tile, in pixels, [1, 20].
*
*
* center: [centerX, centerY],
* scale: scale,
* texSize: [this.width, this.height]
*/
exports.GLSL_FS_pixelate2 = "\nprecision highp float;\nuniform sampler2D texture;\nuniform vec2 center;\nuniform float scale;\nuniform vec2 texSize;\nvarying vec2 texCoord;\nvoid main() {\n vec2 tex = (texCoord * texSize - center) / scale;\n tex.y /= 0.866025404;\n tex.x -= tex.y * 0.5;\n \n vec2 a;\n if (tex.x + tex.y - floor(tex.x) - floor(tex.y) < 1.0) a = vec2(floor(tex.x), floor(tex.y));\n else a = vec2(ceil(tex.x), ceil(tex.y));\n vec2 b = vec2(ceil(tex.x), floor(tex.y));\n vec2 c = vec2(floor(tex.x), ceil(tex.y));\n \n vec3 TEX = vec3(tex.x, tex.y, 1.0 - tex.x - tex.y);\n vec3 A = vec3(a.x, a.y, 1.0 - a.x - a.y);\n vec3 B = vec3(b.x, b.y, 1.0 - b.x - b.y);\n vec3 C = vec3(c.x, c.y, 1.0 - c.x - c.y);\n \n float alen = length(TEX - A);\n float blen = length(TEX - B);\n float clen = length(TEX - C);\n \n vec2 choice;\n if (alen < blen) {\n if (alen < clen) choice = a;\n else choice = c;\n } else {\n if (blen < clen) choice = b;\n else choice = c;\n }\n \n choice.x += choice.y * 0.5;\n choice.y *= 0.866025404;\n choice *= scale / texSize;\n gl_FragColor = texture2D(texture, choice + center / texSize);\n}\n";
/**
* 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;
},
*/
exports.GLSL_FS_blur = "\nprecision highp float;\nuniform sampler2D uTexture;\nuniform vec2 uDelta;\nvarying vec2 vTexCoord;\nconst float nSamples = 15.0;\nvec3 v3offset = vec3(12.9898, 78.233, 151.7182);\nfloat random(vec3 scale) {\n /* use the fragment position for a different seed per-pixel */\n return fract(sin(dot(gl_FragCoord.xyz, scale)) * 43758.5453);\n}\nvoid 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}\n";