Pixastic.Effects = (function() { function defaultOptions(options, defaults) { var O = {}; for (var opt in defaults) { if (typeof options[opt] == "undefined") { O[opt] = defaults[opt]; } else { O[opt] = options[opt]; } } return O; } function clamp(val, min, max) { return Math.min(max, Math.max(min, val)); } function convolve3x3(inData, outData, width, height, kernel, progress, alpha, invert, mono) { var idx, r, g, b, a, pyc, pyp, pyn, pxc, pxp, pxn, x, y, prog, lastProg = 0, n = width * height * 4, k00 = kernel[0][0], k01 = kernel[0][1], k02 = kernel[0][2], k10 = kernel[1][0], k11 = kernel[1][1], k12 = kernel[1][2], k20 = kernel[2][0], k21 = kernel[2][1], k22 = kernel[2][2], p00, p01, p02, p10, p11, p12, p20, p21, p22; for (y=0;y= width-1) pyn = pyc; for (x=0;x= width-1) pxn = pxc; p00 = pyp + pxp; p01 = pyp + pxc; p02 = pyp + pxn; p10 = pyc + pxp; p11 = pyc + pxc; p12 = pyc + pxn; p20 = pyn + pxp; p21 = pyn + pxc; p22 = pyn + pxn; r = inData[p00] * k00 + inData[p01] * k01 + inData[p02] * k02 + inData[p10] * k10 + inData[p11] * k11 + inData[p12] * k12 + inData[p20] * k20 + inData[p21] * k21 + inData[p22] * k22; g = inData[p00 + 1] * k00 + inData[p01 + 1] * k01 + inData[p02 + 1] * k02 + inData[p10 + 1] * k10 + inData[p11 + 1] * k11 + inData[p12 + 1] * k12 + inData[p20 + 1] * k20 + inData[p21 + 1] * k21 + inData[p22 + 1] * k22; b = inData[p00 + 2] * k00 + inData[p01 + 2] * k01 + inData[p02 + 2] * k02 + inData[p10 + 2] * k10 + inData[p11 + 2] * k11 + inData[p12 + 2] * k12 + inData[p20 + 2] * k20 + inData[p21 + 2] * k21 + inData[p22 + 2] * k22; if (alpha) { a = inData[p00 + 3] * k00 + inData[p01 + 3] * k01 + inData[p02 + 3] * k02 + inData[p10 + 3] * k10 + inData[p11 + 3] * k11 + inData[p12 + 3] * k12 + inData[p20 + 3] * k20 + inData[p21 + 3] * k21 + inData[p22 + 3] * k22; } else { a = inData[idx+3]; } if (mono) { r = g = b = (r + g + b) / 3; } if (invert) { r = 255 - r; g = 255 - g; b = 255 - b; } outData[idx] = r; outData[idx+1] = g; outData[idx+2] = b; outData[idx+3] = a; if (progress) { prog = (idx/n*100 >> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } } } function convolve5x5(inData, outData, width, height, kernel, progress, alpha, invert, mono) { var idx, r, g, b, a, pyc, pyp, pyn, pypp, pynn, pxc, pxp, pxn, pxpp, pxnn, x, y, prog, lastProg = 0, n = width * height * 4, k00 = kernel[0][0], k01 = kernel[0][1], k02 = kernel[0][2], k03 = kernel[0][3], k04 = kernel[0][4], k10 = kernel[1][0], k11 = kernel[1][1], k12 = kernel[1][2], k13 = kernel[1][3], k14 = kernel[1][4], k20 = kernel[2][0], k21 = kernel[2][1], k22 = kernel[2][2], k23 = kernel[2][3], k24 = kernel[2][4], k30 = kernel[3][0], k31 = kernel[3][1], k32 = kernel[3][2], k33 = kernel[3][3], k34 = kernel[3][4], k40 = kernel[4][0], k41 = kernel[4][1], k42 = kernel[4][2], k43 = kernel[4][3], k44 = kernel[4][4], p00, p01, p02, p03, p04, p10, p11, p12, p13, p14, p20, p21, p22, p23, p24, p30, p31, p32, p33, p34, p40, p41, p42, p43, p44; for (y=0;y= width-1) pyn = pyc; if (y < 2) pypp = pyp; if (y >= width-2) pynn = pyn; for (x=0;x= width-1) pxn = pxc; if (x < 2) pxpp = pxp; if (x >= width-2) pxnn = pxn; p00 = pypp + pxpp; p01 = pypp + pxp; p02 = pypp + pxc; p03 = pypp + pxn; p04 = pypp + pxnn; p10 = pyp + pxpp; p11 = pyp + pxp; p12 = pyp + pxc; p13 = pyp + pxn; p14 = pyp + pxnn; p20 = pyc + pxpp; p21 = pyc + pxp; p22 = pyc + pxc; p23 = pyc + pxn; p24 = pyc + pxnn; p30 = pyn + pxpp; p31 = pyn + pxp; p32 = pyn + pxc; p33 = pyn + pxn; p34 = pyn + pxnn; p40 = pynn + pxpp; p41 = pynn + pxp; p42 = pynn + pxc; p43 = pynn + pxn; p44 = pynn + pxnn; r = inData[p00] * k00 + inData[p01] * k01 + inData[p02] * k02 + inData[p03] * k04 + inData[p02] * k04 + inData[p10] * k10 + inData[p11] * k11 + inData[p12] * k12 + inData[p13] * k14 + inData[p12] * k14 + inData[p20] * k20 + inData[p21] * k21 + inData[p22] * k22 + inData[p23] * k24 + inData[p22] * k24 + inData[p30] * k30 + inData[p31] * k31 + inData[p32] * k32 + inData[p33] * k34 + inData[p32] * k34 + inData[p40] * k40 + inData[p41] * k41 + inData[p42] * k42 + inData[p43] * k44 + inData[p42] * k44; g = inData[p00+1] * k00 + inData[p01+1] * k01 + inData[p02+1] * k02 + inData[p03+1] * k04 + inData[p02+1] * k04 + inData[p10+1] * k10 + inData[p11+1] * k11 + inData[p12+1] * k12 + inData[p13+1] * k14 + inData[p12+1] * k14 + inData[p20+1] * k20 + inData[p21+1] * k21 + inData[p22+1] * k22 + inData[p23+1] * k24 + inData[p22+1] * k24 + inData[p30+1] * k30 + inData[p31+1] * k31 + inData[p32+1] * k32 + inData[p33+1] * k34 + inData[p32+1] * k34 + inData[p40+1] * k40 + inData[p41+1] * k41 + inData[p42+1] * k42 + inData[p43+1] * k44 + inData[p42+1] * k44; b = inData[p00+2] * k00 + inData[p01+2] * k01 + inData[p02+2] * k02 + inData[p03+2] * k04 + inData[p02+2] * k04 + inData[p10+2] * k10 + inData[p11+2] * k11 + inData[p12+2] * k12 + inData[p13+2] * k14 + inData[p12+2] * k14 + inData[p20+2] * k20 + inData[p21+2] * k21 + inData[p22+2] * k22 + inData[p23+2] * k24 + inData[p22+2] * k24 + inData[p30+2] * k30 + inData[p31+2] * k31 + inData[p32+2] * k32 + inData[p33+2] * k34 + inData[p32+2] * k34 + inData[p40+2] * k40 + inData[p41+2] * k41 + inData[p42+2] * k42 + inData[p43+2] * k44 + inData[p42+2] * k44; if (alpha) { a = inData[p00+3] * k00 + inData[p01+3] * k01 + inData[p02+3] * k02 + inData[p03+3] * k04 + inData[p02+3] * k04 + inData[p10+3] * k10 + inData[p11+3] * k11 + inData[p12+3] * k12 + inData[p13+3] * k14 + inData[p12+3] * k14 + inData[p20+3] * k20 + inData[p21+3] * k21 + inData[p22+3] * k22 + inData[p23+3] * k24 + inData[p22+3] * k24 + inData[p30+3] * k30 + inData[p31+3] * k31 + inData[p32+3] * k32 + inData[p33+3] * k34 + inData[p32+3] * k34 + inData[p40+3] * k40 + inData[p41+3] * k41 + inData[p42+3] * k42 + inData[p43+3] * k44 + inData[p42+3] * k44; } else { a = inData[idx+3]; } if (mono) { r = g = b = (r + g + b) / 3; } if (invert) { r = 255 - r; g = 255 - g; b = 255 - b; } outData[idx] = r; outData[idx+1] = g; outData[idx+2] = b; outData[idx+3] = a; if (progress) { prog = (idx/n*100 >> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } } } function gaussian(inData, outData, width, height, kernelSize, progress) { var r, g, b, a, idx, n = width * height * 4, x, y, i, j, inx, iny, w, tmpData = [], maxKernelSize = 13, kernelSize = clamp(kernelSize, 3, maxKernelSize), k1 = -kernelSize / 2 + (kernelSize % 2 ? 0.5 : 0), k2 = kernelSize + k1, weights, kernels = [[1]], prog, lastProg = 0; for (i=1;i= width) { inx = width - 1; } idx = (iny * width + inx) * 4; r += inData[idx] * w; g += inData[idx + 1] * w; b += inData[idx + 2] * w; a += inData[idx + 3] * w; } idx = (y * width + x) * 4; tmpData[idx] = r; tmpData[idx+1] = g; tmpData[idx+2] = b; tmpData[idx+3] = a; if (progress) { prog = (idx/n*50 >> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } } lastProg = 0; // pass 2 for (y=0;y= height) { iny = height - 1; } idx = (iny * width + inx) * 4; r += tmpData[idx] * w; g += tmpData[idx + 1] * w; b += tmpData[idx + 2] * w; a += tmpData[idx + 3] * w; } idx = (y * width + x) * 4; outData[idx] = r; outData[idx+1] = g; outData[idx+2] = b; outData[idx+3] = a; if (progress) { prog = 0.5 + (idx/n*50 >> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } } } return { invert : function(inData, outData, width, height, options, progress) { var n = width * height * 4, prog, lastProg = 0; for (i=0;i> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } }, sepia : function(inData, outData, width, height, options, progress) { var n = width * height * 4, prog, lastProg = 0, r, g, b; for (var i=0;i> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } }, solarize : function(inData, outData, width, height, options, progress) { var n = width * height * 4, prog, lastProg = 0, r, g, b; for (i=0;i 127 ? 255 - r : r; outData[i+1] = g > 127 ? 255 - g : g; outData[i+2] = b > 127 ? 255 - b : b; outData[i+3] = inData[i+3]; if (progress) { prog = (i/n*100 >> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } }, brightness : function(inData, outData, width, height, options, progress) { options = defaultOptions(options, { brightness : 0, contrast : 0 }); var contrast = clamp(options.contrast, -1, 1) / 2, brightness = 1 + clamp(options.brightness, -1, 1), prog, lastProg = 0, r, g, b, n = width * height * 4; var brightMul = brightness < 0 ? - brightness : brightness; var brightAdd = brightness < 0 ? 0 : brightness; contrast = 0.5 * Math.tan((contrast + 1) * Math.PI/4); contrastAdd = - (contrast - 0.5) * 255; for (var i=0;i> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } }, desaturate : function(inData, outData, width, height, options, progress) { var n = width * height * 4, prog, lastProg = 0, level; for (var i=0;i> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } }, lighten : function(inData, outData, width, height, options, progress) { var n = width * height * 4, prog, lastProg = 0, mul = 1 + clamp(options.amount, 0, 1); for (var i=0;i> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } }, noise : function(inData, outData, width, height, options, progress) { var n = width * height * 4, prog, lastProg = 0, amount = clamp(options.amount, 0, 1), strength = clamp(options.strength, 0, 1), mono = !!options.mono, random = Math.random, rnd, r, g, b; for (var i=0;i> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } }, flipv : function(inData, outData, width, height, options, progress) { var inPix, outPix, n = width * height * 4, prog, lastProg = 0, x, y; for (y=0;y> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } } }, fliph : function(inData, outData, width, height, options, progress) { var inPix, outPix, n = width * height * 4, prog, lastProg = 0, x, y; for (y=0;y> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } } }, blur : function(inData, outData, width, height, options, progress) { gaussian(inData, outData, width, height, options.kernelSize, progress); }, glow : function(inData, outData, width, height, options, progress) { var n = width * height * 4, i, r, g, b, amount = options.amount, tmpData = [], gaussProgress, prog, lastProg = 0; if (progress) { gaussProgress = function(p) { progress(p * 0.8); return p; } } gaussian(inData, tmpData, width, height, options.kernelSize, gaussProgress); for (i=0;i 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255; outData[i] = r; outData[i+1] = g; outData[i+2] = b; outData[i+3] = inData[i+3]; if (progress) { prog = 0.8 + (i/n*100 >> 0) / 100 * 0.2; if (prog > lastProg) { lastProg = progress(prog); } } } }, convolve3x3 : function(inData, outData, width, height, options, progress) { convolve3x3(inData, outData, width, height, options.kernel, progress); }, convolve5x5 : function(inData, outData, width, height, options, progress) { convolve5x5(inData, outData, width, height, options.kernel, progress); }, // A 3x3 high-pass filter sharpen3x3 : function(inData, outData, width, height, options, progress) { var a = - clamp(options.strength, 0, 1); convolve3x3( inData, outData, width, height, [[a, a, a], [a, 1-a*8, a], [a, a, a]], progress ); }, // A 5x5 high-pass filter sharpen5x5 : function(inData, outData, width, height, options, progress) { var a = - clamp(options.strength, 0, 1); convolve5x5( inData, outData, width, height, [[a, a, a, a, a], [a, a, a, a, a], [a, a, 1-a*24, a, a], [a, a, a, a, a], [a, a, a, a, a]], progress ); }, // A 3x3 low-pass mean filter soften3x3 : function(inData, outData, width, height, options, progress) { var c = 1/9; convolve3x3( inData, outData, width, height, [[c, c, c], [c, c, c], [c, c, c]], progress ); }, // A 5x5 low-pass mean filter soften5x5 : function(inData, outData, width, height, options, progress) { var c = 1/25; convolve5x5( inData, outData, width, height, [[c, c, c, c, c], [c, c, c, c, c], [c, c, c, c, c], [c, c, c, c, c], [c, c, c, c, c]], progress ); }, // A 3x3 Cross edge-detect crossedges : function(inData, outData, width, height, options, progress) { var a = clamp(options.strength, 0, 1) * 5 convolve3x3( inData, outData, width, height, [[ 0, -a, 0], [-a, 0, a], [ 0, a, 0]], progress, false, true ); }, // 3x3 directional emboss emboss : function(inData, outData, width, height, options, progress) { var amount = options.amount, angle = options.angle, x = Math.cos(-angle) * amount, y = Math.sin(-angle) * amount, n = width * height * 4, a00 = -x - y, a10 = -x, a20 = y - x, a01 = -y, a21 = y, a02 = -y + x, a12 = x, a22 = y + x, tmpData = [], prog, lastProg = 0, convProgress; if (progress) { convProgress = function(p) { progress(p * 0.5) return p; }; } convolve3x3( inData, tmpData, width, height, [[a00, a01, a02], [a10, 0, a12], [a20, a21, a22]] ); for (var i=0;i> 0) / 100 * 0.5; if (prog > lastProg) { lastProg = progress(prog); } } } }, // A 3x3 Sobel edge detect (similar to Photoshop's) findedges : function(inData, outData, width, height, options, progress) { var n = width * height * 4, i, data1 = [], data2 = [], gr1, gr2, gg1, gg2, gb1, gb2, prog, lastProg = 0, convProgress1, convProgress2; if (progress) { convProgress1 = function(p) { progress(p * 0.4); return p; }; convProgress2 = function(p) { progress(0.4 + p * 0.4); return p; }; } convolve3x3(inData, data1, width, height, [[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]] ); convolve3x3(inData, data2, width, height, [[-1, -2, -1], [ 0, 0, 0], [ 1, 2, 1]] ); for (i=0;i> 0) / 100 * 0.2; if (prog > lastProg) { lastProg = progress(prog); } } } }, // A 3x3 edge enhance edgeenhance3x3 : function(inData, outData, width, height, options, progress) { convolve3x3( inData, outData, width, height, [[-1/9, -1/9, -1/9], [-1/9, 17/9, -1/9], [-1/9, -1/9, -1/9]], progress ); }, // A 5x5 edge enhance edgeenhance5x5 : function(inData, outData, width, height, options, progress) { convolve5x5( inData, outData, width, height, [[-1/25, -1/25, -1/25, -1/25, -1/25], [-1/25, -1/25, -1/25, -1/25, -1/25], [-1/25, -1/25, 49/25, -1/25, -1/25], [-1/25, -1/25, -1/25, -1/25, -1/25], [-1/25, -1/25, -1/25, -1/25, -1/25]], progress ); }, // A 3x3 Laplacian edge-detect laplace3x3 : function(inData, outData, width, height, options, progress) { convolve3x3( inData, outData, width, height, [[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]], progress, false, true, true ); }, // A 5x5 Laplacian edge-detect laplace5x5 : function(inData, outData, width, height, options, progress) { convolve5x5( inData, outData, width, height, [[-1, -1, -1, -1, -1], [-1, -1, -1, -1, -1], [-1, -1, 24, -1, -1], [-1, -1, -1, -1, -1], [-1, -1, -1, -1, -1]], progress, false, true, true ); }, coloradjust : function(inData, outData, width, height, options, progress) { var n = width * height * 4, r, g, b, prog, lastProg = 0, ar = clamp(options.r, -1, 1) * 255, ag = clamp(options.g, -1, 1) * 255, ab = clamp(options.b, -1, 1) * 255; for (var i=0;i 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255; outData[i] = r; outData[i+1] = g; outData[i+2] = b; outData[i+3] = inData[i+3]; if (progress) { prog = (i/n*100 >> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } }, colorfilter : function(inData, outData, width, height, options, progress) { var n = width * height * 4, i, r, g, b, luminosity = !!options.luminosity, prog, lastProg = 0, min, max, h, l, h1, chroma, tmp, m, ar = clamp(options.r, 0, 1), ag = clamp(options.g, 0, 1), ab = clamp(options.b, 0, 1); for (i=0;i max) max = g; if (b > max) max = b; if (g < min) min = g; if (b < min) min = b; chroma = (max - min); if (r == max) { h = ((g - b) / chroma) % 6; } else if (g == max) { h = ((b - r) / chroma) + 2; } else { h = ((r - g) / chroma) + 4; } h1 = h >> 0; tmp = chroma * (h - h1); r = g = b = l - (r * 0.3 + g * 0.59 + b * 0.11); if (h1 == 0) { r += chroma; g += tmp; } else if (h1 == 1) { r += chroma - tmp; g += chroma; } else if (h1 == 2) { g += chroma; b += tmp; } else if (h1 == 3) { g += chroma - tmp; b += chroma; } else if (h1 == 4) { r += tmp; b += chroma; } else if (h1 == 5) { r += chroma; b += chroma - tmp; } } outData[i] = r * 255; outData[i+1] = g * 255; outData[i+2] = b * 255; outData[i+3] = inData[i+3]; if (progress) { prog = (i/n*100 >> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } }, hsl : function(inData, outData, width, height, options, progress) { var n = width * height * 4, hue = clamp(options.hue, -1, 1), saturation = clamp(options.saturation, -1, 1), lightness = clamp(options.lightness, -1, 1), satMul = 1 + saturation * (saturation < 0 ? 1 : 2), lightMul = lightness < 0 ? 1 + lightness : 1 - lightness, lightAdd = lightness < 0 ? 0 : lightness * 255, vs, ms, vm, h, s, l, v, m, vmh, sextant, prog, lastProg = 0; hue = (hue * 6) % 6; for (var i=0;i vs) vs = g; if (b > vs) vs = b; ms = r; if (g < ms) ms = g; if (b < ms) ms = b; vm = (vs-ms); l = (ms+vs)/510; if (l > 0 && vm > 0) { if (l <= 0.5) { s = vm / (vs+ms) * satMul; if (s > 1) s = 1; v = (l * (1+s)); } else { s = vm / (510-vs-ms) * satMul; if (s > 1) s = 1; v = (l+s - l*s); } if (r == vs) { if (g == ms) { h = 5 + ((vs-b)/vm) + hue; } else { h = 1 - ((vs-g)/vm) + hue; } } else if (g == vs) { if (b == ms) { h = 1 + ((vs-r)/vm) + hue; } else { h = 3 - ((vs-b)/vm) + hue; } } else { if (r == ms) { h = 3 + ((vs-g)/vm) + hue; } else { h = 5 - ((vs-r)/vm) + hue; } } if (h < 0) h += 6; if (h >= 6) h -= 6; m = (l + l - v); sextant = h >> 0; vmh = (v - m) * (h - sextant); if (sextant == 0) { r = v; g = m + vmh; b = m; } else if (sextant == 1) { r = v - vmh; g = v; b = m; } else if (sextant == 2) { r = m; g = v; b = m + vmh; } else if (sextant == 3) { r = m; g = v - vmh; b = v; } else if (sextant == 4) { r = m + vmh; g = m; b = v; } else if (sextant == 5) { r = v; g = m; b = v - vmh; } r *= 255; g *= 255; b *= 255; } } r = r * lightMul + lightAdd; g = g * lightMul + lightAdd; b = b * lightMul + lightAdd; if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0; if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255; outData[i] = r; outData[i+1] = g; outData[i+2] = b; outData[i+3] = inData[i+3]; if (progress) { prog = (i/n*100 >> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } }, posterize : function(inData, outData, width, height, options, progress) { var numLevels = clamp(options.levels, 2, 256), numAreas = 256 / numLevels, numValues = 256 / (numLevels-1), r, g, b, n = width * height * 4, prog, lastProg = 0; for (i=0;i>0); outData[i+1] = numValues * ((inData[i+1] / numAreas)>>0); outData[i+2] = numValues * ((inData[i+2] / numAreas)>>0); outData[i+3] = inData[i+3]; if (progress) { prog = (i/n*100 >> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } }, removenoise : function(inData, outData, width, height, options, progress) { var r, g, b, c, y, x, idx, pyc, pyp, pyn, pxc, pxp, pxn, minR, minG, minB, maxR, maxG, maxB, n, prog, lastProg = 0; n = width * height * 4; for (y=0;y= width-1) pyn = pyc; for (x=0;x= width-1) pxn = pxc; minR = maxR = inData[pyc + pxp]; c = inData[pyc + pxn]; if (c < minR) minR = c; if (c > maxR) maxR = c; c = inData[pyp + pxc]; if (c < minR) minR = c; if (c > maxR) maxR = c; c = inData[pyn + pxc]; if (c < minR) minR = c; if (c > maxR) maxR = c; minG = inData[pyc + pxp + 1]; c = inData[pyc + pxn + 1]; if (c < minG) minG = c; c = inData[pyp + pxc + 1]; if (c < minG) minG = c; c = inData[pyn + pxc + 1]; if (c < minG) minG = c; minB = inData[pyc + pxp + 2]; c = inData[pyc + pxn + 2]; if (c < minB) minB = c; c = inData[pyp + pxc + 2]; if (c < minB) minB = c; c = inData[pyn + pxc + 2]; if (c < minB) minB = c; r = inData[idx] g = inData[idx + 1] b = inData[idx + 2] if (r < minR) r = minR; if (r > maxR) r = maxR; if (g < minG) g = minG; if (g > maxG) g = maxG; if (b < minB) b = minB; if (b > maxB) b = maxB; outData[idx] = r; outData[idx+1] = g; outData[idx+2] = b; outData[idx+3] = inData[idx+3]; if (progress) { prog = (idx/n*100 >> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } } }, mosaic : function(inData, outData, width, height, options, progress) { var blockSize = clamp(options.blockSize, 1, Math.max(width, height)), yBlocks = Math.ceil(height / blockSize), xBlocks = Math.ceil(width / blockSize), y0, y1, x0, x1, idx, pidx, n = yBlocks * xBlocks, prog, lastProg = 0; for (i=0, y0=0, bidx=0;i> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } y0 = y1; } }, equalize : function(inData, outData, width, height, options, progress) { var n = width * height, p, i, level, ratio, prog, lastProg; var round = Math.round; // build histogram var pdf = new Array(256); for (i=0;i<256;i++) { pdf[i] = 0; } for (i=0;i> 0) / 100; if (prog > lastProg) { lastProg = progress(prog); } } } } }; })();