PHP Classes

File: uploady/assets/vendor/camansjs/dist/caman.full.js

Recommend this page to a friend!
  Classes of Faris AL-Otabi   Uploady PHP Upload File to MySQL   uploady/assets/vendor/camansjs/dist/caman.full.js   Download  
File: uploady/assets/vendor/camansjs/dist/caman.full.js
Role: Auxiliary data
Content type: text/plain
Description: Auxiliary data
Class: Uploady PHP Upload File to MySQL
Store file upload details in a MySQL database
Author: By
Last change: update permission to 755
Date: 4 months ago
Size: 119,647 bytes
 

Contents

Class file image Download
// Generated by CoffeeScript 1.12.7 (function() { var $, Analyze, Blender, Calculate, Caman, CamanParser, Canvas, Convert, Event, Fiber, Filter, IO, Image, Layer, Log, Module, Pixel, Plugin, Renderer, Root, Store, Util, fs, http, moduleKeywords, slice, vignetteFilters, indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, slice1 = [].slice, hasProp = {}.hasOwnProperty, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; moduleKeywords = ['extended', 'included']; Module = (function() { function Module() {} Module["extends"] = function(obj) { var key, ref, value; for (key in obj) { value = obj[key]; if (indexOf.call(moduleKeywords, key) < 0) { this[key] = value; } } if ((ref = obj.extended) != null) { ref.apply(this); } return this; }; Module.includes = function(obj) { var key, ref, value; for (key in obj) { value = obj[key]; if (indexOf.call(moduleKeywords, key) < 0) { this.prototype[key] = value; } } if ((ref = obj.included) != null) { ref.apply(this); } return this; }; Module.delegate = function() { var args, len, o, results, source, target; args = 1 <= arguments.length ? slice1.call(arguments, 0) : []; target = args.pop(); results = []; for (o = 0, len = args.length; o < len; o++) { source = args[o]; results.push(this.prototype[source] = target.prototype[source]); } return results; }; Module.aliasFunction = function(to, from) { return this.prototype[to] = (function(_this) { return function() { var args; args = 1 <= arguments.length ? slice1.call(arguments, 0) : []; return _this.prototype[from].apply(_this, args); }; })(this); }; Module.aliasProperty = function(to, from) { return Object.defineProperty(this.prototype, to, { get: function() { return this[from]; }, set: function(val) { return this[from] = val; } }); }; Module.included = function(func) { return func.call(this, this.prototype); }; return Module; })(); slice = Array.prototype.slice; $ = function(sel, root) { if (root == null) { root = document; } if (typeof sel === "object" || (typeof exports !== "undefined" && exports !== null)) { return sel; } return root.querySelector(sel); }; Util = (function() { function Util() {} Util.uniqid = (function() { var id; id = 0; return { get: function() { return id++; } }; })(); Util.extend = function() { var copy, dest, len, o, obj, prop, src; obj = arguments[0], src = 2 <= arguments.length ? slice1.call(arguments, 1) : []; dest = obj; for (o = 0, len = src.length; o < len; o++) { copy = src[o]; for (prop in copy) { if (!hasProp.call(copy, prop)) continue; dest[prop] = copy[prop]; } } return dest; }; Util.clampRGB = function(val) { if (val < 0) { return 0; } if (val > 255) { return 255; } return val; }; Util.copyAttributes = function(from, to, opts) { var attr, len, o, ref, ref1, results; if (opts == null) { opts = {}; } ref = from.attributes; results = []; for (o = 0, len = ref.length; o < len; o++) { attr = ref[o]; if ((opts.except != null) && (ref1 = attr.nodeName, indexOf.call(opts.except, ref1) >= 0)) { continue; } results.push(to.setAttribute(attr.nodeName, attr.nodeValue)); } return results; }; Util.dataArray = function(length) { if (length == null) { length = 0; } if (Caman.NodeJS || (window.Uint8Array != null)) { return new Uint8Array(length); } return new Array(length); }; return Util; })(); if (typeof exports !== "undefined" && exports !== null) { Root = exports; Canvas = require('canvas'); Image = Canvas.Image; Fiber = require('fibers'); fs = require('fs'); http = require('http'); } else { Root = window; } Caman = (function(superClass) { extend(Caman, superClass); Caman.version = { release: "4.1.2", date: "7/27/2013" }; Caman.DEBUG = false; Caman.allowRevert = true; Caman.crossOrigin = "anonymous"; Caman.remoteProxy = ""; Caman.proxyParam = "camanProxyUrl"; Caman.NodeJS = typeof exports !== "undefined" && exports !== null; Caman.autoload = !Caman.NodeJS; Caman.toString = function() { return "Version " + Caman.version.release + ", Released " + Caman.version.date; }; Caman.getAttrId = function(canvas) { if (Caman.NodeJS) { return true; } if (typeof canvas === "string") { canvas = $(canvas); } if (!((canvas != null) && (canvas.getAttribute != null))) { return null; } return canvas.getAttribute('data-caman-id'); }; function Caman() { this.nodeFileReady = bind(this.nodeFileReady, this); var args, callback, id; if (arguments.length === 0) { throw "Invalid arguments"; } if (this instanceof Caman) { this.finishInit = this.finishInit.bind(this); this.imageLoaded = this.imageLoaded.bind(this); args = arguments[0]; if (!Caman.NodeJS) { id = parseInt(Caman.getAttrId(args[0]), 10); callback = typeof args[1] === "function" ? args[1] : typeof args[2] === "function" ? args[2] : function() {}; if (!isNaN(id) && Store.has(id)) { return Store.execute(id, callback); } } this.id = Util.uniqid.get(); this.initializedPixelData = this.originalPixelData = null; this.cropCoordinates = { x: 0, y: 0 }; this.cropped = false; this.resized = false; this.rotated = false; this.rotationAngle = 0; this.pixelStack = []; this.layerStack = []; this.canvasQueue = []; this.currentLayer = null; this.scaled = false; this.analyze = new Analyze(this); this.renderer = new Renderer(this); this.domIsLoaded((function(_this) { return function() { _this.parseArguments(args); return _this.setup(); }; })(this)); return this; } else { return new Caman(arguments); } } Caman.prototype.domIsLoaded = function(cb) { var listener; if (Caman.NodeJS) { return setTimeout((function(_this) { return function() { return cb.call(_this); }; })(this), 0); } else { if (document.readyState === "complete") { Log.debug("DOM initialized"); return setTimeout((function(_this) { return function() { return cb.call(_this); }; })(this), 0); } else { listener = (function(_this) { return function() { if (document.readyState === "complete") { Log.debug("DOM initialized"); return cb.call(_this); } }; })(this); return document.addEventListener("readystatechange", listener, false); } } }; Caman.prototype.parseArguments = function(args) { var key, ref, results, val; if (args.length === 0) { throw "Invalid arguments given"; } this.initObj = null; this.initType = null; this.imageUrl = null; this.callback = function() {}; this.setInitObject(args[0]); if (args.length === 1) { return; } switch (typeof args[1]) { case "string": this.imageUrl = args[1]; break; case "function": this.callback = args[1]; } if (args.length === 2) { return; } this.callback = args[2]; if (args.length === 4) { ref = args[4]; results = []; for (key in ref) { if (!hasProp.call(ref, key)) continue; val = ref[key]; results.push(this.options[key] = val); } return results; } }; Caman.prototype.setInitObject = function(obj) { if (Caman.NodeJS) { this.initObj = obj; this.initType = 'node'; return; } if (typeof obj === "object") { this.initObj = obj; } else { this.initObj = $(obj); } if (this.initObj == null) { throw "Could not find image or canvas for initialization."; } return this.initType = this.initObj.nodeName.toLowerCase(); }; Caman.prototype.setup = function() { switch (this.initType) { case "node": return this.initNode(); case "img": return this.initImage(); case "canvas": return this.initCanvas(); } }; Caman.prototype.initNode = function() { Log.debug("Initializing for NodeJS"); if (typeof this.initObj === "string" && this.initObj.match(/^https?:\/\//)) { return this.readFromHttp(this.initObj, this.nodeFileReady); } else if (typeof this.initObj === "string") { return fs.readFile(this.initObj, this.nodeFileReady); } else { return this.nodeFileReady(null, this.initObj); } }; Caman.prototype.readFromHttp = function(url, callback) { var req; Log.debug("Fetching image from " + url); req = http.get(url, function(res) { var buf; buf = ''; res.setEncoding('binary'); res.on('data', function(chunk) { return buf += chunk; }); return res.on('end', function() { return callback(null, new Buffer(buf, 'binary')); }); }); return req.on('error', callback); }; Caman.prototype.nodeFileReady = function(err, data) { if (err) { throw err; } this.image = new Image(); this.image.src = data; Log.debug("Image loaded. Width = " + (this.imageWidth()) + ", Height = " + (this.imageHeight())); this.canvas = new Canvas(this.imageWidth(), this.imageHeight()); this.renderingCanvas = new Canvas(this.imageWidth(), this.imageHeight()); return this.finishInit(); }; Caman.prototype.initImage = function() { this.image = this.initObj; this.canvas = document.createElement('canvas'); this.context = this.canvas.getContext('2d'); this.renderingCanvas = document.createElement('canvas'); this.renderingContext = this.renderingCanvas.getContext('2d'); Util.copyAttributes(this.image, this.canvas, { except: ['src'] }); Util.copyAttributes(this.image, this.renderingCanvas, { except: ['src'] }); if (this.image.parentNode != null) { this.image.parentNode.replaceChild(this.renderingCanvas, this.image); } this.imageAdjustments(); return this.waitForImageLoaded(); }; Caman.prototype.initCanvas = function() { this.canvas = document.createElement('canvas'); this.context = this.canvas.getContext('2d'); this.renderingCanvas = this.initObj; this.renderingContext = this.renderingCanvas.getContext('2d'); this.canvas.width = this.renderingCanvas.width; this.canvas.height = this.renderingCanvas.height; if (this.imageUrl != null) { this.image = document.createElement('img'); this.image.crossOrigin = 'anonymous'; this.image.src = this.imageUrl; this.imageAdjustments(); return this.waitForImageLoaded(); } else { return this.finishInit(); } }; Caman.prototype.imageAdjustments = function() { if (this.needsHiDPISwap()) { Log.debug(this.image.src, "->", this.hiDPIReplacement()); this.swapped = true; this.image.src = this.hiDPIReplacement(); } if (IO.isRemote(this.image)) { this.image.src = IO.proxyUrl(this.image.src); return Log.debug("Remote image detected, using URL = " + this.image.src); } }; Caman.prototype.waitForImageLoaded = function() { if (this.isImageLoaded()) { return this.imageLoaded(); } else { return this.image.onload = this.imageLoaded; } }; Caman.prototype.isImageLoaded = function() { if (!this.image.complete) { return false; } if ((this.image.naturalWidth != null) && this.image.naturalWidth === 0) { return false; } return true; }; Caman.prototype.imageWidth = function() { return this.image.width || this.image.naturalWidth; }; Caman.prototype.imageHeight = function() { return this.image.height || this.image.naturalHeight; }; Caman.prototype.imageLoaded = function() { Log.debug("Image loaded. Width = " + (this.imageWidth()) + ", Height = " + (this.imageHeight())); if (this.swapped) { this.canvas.width = this.imageWidth() / this.hiDPIRatio(); this.canvas.height = this.imageHeight() / this.hiDPIRatio(); this.renderingCanvas.width = this.imageWidth() / this.hiDPIRatio(); this.renderingCanvas.height = this.imageHeight() / this.hiDPIRatio(); } else { this.canvas.width = this.imageWidth(); this.canvas.height = this.imageHeight(); this.renderingCanvas.width = this.imageWidth(); this.renderingCanvas.height = this.imageHeight(); } return this.finishInit(); }; Caman.prototype.finishInit = function() { var i, len, o, pixel, ref; if (this.context == null) { this.context = this.canvas.getContext('2d'); } if (this.renderingContext == null) { this.renderingContext = this.renderingCanvas.getContext('2d'); } this.originalWidth = this.preScaledWidth = this.width = this.canvas.width; this.originalHeight = this.preScaledHeight = this.height = this.canvas.height; this.hiDPIAdjustments(); if (!this.hasId()) { this.assignId(); } if (this.image != null) { this.context.drawImage(this.image, 0, 0, this.imageWidth(), this.imageHeight(), 0, 0, this.preScaledWidth, this.preScaledHeight); this.renderingContext.drawImage(this.image, 0, 0, this.imageWidth(), this.imageHeight(), 0, 0, this.preScaledWidth, this.preScaledHeight); } this.imageData = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height); this.pixelData = this.imageData.data; if (Caman.allowRevert) { this.initializedPixelData = Util.dataArray(this.pixelData.length); this.originalPixelData = Util.dataArray(this.pixelData.length); ref = this.pixelData; for (i = o = 0, len = ref.length; o < len; i = ++o) { pixel = ref[i]; this.initializedPixelData[i] = pixel; this.originalPixelData[i] = pixel; } } this.dimensions = { width: this.canvas.width, height: this.canvas.height }; if (!Caman.NodeJS) { Store.put(this.id, this); } this.callback.call(this, this); return this.callback = function() {}; }; Caman.prototype.reloadCanvasData = function() { this.imageData = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height); return this.pixelData = this.imageData.data; }; Caman.prototype.resetOriginalPixelData = function() { var i, len, o, pixel, ref, results; if (!Caman.allowRevert) { throw "Revert disabled"; } this.originalPixelData = Util.dataArray(this.pixelData.length); ref = this.pixelData; results = []; for (i = o = 0, len = ref.length; o < len; i = ++o) { pixel = ref[i]; results.push(this.originalPixelData[i] = pixel); } return results; }; Caman.prototype.hasId = function() { return Caman.getAttrId(this.canvas) != null; }; Caman.prototype.assignId = function() { if (Caman.NodeJS || this.canvas.getAttribute('data-caman-id')) { return; } return this.canvas.setAttribute('data-caman-id', this.id); }; Caman.prototype.hiDPIDisabled = function() { return this.canvas.getAttribute('data-caman-hidpi-disabled') !== null; }; Caman.prototype.hiDPIAdjustments = function() { var ratio; if (Caman.NodeJS || !this.needsHiDPISwap()) { return; } ratio = this.hiDPIRatio(); if (ratio !== 1) { Log.debug("HiDPI ratio = " + ratio); this.scaled = true; this.preScaledWidth = this.canvas.width; this.preScaledHeight = this.canvas.height; this.canvas.width = this.preScaledWidth * ratio; this.canvas.height = this.preScaledHeight * ratio; this.canvas.style.width = this.preScaledWidth + "px"; this.canvas.style.height = this.preScaledHeight + "px"; this.context.scale(ratio, ratio); this.width = this.originalWidth = this.canvas.width; return this.height = this.originalHeight = this.canvas.height; } }; Caman.prototype.hiDPIRatio = function() { var backingStoreRatio, devicePixelRatio; devicePixelRatio = window.devicePixelRatio || 1; backingStoreRatio = this.context.webkitBackingStorePixelRatio || this.context.mozBackingStorePixelRatio || this.context.msBackingStorePixelRatio || this.context.oBackingStorePixelRatio || this.context.backingStorePixelRatio || 1; return devicePixelRatio / backingStoreRatio; }; Caman.prototype.hiDPICapable = function() { return (window.devicePixelRatio != null) && window.devicePixelRatio !== 1; }; Caman.prototype.needsHiDPISwap = function() { if (this.hiDPIDisabled() || !this.hiDPICapable()) { return false; } return this.hiDPIReplacement() !== null; }; Caman.prototype.hiDPIReplacement = function() { if (this.image == null) { return null; } return this.image.getAttribute('data-caman-hidpi'); }; Caman.prototype.replaceCanvas = function(newCanvas) { var i, len, o, pixel, ref; this.canvas = newCanvas; this.context = this.canvas.getContext('2d'); this.imageData = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height); this.pixelData = this.imageData.data; if (Caman.allowRevert) { this.originalPixelData = Util.dataArray(this.pixelData.length); ref = this.pixelData; for (i = o = 0, len = ref.length; o < len; i = ++o) { pixel = ref[i]; this.originalPixelData[i] = pixel; } } this.width = this.canvas.width; this.height = this.canvas.height; this.reloadCanvasData(); return this.dimensions = { width: this.canvas.width, height: this.canvas.height }; }; Caman.prototype.render = function(callback) { if (callback == null) { callback = function() {}; } Event.trigger(this, "renderStart"); return this.renderer.execute((function(_this) { return function() { _this.renderingCanvas.width = _this.canvas.width; _this.renderingCanvas.height = _this.canvas.height; _this.renderingContext.putImageData(_this.imageData, 0, 0); return callback.call(_this); }; })(this)); }; Caman.prototype.revert = function(updateContext) { var i, len, o, pixel, ref; if (updateContext == null) { updateContext = true; } if (!Caman.allowRevert) { throw "Revert disabled"; } ref = this.originalVisiblePixels(); for (i = o = 0, len = ref.length; o < len; i = ++o) { pixel = ref[i]; this.pixelData[i] = pixel; } if (updateContext) { return this.renderingContext.putImageData(this.imageData, 0, 0); } }; Caman.prototype.reset = function() { var canvas, ctx, i, imageData, len, o, pixel, pixelData, ref; canvas = document.createElement('canvas'); Util.copyAttributes(this.canvas, canvas); canvas.width = this.originalWidth; canvas.height = this.originalHeight; ctx = canvas.getContext('2d'); imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); pixelData = imageData.data; ref = this.initializedPixelData; for (i = o = 0, len = ref.length; o < len; i = ++o) { pixel = ref[i]; pixelData[i] = pixel; } ctx.putImageData(imageData, 0, 0); this.cropCoordinates = { x: 0, y: 0 }; this.resized = false; return this.replaceCanvas(canvas); }; Caman.prototype.originalVisiblePixels = function() { var coord, endX, endY, i, o, pixelData, pixels, ref, ref1, ref2, startX, startY, width; if (!Caman.allowRevert) { throw "Revert disabled"; } pixels = []; startX = 0; endX = startX + this.width; startY = 0; endY = startY + this.height; pixelData = this.originalPixelData; width = this.canvas.width; for (i = o = 0, ref = pixelData.length; o < ref; i = o += 4) { coord = Pixel.locationToCoordinates(i, width); if (((startX <= (ref1 = coord.x) && ref1 < endX)) && ((startY <= (ref2 = coord.y) && ref2 < endY))) { pixels.push(pixelData[i], pixelData[i + 1], pixelData[i + 2], pixelData[i + 3]); } } return pixels; }; Caman.prototype.process = function(name, processFn) { this.renderer.add({ type: Filter.Type.Single, name: name, processFn: processFn }); return this; }; Caman.prototype.processKernel = function(name, adjust, divisor, bias) { var i, o, ref; if (divisor == null) { divisor = null; } if (bias == null) { bias = 0; } if (divisor == null) { divisor = 0; for (i = o = 0, ref = adjust.length; 0 <= ref ? o < ref : o > ref; i = 0 <= ref ? ++o : --o) { divisor += adjust[i]; } } this.renderer.add({ type: Filter.Type.Kernel, name: name, adjust: adjust, divisor: divisor, bias: bias }); return this; }; Caman.prototype.processPlugin = function(plugin, args) { this.renderer.add({ type: Filter.Type.Plugin, plugin: plugin, args: args }); return this; }; Caman.prototype.newLayer = function(callback) { var layer; layer = new Layer(this); this.canvasQueue.push(layer); this.renderer.add({ type: Filter.Type.LayerDequeue }); callback.call(layer); this.renderer.add({ type: Filter.Type.LayerFinished }); return this; }; Caman.prototype.executeLayer = function(layer) { return this.pushContext(layer); }; Caman.prototype.pushContext = function(layer) { this.layerStack.push(this.currentLayer); this.pixelStack.push(this.pixelData); this.currentLayer = layer; return this.pixelData = layer.pixelData; }; Caman.prototype.popContext = function() { this.pixelData = this.pixelStack.pop(); return this.currentLayer = this.layerStack.pop(); }; Caman.prototype.applyCurrentLayer = function() { return this.currentLayer.applyToParent(); }; return Caman; })(Module); Root.Caman = Caman; Caman.Analyze = (function() { function Analyze(c1) { this.c = c1; } Analyze.prototype.calculateLevels = function() { var i, levels, numPixels, o, ref, u, w; levels = { r: {}, g: {}, b: {} }; for (i = o = 0; o <= 255; i = ++o) { levels.r[i] = 0; levels.g[i] = 0; levels.b[i] = 0; } for (i = u = 0, ref = this.c.pixelData.length; u < ref; i = u += 4) { levels.r[this.c.pixelData[i]]++; levels.g[this.c.pixelData[i + 1]]++; levels.b[this.c.pixelData[i + 2]]++; } numPixels = this.c.pixelData.length / 4; for (i = w = 0; w <= 255; i = ++w) { levels.r[i] /= numPixels; levels.g[i] /= numPixels; levels.b[i] /= numPixels; } return levels; }; return Analyze; })(); Analyze = Caman.Analyze; Caman.DOMUpdated = function() { var img, imgs, len, o, parser, results; imgs = document.querySelectorAll("img[data-caman]"); if (!(imgs.length > 0)) { return; } results = []; for (o = 0, len = imgs.length; o < len; o++) { img = imgs[o]; results.push(parser = new CamanParser(img, function() { this.parse(); return this.execute(); })); } return results; }; if (Caman.autoload) { (function() { if (document.readyState === "complete") { return Caman.DOMUpdated(); } else { return document.addEventListener("DOMContentLoaded", Caman.DOMUpdated, false); } })(); } CamanParser = (function() { var INST_REGEX; INST_REGEX = "(\\w+)\\((.*?)\\)"; function CamanParser(ele, ready) { this.dataStr = ele.getAttribute('data-caman'); this.caman = Caman(ele, ready.bind(this)); } CamanParser.prototype.parse = function() { var args, e, filter, func, inst, instFunc, len, m, o, r, ref, results, unparsedInstructions; this.ele = this.caman.canvas; r = new RegExp(INST_REGEX, 'g'); unparsedInstructions = this.dataStr.match(r); if (!(unparsedInstructions.length > 0)) { return; } r = new RegExp(INST_REGEX); results = []; for (o = 0, len = unparsedInstructions.length; o < len; o++) { inst = unparsedInstructions[o]; ref = inst.match(r), m = ref[0], filter = ref[1], args = ref[2]; instFunc = new Function("return function() { this." + filter + "(" + args + "); };"); try { func = instFunc(); results.push(func.call(this.caman)); } catch (error) { e = error; results.push(Log.debug(e)); } } return results; }; CamanParser.prototype.execute = function() { var ele; ele = this.ele; return this.caman.render(function() { return ele.parentNode.replaceChild(this.toImage(), ele); }); }; return CamanParser; })(); Caman.Blender = (function() { function Blender() {} Blender.blenders = {}; Blender.register = function(name, func) { return this.blenders[name] = func; }; Blender.execute = function(name, rgbaLayer, rgbaParent) { return this.blenders[name](rgbaLayer, rgbaParent); }; return Blender; })(); Blender = Caman.Blender; Caman.Calculate = (function() { function Calculate() {} Calculate.distance = function(x1, y1, x2, y2) { return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); }; Calculate.randomRange = function(min, max, getFloat) { var rand; if (getFloat == null) { getFloat = false; } rand = min + (Math.random() * (max - min)); if (getFloat) { return rand.toFixed(getFloat); } else { return Math.round(rand); } }; Calculate.luminance = function(rgba) { return (0.299 * rgba.r) + (0.587 * rgba.g) + (0.114 * rgba.b); }; Calculate.bezier = function(start, ctrl1, ctrl2, end, lowBound, highBound) { var bezier, clamp, controlPoints, endX, i, j, lerp, next, o, prev, ref, t, u; if (lowBound == null) { lowBound = 0; } if (highBound == null) { highBound = 255; } if (start[0] instanceof Array) { controlPoints = start; lowBound = ctrl1; highBound = ctrl2; } else { controlPoints = [start, ctrl1, ctrl2, end]; } if (controlPoints.length < 2) { throw "Invalid number of arguments to bezier"; } bezier = {}; lerp = function(a, b, t) { return a * (1 - t) + b * t; }; clamp = function(a, min, max) { return Math.min(Math.max(a, min), max); }; for (i = o = 0; o < 1000; i = ++o) { t = i / 1000; prev = controlPoints; while (prev.length > 1) { next = []; for (j = u = 0, ref = prev.length - 2; 0 <= ref ? u <= ref : u >= ref; j = 0 <= ref ? ++u : --u) { next.push([lerp(prev[j][0], prev[j + 1][0], t), lerp(prev[j][1], prev[j + 1][1], t)]); } prev = next; } bezier[Math.round(prev[0][0])] = Math.round(clamp(prev[0][1], lowBound, highBound)); } endX = controlPoints[controlPoints.length - 1][0]; bezier = Caman.Calculate.missingValues(bezier, endX); if (bezier[endX] == null) { bezier[endX] = bezier[endX - 1]; } return bezier; }; Calculate.hermite = function(controlPoints, lowBound, highBound) { var add, clamp, count, endX, fac0, fac1, fac2, fac3, i, j, lerp, m0, m1, mul, o, p, p0, p1, pointsPerSegment, pointsPerStep, pos, ref, ref1, ret, sub, t, u; if (controlPoints.length < 2) { throw "Invalid number of arguments to hermite"; } ret = {}; lerp = function(a, b, t) { return a * (1 - t) + b * t; }; add = (function(_this) { return function(a, b, c, d) { return [a[0] + b[0] + c[0] + d[0], a[1] + b[1] + c[1] + d[1]]; }; })(this); mul = (function(_this) { return function(a, b) { return [a[0] * b[0], a[1] * b[1]]; }; })(this); sub = (function(_this) { return function(a, b) { return [a[0] - b[0], a[1] - b[1]]; }; })(this); clamp = function(a, min, max) { return Math.min(Math.max(a, min), max); }; count = 0; for (i = o = 0, ref = controlPoints.length - 2; 0 <= ref ? o <= ref : o >= ref; i = 0 <= ref ? ++o : --o) { p0 = controlPoints[i]; p1 = controlPoints[i + 1]; pointsPerSegment = p1[0] - p0[0]; pointsPerStep = 1 / pointsPerSegment; if (i === controlPoints.length - 2) { pointsPerStep = 1 / (pointsPerSegment - 1); } p = i > 0 ? controlPoints[i - 1] : p0; m0 = mul(sub(p1, p), [0.5, 0.5]); p = i < controlPoints.length - 2 ? controlPoints[i + 2] : p1; m1 = mul(sub(p, p0), [0.5, 0.5]); for (j = u = 0, ref1 = pointsPerSegment; 0 <= ref1 ? u <= ref1 : u >= ref1; j = 0 <= ref1 ? ++u : --u) { t = j * pointsPerStep; fac0 = 2.0 * t * t * t - 3.0 * t * t + 1.0; fac1 = t * t * t - 2.0 * t * t + t; fac2 = -2.0 * t * t * t + 3.0 * t * t; fac3 = t * t * t - t * t; pos = add(mul(p0, [fac0, fac0]), mul(m0, [fac1, fac1]), mul(p1, [fac2, fac2]), mul(m1, [fac3, fac3])); ret[Math.round(pos[0])] = Math.round(clamp(pos[1], lowBound, highBound)); count += 1; } } endX = controlPoints[controlPoints.length - 1][0]; ret = Caman.Calculate.missingValues(ret, endX); return ret; }; Calculate.missingValues = function(values, endX) { var i, j, leftCoord, o, ref, ref1, ref2, ret, rightCoord, u; if (Object.keys(values).length < endX + 1) { ret = {}; for (i = o = 0, ref = endX; 0 <= ref ? o <= ref : o >= ref; i = 0 <= ref ? ++o : --o) { if (values[i] != null) { ret[i] = values[i]; } else { leftCoord = [i - 1, ret[i - 1]]; for (j = u = ref1 = i, ref2 = endX; ref1 <= ref2 ? u <= ref2 : u >= ref2; j = ref1 <= ref2 ? ++u : --u) { if (values[j] != null) { rightCoord = [j, values[j]]; break; } } if (rightCoord) { ret[i] = leftCoord[1] + ((rightCoord[1] - leftCoord[1]) / (rightCoord[0] - leftCoord[0])) * (i - leftCoord[0]); } } } return ret; } return values; }; return Calculate; })(); Calculate = Caman.Calculate; Caman.Convert = (function() { function Convert() {} Convert.hexToRGB = function(hex) { var b, g, r; if (hex.charAt(0) === "#") { hex = hex.substr(1); } r = parseInt(hex.substr(0, 2), 16); g = parseInt(hex.substr(2, 2), 16); b = parseInt(hex.substr(4, 2), 16); return { r: r, g: g, b: b }; }; Convert.rgbToHSL = function(r, g, b) { var d, h, l, max, min, s; if (typeof r === "object") { g = r.g; b = r.b; r = r.r; } r /= 255; g /= 255; b /= 255; max = Math.max(r, g, b); min = Math.min(r, g, b); l = (max + min) / 2; if (max === min) { h = s = 0; } else { d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); h = (function() { switch (max) { case r: return (g - b) / d + (g < b ? 6 : 0); case g: return (b - r) / d + 2; case b: return (r - g) / d + 4; } })(); h /= 6; } return { h: h, s: s, l: l }; }; Convert.hslToRGB = function(h, s, l) { var b, g, p, q, r; if (typeof h === "object") { s = h.s; l = h.l; h = h.h; } if (s === 0) { r = g = b = l; } else { q = l < 0.5 ? l * (1 + s) : l + s - l * s; p = 2 * l - q; r = this.hueToRGB(p, q, h + 1 / 3); g = this.hueToRGB(p, q, h); b = this.hueToRGB(p, q, h - 1 / 3); } return { r: r * 255, g: g * 255, b: b * 255 }; }; Convert.hueToRGB = 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; }; Convert.rgbToHSV = function(r, g, b) { var d, h, max, min, s, v; r /= 255; g /= 255; b /= 255; max = Math.max(r, g, b); min = Math.min(r, g, b); v = max; d = max - min; s = max === 0 ? 0 : d / max; if (max === min) { h = 0; } else { h = (function() { switch (max) { case r: return (g - b) / d + (g < b ? 6 : 0); case g: return (b - r) / d + 2; case b: return (r - g) / d + 4; } })(); h /= 6; } return { h: h, s: s, v: v }; }; Convert.hsvToRGB = function(h, s, v) { var b, f, g, i, p, q, r, t; i = Math.floor(h * 6); f = h * 6 - i; p = v * (1 - s); q = v * (1 - f * s); t = v * (1 - (1 - f) * s); switch (i % 6) { case 0: r = v; g = t; b = p; break; case 1: r = q; g = v; b = p; break; case 2: r = p; g = v; b = t; break; case 3: r = p; g = q; b = v; break; case 4: r = t; g = p; b = v; break; case 5: r = v; g = p; b = q; } return { r: Math.floor(r * 255), g: Math.floor(g * 255), b: Math.floor(b * 255) }; }; Convert.rgbToXYZ = function(r, g, b) { var x, y, z; r /= 255; g /= 255; b /= 255; if (r > 0.04045) { r = Math.pow((r + 0.055) / 1.055, 2.4); } else { r /= 12.92; } if (g > 0.04045) { g = Math.pow((g + 0.055) / 1.055, 2.4); } else { g /= 12.92; } if (b > 0.04045) { b = Math.pow((b + 0.055) / 1.055, 2.4); } else { b /= 12.92; } x = r * 0.4124 + g * 0.3576 + b * 0.1805; y = r * 0.2126 + g * 0.7152 + b * 0.0722; z = r * 0.0193 + g * 0.1192 + b * 0.9505; return { x: x * 100, y: y * 100, z: z * 100 }; }; Convert.xyzToRGB = function(x, y, z) { var b, g, r; x /= 100; y /= 100; z /= 100; r = (3.2406 * x) + (-1.5372 * y) + (-0.4986 * z); g = (-0.9689 * x) + (1.8758 * y) + (0.0415 * z); b = (0.0557 * x) + (-0.2040 * y) + (1.0570 * z); if (r > 0.0031308) { r = (1.055 * Math.pow(r, 0.4166666667)) - 0.055; } else { r *= 12.92; } if (g > 0.0031308) { g = (1.055 * Math.pow(g, 0.4166666667)) - 0.055; } else { g *= 12.92; } if (b > 0.0031308) { b = (1.055 * Math.pow(b, 0.4166666667)) - 0.055; } else { b *= 12.92; } return { r: r * 255, g: g * 255, b: b * 255 }; }; Convert.xyzToLab = function(x, y, z) { var a, b, l, whiteX, whiteY, whiteZ; if (typeof x === "object") { y = x.y; z = x.z; x = x.x; } whiteX = 95.047; whiteY = 100.0; whiteZ = 108.883; x /= whiteX; y /= whiteY; z /= whiteZ; if (x > 0.008856451679) { x = Math.pow(x, 0.3333333333); } else { x = (7.787037037 * x) + 0.1379310345; } if (y > 0.008856451679) { y = Math.pow(y, 0.3333333333); } else { y = (7.787037037 * y) + 0.1379310345; } if (z > 0.008856451679) { z = Math.pow(z, 0.3333333333); } else { z = (7.787037037 * z) + 0.1379310345; } l = 116 * y - 16; a = 500 * (x - y); b = 200 * (y - z); return { l: l, a: a, b: b }; }; Convert.labToXYZ = function(l, a, b) { var x, y, z; if (typeof l === "object") { a = l.a; b = l.b; l = l.l; } y = (l + 16) / 116; x = y + (a / 500); z = y - (b / 200); if (x > 0.2068965517) { x = x * x * x; } else { x = 0.1284185493 * (x - 0.1379310345); } if (y > 0.2068965517) { y = y * y * y; } else { y = 0.1284185493 * (y - 0.1379310345); } if (z > 0.2068965517) { z = z * z * z; } else { z = 0.1284185493 * (z - 0.1379310345); } return { x: x * 95.047, y: y * 100.0, z: z * 108.883 }; }; Convert.rgbToLab = function(r, g, b) { var xyz; if (typeof r === "object") { g = r.g; b = r.b; r = r.r; } xyz = this.rgbToXYZ(r, g, b); return this.xyzToLab(xyz); }; Convert.labToRGB = function(l, a, b) {}; return Convert; })(); Convert = Caman.Convert; Caman.Event = (function() { function Event() {} Event.events = {}; Event.types = ["processStart", "processComplete", "renderStart", "renderFinished", "blockStarted", "blockFinished"]; Event.trigger = function(target, type, data) { var event, len, o, ref, results; if (data == null) { data = null; } if (this.events[type] && this.events[type].length) { ref = this.events[type]; results = []; for (o = 0, len = ref.length; o < len; o++) { event = ref[o]; if (event.target === null || target.id === event.target.id) { results.push(event.fn.call(target, data)); } else { results.push(void 0); } } return results; } }; Event.listen = function(target, type, fn) { var _fn, _type; if (typeof target === "string") { _type = target; _fn = type; target = null; type = _type; fn = _fn; } if (indexOf.call(this.types, type) < 0) { return false; } if (!this.events[type]) { this.events[type] = []; } this.events[type].push({ target: target, fn: fn }); return true; }; return Event; })(); Event = Caman.Event; Caman.Filter = (function() { function Filter() {} Filter.Type = { Single: 1, Kernel: 2, LayerDequeue: 3, LayerFinished: 4, LoadOverlay: 5, Plugin: 6 }; Filter.register = function(name, filterFunc) { return Caman.prototype[name] = filterFunc; }; return Filter; })(); Filter = Caman.Filter; Caman.IO = (function() { function IO() {} IO.domainRegex = /(?:(?:http|https):\/\/)((?:[-|\w]+)\.(?:(?:-|\w|\.)+))/; IO.isRemote = function(img) { if (img == null) { return false; } if (this.corsEnabled(img)) { return false; } return this.isURLRemote(img.src); }; IO.corsEnabled = function(img) { return true; }; IO.isURLRemote = function(url) { var matches; matches = url.match(this.domainRegex); if (matches) { return matches[1] !== document.domain; } else { return false; } }; IO.remoteCheck = function(src) { if (this.isURLRemote(src)) { if (!Caman.remoteProxy.length) { Log.info("Attempting to load a remote image without a configured proxy. URL: " + src); } else { if (Caman.isURLRemote(Caman.remoteProxy)) { Log.info("Cannot use a remote proxy for loading images."); return; } return this.proxyUrl(src); } } }; IO.proxyUrl = function(src) { return Caman.remoteProxy + "?" + Caman.proxyParam + "=" + (encodeURIComponent(src)); }; IO.useProxy = function(lang) { var langToExt; langToExt = { ruby: 'rb', python: 'py', perl: 'pl', javascript: 'js' }; lang = lang.toLowerCase(); if (langToExt[lang] != null) { lang = langToExt[lang]; } return "proxies/caman_proxy." + lang; }; return IO; })(); Caman.prototype.save = function() { if (typeof exports !== "undefined" && exports !== null) { return this.nodeSave.apply(this, arguments); } else { return this.browserSave.apply(this, arguments); } }; Caman.prototype.browserSave = function(type) { var image; if (type == null) { type = "png"; } type = type.toLowerCase(); image = this.toBase64(type).replace("image/" + type, "image/octet-stream"); return document.location.href = image; }; Caman.prototype.nodeSave = function(file, overwrite, callback) { var e, stats; if (overwrite == null) { overwrite = true; } if (callback == null) { callback = null; } try { stats = fs.statSync(file); if (stats.isFile() && !overwrite) { return false; } } catch (error) { e = error; Log.debug("Creating output file " + file); } return fs.writeFile(file, this.canvas.toBuffer(), function(err) { Log.debug("Finished writing to " + file); if (callback) { return callback.call(this, err); } }); }; Caman.prototype.toImage = function(type) { var img; img = new Image(); img.src = this.toBase64(type); img.width = this.dimensions.width; img.height = this.dimensions.height; if (window.devicePixelRatio) { img.width /= window.devicePixelRatio; img.height /= window.devicePixelRatio; } return img; }; Caman.prototype.toBase64 = function(type) { if (type == null) { type = "png"; } type = type.toLowerCase(); return this.renderingCanvas.toDataURL("image/" + type); }; IO = Caman.IO; Caman.Layer = (function() { function Layer(c1) { this.c = c1; this.filter = this.c; this.options = { blendingMode: 'normal', opacity: 1.0 }; this.layerID = Util.uniqid.get(); this.canvas = typeof exports !== "undefined" && exports !== null ? new Canvas() : document.createElement('canvas'); this.canvas.width = this.c.dimensions.width; this.canvas.height = this.c.dimensions.height; this.context = this.canvas.getContext('2d'); this.context.createImageData(this.canvas.width, this.canvas.height); this.imageData = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height); this.pixelData = this.imageData.data; } Layer.prototype.newLayer = function(cb) { return this.c.newLayer.call(this.c, cb); }; Layer.prototype.setBlendingMode = function(mode) { this.options.blendingMode = mode; return this; }; Layer.prototype.opacity = function(opacity) { this.options.opacity = opacity / 100; return this; }; Layer.prototype.copyParent = function() { var i, o, parentData, ref; parentData = this.c.pixelData; for (i = o = 0, ref = this.c.pixelData.length; o < ref; i = o += 4) { this.pixelData[i] = parentData[i]; this.pixelData[i + 1] = parentData[i + 1]; this.pixelData[i + 2] = parentData[i + 2]; this.pixelData[i + 3] = parentData[i + 3]; } return this; }; Layer.prototype.fillColor = function() { return this.c.fillColor.apply(this.c, arguments); }; Layer.prototype.overlayImage = function(image) { if (typeof image === "object") { image = image.src; } else if (typeof image === "string" && image[0] === "#") { image = $(image).src; } if (!image) { return this; } this.c.renderer.renderQueue.push({ type: Filter.Type.LoadOverlay, src: image, layer: this }); return this; }; Layer.prototype.applyToParent = function() { var i, layerData, o, parentData, ref, result, results, rgbaLayer, rgbaParent; parentData = this.c.pixelStack[this.c.pixelStack.length - 1]; layerData = this.c.pixelData; results = []; for (i = o = 0, ref = layerData.length; o < ref; i = o += 4) { rgbaParent = { r: parentData[i], g: parentData[i + 1], b: parentData[i + 2], a: parentData[i + 3] }; rgbaLayer = { r: layerData[i], g: layerData[i + 1], b: layerData[i + 2], a: layerData[i + 3] }; result = Blender.execute(this.options.blendingMode, rgbaLayer, rgbaParent); result.r = Util.clampRGB(result.r); result.g = Util.clampRGB(result.g); result.b = Util.clampRGB(result.b); if (result.a == null) { result.a = rgbaLayer.a; } parentData[i] = rgbaParent.r - ((rgbaParent.r - result.r) * (this.options.opacity * (result.a / 255))); parentData[i + 1] = rgbaParent.g - ((rgbaParent.g - result.g) * (this.options.opacity * (result.a / 255))); results.push(parentData[i + 2] = rgbaParent.b - ((rgbaParent.b - result.b) * (this.options.opacity * (result.a / 255)))); } return results; }; return Layer; })(); Layer = Caman.Layer; Caman.Logger = (function() { function Logger() { var len, name, o, ref; ref = ['log', 'info', 'warn', 'error']; for (o = 0, len = ref.length; o < len; o++) { name = ref[o]; this[name] = (function(name) { return function() { var args, e; args = 1 <= arguments.length ? slice1.call(arguments, 0) : []; if (!Caman.DEBUG) { return; } try { return console[name].apply(console, args); } catch (error) { e = error; return console[name](args); } }; })(name); } this.debug = this.log; } return Logger; })(); Log = new Caman.Logger(); Caman.Pixel = (function() { Pixel.coordinatesToLocation = function(x, y, width) { return (y * width + x) * 4; }; Pixel.locationToCoordinates = function(loc, width) { var x, y; y = Math.floor(loc / (width * 4)); x = (loc % (width * 4)) / 4; return { x: x, y: y }; }; function Pixel(r1, g1, b1, a1, c1) { this.r = r1 != null ? r1 : 0; this.g = g1 != null ? g1 : 0; this.b = b1 != null ? b1 : 0; this.a = a1 != null ? a1 : 255; this.c = c1 != null ? c1 : null; this.loc = 0; } Pixel.prototype.setContext = function(c) { return this.c = c; }; Pixel.prototype.locationXY = function() { var x, y; if (this.c == null) { throw "Requires a CamanJS context"; } y = this.c.dimensions.height - Math.floor(this.loc / (this.c.dimensions.width * 4)); x = (this.loc % (this.c.dimensions.width * 4)) / 4; return { x: x, y: y }; }; Pixel.prototype.pixelAtLocation = function(loc) { if (this.c == null) { throw "Requires a CamanJS context"; } return new Pixel(this.c.pixelData[loc], this.c.pixelData[loc + 1], this.c.pixelData[loc + 2], this.c.pixelData[loc + 3], this.c); }; Pixel.prototype.getPixelRelative = function(horiz, vert) { var newLoc; if (this.c == null) { throw "Requires a CamanJS context"; } newLoc = this.loc + (this.c.dimensions.width * 4 * (vert * -1)) + (4 * horiz); if (newLoc > this.c.pixelData.length || newLoc < 0) { return new Pixel(0, 0, 0, 255, this.c); } return this.pixelAtLocation(newLoc); }; Pixel.prototype.putPixelRelative = function(horiz, vert, rgba) { var nowLoc; if (this.c == null) { throw "Requires a CamanJS context"; } nowLoc = this.loc + (this.c.dimensions.width * 4 * (vert * -1)) + (4 * horiz); if (newLoc > this.c.pixelData.length || newLoc < 0) { return; } this.c.pixelData[newLoc] = rgba.r; this.c.pixelData[newLoc + 1] = rgba.g; this.c.pixelData[newLoc + 2] = rgba.b; this.c.pixelData[newLoc + 3] = rgba.a; return true; }; Pixel.prototype.getPixel = function(x, y) { var loc; if (this.c == null) { throw "Requires a CamanJS context"; } loc = this.coordinatesToLocation(x, y, this.width); return this.pixelAtLocation(loc); }; Pixel.prototype.putPixel = function(x, y, rgba) { var loc; if (this.c == null) { throw "Requires a CamanJS context"; } loc = this.coordinatesToLocation(x, y, this.width); this.c.pixelData[loc] = rgba.r; this.c.pixelData[loc + 1] = rgba.g; this.c.pixelData[loc + 2] = rgba.b; return this.c.pixelData[loc + 3] = rgba.a; }; Pixel.prototype.toString = function() { return this.toKey(); }; Pixel.prototype.toHex = function(includeAlpha) { var hex; if (includeAlpha == null) { includeAlpha = false; } hex = '#' + this.r.toString(16) + this.g.toString(16) + this.b.toString(16); if (includeAlpha) { return hex + this.a.toString(16); } else { return hex; } }; return Pixel; })(); Pixel = Caman.Pixel; Caman.Plugin = (function() { function Plugin() {} Plugin.plugins = {}; Plugin.register = function(name, plugin) { return this.plugins[name] = plugin; }; Plugin.execute = function(context, name, args) { return this.plugins[name].apply(context, args); }; return Plugin; })(); Plugin = Caman.Plugin; Caman.Renderer = (function() { Renderer.Blocks = Caman.NodeJS ? require('os').cpus().length : 4; function Renderer(c1) { this.c = c1; this.processNext = bind(this.processNext, this); this.renderQueue = []; this.modPixelData = null; } Renderer.prototype.add = function(job) { if (job == null) { return; } return this.renderQueue.push(job); }; Renderer.prototype.processNext = function() { var layer; if (this.renderQueue.length === 0) { Event.trigger(this, "renderFinished"); if (this.finishedFn != null) { this.finishedFn.call(this.c); } return this; } this.currentJob = this.renderQueue.shift(); switch (this.currentJob.type) { case Filter.Type.LayerDequeue: layer = this.c.canvasQueue.shift(); this.c.executeLayer(layer); return this.processNext(); case Filter.Type.LayerFinished: this.c.applyCurrentLayer(); this.c.popContext(); return this.processNext(); case Filter.Type.LoadOverlay: return this.loadOverlay(this.currentJob.layer, this.currentJob.src); case Filter.Type.Plugin: return this.executePlugin(); default: return this.executeFilter(); } }; Renderer.prototype.execute = function(callback) { this.finishedFn = callback; this.modPixelData = Util.dataArray(this.c.pixelData.length); return this.processNext(); }; Renderer.prototype.eachBlock = function(fn) { var blockN, blockPixelLength, bnum, end, f, i, lastBlockN, n, o, ref, results, start; this.blocksDone = 0; n = this.c.pixelData.length; blockPixelLength = Math.floor((n / 4) / Renderer.Blocks); blockN = blockPixelLength * 4; lastBlockN = blockN + ((n / 4) % Renderer.Blocks) * 4; results = []; for (i = o = 0, ref = Renderer.Blocks; 0 <= ref ? o < ref : o > ref; i = 0 <= ref ? ++o : --o) { start = i * blockN; end = start + (i === Renderer.Blocks - 1 ? lastBlockN : blockN); if (Caman.NodeJS) { f = Fiber((function(_this) { return function() { return fn.call(_this, i, start, end); }; })(this)); bnum = f.run(); results.push(this.blockFinished(bnum)); } else { results.push(setTimeout((function(_this) { return function(i, start, end) { return function() { return fn.call(_this, i, start, end); }; }; })(this)(i, start, end), 0)); } } return results; }; Renderer.prototype.executeFilter = function() { Event.trigger(this.c, "processStart", this.currentJob); if (this.currentJob.type === Filter.Type.Single) { return this.eachBlock(this.renderBlock); } else { return this.eachBlock(this.renderKernel); } }; Renderer.prototype.executePlugin = function() { Log.debug("Executing plugin " + this.currentJob.plugin); Plugin.execute(this.c, this.currentJob.plugin, this.currentJob.args); Log.debug("Plugin " + this.currentJob.plugin + " finished!"); return this.processNext(); }; Renderer.prototype.renderBlock = function(bnum, start, end) { var i, o, pixel, ref, ref1; Log.debug("Block #" + bnum + " - Filter: " + this.currentJob.name + ", Start: " + start + ", End: " + end); Event.trigger(this.c, "blockStarted", { blockNum: bnum, totalBlocks: Renderer.Blocks, startPixel: start, endPixel: end }); pixel = new Pixel(); pixel.setContext(this.c); for (i = o = ref = start, ref1 = end; o < ref1; i = o += 4) { pixel.loc = i; pixel.r = this.c.pixelData[i]; pixel.g = this.c.pixelData[i + 1]; pixel.b = this.c.pixelData[i + 2]; pixel.a = this.c.pixelData[i + 3]; if (this.currentJob.processFn) { this.currentJob.processFn(pixel); } this.c.pixelData[i] = Util.clampRGB(pixel.r); this.c.pixelData[i + 1] = Util.clampRGB(pixel.g); this.c.pixelData[i + 2] = Util.clampRGB(pixel.b); this.c.pixelData[i + 3] = Util.clampRGB(pixel.a); } if (Caman.NodeJS) { return Fiber["yield"](bnum); } else { return this.blockFinished(bnum); } }; Renderer.prototype.renderKernel = function(bnum, start, end) { var adjust, adjustSize, bias, builder, builderIndex, divisor, i, j, k, kernel, n, name, o, p, pixel, ref, ref1, ref2, ref3, ref4, ref5, res, u, w; name = this.currentJob.name; bias = this.currentJob.bias; divisor = this.currentJob.divisor; n = this.c.pixelData.length; adjust = this.currentJob.adjust; if (!adjust) { this.blockFinished(bnum); return; } adjustSize = Math.sqrt(adjust.length); kernel = []; Log.debug("Rendering kernel - Filter: " + this.currentJob.name); start = Math.max(start, this.c.dimensions.width * 4 * ((adjustSize - 1) / 2)); end = Math.min(end, n - (this.c.dimensions.width * 4 * ((adjustSize - 1) / 2))); builder = (adjustSize - 1) / 2; pixel = new Pixel(); pixel.setContext(this.c); for (i = o = ref = start, ref1 = end; o < ref1; i = o += 4) { pixel.loc = i; builderIndex = 0; for (j = u = ref2 = -builder, ref3 = builder; ref2 <= ref3 ? u <= ref3 : u >= ref3; j = ref2 <= ref3 ? ++u : --u) { for (k = w = ref4 = builder, ref5 = -builder; ref4 <= ref5 ? w <= ref5 : w >= ref5; k = ref4 <= ref5 ? ++w : --w) { p = pixel.getPixelRelative(j, k); kernel[builderIndex * 3] = p.r; kernel[builderIndex * 3 + 1] = p.g; kernel[builderIndex * 3 + 2] = p.b; builderIndex++; } } res = this.processKernel(adjust, kernel, divisor, bias); this.modPixelData[i] = Util.clampRGB(res.r); this.modPixelData[i + 1] = Util.clampRGB(res.g); this.modPixelData[i + 2] = Util.clampRGB(res.b); this.modPixelData[i + 3] = this.c.pixelData[i + 3]; } if (Caman.NodeJS) { return Fiber["yield"](bnum); } else { return this.blockFinished(bnum); } }; Renderer.prototype.blockFinished = function(bnum) { var i, o, ref; if (bnum >= 0) { Log.debug("Block #" + bnum + " finished! Filter: " + this.currentJob.name); } this.blocksDone++; Event.trigger(this.c, "blockFinished", { blockNum: bnum, blocksFinished: this.blocksDone, totalBlocks: Renderer.Blocks }); if (this.blocksDone === Renderer.Blocks) { if (this.currentJob.type === Filter.Type.Kernel) { for (i = o = 0, ref = this.c.pixelData.length; 0 <= ref ? o < ref : o > ref; i = 0 <= ref ? ++o : --o) { this.c.pixelData[i] = this.modPixelData[i]; } } if (bnum >= 0) { Log.debug("Filter " + this.currentJob.name + " finished!"); } Event.trigger(this.c, "processComplete", this.currentJob); return this.processNext(); } }; Renderer.prototype.processKernel = function(adjust, kernel, divisor, bias) { var i, o, ref, val; val = { r: 0, g: 0, b: 0 }; for (i = o = 0, ref = adjust.length; 0 <= ref ? o < ref : o > ref; i = 0 <= ref ? ++o : --o) { val.r += adjust[i] * kernel[i * 3]; val.g += adjust[i] * kernel[i * 3 + 1]; val.b += adjust[i] * kernel[i * 3 + 2]; } val.r = (val.r / divisor) + bias; val.g = (val.g / divisor) + bias; val.b = (val.b / divisor) + bias; return val; }; Renderer.prototype.loadOverlay = function(layer, src) { var img, proxyUrl; img = new Image(); img.onload = (function(_this) { return function() { layer.context.drawImage(img, 0, 0, _this.c.dimensions.width, _this.c.dimensions.height); layer.imageData = layer.context.getImageData(0, 0, _this.c.dimensions.width, _this.c.dimensions.height); layer.pixelData = layer.imageData.data; _this.c.pixelData = layer.pixelData; return _this.processNext(); }; })(this); proxyUrl = IO.remoteCheck(src); return img.src = proxyUrl != null ? proxyUrl : src; }; return Renderer; })(); Renderer = Caman.Renderer; Caman.Store = (function() { function Store() {} Store.items = {}; Store.has = function(search) { return this.items[search] != null; }; Store.get = function(search) { return this.items[search]; }; Store.put = function(name, obj) { return this.items[name] = obj; }; Store.execute = function(search, callback) { setTimeout((function(_this) { return function() { return callback.call(_this.get(search), _this.get(search)); }; })(this), 0); return this.get(search); }; Store.flush = function(name) { if (name == null) { name = false; } if (name) { return delete this.items[name]; } else { return this.items = {}; } }; return Store; })(); Store = Caman.Store; Blender.register("normal", function(rgbaLayer, rgbaParent) { return { r: rgbaLayer.r, g: rgbaLayer.g, b: rgbaLayer.b }; }); Blender.register("multiply", function(rgbaLayer, rgbaParent) { return { r: (rgbaLayer.r * rgbaParent.r) / 255, g: (rgbaLayer.g * rgbaParent.g) / 255, b: (rgbaLayer.b * rgbaParent.b) / 255 }; }); Blender.register("screen", function(rgbaLayer, rgbaParent) { return { r: 255 - (((255 - rgbaLayer.r) * (255 - rgbaParent.r)) / 255), g: 255 - (((255 - rgbaLayer.g) * (255 - rgbaParent.g)) / 255), b: 255 - (((255 - rgbaLayer.b) * (255 - rgbaParent.b)) / 255) }; }); Blender.register("overlay", function(rgbaLayer, rgbaParent) { var result; result = {}; result.r = rgbaParent.r > 128 ? 255 - 2 * (255 - rgbaLayer.r) * (255 - rgbaParent.r) / 255 : (rgbaParent.r * rgbaLayer.r * 2) / 255; result.g = rgbaParent.g > 128 ? 255 - 2 * (255 - rgbaLayer.g) * (255 - rgbaParent.g) / 255 : (rgbaParent.g * rgbaLayer.g * 2) / 255; result.b = rgbaParent.b > 128 ? 255 - 2 * (255 - rgbaLayer.b) * (255 - rgbaParent.b) / 255 : (rgbaParent.b * rgbaLayer.b * 2) / 255; return result; }); Blender.register("difference", function(rgbaLayer, rgbaParent) { return { r: rgbaLayer.r - rgbaParent.r, g: rgbaLayer.g - rgbaParent.g, b: rgbaLayer.b - rgbaParent.b }; }); Blender.register("addition", function(rgbaLayer, rgbaParent) { return { r: rgbaParent.r + rgbaLayer.r, g: rgbaParent.g + rgbaLayer.g, b: rgbaParent.b + rgbaLayer.b }; }); Blender.register("exclusion", function(rgbaLayer, rgbaParent) { return { r: 128 - 2 * (rgbaParent.r - 128) * (rgbaLayer.r - 128) / 255, g: 128 - 2 * (rgbaParent.g - 128) * (rgbaLayer.g - 128) / 255, b: 128 - 2 * (rgbaParent.b - 128) * (rgbaLayer.b - 128) / 255 }; }); Blender.register("softLight", function(rgbaLayer, rgbaParent) { var result; result = {}; result.r = rgbaParent.r > 128 ? 255 - ((255 - rgbaParent.r) * (255 - (rgbaLayer.r - 128))) / 255 : (rgbaParent.r * (rgbaLayer.r + 128)) / 255; result.g = rgbaParent.g > 128 ? 255 - ((255 - rgbaParent.g) * (255 - (rgbaLayer.g - 128))) / 255 : (rgbaParent.g * (rgbaLayer.g + 128)) / 255; result.b = rgbaParent.b > 128 ? 255 - ((255 - rgbaParent.b) * (255 - (rgbaLayer.b - 128))) / 255 : (rgbaParent.b * (rgbaLayer.b + 128)) / 255; return result; }); Blender.register("lighten", function(rgbaLayer, rgbaParent) { return { r: rgbaParent.r > rgbaLayer.r ? rgbaParent.r : rgbaLayer.r, g: rgbaParent.g > rgbaLayer.g ? rgbaParent.g : rgbaLayer.g, b: rgbaParent.b > rgbaLayer.b ? rgbaParent.b : rgbaLayer.b }; }); Blender.register("darken", function(rgbaLayer, rgbaParent) { return { r: rgbaParent.r > rgbaLayer.r ? rgbaLayer.r : rgbaParent.r, g: rgbaParent.g > rgbaLayer.g ? rgbaLayer.g : rgbaParent.g, b: rgbaParent.b > rgbaLayer.b ? rgbaLayer.b : rgbaParent.b }; }); Filter.register("fillColor", function() { var color; if (arguments.length === 1) { color = Convert.hexToRGB(arguments[0]); } else { color = { r: arguments[0], g: arguments[1], b: arguments[2] }; } return this.process("fillColor", function(rgba) { rgba.r = color.r; rgba.g = color.g; rgba.b = color.b; rgba.a = 255; return rgba; }); }); Filter.register("brightness", function(adjust) { adjust = Math.floor(255 * (adjust / 100)); return this.process("brightness", function(rgba) { rgba.r += adjust; rgba.g += adjust; rgba.b += adjust; return rgba; }); }); Filter.register("saturation", function(adjust) { adjust *= -0.01; return this.process("saturation", function(rgba) { var max; max = Math.max(rgba.r, rgba.g, rgba.b); if (rgba.r !== max) { rgba.r += (max - rgba.r) * adjust; } if (rgba.g !== max) { rgba.g += (max - rgba.g) * adjust; } if (rgba.b !== max) { rgba.b += (max - rgba.b) * adjust; } return rgba; }); }); Filter.register("vibrance", function(adjust) { adjust *= -1; return this.process("vibrance", function(rgba) { var amt, avg, max; max = Math.max(rgba.r, rgba.g, rgba.b); avg = (rgba.r + rgba.g + rgba.b) / 3; amt = ((Math.abs(max - avg) * 2 / 255) * adjust) / 100; if (rgba.r !== max) { rgba.r += (max - rgba.r) * amt; } if (rgba.g !== max) { rgba.g += (max - rgba.g) * amt; } if (rgba.b !== max) { rgba.b += (max - rgba.b) * amt; } return rgba; }); }); Filter.register("greyscale", function(adjust) { return this.process("greyscale", function(rgba) { var avg; avg = Calculate.luminance(rgba); rgba.r = avg; rgba.g = avg; rgba.b = avg; return rgba; }); }); Filter.register("contrast", function(adjust) { adjust = Math.pow((adjust + 100) / 100, 2); return this.process("contrast", function(rgba) { rgba.r /= 255; rgba.r -= 0.5; rgba.r *= adjust; rgba.r += 0.5; rgba.r *= 255; rgba.g /= 255; rgba.g -= 0.5; rgba.g *= adjust; rgba.g += 0.5; rgba.g *= 255; rgba.b /= 255; rgba.b -= 0.5; rgba.b *= adjust; rgba.b += 0.5; rgba.b *= 255; return rgba; }); }); Filter.register("hue", function(adjust) { return this.process("hue", function(rgba) { var b, g, h, hsv, r, ref; hsv = Convert.rgbToHSV(rgba.r, rgba.g, rgba.b); h = hsv.h * 100; h += Math.abs(adjust); h = h % 100; h /= 100; hsv.h = h; ref = Convert.hsvToRGB(hsv.h, hsv.s, hsv.v), r = ref.r, g = ref.g, b = ref.b; rgba.r = r; rgba.g = g; rgba.b = b; return rgba; }); }); Filter.register("colorize", function() { var level, rgb; if (arguments.length === 2) { rgb = Convert.hexToRGB(arguments[0]); level = arguments[1]; } else if (arguments.length === 4) { rgb = { r: arguments[0], g: arguments[1], b: arguments[2] }; level = arguments[3]; } return this.process("colorize", function(rgba) { rgba.r -= (rgba.r - rgb.r) * (level / 100); rgba.g -= (rgba.g - rgb.g) * (level / 100); rgba.b -= (rgba.b - rgb.b) * (level / 100); return rgba; }); }); Filter.register("invert", function() { return this.process("invert", function(rgba) { rgba.r = 255 - rgba.r; rgba.g = 255 - rgba.g; rgba.b = 255 - rgba.b; return rgba; }); }); Filter.register("sepia", function(adjust) { if (adjust == null) { adjust = 100; } adjust /= 100; return this.process("sepia", function(rgba) { rgba.r = Math.min(255, (rgba.r * (1 - (0.607 * adjust))) + (rgba.g * (0.769 * adjust)) + (rgba.b * (0.189 * adjust))); rgba.g = Math.min(255, (rgba.r * (0.349 * adjust)) + (rgba.g * (1 - (0.314 * adjust))) + (rgba.b * (0.168 * adjust))); rgba.b = Math.min(255, (rgba.r * (0.272 * adjust)) + (rgba.g * (0.534 * adjust)) + (rgba.b * (1 - (0.869 * adjust)))); return rgba; }); }); Filter.register("gamma", function(adjust) { return this.process("gamma", function(rgba) { rgba.r = Math.pow(rgba.r / 255, adjust) * 255; rgba.g = Math.pow(rgba.g / 255, adjust) * 255; rgba.b = Math.pow(rgba.b / 255, adjust) * 255; return rgba; }); }); Filter.register("noise", function(adjust) { adjust = Math.abs(adjust) * 2.55; return this.process("noise", function(rgba) { var rand; rand = Calculate.randomRange(adjust * -1, adjust); rgba.r += rand; rgba.g += rand; rgba.b += rand; return rgba; }); }); Filter.register("clip", function(adjust) { adjust = Math.abs(adjust) * 2.55; return this.process("clip", function(rgba) { if (rgba.r > 255 - adjust) { rgba.r = 255; } else if (rgba.r < adjust) { rgba.r = 0; } if (rgba.g > 255 - adjust) { rgba.g = 255; } else if (rgba.g < adjust) { rgba.g = 0; } if (rgba.b > 255 - adjust) { rgba.b = 255; } else if (rgba.b < adjust) { rgba.b = 0; } return rgba; }); }); Filter.register("channels", function(options) { var chan, value; if (typeof options !== "object") { return this; } for (chan in options) { if (!hasProp.call(options, chan)) continue; value = options[chan]; if (value === 0) { delete options[chan]; continue; } options[chan] /= 100; } if (options.length === 0) { return this; } return this.process("channels", function(rgba) { if (options.red != null) { if (options.red > 0) { rgba.r += (255 - rgba.r) * options.red; } else { rgba.r -= rgba.r * Math.abs(options.red); } } if (options.green != null) { if (options.green > 0) { rgba.g += (255 - rgba.g) * options.green; } else { rgba.g -= rgba.g * Math.abs(options.green); } } if (options.blue != null) { if (options.blue > 0) { rgba.b += (255 - rgba.b) * options.blue; } else { rgba.b -= rgba.b * Math.abs(options.blue); } } return rgba; }); }); Filter.register("curves", function() { var algo, bezier, chans, cps, end, i, last, o, ref, ref1, start, u; chans = arguments[0], cps = 2 <= arguments.length ? slice1.call(arguments, 1) : []; last = cps[cps.length - 1]; if (typeof last === "function") { algo = last; cps.pop(); } else if (typeof last === "string") { algo = Calculate[last]; cps.pop(); } else { algo = Calculate.bezier; } if (typeof chans === "string") { chans = chans.split(""); } if (chans[0] === "v") { chans = ['r', 'g', 'b']; } if (cps.length < 2) { throw "Invalid number of arguments to curves filter"; } bezier = algo(cps, 0, 255); start = cps[0]; if (start[0] > 0) { for (i = o = 0, ref = start[0]; 0 <= ref ? o < ref : o > ref; i = 0 <= ref ? ++o : --o) { bezier[i] = start[1]; } } end = cps[cps.length - 1]; if (end[0] < 255) { for (i = u = ref1 = end[0]; ref1 <= 255 ? u <= 255 : u >= 255; i = ref1 <= 255 ? ++u : --u) { bezier[i] = end[1]; } } return this.process("curves", function(rgba) { var ref2, w; for (i = w = 0, ref2 = chans.length; 0 <= ref2 ? w < ref2 : w > ref2; i = 0 <= ref2 ? ++w : --w) { rgba[chans[i]] = bezier[rgba[chans[i]]]; } return rgba; }); }); Filter.register("exposure", function(adjust) { var ctrl1, ctrl2, p; p = Math.abs(adjust) / 100; ctrl1 = [0, 255 * p]; ctrl2 = [255 - (255 * p), 255]; if (adjust < 0) { ctrl1 = ctrl1.reverse(); ctrl2 = ctrl2.reverse(); } return this.curves('rgb', [0, 0], ctrl1, ctrl2, [255, 255]); }); Caman.Plugin.register("crop", function(width, height, x, y) { var canvas, ctx; if (x == null) { x = 0; } if (y == null) { y = 0; } if (typeof exports !== "undefined" && exports !== null) { canvas = new Canvas(width, height); } else { canvas = document.createElement('canvas'); Util.copyAttributes(this.canvas, canvas); canvas.width = width; canvas.height = height; } ctx = canvas.getContext('2d'); ctx.drawImage(this.canvas, x, y, width, height, 0, 0, width, height); this.cropCoordinates = { x: x, y: y }; this.cropped = true; return this.replaceCanvas(canvas); }); Caman.Plugin.register("resize", function(newDims) { var canvas, ctx; if (newDims == null) { newDims = null; } if (newDims === null || ((newDims.width == null) && (newDims.height == null))) { Log.error("Invalid or missing dimensions given for resize"); return; } if (newDims.width == null) { newDims.width = this.canvas.width * newDims.height / this.canvas.height; } else if (newDims.height == null) { newDims.height = this.canvas.height * newDims.width / this.canvas.width; } if (typeof exports !== "undefined" && exports !== null) { canvas = new Canvas(newDims.width, newDims.height); } else { canvas = document.createElement('canvas'); Util.copyAttributes(this.canvas, canvas); canvas.width = newDims.width; canvas.height = newDims.height; } ctx = canvas.getContext('2d'); ctx.drawImage(this.canvas, 0, 0, this.canvas.width, this.canvas.height, 0, 0, newDims.width, newDims.height); this.resized = true; return this.replaceCanvas(canvas); }); Caman.Filter.register("crop", function() { return this.processPlugin("crop", Array.prototype.slice.call(arguments, 0)); }); Caman.Filter.register("resize", function() { return this.processPlugin("resize", Array.prototype.slice.call(arguments, 0)); }); Caman.Filter.register("boxBlur", function() { return this.processKernel("Box Blur", [1, 1, 1, 1, 1, 1, 1, 1, 1]); }); Caman.Filter.register("heavyRadialBlur", function() { return this.processKernel("Heavy Radial Blur", [0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0]); }); Caman.Filter.register("gaussianBlur", function() { return this.processKernel("Gaussian Blur", [1, 4, 6, 4, 1, 4, 16, 24, 16, 4, 6, 24, 36, 24, 6, 4, 16, 24, 16, 4, 1, 4, 6, 4, 1]); }); Caman.Filter.register("motionBlur", function(degrees) { var kernel; if (degrees === 0 || degrees === 180) { kernel = [0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0]; } else if ((degrees > 0 && degrees < 90) || (degrees > 180 && degrees < 270)) { kernel = [0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0]; } else if (degrees === 90 || degrees === 270) { kernel = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; } else { kernel = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1]; } return this.processKernel("Motion Blur", kernel); }); Caman.Filter.register("sharpen", function(amt) { if (amt == null) { amt = 100; } amt /= 100; return this.processKernel("Sharpen", [0, -amt, 0, -amt, 4 * amt + 1, -amt, 0, -amt, 0]); }); vignetteFilters = { brightness: function(rgba, amt, opts) { rgba.r = rgba.r - (rgba.r * amt * opts.strength); rgba.g = rgba.g - (rgba.g * amt * opts.strength); rgba.b = rgba.b - (rgba.b * amt * opts.strength); return rgba; }, gamma: function(rgba, amt, opts) { rgba.r = Math.pow(rgba.r / 255, Math.max(10 * amt * opts.strength, 1)) * 255; rgba.g = Math.pow(rgba.g / 255, Math.max(10 * amt * opts.strength, 1)) * 255; rgba.b = Math.pow(rgba.b / 255, Math.max(10 * amt * opts.strength, 1)) * 255; return rgba; }, colorize: function(rgba, amt, opts) { rgba.r -= (rgba.r - opts.color.r) * amt; rgba.g -= (rgba.g - opts.color.g) * amt; rgba.b -= (rgba.b - opts.color.b) * amt; return rgba; } }; Filter.register("vignette", function(size, strength) { var bezier, center, end, start; if (strength == null) { strength = 60; } if (typeof size === "string" && size.substr(-1) === "%") { if (this.dimensions.height > this.dimensions.width) { size = this.dimensions.width * (parseInt(size.substr(0, size.length - 1), 10) / 100); } else { size = this.dimensions.height * (parseInt(size.substr(0, size.length - 1), 10) / 100); } } strength /= 100; center = [this.dimensions.width / 2, this.dimensions.height / 2]; start = Math.sqrt(Math.pow(center[0], 2) + Math.pow(center[1], 2)); end = start - size; bezier = Calculate.bezier([0, 1], [30, 30], [70, 60], [100, 80]); return this.process("vignette", function(rgba) { var dist, div, loc; loc = rgba.locationXY(); dist = Calculate.distance(loc.x, loc.y, center[0], center[1]); if (dist > end) { div = Math.max(1, (bezier[Math.round(((dist - end) / size) * 100)] / 10) * strength); rgba.r = Math.pow(rgba.r / 255, div) * 255; rgba.g = Math.pow(rgba.g / 255, div) * 255; rgba.b = Math.pow(rgba.b / 255, div) * 255; } return rgba; }); }); Filter.register("rectangularVignette", function(opts) { var defaults, dim, len, o, percent, ref, size; defaults = { strength: 50, cornerRadius: 0, method: 'brightness', color: { r: 0, g: 0, b: 0 } }; opts = Util.extend(defaults, opts); if (!opts.size) { return this; } else if (typeof opts.size === "string") { percent = parseInt(opts.size, 10) / 100; opts.size = { width: this.dimensions.width * percent, height: this.dimensions.height * percent }; } else if (typeof opts.size === "object") { ref = ["width", "height"]; for (o = 0, len = ref.length; o < len; o++) { dim = ref[o]; if (typeof opts.size[dim] === "string") { opts.size[dim] = this.dimensions[dim] * (parseInt(opts.size[dim], 10) / 100); } } } else if (opts.size === "number") { size = opts.size; opts.size = { width: size, height: size }; } if (typeof opts.cornerRadius === "string") { opts.cornerRadius = (opts.size.width / 2) * (parseInt(opts.cornerRadius, 10) / 100); } opts.strength /= 100; opts.size.width = Math.floor(opts.size.width); opts.size.height = Math.floor(opts.size.height); opts.image = { width: this.dimensions.width, height: this.dimensions.height }; if (opts.method === "colorize" && typeof opts.color === "string") { opts.color = Convert.hexToRGB(opts.color); } opts.coords = { left: (this.dimensions.width - opts.size.width) / 2, right: this.dimensions.width - opts.coords.left, bottom: (this.dimensions.height - opts.size.height) / 2, top: this.dimensions.height - opts.coords.bottom }; opts.corners = [ { x: opts.coords.left + opts.cornerRadius, y: opts.coords.top - opts.cornerRadius }, { x: opts.coords.right - opts.cornerRadius, y: opts.coords.top - opts.cornerRadius }, { x: opts.coords.right - opts.cornerRadius, y: opts.coords.bottom + opts.cornerRadius }, { x: opts.coords.left + opts.cornerRadius, y: opts.coords.bottom + opts.cornerRadius } ]; opts.maxDist = Calculate.distance(0, 0, opts.corners[3].x, opts.corners[3].y) - opts.cornerRadius; return this.process("rectangularVignette", function(rgba) { var amt, loc, radialDist; loc = rgba.locationXY(); if ((loc.x > opts.corners[0].x && loc.x < opts.corners[1].x) && (loc.y > opts.coords.bottom && loc.y < opts.coords.top)) { return rgba; } if ((loc.x > opts.coords.left && loc.x < opts.coords.right) && (loc.y > opts.corners[3].y && loc.y < opts.corners[2].y)) { return rgba; } if (loc.x > opts.corners[0].x && loc.x < opts.corners[1].x && loc.y > opts.coords.top) { amt = (loc.y - opts.coords.top) / opts.maxDist; } else if (loc.y > opts.corners[2].y && loc.y < opts.corners[1].y && loc.x > opts.coords.right) { amt = (loc.x - opts.coords.right) / opts.maxDist; } else if (loc.x > opts.corners[0].x && loc.x < opts.corners[1].x && loc.y < opts.coords.bottom) { amt = (opts.coords.bottom - loc.y) / opts.maxDist; } else if (loc.y > opts.corners[2].y && loc.y < opts.corners[1].y && loc.x < opts.coords.left) { amt = (opts.coords.left - loc.x) / opts.maxDist; } else if (loc.x <= opts.corners[0].x && loc.y >= opts.corners[0].y) { radialDist = Caman.distance(loc.x, loc.y, opts.corners[0].x, opts.corners[0].y); amt = (radialDist - opts.cornerRadius) / opts.maxDist; } else if (loc.x >= opts.corners[1].x && loc.y >= opts.corners[1].y) { radialDist = Caman.distance(loc.x, loc.y, opts.corners[1].x, opts.corners[1].y); amt = (radialDist - opts.cornerRadius) / opts.maxDist; } else if (loc.x >= opts.corners[2].x && loc.y <= opts.corners[2].y) { radialDist = Caman.distance(loc.x, loc.y, opts.corners[2].x, opts.corners[2].y); amt = (radialDist - opts.cornerRadius) / opts.maxDist; } else if (loc.x <= opts.corners[3].x && loc.y <= opts.corners[3].y) { radialDist = Caman.distance(loc.x, loc.y, opts.corners[3].x, opts.corners[3].y); amt = (radialDist - opts.cornerRadius) / opts.maxDist; } if (amt < 0) { return rgba; } return vignetteFilters[opts.method](rgba, amt, opts); }); }); /* CompoundBlur - Blurring with varying radii for Canvas Version: 0.1 Author: Mario Klingemann Contact: mario@quasimondo.com Website: http://www.quasimondo.com/StackBlurForCanvas Twitter: @quasimondo Modified By: Ryan LeFevre (@meltingice) In case you find this class useful - especially in commercial projects - I am not totally unhappy for a small donation to my PayPal account mario@quasimondo.de Copyright (c) 2011 Mario Klingemann Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ (function() { var BlurStack, getLinearGradientMap, getRadialGradientMap, mul_table, shg_table; mul_table = [512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512, 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512, 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456, 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512, 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328, 320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456, 446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335, 329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512, 505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405, 399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328, 324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271, 268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456, 451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388, 385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335, 332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292, 289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259]; shg_table = [9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24]; getLinearGradientMap = function(width, height, centerX, centerY, angle, length, mirrored) { var cnv, context, gradient, x1, x2, y1, y2; cnv = typeof exports !== "undefined" && exports !== null ? new Canvas() : document.createElement('canvas'); cnv.width = width; cnv.height = height; x1 = centerX + Math.cos(angle) * length * 0.5; y1 = centerY + Math.sin(angle) * length * 0.5; x2 = centerX - Math.cos(angle) * length * 0.5; y2 = centerY - Math.sin(angle) * length * 0.5; context = cnv.getContext("2d"); gradient = context.createLinearGradient(x1, y1, x2, y2); if (!mirrored) { gradient.addColorStop(0, "white"); gradient.addColorStop(1, "black"); } else { gradient.addColorStop(0, "white"); gradient.addColorStop(0.5, "black"); gradient.addColorStop(1, "white"); } context.fillStyle = gradient; context.fillRect(0, 0, width, height); return context.getImageData(0, 0, width, height); }; getRadialGradientMap = function(width, height, centerX, centerY, radius1, radius2) { var cnv, context, gradient; cnv = typeof exports !== "undefined" && exports !== null ? new Canvas() : document.createElement('canvas'); cnv.width = width; cnv.height = height; context = cnv.getContext("2d"); gradient = context.createRadialGradient(centerX, centerY, radius1, centerX, centerY, radius2); gradient.addColorStop(1, "white"); gradient.addColorStop(0, "black"); context.fillStyle = gradient; context.fillRect(0, 0, width, height); return context.getImageData(0, 0, width, height); }; BlurStack = function() { this.r = 0; this.g = 0; this.b = 0; this.a = 0; return this.next = null; }; Caman.Plugin.register("compoundBlur", function(radiusData, radius, increaseFactor, blurLevels) { var b_in_sum, b_out_sum, b_sum, blend, currentIndex, div, g_in_sum, g_out_sum, g_sum, height, heightMinus1, i, i1, iblend, idx, imagePixels, index, iradius, j1, k1, l1, lookupValue, mul_sum, n1, o, o1, p, pb, pg, pixels, pr, q1, r_in_sum, r_out_sum, r_sum, radiusPixels, radiusPlus1, rbs, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, shg_sum, stack, stackEnd, stackIn, stackOut, stackStart, steps, sumFactor, u, w, w4, wh, wh4, width, widthMinus1, x, y, yi, yp, yw; width = this.dimensions.width; height = this.dimensions.height; imagePixels = this.pixelData; radiusPixels = radiusData.data; wh = width * height; wh4 = wh << 2; pixels = []; for (i = o = 0, ref = wh4; 0 <= ref ? o < ref : o > ref; i = 0 <= ref ? ++o : --o) { pixels[i] = imagePixels[i]; } currentIndex = 0; steps = blurLevels; blurLevels -= 1; while (steps-- >= 0) { iradius = (radius + 0.5) | 0; if (iradius === 0) { continue; } if (iradius > 256) { iradius = 256; } div = iradius + iradius + 1; w4 = width << 2; widthMinus1 = width - 1; heightMinus1 = height - 1; radiusPlus1 = iradius + 1; sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2; stackStart = new BlurStack(); stackEnd = void 0; stack = stackStart; for (i = u = 1, ref1 = div; 1 <= ref1 ? u < ref1 : u > ref1; i = 1 <= ref1 ? ++u : --u) { stack = stack.next = new BlurStack(); if (i === radiusPlus1) { stackEnd = stack; } } stack.next = stackStart; stackIn = null; stackOut = null; yw = yi = 0; mul_sum = mul_table[iradius]; shg_sum = shg_table[iradius]; for (y = w = 0, ref2 = height; 0 <= ref2 ? w < ref2 : w > ref2; y = 0 <= ref2 ? ++w : --w) { r_in_sum = g_in_sum = b_in_sum = r_sum = g_sum = b_sum = 0; r_out_sum = radiusPlus1 * (pr = pixels[yi]); g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]); b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]); r_sum += sumFactor * pr; g_sum += sumFactor * pg; b_sum += sumFactor * pb; stack = stackStart; for (i = i1 = 0, ref3 = radiusPlus1; 0 <= ref3 ? i1 < ref3 : i1 > ref3; i = 0 <= ref3 ? ++i1 : --i1) { stack.r = pr; stack.g = pg; stack.b = pb; stack = stack.next; } for (i = j1 = 1, ref4 = radiusPlus1; 1 <= ref4 ? j1 < ref4 : j1 > ref4; i = 1 <= ref4 ? ++j1 : --j1) { p = yi + ((widthMinus1 < i ? widthMinus1 : i) << 2); r_sum += (stack.r = (pr = pixels[p])) * (rbs = radiusPlus1 - i); g_sum += (stack.g = (pg = pixels[p + 1])) * rbs; b_sum += (stack.b = (pb = pixels[p + 2])) * rbs; r_in_sum += pr; g_in_sum += pg; b_in_sum += pb; stack = stack.next; } stackIn = stackStart; stackOut = stackEnd; for (x = k1 = 0, ref5 = width; 0 <= ref5 ? k1 < ref5 : k1 > ref5; x = 0 <= ref5 ? ++k1 : --k1) { pixels[yi] = (r_sum * mul_sum) >> shg_sum; pixels[yi + 1] = (g_sum * mul_sum) >> shg_sum; pixels[yi + 2] = (b_sum * mul_sum) >> shg_sum; r_sum -= r_out_sum; g_sum -= g_out_sum; b_sum -= b_out_sum; r_out_sum -= stackIn.r; g_out_sum -= stackIn.g; b_out_sum -= stackIn.b; p = (yw + ((p = x + radiusPlus1) < widthMinus1 ? p : widthMinus1)) << 2; r_in_sum += (stackIn.r = pixels[p]); g_in_sum += (stackIn.g = pixels[p + 1]); b_in_sum += (stackIn.b = pixels[p + 2]); r_sum += r_in_sum; g_sum += g_in_sum; b_sum += b_in_sum; stackIn = stackIn.next; r_out_sum += (pr = stackOut.r); g_out_sum += (pg = stackOut.g); b_out_sum += (pb = stackOut.b); r_in_sum -= pr; g_in_sum -= pg; b_in_sum -= pb; stackOut = stackOut.next; yi += 4; } yw += width; } for (x = l1 = 0, ref6 = width; 0 <= ref6 ? l1 < ref6 : l1 > ref6; x = 0 <= ref6 ? ++l1 : --l1) { g_in_sum = b_in_sum = r_in_sum = g_sum = b_sum = r_sum = 0; yi = x << 2; r_out_sum = radiusPlus1 * (pr = pixels[yi]); g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]); b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]); r_sum += sumFactor * pr; g_sum += sumFactor * pg; b_sum += sumFactor * pb; stack = stackStart; for (i = n1 = 0, ref7 = radiusPlus1; 0 <= ref7 ? n1 < ref7 : n1 > ref7; i = 0 <= ref7 ? ++n1 : --n1) { stack.r = pr; stack.g = pg; stack.b = pb; stack = stack.next; } yp = width; for (i = o1 = 1, ref8 = radiusPlus1; 1 <= ref8 ? o1 < ref8 : o1 > ref8; i = 1 <= ref8 ? ++o1 : --o1) { yi = (yp + x) << 2; r_sum += (stack.r = (pr = pixels[yi])) * (rbs = radiusPlus1 - i); g_sum += (stack.g = (pg = pixels[yi + 1])) * rbs; b_sum += (stack.b = (pb = pixels[yi + 2])) * rbs; r_in_sum += pr; g_in_sum += pg; b_in_sum += pb; stack = stack.next; if (i < heightMinus1) { yp += width; } } yi = x; stackIn = stackStart; stackOut = stackEnd; for (y = q1 = 0, ref9 = height; 0 <= ref9 ? q1 < ref9 : q1 > ref9; y = 0 <= ref9 ? ++q1 : --q1) { p = yi << 2; pixels[p] = (r_sum * mul_sum) >> shg_sum; pixels[p + 1] = (g_sum * mul_sum) >> shg_sum; pixels[p + 2] = (b_sum * mul_sum) >> shg_sum; r_sum -= r_out_sum; g_sum -= g_out_sum; b_sum -= b_out_sum; r_out_sum -= stackIn.r; g_out_sum -= stackIn.g; b_out_sum -= stackIn.b; p = (x + (((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width)) << 2; r_sum += (r_in_sum += (stackIn.r = pixels[p])); g_sum += (g_in_sum += (stackIn.g = pixels[p + 1])); b_sum += (b_in_sum += (stackIn.b = pixels[p + 2])); stackIn = stackIn.next; r_out_sum += (pr = stackOut.r); g_out_sum += (pg = stackOut.g); b_out_sum += (pb = stackOut.b); r_in_sum -= pr; g_in_sum -= pg; b_in_sum -= pb; stackOut = stackOut.next; yi += width; } } radius *= increaseFactor; i = wh; while (--i > -1) { idx = i << 2; lookupValue = (radiusPixels[idx + 2] & 0xff) / 255.0 * blurLevels; index = lookupValue | 0; if (index === currentIndex) { blend = 256.0 * (lookupValue - (lookupValue | 0)); iblend = 256 - blend; imagePixels[idx] = (imagePixels[idx] * iblend + pixels[idx] * blend) >> 8; imagePixels[idx + 1] = (imagePixels[idx + 1] * iblend + pixels[idx + 1] * blend) >> 8; imagePixels[idx + 2] = (imagePixels[idx + 2] * iblend + pixels[idx + 2] * blend) >> 8; } else if (index === currentIndex + 1) { imagePixels[idx] = pixels[idx]; imagePixels[idx + 1] = pixels[idx + 1]; imagePixels[idx + 2] = pixels[idx + 2]; } } currentIndex++; } return this; }); Caman.Filter.register("tiltShift", function(opts) { var defaults, gradient; defaults = { center: { x: this.dimensions.width / 2, y: this.dimensions.height / 2 }, angle: 45, focusWidth: 200, startRadius: 3, radiusFactor: 1.5, steps: 3 }; opts = Util.extend(defaults, opts); opts.angle *= Math.PI / 180; gradient = getLinearGradientMap(this.dimensions.width, this.dimensions.height, opts.center.x, opts.center.y, opts.angle, opts.focusWidth, true); return this.processPlugin("compoundBlur", [gradient, opts.startRadius, opts.radiusFactor, opts.steps]); }); return Caman.Filter.register("radialBlur", function(opts) { var defaults, gradient, radius1, radius2; defaults = { size: 50, center: { x: this.dimensions.width / 2, y: this.dimensions.height / 2 }, startRadius: 3, radiusFactor: 1.5, steps: 3, radius: null }; opts = Util.extend(defaults, opts); if (!opts.radius) { opts.radius = this.dimensions.width < this.dimensions.height ? this.dimensions.height : this.dimensions.width; } radius1 = (opts.radius / 2) - opts.size; radius2 = opts.radius / 2; gradient = getRadialGradientMap(this.dimensions.width, this.dimensions.height, opts.center.x, opts.center.y, radius1, radius2); return this.processPlugin("compoundBlur", [gradient, opts.startRadius, opts.radiusFactor, opts.steps]); }); })(); Caman.Filter.register("edgeEnhance", function() { return this.processKernel("Edge Enhance", [0, 0, 0, -1, 1, 0, 0, 0, 0]); }); Caman.Filter.register("edgeDetect", function() { return this.processKernel("Edge Detect", [-1, -1, -1, -1, 8, -1, -1, -1, -1]); }); Caman.Filter.register("emboss", function() { return this.processKernel("Emboss", [-2, -1, 0, -1, 1, 1, 0, 1, 2]); }); Caman.Filter.register("posterize", function(adjust) { var numOfAreas, numOfValues; numOfAreas = 256 / adjust; numOfValues = 255 / (adjust - 1); return this.process("posterize", function(rgba) { rgba.r = Math.floor(Math.floor(rgba.r / numOfAreas) * numOfValues); rgba.g = Math.floor(Math.floor(rgba.g / numOfAreas) * numOfValues); rgba.b = Math.floor(Math.floor(rgba.b / numOfAreas) * numOfValues); return rgba; }); }); Caman.Filter.register("vintage", function(vignette) { if (vignette == null) { vignette = true; } this.greyscale(); this.contrast(5); this.noise(3); this.sepia(100); this.channels({ red: 8, blue: 2, green: 4 }); this.gamma(0.87); if (vignette) { return this.vignette("40%", 30); } }); Caman.Filter.register("lomo", function(vignette) { if (vignette == null) { vignette = true; } this.brightness(15); this.exposure(15); this.curves('rgb', [0, 0], [200, 0], [155, 255], [255, 255]); this.saturation(-20); this.gamma(1.8); if (vignette) { this.vignette("50%", 60); } return this.brightness(5); }); Caman.Filter.register("clarity", function(grey) { if (grey == null) { grey = false; } this.vibrance(20); this.curves('rgb', [5, 0], [130, 150], [190, 220], [250, 255]); this.sharpen(15); this.vignette("45%", 20); if (grey) { this.greyscale(); this.contrast(4); } return this; }); Caman.Filter.register("sinCity", function() { this.contrast(100); this.brightness(15); this.exposure(10); this.posterize(80); this.clip(30); return this.greyscale(); }); Caman.Filter.register("sunrise", function() { this.exposure(3.5); this.saturation(-5); this.vibrance(50); this.sepia(60); this.colorize("#e87b22", 10); this.channels({ red: 8, blue: 8 }); this.contrast(5); this.gamma(1.2); return this.vignette("55%", 25); }); Caman.Filter.register("crossProcess", function() { this.exposure(5); this.colorize("#e87b22", 4); this.sepia(20); this.channels({ blue: 8, red: 3 }); this.curves('b', [0, 0], [100, 150], [180, 180], [255, 255]); this.contrast(15); this.vibrance(75); return this.gamma(1.6); }); Caman.Filter.register("orangePeel", function() { this.curves('rgb', [0, 0], [100, 50], [140, 200], [255, 255]); this.vibrance(-30); this.saturation(-30); this.colorize('#ff9000', 30); this.contrast(-5); return this.gamma(1.4); }); Caman.Filter.register("love", function() { this.brightness(5); this.exposure(8); this.contrast(4); this.colorize('#c42007', 30); this.vibrance(50); return this.gamma(1.3); }); Caman.Filter.register("grungy", function() { this.gamma(1.5); this.clip(25); this.saturation(-60); this.contrast(5); this.noise(5); return this.vignette("50%", 30); }); Caman.Filter.register("jarques", function() { this.saturation(-35); this.curves('b', [20, 0], [90, 120], [186, 144], [255, 230]); this.curves('r', [0, 0], [144, 90], [138, 120], [255, 255]); this.curves('g', [10, 0], [115, 105], [148, 100], [255, 248]); this.curves('rgb', [0, 0], [120, 100], [128, 140], [255, 255]); return this.sharpen(20); }); Caman.Filter.register("pinhole", function() { this.greyscale(); this.sepia(10); this.exposure(10); this.contrast(15); return this.vignette("60%", 35); }); Caman.Filter.register("oldBoot", function() { this.saturation(-20); this.vibrance(-50); this.gamma(1.1); this.sepia(30); this.channels({ red: -10, blue: 5 }); this.curves('rgb', [0, 0], [80, 50], [128, 230], [255, 255]); return this.vignette("60%", 30); }); Caman.Filter.register("glowingSun", function(vignette) { if (vignette == null) { vignette = true; } this.brightness(10); this.newLayer(function() { this.setBlendingMode("multiply"); this.opacity(80); this.copyParent(); this.filter.gamma(0.8); this.filter.contrast(50); return this.filter.exposure(10); }); this.newLayer(function() { this.setBlendingMode("softLight"); this.opacity(80); return this.fillColor("#f49600"); }); this.exposure(20); this.gamma(0.8); if (vignette) { return this.vignette("45%", 20); } }); Caman.Filter.register("hazyDays", function() { this.gamma(1.2); this.newLayer(function() { this.setBlendingMode("overlay"); this.opacity(60); this.copyParent(); this.filter.channels({ red: 5 }); return this.filter.stackBlur(15); }); this.newLayer(function() { this.setBlendingMode("addition"); this.opacity(40); return this.fillColor("#6899ba"); }); this.newLayer(function() { this.setBlendingMode("multiply"); this.opacity(35); this.copyParent(); this.filter.brightness(40); this.filter.vibrance(40); this.filter.exposure(30); this.filter.contrast(15); this.filter.curves('r', [0, 40], [128, 128], [128, 128], [255, 215]); this.filter.curves('g', [0, 40], [128, 128], [128, 128], [255, 215]); this.filter.curves('b', [0, 40], [128, 128], [128, 128], [255, 215]); return this.filter.stackBlur(5); }); this.curves('r', [20, 0], [128, 158], [128, 128], [235, 255]); this.curves('g', [20, 0], [128, 128], [128, 128], [235, 255]); this.curves('b', [20, 0], [128, 108], [128, 128], [235, 255]); return this.vignette("45%", 20); }); Caman.Filter.register("herMajesty", function() { this.brightness(40); this.colorize("#ea1c5d", 10); this.curves('b', [0, 10], [128, 180], [190, 190], [255, 255]); this.newLayer(function() { this.setBlendingMode('overlay'); this.opacity(50); this.copyParent(); this.filter.gamma(0.7); return this.newLayer(function() { this.setBlendingMode('normal'); this.opacity(60); return this.fillColor('#ea1c5d'); }); }); this.newLayer(function() { this.setBlendingMode('multiply'); this.opacity(60); this.copyParent(); this.filter.saturation(50); this.filter.hue(90); return this.filter.contrast(10); }); this.gamma(1.4); this.vibrance(-30); this.newLayer(function() { this.opacity(10); return this.fillColor('#e5f0ff'); }); return this; }); Caman.Filter.register("nostalgia", function() { this.saturation(20); this.gamma(1.4); this.greyscale(); this.contrast(5); this.sepia(100); this.channels({ red: 8, blue: 2, green: 4 }); this.gamma(0.8); this.contrast(5); this.exposure(10); this.newLayer(function() { this.setBlendingMode('overlay'); this.copyParent(); this.opacity(55); return this.filter.stackBlur(10); }); return this.vignette("50%", 30); }); Caman.Filter.register("hemingway", function() { this.greyscale(); this.contrast(10); this.gamma(0.9); this.newLayer(function() { this.setBlendingMode("multiply"); this.opacity(40); this.copyParent(); this.filter.exposure(15); this.filter.contrast(15); return this.filter.channels({ green: 10, red: 5 }); }); this.sepia(30); this.curves('rgb', [0, 10], [120, 90], [180, 200], [235, 255]); this.channels({ red: 5, green: -2 }); return this.exposure(15); }); Caman.Filter.register("concentrate", function() { this.sharpen(40); this.saturation(-50); this.channels({ red: 3 }); this.newLayer(function() { this.setBlendingMode("multiply"); this.opacity(80); this.copyParent(); this.filter.sharpen(5); this.filter.contrast(50); this.filter.exposure(10); return this.filter.channels({ blue: 5 }); }); return this.brightness(10); }); Caman.Plugin.register("rotate", function(degrees) { var angle, canvas, ctx, height, to_radians, width, x, y; angle = degrees % 360; if (angle === 0) { return this.dimensions = { width: this.canvas.width, height: this.canvas.height }; } to_radians = Math.PI / 180; if (typeof exports !== "undefined" && exports !== null) { canvas = new Canvas(); } else { canvas = document.createElement('canvas'); Util.copyAttributes(this.canvas, canvas); } if (angle === 90 || angle === -270 || angle === 270 || angle === -90) { width = this.canvas.height; height = this.canvas.width; x = width / 2; y = height / 2; } else if (angle === 180) { width = this.canvas.width; height = this.canvas.height; x = width / 2; y = height / 2; } else { width = Math.sqrt(Math.pow(this.originalWidth, 2) + Math.pow(this.originalHeight, 2)); height = width; x = this.canvas.height / 2; y = this.canvas.width / 2; } canvas.width = width; canvas.height = height; ctx = canvas.getContext('2d'); ctx.save(); ctx.translate(x, y); ctx.rotate(angle * to_radians); ctx.drawImage(this.canvas, -this.canvas.width / 2, -this.canvas.height / 2, this.canvas.width, this.canvas.height); ctx.restore(); this.rotationAngle += degrees; this.rotated = true; return this.replaceCanvas(canvas); }); Caman.Filter.register("rotate", function() { return this.processPlugin("rotate", Array.prototype.slice.call(arguments, 0)); }); /* StackBlur - a fast almost Gaussian Blur For Canvas v0.31 modified for CamanJS Version: 0.31 Author: Mario Klingemann Contact: mario@quasimondo.com Website: http://www.quasimondo.com/StackBlurForCanvas Twitter: @quasimondo Modified By: Ryan LeFevre (@meltingice) In case you find this class useful - especially in commercial projects - I am not totally unhappy for a small donation to my PayPal account mario@quasimondo.de Or support me on flattr: https://flattr.com/thing/72791/StackBlur-a-fast-almost-Gaussian-Blur-Effect-for-CanvasJavascript Copyright (c) 2010 Mario Klingemann Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ (function() { var BlurStack, mul_table, shg_table; mul_table = [512, 512, 456, 512, 328, 456, 335, 512, 405, 328, 271, 456, 388, 335, 292, 512, 454, 405, 364, 328, 298, 271, 496, 456, 420, 388, 360, 335, 312, 292, 273, 512, 482, 454, 428, 405, 383, 364, 345, 328, 312, 298, 284, 271, 259, 496, 475, 456, 437, 420, 404, 388, 374, 360, 347, 335, 323, 312, 302, 292, 282, 273, 265, 512, 497, 482, 468, 454, 441, 428, 417, 405, 394, 383, 373, 364, 354, 345, 337, 328, 320, 312, 305, 298, 291, 284, 278, 271, 265, 259, 507, 496, 485, 475, 465, 456, 446, 437, 428, 420, 412, 404, 396, 388, 381, 374, 367, 360, 354, 347, 341, 335, 329, 323, 318, 312, 307, 302, 297, 292, 287, 282, 278, 273, 269, 265, 261, 512, 505, 497, 489, 482, 475, 468, 461, 454, 447, 441, 435, 428, 422, 417, 411, 405, 399, 394, 389, 383, 378, 373, 368, 364, 359, 354, 350, 345, 341, 337, 332, 328, 324, 320, 316, 312, 309, 305, 301, 298, 294, 291, 287, 284, 281, 278, 274, 271, 268, 265, 262, 259, 257, 507, 501, 496, 491, 485, 480, 475, 470, 465, 460, 456, 451, 446, 442, 437, 433, 428, 424, 420, 416, 412, 408, 404, 400, 396, 392, 388, 385, 381, 377, 374, 370, 367, 363, 360, 357, 354, 350, 347, 344, 341, 338, 335, 332, 329, 326, 323, 320, 318, 315, 312, 310, 307, 304, 302, 299, 297, 294, 292, 289, 287, 285, 282, 280, 278, 275, 273, 271, 269, 267, 265, 263, 261, 259]; shg_table = [9, 11, 12, 13, 13, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24]; BlurStack = function() { this.r = 0; this.g = 0; this.b = 0; this.a = 0; return this.next = null; }; Caman.Plugin.register("stackBlur", function(radius) { var b_in_sum, b_out_sum, b_sum, div, g_in_sum, g_out_sum, g_sum, height, heightMinus1, i, i1, j1, k1, l1, mul_sum, n1, o, o1, p, pb, pg, pixels, pr, r_in_sum, r_out_sum, r_sum, radiusPlus1, rbs, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ref8, shg_sum, stack, stackEnd, stackIn, stackOut, stackStart, sumFactor, u, w, w4, width, widthMinus1, x, y, yi, yp, yw; if (isNaN(radius) || radius < 1) { return; } radius |= 0; pixels = this.pixelData; width = this.dimensions.width; height = this.dimensions.height; div = radius + radius + 1; w4 = width << 2; widthMinus1 = width - 1; heightMinus1 = height - 1; radiusPlus1 = radius + 1; sumFactor = radiusPlus1 * (radiusPlus1 + 1) / 2; stackStart = new BlurStack(); stack = stackStart; for (i = o = 1, ref = div; 1 <= ref ? o < ref : o > ref; i = 1 <= ref ? ++o : --o) { stack = stack.next = new BlurStack(); if (i === radiusPlus1) { stackEnd = stack; } } stack.next = stackStart; stackIn = null; stackOut = null; yw = yi = 0; mul_sum = mul_table[radius]; shg_sum = shg_table[radius]; for (y = u = 0, ref1 = height; 0 <= ref1 ? u < ref1 : u > ref1; y = 0 <= ref1 ? ++u : --u) { r_in_sum = g_in_sum = b_in_sum = r_sum = g_sum = b_sum = 0; r_out_sum = radiusPlus1 * (pr = pixels[yi]); g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]); b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]); r_sum += sumFactor * pr; g_sum += sumFactor * pg; b_sum += sumFactor * pb; stack = stackStart; for (i = w = 0, ref2 = radiusPlus1; 0 <= ref2 ? w < ref2 : w > ref2; i = 0 <= ref2 ? ++w : --w) { stack.r = pr; stack.g = pg; stack.b = pb; stack = stack.next; } for (i = i1 = 1, ref3 = radiusPlus1; 1 <= ref3 ? i1 < ref3 : i1 > ref3; i = 1 <= ref3 ? ++i1 : --i1) { p = yi + ((widthMinus1 < i ? widthMinus1 : i) << 2); r_sum += (stack.r = (pr = pixels[p])) * (rbs = radiusPlus1 - i); g_sum += (stack.g = (pg = pixels[p + 1])) * rbs; b_sum += (stack.b = (pb = pixels[p + 2])) * rbs; r_in_sum += pr; g_in_sum += pg; b_in_sum += pb; stack = stack.next; } stackIn = stackStart; stackOut = stackEnd; for (x = j1 = 0, ref4 = width; 0 <= ref4 ? j1 < ref4 : j1 > ref4; x = 0 <= ref4 ? ++j1 : --j1) { pixels[yi] = (r_sum * mul_sum) >> shg_sum; pixels[yi + 1] = (g_sum * mul_sum) >> shg_sum; pixels[yi + 2] = (b_sum * mul_sum) >> shg_sum; r_sum -= r_out_sum; g_sum -= g_out_sum; b_sum -= b_out_sum; r_out_sum -= stackIn.r; g_out_sum -= stackIn.g; b_out_sum -= stackIn.b; p = (yw + ((p = x + radius + 1) < widthMinus1 ? p : widthMinus1)) << 2; r_in_sum += (stackIn.r = pixels[p]); g_in_sum += (stackIn.g = pixels[p + 1]); b_in_sum += (stackIn.b = pixels[p + 2]); r_sum += r_in_sum; g_sum += g_in_sum; b_sum += b_in_sum; stackIn = stackIn.next; r_out_sum += (pr = stackOut.r); g_out_sum += (pg = stackOut.g); b_out_sum += (pb = stackOut.b); r_in_sum -= pr; g_in_sum -= pg; b_in_sum -= pb; stackOut = stackOut.next; yi += 4; } yw += width; } for (x = k1 = 0, ref5 = width; 0 <= ref5 ? k1 < ref5 : k1 > ref5; x = 0 <= ref5 ? ++k1 : --k1) { g_in_sum = b_in_sum = r_in_sum = g_sum = b_sum = r_sum = 0; yi = x << 2; r_out_sum = radiusPlus1 * (pr = pixels[yi]); g_out_sum = radiusPlus1 * (pg = pixels[yi + 1]); b_out_sum = radiusPlus1 * (pb = pixels[yi + 2]); r_sum += sumFactor * pr; g_sum += sumFactor * pg; b_sum += sumFactor * pb; stack = stackStart; for (i = l1 = 0, ref6 = radiusPlus1; 0 <= ref6 ? l1 < ref6 : l1 > ref6; i = 0 <= ref6 ? ++l1 : --l1) { stack.r = pr; stack.g = pg; stack.b = pb; stack = stack.next; } yp = width; for (i = n1 = 1, ref7 = radius; 1 <= ref7 ? n1 <= ref7 : n1 >= ref7; i = 1 <= ref7 ? ++n1 : --n1) { yi = (yp + x) << 2; r_sum += (stack.r = (pr = pixels[yi])) * (rbs = radiusPlus1 - i); g_sum += (stack.g = (pg = pixels[yi + 1])) * rbs; b_sum += (stack.b = (pb = pixels[yi + 2])) * rbs; r_in_sum += pr; g_in_sum += pg; b_in_sum += pb; stack = stack.next; if (i < heightMinus1) { yp += width; } } yi = x; stackIn = stackStart; stackOut = stackEnd; for (y = o1 = 0, ref8 = height; 0 <= ref8 ? o1 < ref8 : o1 > ref8; y = 0 <= ref8 ? ++o1 : --o1) { p = yi << 2; pixels[p] = (r_sum * mul_sum) >> shg_sum; pixels[p + 1] = (g_sum * mul_sum) >> shg_sum; pixels[p + 2] = (b_sum * mul_sum) >> shg_sum; r_sum -= r_out_sum; g_sum -= g_out_sum; b_sum -= b_out_sum; r_out_sum -= stackIn.r; g_out_sum -= stackIn.g; b_out_sum -= stackIn.b; p = (x + (((p = y + radiusPlus1) < heightMinus1 ? p : heightMinus1) * width)) << 2; r_sum += (r_in_sum += (stackIn.r = pixels[p])); g_sum += (g_in_sum += (stackIn.g = pixels[p + 1])); b_sum += (b_in_sum += (stackIn.b = pixels[p + 2])); stackIn = stackIn.next; r_out_sum += (pr = stackOut.r); g_out_sum += (pg = stackOut.g); b_out_sum += (pb = stackOut.b); r_in_sum -= pr; g_in_sum -= pg; b_in_sum -= pb; stackOut = stackOut.next; yi += width; } } return this; }); return Caman.Filter.register("stackBlur", function(radius) { return this.processPlugin("stackBlur", [radius]); }); })(); Caman.Filter.register("threshold", function(adjust) { return this.process("threshold", function(rgba) { var luminance; luminance = (0.2126 * rgba.r) + (0.7152 * rgba.g) + (0.0722 * rgba.b); if (luminance < adjust) { rgba.r = 0; rgba.g = 0; rgba.b = 0; } else { rgba.r = 255; rgba.g = 255; rgba.b = 255; } return rgba; }); }); }).call(this);