2 * Pixastic Lib - Core Functions - v0.1.3
3 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
4 * License: [http://www.pixastic.com/lib/license.txt]
7 var Pixastic
= (function() {
10 function addEvent(el
, event
, handler
) {
11 if (el
.addEventListener
)
12 el
.addEventListener(event
, handler
, false);
13 else if (el
.attachEvent
)
14 el
.attachEvent("on" + event
, handler
);
17 function onready(handler
) {
18 var handlerDone
= false;
19 var execHandler = function() {
25 document
.write("<"+"script defer src=\"//:\" id=\"__onload_ie_sumbox__\"></"+"script>");
26 var script
= document
.getElementById("__onload_ie_sumbox__");
27 script
.onreadystatechange = function() {
28 if (script
.readyState
== "complete") {
29 script
.parentNode
.removeChild(script
);
33 if (document
.addEventListener
)
34 document
.addEventListener("DOMContentLoaded", execHandler
, false);
35 addEvent(window
, "load", execHandler
);
39 if (!Pixastic
.parseOnLoad
) return;
40 var imgEls
= getElementsByClass("pixastic", null, "img");
41 var canvasEls
= getElementsByClass("pixastic", null, "canvas");
42 var elements
= imgEls
.concat(canvasEls
);
43 for (var i
=0;i
<elements
.length
;i
++) {
48 var classes
= el
.className
.split(" ");
49 for (var c
=0;c
<classes
.length
;c
++) {
51 if (cls
.substring(0,9) == "pixastic-") {
52 var actionName
= cls
.substring(9);
54 actions
.push(actionName
);
58 if (el
.tagName
.toLowerCase() == "img") {
59 var dataImg
= new Image();
61 if (dataImg
.complete
) {
62 for (var a
=0;a
<actions
.length
;a
++) {
63 var res
= Pixastic
.applyAction(el
, el
, actions
[a
], null);
68 dataImg
.onload = function() {
69 for (var a
=0;a
<actions
.length
;a
++) {
70 var res
= Pixastic
.applyAction(el
, el
, actions
[a
], null)
77 setTimeout(function() {
78 for (var a
=0;a
<actions
.length
;a
++) {
79 var res
= Pixastic
.applyAction(
80 el
, el
, actions
[a
], null
93 // if (typeof pixastic_no_onready == "undefined") // yuck.
96 // getElementsByClass by Dustin Diaz, http://www.dustindiaz.com/getelementsbyclass/
97 function getElementsByClass(searchClass
,node
,tag
) {
98 var classElements
= new Array();
104 var els
= node
.getElementsByTagName(tag
);
105 var elsLen
= els
.length
;
106 var pattern
= new RegExp("(^|\\s)"+searchClass
+"(\\s|$)");
107 for (i
= 0, j
= 0; i
< elsLen
; i
++) {
108 if ( pattern
.test(els
[i
].className
) ) {
109 classElements
[j
] = els
[i
];
113 return classElements
;
118 function writeDebug(text
, level
) {
119 if (!Pixastic
.debug
) return;
123 console
.warn("Pixastic:", text
);
126 console
.error("Pixastic:", text
);
129 console
.log("Pixastic:", text
);
145 applyAction : function(img
, dataImg
, actionName
, options
) {
147 options
= options
|| {};
149 var imageIsCanvas
= (img
.tagName
.toLowerCase() == "canvas");
150 if (imageIsCanvas
&& Pixastic
.Client
.isIE()) {
151 if (Pixastic
.debug
) writeDebug("Tried to process a canvas element but browser is IE.");
156 if (Pixastic
.Client
.hasCanvas()) {
157 canvas
= document
.createElement("canvas");
158 ctx
= canvas
.getContext("2d");
161 var w
= parseInt(img
.offsetWidth
);
162 var h
= parseInt(img
.offsetHeight
);
169 if (actionName
.indexOf("(") > -1) {
170 var tmp
= actionName
;
171 actionName
= tmp
.substr(0, tmp
.indexOf("("));
172 var arg
= tmp
.match(/\((.*?)\)/);
174 arg
= arg
[1].split(";");
175 for (var a
=0;a
<arg
.length
;a
++) {
176 thisArg
= arg
[a
].split("=");
177 if (thisArg
.length
== 2) {
178 if (thisArg
[0] == "rect") {
179 var rectVal
= thisArg
[1].split(",");
180 options
[thisArg
[0]] = {
181 left
: parseInt(rectVal
[0],10)||0,
182 top
: parseInt(rectVal
[1],10)||0,
183 width
: parseInt(rectVal
[2],10)||0,
184 height
: parseInt(rectVal
[3],10)||0
187 options
[thisArg
[0]] = thisArg
[1];
196 left
: 0, top
: 0, width
: w
, height
: h
199 var validAction
= false;
200 if (Pixastic
.Actions
[actionName
] && typeof Pixastic
.Actions
[actionName
].process
== "function") {
204 if (Pixastic
.debug
) writeDebug("Invalid action \"" + actionName
+ "\". Maybe file not included?");
207 if (!Pixastic
.Actions
[actionName
].checkSupport()) {
208 if (Pixastic
.debug
) writeDebug("Action \"" + actionName
+ "\" not supported by this browser.");
212 if (Pixastic
.Client
.hasCanvas()) {
215 canvas
.style
.width
= w
+"px";
216 canvas
.style
.height
= h
+"px";
217 ctx
.drawImage(dataImg
,0,0,w
,h
);
219 if (!img
.__pixastic_org_image
) {
220 canvas
.__pixastic_org_image
= img
;
221 canvas
.__pixastic_org_width
= w
;
222 canvas
.__pixastic_org_height
= h
;
224 canvas
.__pixastic_org_image
= img
.__pixastic_org_image
;
225 canvas
.__pixastic_org_width
= img
.__pixastic_org_width
;
226 canvas
.__pixastic_org_height
= img
.__pixastic_org_height
;
229 } else if (Pixastic
.Client
.isIE() && typeof img
.__pixastic_org_style
== "undefined") {
230 img
.__pixastic_org_style
= img
.style
.cssText
;
244 var res
= Pixastic
.Actions
[actionName
].process(params
);
250 if (Pixastic
.Client
.hasCanvas()) {
251 if (params
.useData
) {
252 if (Pixastic
.Client
.hasCanvasImageData()) {
253 canvas
.getContext("2d").putImageData(params
.canvasData
, options
.rect
.left
, options
.rect
.top
);
255 // Opera doesn't seem to update the canvas until we draw something on it, lets draw a 0x0 rectangle.
256 canvas
.getContext("2d").fillRect(0,0,0,0);
260 if (!options
.leaveDOM
) {
261 // copy properties and stuff from the source image
262 canvas
.title
= img
.title
;
263 canvas
.imgsrc
= img
.imgsrc
;
264 if (!imageIsCanvas
) canvas
.alt
= img
.alt
;
265 if (!imageIsCanvas
) canvas
.imgsrc
= img
.src
;
266 canvas
.className
= img
.className
;
267 canvas
.style
.cssText
= img
.style
.cssText
;
268 canvas
.name
= img
.name
;
269 canvas
.tabIndex
= img
.tabIndex
;
271 if (img
.parentNode
&& img
.parentNode
.replaceChild
) {
272 img
.parentNode
.replaceChild(canvas
, img
);
276 options
.resultCanvas
= canvas
;
284 prepareData : function(params
, getCopy
) {
285 var ctx
= params
.canvas
.getContext("2d");
286 var rect
= params
.options
.rect
;
287 var dataDesc
= ctx
.getImageData(rect
.left
, rect
.top
, rect
.width
, rect
.height
);
288 var data
= dataDesc
.data
;
289 if (!getCopy
) params
.canvasData
= dataDesc
;
293 // load the image file
294 process : function(img
, actionName
, options
, callback
)
296 if (img
.tagName
.toLowerCase() == "img") {
297 var dataImg
= new Image();
298 dataImg
.src
= img
.src
;
299 if (dataImg
.complete
) {
300 var res
= Pixastic
.applyAction(img
, dataImg
, actionName
, options
);
301 if (callback
) callback(res
);
304 dataImg
.onload = function() {
305 var res
= Pixastic
.applyAction(img
, dataImg
, actionName
, options
)
306 if (callback
) callback(res
);
310 if (img
.tagName
.toLowerCase() == "canvas") {
311 var res
= Pixastic
.applyAction(img
, img
, actionName
, options
);
312 if (callback
) callback(res
);
317 revert : function(img
) {
318 if (Pixastic
.Client
.hasCanvas()) {
319 if (img
.tagName
.toLowerCase() == "canvas" && img
.__pixastic_org_image
) {
320 img
.width
= img
.__pixastic_org_width
;
321 img
.height
= img
.__pixastic_org_height
;
322 img
.getContext("2d").drawImage(img
.__pixastic_org_image
, 0, 0);
324 if (img
.parentNode
&& img
.parentNode
.replaceChild
) {
325 img
.parentNode
.replaceChild(img
.__pixastic_org_image
, img
);
330 } else if (Pixastic
.Client
.isIE() && typeof img
.__pixastic_org_style
!= "undefined") {
331 img
.style
.cssText
= img
.__pixastic_org_style
;
336 hasCanvas
: (function() {
337 var c
= document
.createElement("canvas");
340 val
= !!((typeof c
.getContext
== "function") && c
.getContext("2d"));
347 hasCanvasImageData
: (function() {
348 var c
= document
.createElement("canvas");
352 if (typeof c
.getContext
== "function" && (ctx
= c
.getContext("2d"))) {
353 val
= (typeof ctx
.getImageData
== "function");
362 return !!document
.all
&& !!window
.attachEvent
&& !window
.opera
;
372 * Pixastic Lib - jQuery plugin
373 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
374 * License: [http://www.pixastic.com/lib/license.txt]
377 if (typeof jQuery
!= "undefined" && jQuery
&& jQuery
.fn
) {
378 jQuery
.fn
.pixastic = function(action
, options
) {
379 var newElements
= [];
382 if (this.tagName
.toLowerCase() == "img" && !this.complete
) {
385 var res
= Pixastic
.process(this, action
, options
);
387 newElements
.push(res
);
391 if (newElements
.length
> 0)
392 return jQuery(newElements
);
399 * Pixastic Lib - Blend - v0.1.1
400 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
401 * License: [http://www.pixastic.com/lib/license.txt]
404 Pixastic
.Actions
.blend
= {
406 process : function(params
) {
407 var amount
= parseFloat(params
.options
.amount
);
408 var mode
= (params
.options
.mode
|| "normal").toLowerCase();
409 var image
= params
.options
.image
;
411 amount
= Math
.max(0,Math
.min(1,amount
));
413 if (!image
) return false;
415 if (Pixastic
.Client
.hasCanvasImageData()) {
416 var rect
= params
.options
.rect
;
417 var data
= Pixastic
.prepareData(params
);
421 params
.useData
= false;
423 var otherCanvas
= document
.createElement("canvas");
424 otherCanvas
.width
= params
.canvas
.width
;
425 otherCanvas
.height
= params
.canvas
.height
;
426 var otherCtx
= otherCanvas
.getContext("2d");
427 otherCtx
.drawImage(image
,0,0);
429 var params2
= {canvas
:otherCanvas
,options
:params
.options
};
430 var data2
= Pixastic
.prepareData(params2
);
431 var dataDesc2
= params2
.canvasData
;
441 var dataChanged
= false;
446 // data2[pix-=4] = data2[pix];
447 // data2[pix1=pix+1] = data2[pix1];
448 // data2[pix2=pix+2] = data2[pix2];
454 data2
[pix
-=4] = data
[pix
] * data2
[pix
] / 255;
455 data2
[pix1
=pix
+1] = data
[pix1
] * data2
[pix1
] / 255;
456 data2
[pix2
=pix
+2] = data
[pix2
] * data2
[pix2
] / 255;
463 if ((r1
= data
[pix
-=4]) > data2
[pix
])
465 if ((g1
= data
[pix1
=pix
+1]) > data2
[pix1
])
467 if ((b1
= data
[pix2
=pix
+2]) > data2
[pix2
])
475 if ((r1
= data
[pix
-=4]) < data2
[pix
])
477 if ((g1
= data
[pix1
=pix
+1]) < data2
[pix1
])
479 if ((b1
= data
[pix2
=pix
+2]) < data2
[pix2
])
488 if (((r1
= data
[pix
-=4])*0.3+(g1
= data
[pix1
=pix
+1])*0.59+(b1
= data
[pix2
=pix
+2])*0.11) <= (data2
[pix
]*0.3+data2
[pix1
]*0.59+data2
[pix2
]*0.11)) {
497 case "lightercolor" :
499 if (((r1
= data
[pix
-=4])*0.3+(g1
= data
[pix1
=pix
+1])*0.59+(b1
= data
[pix2
=pix
+2])*0.11) > (data2
[pix
]*0.3+data2
[pix1
]*0.59+data2
[pix2
]*0.11)) {
509 otherCtx
.globalCompositeOperation
= "source-over";
510 otherCtx
.drawImage(params
.canvas
, 0, 0);
511 otherCtx
.globalCompositeOperation
= "lighter";
512 otherCtx
.drawImage(image
, 0, 0);
516 if ((r3 = data[pix-=4] + data2[pix]) > 255)
520 if ((g3 = data[pix1=pix+1] + data2[pix1]) > 255)
524 if ((b3 = data[pix2=pix+2] + data2[pix2]) > 255)
536 if ((r3
= data
[pix
-=4] + data2
[pix
]) < 255)
539 data2
[pix
] = (r3
- 255);
540 if ((g3
= data
[pix1
=pix
+1] + data2
[pix1
]) < 255)
543 data2
[pix1
] = (g3
- 255);
544 if ((b3
= data
[pix2
=pix
+2] + data2
[pix2
]) < 255)
547 data2
[pix2
] = (b3
- 255);
554 if ((r3
= data
[pix
-=4] - data2
[pix
]) < 0)
558 if ((g3
= data
[pix1
=pix
+1] - data2
[pix1
]) < 0)
562 if ((b3
= data
[pix2
=pix
+2] - data2
[pix2
]) < 0)
572 data2
[pix
-=4] = (255 - ( ((255-data2
[pix
])*(255-data
[pix
])) >> 8));
573 data2
[pix1
=pix
+1] = (255 - ( ((255-data2
[pix1
])*(255-data
[pix1
])) >> 8));
574 data2
[pix2
=pix
+2] = (255 - ( ((255-data2
[pix2
])*(255-data
[pix2
])) >> 8));
580 var div_2_255
= 2 / 255;
582 data2
[pix
-=4] = (r1
= data
[pix
]) - (r1
* div_2_255
- 1) * data2
[pix
];
583 data2
[pix1
=pix
+1] = (g1
= data
[pix1
]) - (g1
* div_2_255
- 1) * data2
[pix1
];
584 data2
[pix2
=pix
+2] = (b1
= data
[pix2
]) - (b1
* div_2_255
- 1) * data2
[pix2
];
590 var div_2_255
= 2 / 255;
592 if ((r1
= data
[pix
-=4]) < 128)
593 data2
[pix
] = data2
[pix
]*r1
*div_2_255
;
595 data2
[pix
] = 255 - (255-data2
[pix
])*(255-r1
)*div_2_255
;
597 if ((g1
= data
[pix1
=pix
+1]) < 128)
598 data2
[pix1
] = data2
[pix1
]*g1
*div_2_255
;
600 data2
[pix1
] = 255 - (255-data2
[pix1
])*(255-g1
)*div_2_255
;
602 if ((b1
= data
[pix2
=pix
+2]) < 128)
603 data2
[pix2
] = data2
[pix2
]*b1
*div_2_255
;
605 data2
[pix2
] = 255 - (255-data2
[pix2
])*(255-b1
)*div_2_255
;
612 var div_2_255
= 2 / 255;
614 if ((r1
= data
[pix
-=4]) < 128)
615 data2
[pix
] = ((data2
[pix
]>>1) + 64) * r1
* div_2_255
;
617 data2
[pix
] = 255 - (191 - (data2
[pix
]>>1)) * (255-r1
) * div_2_255
;
619 if ((g1
= data
[pix1
=pix
+1]) < 128)
620 data2
[pix1
] = ((data2
[pix1
]>>1)+64) * g1
* div_2_255
;
622 data2
[pix1
] = 255 - (191 - (data2
[pix1
]>>1)) * (255-g1
) * div_2_255
;
624 if ((b1
= data
[pix2
=pix
+2]) < 128)
625 data2
[pix2
] = ((data2
[pix2
]>>1)+64) * b1
* div_2_255
;
627 data2
[pix2
] = 255 - (191 - (data2
[pix2
]>>1)) * (255-b1
) * div_2_255
;
634 var div_2_255
= 2 / 255;
636 if ((r2
= data2
[pix
-=4]) < 128)
637 data2
[pix
] = data
[pix
] * r2
* div_2_255
;
639 data2
[pix
] = 255 - (255-data
[pix
]) * (255-r2
) * div_2_255
;
641 if ((g2
= data2
[pix1
=pix
+1]) < 128)
642 data2
[pix1
] = data
[pix1
] * g2
* div_2_255
;
644 data2
[pix1
] = 255 - (255-data
[pix1
]) * (255-g2
) * div_2_255
;
646 if ((b2
= data2
[pix2
=pix
+2]) < 128)
647 data2
[pix2
] = data
[pix2
] * b2
* div_2_255
;
649 data2
[pix2
] = 255 - (255-data
[pix2
]) * (255-b2
) * div_2_255
;
657 if ((r3
= (data
[pix
-=4]<<8)/(255-(r2
= data2
[pix
]))) > 255 || r2
== 255)
662 if ((g3
= (data
[pix1
=pix
+1]<<8)/(255-(g2
= data2
[pix1
]))) > 255 || g2
== 255)
667 if ((b3
= (data
[pix2
=pix
+2]<<8)/(255-(b2
= data2
[pix2
]))) > 255 || b2
== 255)
677 if ((r3
= 255-((255-data
[pix
-=4])<<8)/data2
[pix
]) < 0 || data2
[pix
] == 0)
682 if ((g3
= 255-((255-data
[pix1
=pix
+1])<<8)/data2
[pix1
]) < 0 || data2
[pix1
] == 0)
687 if ((b3
= 255-((255-data
[pix2
=pix
+2])<<8)/data2
[pix2
]) < 0 || data2
[pix2
] == 0)
697 if ( ((r3
= 2*(r2
=data2
[pix
-=4])+data
[pix
]-256) < 0) || (r2
< 128 && r3
< 0)) {
705 if ( ((g3
= 2*(g2
=data2
[pix1
=pix
+1])+data
[pix1
]-256) < 0) || (g2
< 128 && g3
< 0)) {
713 if ( ((b3
= 2*(b2
=data2
[pix2
=pix
+2])+data
[pix2
]-256) < 0) || (b2
< 128 && b3
< 0)) {
727 if ((r2
=data2
[pix
-=4]) < 128) {
729 if ((r3
= 255 - ((255-data
[pix
])<<8) / (2*r2
)) < 0)
736 } else if ((r3
= (r4
=2*r2
-256)) < 255) {
737 if ((r3
= (data
[pix
]<<8)/(255-r4
)) > 255)
748 if ((g2
=data2
[pix1
=pix
+1]) < 128) {
750 if ((g3
= 255 - ((255-data
[pix1
])<<8) / (2*g2
)) < 0)
757 } else if ((g3
= (g4
=2*g2
-256)) < 255) {
758 if ((g3
= (data
[pix1
]<<8)/(255-g4
)) > 255)
769 if ((b2
=data2
[pix2
=pix
+2]) < 128) {
771 if ((b3
= 255 - ((255-data
[pix2
])<<8) / (2*b2
)) < 0)
778 } else if ((b3
= (b4
=2*b2
-256)) < 255) {
779 if ((b3
= (data
[pix2
]<<8)/(255-b4
)) > 255)
795 if ((r2
=data2
[pix
-=4]) < 128)
796 if ((r1
=data
[pix
]) < (r4
=2*r2
))
801 if ((r1
=data
[pix
]) > (r4
=2*r2
-256))
806 if ((g2
=data2
[pix1
=pix
+1]) < 128)
807 if ((g1
=data
[pix1
]) < (g4
=2*g2
))
812 if ((g1
=data
[pix1
]) > (g4
=2*g2
-256))
817 if ((r2
=data2
[pix2
=pix
+2]) < 128)
818 if ((r1
=data
[pix2
]) < (r4
=2*r2
))
823 if ((r1
=data
[pix2
]) > (r4
=2*r2
-256))
833 if ((r2
= data2
[pix
-=4]) < 128)
834 if (255 - ((255-data
[pix
])<<8)/(2*r2
) < 128 || r2
== 0)
838 else if ((r4
=2*r2
-256) < 255 && (data
[pix
]<<8)/(255-r4
) < 128)
843 if ((g2
= data2
[pix1
=pix
+1]) < 128)
844 if (255 - ((255-data
[pix1
])<<8)/(2*g2
) < 128 || g2
== 0)
848 else if ((g4
=2*g2
-256) < 255 && (data
[pix1
]<<8)/(255-g4
) < 128)
853 if ((b2
= data2
[pix2
=pix
+2]) < 128)
854 if (255 - ((255-data
[pix2
])<<8)/(2*b2
) < 128 || b2
== 0)
858 else if ((b4
=2*b2
-256) < 255 && (data
[pix2
]<<8)/(255-b4
) < 128)
868 otherCtx
.putImageData(dataDesc2
,0,0);
870 var ctx
= params
.canvas
.getContext("2d");
872 ctx
.globalAlpha
= amount
;
875 0,0,rect
.width
,rect
.height
,
876 rect
.left
,rect
.top
,rect
.width
,rect
.height
884 checkSupport : function() {
885 return Pixastic
.Client
.hasCanvasImageData();
888 * Pixastic Lib - Blur filter - v0.1.0
889 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
890 * License: [http://www.pixastic.com/lib/license.txt]
893 Pixastic
.Actions
.blur
= {
894 process : function(params
) {
896 if (typeof params
.options
.fixMargin
== "undefined")
897 params
.options
.fixMargin
= true;
899 if (Pixastic
.Client
.hasCanvasImageData()) {
900 var data
= Pixastic
.prepareData(params
);
901 var dataCopy
= Pixastic
.prepareData(params
, true)
918 for (var i
=0;i
<3;i
++) {
919 for (var j
=0;j
<3;j
++) {
920 weight
+= kernel
[i
][j
];
924 weight
= 1 / (weight
*2);
926 var rect
= params
.options
.rect
;
933 var offsetY
= (y
-1)*w4
;
935 var prevY
= (y
== 1) ? 0 : y
-2;
936 var nextY
= (y
== h
) ? y
- 1 : y
;
938 var offsetYPrev
= prevY
*w
*4;
939 var offsetYNext
= nextY
*w
*4;
943 var offset
= offsetY
+ (x
*4-4);
945 var offsetPrev
= offsetYPrev
+ ((x
== 1) ? 0 : x
-2) * 4;
946 var offsetNext
= offsetYNext
+ ((x
== w
) ? x
-1 : x
) * 4;
950 dataCopy[offsetPrev - 4]
951 + dataCopy[offsetPrev+4]
952 + dataCopy[offsetNext - 4]
953 + dataCopy[offsetNext+4]
956 (dataCopy
[offsetPrev
]
959 + dataCopy
[offsetNext
]) * 2
960 + dataCopy
[offset
] * 4
965 dataCopy[offsetPrev - 3]
966 + dataCopy[offsetPrev+5]
967 + dataCopy[offsetNext - 3]
968 + dataCopy[offsetNext+5]
971 (dataCopy
[offsetPrev
+1]
974 + dataCopy
[offsetNext
+1]) * 2
975 + dataCopy
[offset
+1] * 4
980 dataCopy[offsetPrev - 2]
981 + dataCopy[offsetPrev+6]
982 + dataCopy[offsetNext - 2]
983 + dataCopy[offsetNext+6]
986 (dataCopy
[offsetPrev
+2]
989 + dataCopy
[offsetNext
+2]) * 2
990 + dataCopy
[offset
+2] * 4
998 } else if (Pixastic
.Client
.isIE()) {
999 params
.image
.style
.filter
+= " progid:DXImageTransform.Microsoft.Blur(pixelradius=1.5)";
1001 if (params
.options
.fixMargin
) {
1002 params
.image
.style
.marginLeft
= (parseInt(params
.image
.style
.marginLeft
,10)||0) - 2 + "px";
1003 params
.image
.style
.marginTop
= (parseInt(params
.image
.style
.marginTop
,10)||0) - 2 + "px";
1009 checkSupport : function() {
1010 return (Pixastic
.Client
.hasCanvasImageData() || Pixastic
.Client
.isIE());
1013 * Pixastic Lib - Blur Fast - v0.1.1
1014 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
1015 * License: [http://www.pixastic.com/lib/license.txt]
1018 Pixastic
.Actions
.blurfast
= {
1019 process : function(params
) {
1021 var amount
= parseFloat(params
.options
.amount
)||0;
1022 var clear
= !!(params
.options
.clear
&& params
.options
.clear
!= "false");
1024 amount
= Math
.max(0,Math
.min(5,amount
));
1026 if (Pixastic
.Client
.hasCanvas()) {
1027 var rect
= params
.options
.rect
;
1029 var ctx
= params
.canvas
.getContext("2d");
1032 ctx
.rect(rect
.left
, rect
.top
, rect
.width
, rect
.height
);
1036 var smallWidth
= Math
.round(params
.width
/ scale
);
1037 var smallHeight
= Math
.round(params
.height
/ scale
);
1039 var copy
= document
.createElement("canvas");
1040 copy
.width
= smallWidth
;
1041 copy
.height
= smallHeight
;
1044 var steps
= Math
.round(amount
* 20);
1046 var copyCtx
= copy
.getContext("2d");
1047 for (var i
=0;i
<steps
;i
++) {
1048 var scaledWidth
= Math
.max(1,Math
.round(smallWidth
- i
));
1049 var scaledHeight
= Math
.max(1,Math
.round(smallHeight
- i
));
1051 copyCtx
.clearRect(0,0,smallWidth
,smallHeight
);
1055 0,0,params
.width
,params
.height
,
1056 0,0,scaledWidth
,scaledHeight
1060 ctx
.clearRect(rect
.left
,rect
.top
,rect
.width
,rect
.height
);
1064 0,0,scaledWidth
,scaledHeight
,
1065 0,0,params
.width
,params
.height
1071 params
.useData
= false;
1073 } else if (Pixastic
.Client
.isIE()) {
1074 var radius
= 10 * amount
;
1075 params
.image
.style
.filter
+= " progid:DXImageTransform.Microsoft.Blur(pixelradius=" + radius
+ ")";
1077 if (params
.options
.fixMargin
|| 1) {
1078 params
.image
.style
.marginLeft
= (parseInt(params
.image
.style
.marginLeft
,10)||0) - Math
.round(radius
) + "px";
1079 params
.image
.style
.marginTop
= (parseInt(params
.image
.style
.marginTop
,10)||0) - Math
.round(radius
) + "px";
1085 checkSupport : function() {
1086 return (Pixastic
.Client
.hasCanvas() || Pixastic
.Client
.isIE());
1090 * Pixastic Lib - Brightness/Contrast filter - v0.1.1
1091 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
1092 * License: [http://www.pixastic.com/lib/license.txt]
1095 Pixastic
.Actions
.brightness
= {
1097 process : function(params
) {
1099 var brightness
= parseInt(params
.options
.brightness
,10) || 0;
1100 var contrast
= parseFloat(params
.options
.contrast
)||0;
1101 var legacy
= !!(params
.options
.legacy
&& params
.options
.legacy
!= "false");
1104 brightness
= Math
.min(150,Math
.max(-150,brightness
));
1106 var brightMul
= 1 + Math
.min(150,Math
.max(-150,brightness
)) / 150;
1108 contrast
= Math
.max(0,contrast
+1);
1110 if (Pixastic
.Client
.hasCanvasImageData()) {
1111 var data
= Pixastic
.prepareData(params
);
1112 var rect
= params
.options
.rect
;
1114 var h
= rect
.height
;
1117 var pix
= p
*4, pix1
, pix2
;
1120 if (contrast
!= 1) {
1123 add
= (brightness
- 128) * contrast
+ 128;
1125 mul
= brightMul
* contrast
;
1126 add
= - contrast
* 128 + 128;
1128 } else { // this if-then is not necessary anymore, is it?
1139 if ((r
= data
[pix
-=4] * mul
+ add
) > 255 )
1146 if ((g
= data
[pix1
=pix
+1] * mul
+ add
) > 255 )
1153 if ((b
= data
[pix2
=pix
+2] * mul
+ add
) > 255 )
1163 checkSupport : function() {
1164 return Pixastic
.Client
.hasCanvasImageData();
1169 * Pixastic Lib - Color adjust filter - v0.1.1
1170 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
1171 * License: [http://www.pixastic.com/lib/license.txt]
1174 Pixastic
.Actions
.coloradjust
= {
1176 process : function(params
) {
1177 var red
= parseFloat(params
.options
.red
) || 0;
1178 var green
= parseFloat(params
.options
.green
) || 0;
1179 var blue
= parseFloat(params
.options
.blue
) || 0;
1181 red
= Math
.round(red
*255);
1182 green
= Math
.round(green
*255);
1183 blue
= Math
.round(blue
*255);
1185 if (Pixastic
.Client
.hasCanvasImageData()) {
1186 var data
= Pixastic
.prepareData(params
);
1187 var rect
= params
.options
.rect
;
1189 var p
= rect
.width
*rect
.height
;
1190 var pix
= p
*4, pix1
, pix2
;
1197 if ((r
= data
[pix
] + red
) < 0 )
1206 if ((g
= data
[pix1
=pix
+1] + green
) < 0 )
1215 if ((b
= data
[pix2
=pix
+2] + blue
) < 0 )
1226 checkSupport : function() {
1227 return (Pixastic
.Client
.hasCanvasImageData());
1231 * Pixastic Lib - Histogram - v0.1.0
1232 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
1233 * License: [http://www.pixastic.com/lib/license.txt]
1237 Pixastic
.Actions
.colorhistogram
= {
1239 array256 : function(default_value
) {
1241 for (var i
=0; i
<256; i
++) { arr
[i
] = default_value
; }
1245 process : function(params
) {
1247 if (typeof params
.options
.returnValue
!= "object") {
1248 params
.options
.returnValue
= {rvals
:[], gvals
:[], bvals
:[]};
1250 var paint
= !!(params
.options
.paint
);
1252 var returnValue
= params
.options
.returnValue
;
1253 if (typeof returnValue
.values
!= "array") {
1254 returnValue
.rvals
= [];
1255 returnValue
.gvals
= [];
1256 returnValue
.bvals
= [];
1259 if (Pixastic
.Client
.hasCanvasImageData()) {
1260 var data
= Pixastic
.prepareData(params
);
1261 params
.useData
= false;
1263 var rvals
= this.array256(0);
1264 var gvals
= this.array256(0);
1265 var bvals
= this.array256(0);
1267 var rect
= params
.options
.rect
;
1269 var p
= rect
.width
*rect
.height
;
1272 rvals
[data
[pix
-=4]]++;
1273 gvals
[data
[pix
+1]]++;
1274 bvals
[data
[pix
+2]]++;
1277 returnValue
.rvals
= rvals
;
1278 returnValue
.gvals
= gvals
;
1279 returnValue
.bvals
= bvals
;
1282 var ctx
= params
.canvas
.getContext("2d");
1283 var vals
= [rvals
, gvals
, bvals
];
1284 for (var v
=0;v
<3;v
++) {
1285 var yoff
= (v
+1) * params
.height
/ 3;
1287 for (var i
=0;i
<256;i
++) {
1288 if (vals
[v
][i
] > maxValue
)
1289 maxValue
= vals
[v
][i
];
1291 var heightScale
= params
.height
/ 3 / maxValue
;
1292 var widthScale
= params
.width
/ 256;
1293 if (v
==0) ctx
.fillStyle
= "rgba(255,0,0,0.5)";
1294 else if (v
==1) ctx
.fillStyle
= "rgba(0,255,0,0.5)";
1295 else if (v
==2) ctx
.fillStyle
= "rgba(0,0,255,0.5)";
1296 for (var i
=0;i
<256;i
++) {
1298 i
* widthScale
, params
.height
- heightScale
* vals
[v
][i
] - params
.height
+ yoff
,
1299 widthScale
, vals
[v
][i
] * heightScale
1308 checkSupport : function() {
1309 return Pixastic
.Client
.hasCanvasImageData();
1312 * Pixastic Lib - Crop - v0.1.1
1313 * Copyright (c) 2008-2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
1314 * License: [http://www.pixastic.com/lib/license.txt]
1317 Pixastic
.Actions
.crop
= {
1318 process : function(params
) {
1319 if (Pixastic
.Client
.hasCanvas()) {
1320 var rect
= params
.options
.rect
;
1322 var width
= rect
.width
;
1323 var height
= rect
.height
;
1325 var left
= rect
.left
;
1327 if (typeof params
.options
.left
!= "undefined")
1328 left
= parseInt(params
.options
.left
,10);
1329 if (typeof params
.options
.top
!= "undefined")
1330 top
= parseInt(params
.options
.top
,10);
1331 if (typeof params
.options
.height
!= "undefined")
1332 width
= parseInt(params
.options
.width
,10);
1333 if (typeof params
.options
.height
!= "undefined")
1334 height
= parseInt(params
.options
.height
,10);
1336 if (left
< 0) left
= 0;
1337 if (left
> params
.width
-1) left
= params
.width
-1;
1339 if (top
< 0) top
= 0;
1340 if (top
> params
.height
-1) top
= params
.height
-1;
1342 if (width
< 1) width
= 1;
1343 if (left
+ width
> params
.width
)
1344 width
= params
.width
- left
;
1346 if (height
< 1) height
= 1;
1347 if (top
+ height
> params
.height
)
1348 height
= params
.height
- top
;
1350 var copy
= document
.createElement("canvas");
1351 copy
.width
= params
.width
;
1352 copy
.height
= params
.height
;
1353 copy
.getContext("2d").drawImage(params
.canvas
,0,0);
1355 params
.canvas
.width
= width
;
1356 params
.canvas
.height
= height
;
1357 params
.canvas
.getContext("2d").clearRect(0,0,width
,height
);
1359 params
.canvas
.getContext("2d").drawImage(copy
,
1360 left
,top
,width
,height
,
1364 params
.useData
= false;
1368 checkSupport : function() {
1369 return Pixastic
.Client
.hasCanvas();
1375 * Pixastic Lib - Desaturation filter - v0.1.1
1376 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
1377 * License: [http://www.pixastic.com/lib/license.txt]
1380 Pixastic
.Actions
.desaturate
= {
1382 process : function(params
) {
1383 var useAverage
= !!(params
.options
.average
&& params
.options
.average
!= "false");
1385 if (Pixastic
.Client
.hasCanvasImageData()) {
1386 var data
= Pixastic
.prepareData(params
);
1387 var rect
= params
.options
.rect
;
1389 var h
= rect
.height
;
1392 var pix
= p
*4, pix1
, pix2
;
1396 data
[pix
-=4] = data
[pix1
=pix
+1] = data
[pix2
=pix
+2] = (data
[pix
]+data
[pix1
]+data
[pix2
])/3
1399 data
[pix
-=4] = data
[pix1
=pix
+1] = data
[pix2
=pix
+2] = (data
[pix
]*0.3 + data
[pix1
]*0.59 + data
[pix2
]*0.11);
1402 } else if (Pixastic
.Client
.isIE()) {
1403 params
.image
.style
.filter
+= " gray";
1407 checkSupport : function() {
1408 return (Pixastic
.Client
.hasCanvasImageData() || Pixastic
.Client
.isIE());
1411 * Pixastic Lib - Edge detection filter - v0.1.1
1412 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
1413 * License: [http://www.pixastic.com/lib/license.txt]
1416 Pixastic
.Actions
.edges
= {
1417 process : function(params
) {
1419 var mono
= !!(params
.options
.mono
&& params
.options
.mono
!= "false");
1420 var invert
= !!(params
.options
.invert
&& params
.options
.invert
!= "false");
1422 if (Pixastic
.Client
.hasCanvasImageData()) {
1423 var data
= Pixastic
.prepareData(params
);
1424 var dataCopy
= Pixastic
.prepareData(params
, true)
1435 var rect
= params
.options
.rect
;
1437 var h
= rect
.height
;
1442 var offsetY
= (y
-1)*w4
;
1444 var nextY
= (y
== h
) ? y
- 1 : y
;
1445 var prevY
= (y
== 1) ? 0 : y
-2;
1447 var offsetYPrev
= prevY
*w
*4;
1448 var offsetYNext
= nextY
*w
*4;
1452 var offset
= offsetY
+ (x
*4-4);
1454 var offsetPrev
= offsetYPrev
+ ((x
== 1) ? 0 : x
-2) * 4;
1455 var offsetNext
= offsetYNext
+ ((x
== w
) ? x
-1 : x
) * 4;
1457 var r
= ((dataCopy
[offsetPrev
-4]
1458 + dataCopy
[offsetPrev
]
1459 + dataCopy
[offsetPrev
+4]
1460 + dataCopy
[offset
-4]
1461 + dataCopy
[offset
+4]
1462 + dataCopy
[offsetNext
-4]
1463 + dataCopy
[offsetNext
]
1464 + dataCopy
[offsetNext
+4]) * c
1469 var g
= ((dataCopy
[offsetPrev
-3]
1470 + dataCopy
[offsetPrev
+1]
1471 + dataCopy
[offsetPrev
+5]
1472 + dataCopy
[offset
-3]
1473 + dataCopy
[offset
+5]
1474 + dataCopy
[offsetNext
-3]
1475 + dataCopy
[offsetNext
+1]
1476 + dataCopy
[offsetNext
+5]) * c
1477 + dataCopy
[offset
+1])
1480 var b
= ((dataCopy
[offsetPrev
-2]
1481 + dataCopy
[offsetPrev
+2]
1482 + dataCopy
[offsetPrev
+6]
1483 + dataCopy
[offset
-2]
1484 + dataCopy
[offset
+6]
1485 + dataCopy
[offsetNext
-2]
1486 + dataCopy
[offsetNext
+2]
1487 + dataCopy
[offsetNext
+6]) * c
1488 + dataCopy
[offset
+2])
1492 var brightness
= (r
*0.3 + g
*0.59 + b
*0.11)||0;
1493 if (invert
) brightness
= 255 - brightness
;
1494 if (brightness
< 0 ) brightness
= 0;
1495 if (brightness
> 255 ) brightness
= 255;
1496 r
= g
= b
= brightness
;
1506 if (r
> 255 ) r
= 255;
1507 if (g
> 255 ) g
= 255;
1508 if (b
> 255 ) b
= 255;
1521 checkSupport : function() {
1522 return Pixastic
.Client
.hasCanvasImageData();
1525 * Pixastic Lib - Edge detection 2 - v0.1.0
1526 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
1527 * License: [http://www.pixastic.com/lib/license.txt]
1529 * Contribution by Oliver Hunt (http://nerget.com/, http://nerget.com/canvas/edgeDetection.js). Thanks Oliver!
1533 Pixastic
.Actions
.edges2
= {
1534 process : function(params
) {
1536 if (Pixastic
.Client
.hasCanvasImageData()) {
1537 var data
= Pixastic
.prepareData(params
);
1538 var dataCopy
= Pixastic
.prepareData(params
, true)
1540 var rect
= params
.options
.rect
;
1542 var h
= rect
.height
;
1545 var pixel
= w4
+ 4; // Start at (1,1)
1548 for (var y
= 1; y
< hm1
; ++y
) {
1549 // Prepare initial cached values for current row
1550 var centerRow
= pixel
- 4;
1551 var priorRow
= centerRow
- w4
;
1552 var nextRow
= centerRow
+ w4
;
1554 var r1
= - dataCopy
[priorRow
] - dataCopy
[centerRow
] - dataCopy
[nextRow
];
1555 var g1
= - dataCopy
[++priorRow
] - dataCopy
[++centerRow
] - dataCopy
[++nextRow
];
1556 var b1
= - dataCopy
[++priorRow
] - dataCopy
[++centerRow
] - dataCopy
[++nextRow
];
1558 var rp
= dataCopy
[priorRow
+= 2];
1559 var gp
= dataCopy
[++priorRow
];
1560 var bp
= dataCopy
[++priorRow
];
1562 var rc
= dataCopy
[centerRow
+= 2];
1563 var gc
= dataCopy
[++centerRow
];
1564 var bc
= dataCopy
[++centerRow
];
1566 var rn
= dataCopy
[nextRow
+= 2];
1567 var gn
= dataCopy
[++nextRow
];
1568 var bn
= dataCopy
[++nextRow
];
1570 var r2
= - rp
- rc
- rn
;
1571 var g2
= - gp
- gc
- gn
;
1572 var b2
= - bp
- bc
- bn
;
1574 // Main convolution loop
1575 for (var x
= 1; x
< wm1
; ++x
) {
1576 centerRow
= pixel
+ 4;
1577 priorRow
= centerRow
- w4
;
1578 nextRow
= centerRow
+ w4
;
1580 var r
= 127 + r1
- rp
- (rc
* -8) - rn
;
1581 var g
= 127 + g1
- gp
- (gc
* -8) - gn
;
1582 var b
= 127 + b1
- bp
- (bc
* -8) - bn
;
1588 rp
= dataCopy
[ priorRow
];
1589 gp
= dataCopy
[++priorRow
];
1590 bp
= dataCopy
[++priorRow
];
1592 rc
= dataCopy
[ centerRow
];
1593 gc
= dataCopy
[++centerRow
];
1594 bc
= dataCopy
[++centerRow
];
1596 rn
= dataCopy
[ nextRow
];
1597 gn
= dataCopy
[++nextRow
];
1598 bn
= dataCopy
[++nextRow
];
1600 r
+= (r2
= - rp
- rc
- rn
);
1601 g
+= (g2
= - gp
- gc
- gn
);
1602 b
+= (b2
= - bp
- bc
- bn
);
1604 if (r
> 255) r
= 255;
1605 if (g
> 255) g
= 255;
1606 if (b
> 255) b
= 255;
1614 //data[++pixel] = 255; // alpha
1623 checkSupport : function() {
1624 return Pixastic
.Client
.hasCanvasImageData();
1627 * Pixastic Lib - Emboss filter - v0.1.0
1628 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
1629 * License: [http://www.pixastic.com/lib/license.txt]
1632 Pixastic
.Actions
.emboss
= {
1633 process : function(params
) {
1635 var strength
= parseFloat(params
.options
.strength
)||1;
1636 var greyLevel
= typeof params
.options
.greyLevel
!= "undefined" ? parseInt(params
.options
.greyLevel
) : 180;
1637 var direction
= params
.options
.direction
||"topleft";
1638 var blend
= !!(params
.options
.blend
&& params
.options
.blend
!= "false");
1643 switch (direction
) {
1644 case "topleft": // top left
1652 case "topright": // top right
1656 case "right": // right
1660 case "bottomright": // bottom right
1664 case "bottom": // bottom
1668 case "bottomleft": // bottom left
1672 case "left": // left
1678 if (Pixastic
.Client
.hasCanvasImageData()) {
1679 var data
= Pixastic
.prepareData(params
);
1680 var dataCopy
= Pixastic
.prepareData(params
, true)
1682 var invertAlpha
= !!params
.options
.invertAlpha
;
1683 var rect
= params
.options
.rect
;
1685 var h
= rect
.height
;
1690 var offsetY
= (y
-1)*w4
;
1693 if (y
+ otherY
< 1) otherY
= 0;
1694 if (y
+ otherY
> h
) otherY
= 0;
1696 var offsetYOther
= (y
-1+otherY
)*w
*4;
1700 var offset
= offsetY
+ (x
-1)*4;
1703 if (x
+ otherX
< 1) otherX
= 0;
1704 if (x
+ otherX
> w
) otherX
= 0;
1706 var offsetOther
= offsetYOther
+ (x
-1+otherX
)*4;
1708 var dR
= dataCopy
[offset
] - dataCopy
[offsetOther
];
1709 var dG
= dataCopy
[offset
+1] - dataCopy
[offsetOther
+1];
1710 var dB
= dataCopy
[offset
+2] - dataCopy
[offsetOther
+2];
1713 var absDif
= dif
> 0 ? dif
: -dif
;
1715 var absG
= dG
> 0 ? dG
: -dG
;
1716 var absB
= dB
> 0 ? dB
: -dB
;
1718 if (absG
> absDif
) {
1721 if (absB
> absDif
) {
1728 var r
= data
[offset
] + dif
;
1729 var g
= data
[offset
+1] + dif
;
1730 var b
= data
[offset
+2] + dif
;
1732 data
[offset
] = (r
> 255) ? 255 : (r
< 0 ? 0 : r
);
1733 data
[offset
+1] = (g
> 255) ? 255 : (g
< 0 ? 0 : g
);
1734 data
[offset
+2] = (b
> 255) ? 255 : (b
< 0 ? 0 : b
);
1736 var grey
= greyLevel
- dif
;
1739 } else if (grey
> 255) {
1743 data
[offset
] = data
[offset
+1] = data
[offset
+2] = grey
;
1750 } else if (Pixastic
.Client
.isIE()) {
1751 params
.image
.style
.filter
+= " progid:DXImageTransform.Microsoft.emboss()";
1755 checkSupport : function() {
1756 return (Pixastic
.Client
.hasCanvasImageData() || Pixastic
.Client
.isIE());
1761 * Pixastic Lib - Flip - v0.1.0
1762 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
1763 * License: [http://www.pixastic.com/lib/license.txt]
1766 Pixastic
.Actions
.flip
= {
1767 process : function(params
) {
1768 var rect
= params
.options
.rect
;
1769 var copyCanvas
= document
.createElement("canvas");
1770 copyCanvas
.width
= rect
.width
;
1771 copyCanvas
.height
= rect
.height
;
1772 copyCanvas
.getContext("2d").drawImage(params
.image
, rect
.left
, rect
.top
, rect
.width
, rect
.height
, 0, 0, rect
.width
, rect
.height
);
1774 var ctx
= params
.canvas
.getContext("2d");
1775 ctx
.clearRect(rect
.left
, rect
.top
, rect
.width
, rect
.height
);
1777 if (params
.options
.axis
== "horizontal") {
1779 ctx
.drawImage(copyCanvas
, -rect
.left
-rect
.width
, rect
.top
, rect
.width
, rect
.height
)
1782 ctx
.drawImage(copyCanvas
, rect
.left
, -rect
.top
-rect
.height
, rect
.width
, rect
.height
)
1785 params
.useData
= false;
1789 checkSupport : function() {
1790 return Pixastic
.Client
.hasCanvas();
1795 * Pixastic Lib - Horizontal flip - v0.1.0
1796 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
1797 * License: [http://www.pixastic.com/lib/license.txt]
1800 Pixastic
.Actions
.fliph
= {
1801 process : function(params
) {
1802 if (Pixastic
.Client
.hasCanvas()) {
1803 var rect
= params
.options
.rect
;
1804 var copyCanvas
= document
.createElement("canvas");
1805 copyCanvas
.width
= rect
.width
;
1806 copyCanvas
.height
= rect
.height
;
1807 copyCanvas
.getContext("2d").drawImage(params
.image
, rect
.left
, rect
.top
, rect
.width
, rect
.height
, 0, 0, rect
.width
, rect
.height
);
1809 var ctx
= params
.canvas
.getContext("2d");
1810 ctx
.clearRect(rect
.left
, rect
.top
, rect
.width
, rect
.height
);
1812 ctx
.drawImage(copyCanvas
, -rect
.left
-rect
.width
, rect
.top
, rect
.width
, rect
.height
)
1813 params
.useData
= false;
1817 } else if (Pixastic
.Client
.isIE()) {
1818 params
.image
.style
.filter
+= " fliph";
1822 checkSupport : function() {
1823 return (Pixastic
.Client
.hasCanvas() || Pixastic
.Client
.isIE());
1828 * Pixastic Lib - Vertical flip - v0.1.0
1829 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
1830 * License: [http://www.pixastic.com/lib/license.txt]
1833 Pixastic
.Actions
.flipv
= {
1834 process : function(params
) {
1835 if (Pixastic
.Client
.hasCanvas()) {
1836 var rect
= params
.options
.rect
;
1837 var copyCanvas
= document
.createElement("canvas");
1838 copyCanvas
.width
= rect
.width
;
1839 copyCanvas
.height
= rect
.height
;
1840 copyCanvas
.getContext("2d").drawImage(params
.image
, rect
.left
, rect
.top
, rect
.width
, rect
.height
, 0, 0, rect
.width
, rect
.height
);
1842 var ctx
= params
.canvas
.getContext("2d");
1843 ctx
.clearRect(rect
.left
, rect
.top
, rect
.width
, rect
.height
);
1845 ctx
.drawImage(copyCanvas
, rect
.left
, -rect
.top
-rect
.height
, rect
.width
, rect
.height
)
1846 params
.useData
= false;
1850 } else if (Pixastic
.Client
.isIE()) {
1851 params
.image
.style
.filter
+= " flipv";
1855 checkSupport : function() {
1856 return (Pixastic
.Client
.hasCanvas() || Pixastic
.Client
.isIE());
1861 * Pixastic Lib - Glow - v0.1.0
1862 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
1863 * License: [http://www.pixastic.com/lib/license.txt]
1867 Pixastic
.Actions
.glow
= {
1868 process : function(params
) {
1870 var amount
= (parseFloat(params
.options
.amount
)||0);
1871 var blurAmount
= parseFloat(params
.options
.radius
)||0;
1873 amount
= Math
.min(1,Math
.max(0,amount
));
1874 blurAmount
= Math
.min(5,Math
.max(0,blurAmount
));
1876 if (Pixastic
.Client
.hasCanvasImageData()) {
1877 var rect
= params
.options
.rect
;
1879 var blurCanvas
= document
.createElement("canvas");
1880 blurCanvas
.width
= params
.width
;
1881 blurCanvas
.height
= params
.height
;
1882 var blurCtx
= blurCanvas
.getContext("2d");
1883 blurCtx
.drawImage(params
.canvas
,0,0);
1886 var smallWidth
= Math
.round(params
.width
/ scale
);
1887 var smallHeight
= Math
.round(params
.height
/ scale
);
1889 var copy
= document
.createElement("canvas");
1890 copy
.width
= smallWidth
;
1891 copy
.height
= smallHeight
;
1894 var steps
= Math
.round(blurAmount
* 20);
1896 var copyCtx
= copy
.getContext("2d");
1897 for (var i
=0;i
<steps
;i
++) {
1898 var scaledWidth
= Math
.max(1,Math
.round(smallWidth
- i
));
1899 var scaledHeight
= Math
.max(1,Math
.round(smallHeight
- i
));
1901 copyCtx
.clearRect(0,0,smallWidth
,smallHeight
);
1905 0,0,params
.width
,params
.height
,
1906 0,0,scaledWidth
,scaledHeight
1909 blurCtx
.clearRect(0,0,params
.width
,params
.height
);
1913 0,0,scaledWidth
,scaledHeight
,
1914 0,0,params
.width
,params
.height
1918 var data
= Pixastic
.prepareData(params
);
1919 var blurData
= Pixastic
.prepareData({canvas
:blurCanvas
,options
:params
.options
});
1921 var h
= rect
.height
;
1925 var offsetY
= (y
-1)*w4
;
1928 var offset
= offsetY
+ (x
*4-4);
1930 var r
= data
[offset
] + amount
* blurData
[offset
];
1931 var g
= data
[offset
+1] + amount
* blurData
[offset
+1];
1932 var b
= data
[offset
+2] + amount
* blurData
[offset
+2];
1934 if (r
> 255) r
= 255;
1935 if (g
> 255) g
= 255;
1936 if (b
> 255) b
= 255;
1951 checkSupport : function() {
1952 return Pixastic
.Client
.hasCanvasImageData();
1959 * Pixastic Lib - Histogram - v0.1.0
1960 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
1961 * License: [http://www.pixastic.com/lib/license.txt]
1964 Pixastic
.Actions
.histogram
= {
1965 process : function(params
) {
1967 var average
= !!(params
.options
.average
&& params
.options
.average
!= "false");
1968 var paint
= !!(params
.options
.paint
&& params
.options
.paint
!= "false");
1969 var color
= params
.options
.color
|| "rgba(255,255,255,0.5)";
1971 if (typeof params
.options
.returnValue
!= "object") {
1972 params
.options
.returnValue
= {values
:[]};
1974 var returnValue
= params
.options
.returnValue
;
1975 if (typeof returnValue
.values
!= "array") {
1976 returnValue
.values
= [];
1978 values
= returnValue
.values
;
1980 if (Pixastic
.Client
.hasCanvasImageData()) {
1981 var data
= Pixastic
.prepareData(params
);
1982 params
.useData
= false;
1984 for (var i
=0;i
<256;i
++) {
1988 var rect
= params
.options
.rect
;
1990 var h
= rect
.height
;
1994 var offsetY
= (y
-1)*w4
;
1997 var offset
= offsetY
+ (x
*4-4);
1998 var brightness
= average
?
1999 Math
.round((data
[offset
]+data
[offset
+1]+data
[offset
+2])/3)
2000 : Math
.round(data
[offset
]*0.3 + data
[offset
+1]*0.59 + data
[offset
+2]*0.11);
2001 values
[brightness
]++;
2008 for (var i
=0;i
<256;i
++) {
2009 if (values
[i
] > maxValue
) {
2010 maxValue
= values
[i
];
2013 var heightScale
= params
.height
/ maxValue
;
2014 var widthScale
= params
.width
/ 256;
2015 var ctx
= params
.canvas
.getContext("2d");
2016 ctx
.fillStyle
= color
;
2017 for (var i
=0;i
<256;i
++) {
2019 i
* widthScale
, params
.height
- heightScale
* values
[i
],
2020 widthScale
, values
[i
] * heightScale
2025 returnValue
.values
= values
;
2030 checkSupport : function() {
2031 return Pixastic
.Client
.hasCanvasImageData();
2035 * Pixastic Lib - HSL Adjust - v0.1.0
2036 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
2037 * License: [http://www.pixastic.com/lib/license.txt]
2040 Pixastic
.Actions
.hsl
= {
2041 process : function(params
) {
2043 var hue
= parseInt(params
.options
.hue
,10)||0;
2044 var saturation
= (parseInt(params
.options
.saturation
,10)||0) / 100;
2045 var lightness
= (parseInt(params
.options
.lightness
,10)||0) / 100;
2048 // this seems to give the same result as Photoshop
2049 if (saturation
< 0) {
2050 var satMul
= 1+saturation
;
2052 var satMul
= 1+saturation
*2;
2055 hue
= (hue
%360) / 360;
2058 var rgbDiv
= 1 / 255;
2060 var light255
= lightness
* 255;
2061 var lightp1
= 1 + lightness
;
2062 var lightm1
= 1 - lightness
;
2063 if (Pixastic
.Client
.hasCanvasImageData()) {
2064 var data
= Pixastic
.prepareData(params
);
2066 var rect
= params
.options
.rect
;
2068 var h
= rect
.height
;
2074 var offsetY
= (y
-1)*w4
;
2077 var offset
= offsetY
+ (x
*4-4);
2079 var r
= data
[offset
];
2080 var g
= data
[offset
+1];
2081 var b
= data
[offset
+2];
2083 if (hue
!= 0 || saturation
!= 0) {
2084 // ok, here comes rgb to hsl + adjust + hsl to rgb, all in one jumbled mess.
2085 // It's not so pretty, but it's been optimized to get somewhat decent performance.
2086 // The transforms were originally adapted from the ones found in Graphics Gems, but have been heavily modified.
2094 var l
= (ms
+vs
)/255 * 0.5;
2098 var s
= vm
/ (vs
+ms
) * satMul
;
2100 var v
= (l
* (1+s
));
2102 var s
= vm
/ (510-vs
-ms
) * satMul
;
2104 var v
= (l
+s
- l
*s
);
2108 var h
= 5 + ((vs
-b
)/vm
) + hue6
;
2110 var h
= 1 - ((vs
-g
)/vm
) + hue6
;
2111 } else if (g
== vs
) {
2113 var h
= 1 + ((vs
-r
)/vm
) + hue6
;
2115 var h
= 3 - ((vs
-b
)/vm
) + hue6
;
2118 var h
= 3 + ((vs
-g
)/vm
) + hue6
;
2120 var h
= 5 - ((vs
-r
)/vm
) + hue6
;
2127 case 0: r
= v
*255; g
= (m
+((v
-m
)*(h
-sextant
)))*255; b
= m
*255; break;
2128 case 1: r
= (v
-((v
-m
)*(h
-sextant
)))*255; g
= v
*255; b
= m
*255; break;
2129 case 2: r
= m
*255; g
= v
*255; b
= (m
+((v
-m
)*(h
-sextant
)))*255; break;
2130 case 3: r
= m
*255; g
= (v
-((v
-m
)*(h
-sextant
)))*255; b
= v
*255; break;
2131 case 4: r
= (m
+((v
-m
)*(h
-sextant
)))*255; g
= m
*255; b
= v
*255; break;
2132 case 5: r
= v
*255; g
= m
*255; b
= (v
-((v
-m
)*(h
-sextant
)))*255; break;
2138 if (lightness
< 0) {
2142 } else if (lightness
> 0) {
2143 r
= r
* lightm1
+ light255
;
2144 g
= g
* lightm1
+ light255
;
2145 b
= b
* lightm1
+ light255
;
2151 if (r
> 255) r
= 255;
2152 if (g
> 255) g
= 255;
2153 if (b
> 255) b
= 255;
2164 checkSupport : function() {
2165 return Pixastic
.Client
.hasCanvasImageData();
2170 * Pixastic Lib - Invert filter - v0.1.0
2171 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
2172 * License: [http://www.pixastic.com/lib/license.txt]
2175 Pixastic
.Actions
.invert
= {
2176 process : function(params
) {
2177 if (Pixastic
.Client
.hasCanvasImageData()) {
2178 var data
= Pixastic
.prepareData(params
);
2180 var invertAlpha
= !!params
.options
.invertAlpha
;
2181 var rect
= params
.options
.rect
;
2183 var h
= rect
.height
;
2188 var offsetY
= (y
-1)*w4
;
2191 var offset
= offsetY
+ (x
-1)*4;
2192 data
[offset
] = 255 - data
[offset
];
2193 data
[offset
+1] = 255 - data
[offset
+1];
2194 data
[offset
+2] = 255 - data
[offset
+2];
2195 if (invertAlpha
) data
[offset
+3] = 255 - data
[offset
+3];
2200 } else if (Pixastic
.Client
.isIE()) {
2201 params
.image
.style
.filter
+= " invert";
2205 checkSupport : function() {
2206 return (Pixastic
.Client
.hasCanvasImageData() || Pixastic
.Client
.isIE());
2210 * Pixastic Lib - Laplace filter - v0.1.0
2211 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
2212 * License: [http://www.pixastic.com/lib/license.txt]
2215 Pixastic
.Actions
.laplace
= {
2216 process : function(params
) {
2219 var invert
= !!(params
.options
.invert
&& params
.options
.invert
!= "false");
2220 var contrast
= parseFloat(params
.options
.edgeStrength
)||0;
2222 var greyLevel
= parseInt(params
.options
.greyLevel
)||0;
2224 contrast
= -contrast
;
2226 if (Pixastic
.Client
.hasCanvasImageData()) {
2227 var data
= Pixastic
.prepareData(params
);
2228 var dataCopy
= Pixastic
.prepareData(params
, true)
2238 var rect
= params
.options
.rect
;
2240 var h
= rect
.height
;
2245 var offsetY
= (y
-1)*w4
;
2247 var nextY
= (y
== h
) ? y
- 1 : y
;
2248 var prevY
= (y
== 1) ? 0 : y
-2;
2250 var offsetYPrev
= prevY
*w
*4;
2251 var offsetYNext
= nextY
*w
*4;
2255 var offset
= offsetY
+ (x
*4-4);
2257 var offsetPrev
= offsetYPrev
+ ((x
== 1) ? 0 : x
-2) * 4;
2258 var offsetNext
= offsetYNext
+ ((x
== w
) ? x
-1 : x
) * 4;
2260 var r
= ((-dataCopy
[offsetPrev
-4]
2261 - dataCopy
[offsetPrev
]
2262 - dataCopy
[offsetPrev
+4]
2263 - dataCopy
[offset
-4]
2264 - dataCopy
[offset
+4]
2265 - dataCopy
[offsetNext
-4]
2266 - dataCopy
[offsetNext
]
2267 - dataCopy
[offsetNext
+4])
2268 + dataCopy
[offset
] * 8)
2271 var g
= ((-dataCopy
[offsetPrev
-3]
2272 - dataCopy
[offsetPrev
+1]
2273 - dataCopy
[offsetPrev
+5]
2274 - dataCopy
[offset
-3]
2275 - dataCopy
[offset
+5]
2276 - dataCopy
[offsetNext
-3]
2277 - dataCopy
[offsetNext
+1]
2278 - dataCopy
[offsetNext
+5])
2279 + dataCopy
[offset
+1] * 8)
2282 var b
= ((-dataCopy
[offsetPrev
-2]
2283 - dataCopy
[offsetPrev
+2]
2284 - dataCopy
[offsetPrev
+6]
2285 - dataCopy
[offset
-2]
2286 - dataCopy
[offset
+6]
2287 - dataCopy
[offsetNext
-2]
2288 - dataCopy
[offsetNext
+2]
2289 - dataCopy
[offsetNext
+6])
2290 + dataCopy
[offset
+2] * 8)
2293 var brightness
= ((r
+ g
+ b
)/3) + greyLevel
;
2295 if (contrast
!= 0) {
2296 if (brightness
> 127) {
2297 brightness
+= ((brightness
+ 1) - 128) * contrast
;
2298 } else if (brightness
< 127) {
2299 brightness
-= (brightness
+ 1) * contrast
;
2303 brightness
= 255 - brightness
;
2305 if (brightness
< 0 ) brightness
= 0;
2306 if (brightness
> 255 ) brightness
= 255;
2308 data
[offset
] = data
[offset
+1] = data
[offset
+2] = brightness
;
2316 checkSupport : function() {
2317 return Pixastic
.Client
.hasCanvasImageData();
2322 * Pixastic Lib - Lighten filter - v0.1.0
2323 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
2324 * License: [http://www.pixastic.com/lib/license.txt]
2327 Pixastic
.Actions
.lighten
= {
2329 process : function(params
) {
2330 var amount
= parseFloat(params
.options
.amount
) || 0;
2332 if (Pixastic
.Client
.hasCanvasImageData()) {
2333 var data
= Pixastic
.prepareData(params
);
2334 var rect
= params
.options
.rect
;
2336 var h
= rect
.height
;
2340 var offsetY
= (y
-1)*w4
;
2343 var offset
= offsetY
+ (x
-1)*4;
2345 var r
= data
[offset
];
2346 var g
= data
[offset
+1];
2347 var b
= data
[offset
+2];
2356 if (r
> 255 ) r
= 255;
2357 if (g
> 255 ) g
= 255;
2358 if (b
> 255 ) b
= 255;
2368 } else if (Pixastic
.Client
.isIE()) {
2369 var img
= params
.image
;
2371 img
.style
.filter
+= " light()";
2372 img
.filters
[img
.filters
.length
-1].addAmbient(
2376 } else if (amount
> 0) {
2377 img
.style
.filter
+= " light()";
2378 img
.filters
[img
.filters
.length
-1].addAmbient(
2382 img
.filters
[img
.filters
.length
-1].addAmbient(
2390 checkSupport : function() {
2391 return (Pixastic
.Client
.hasCanvasImageData() || Pixastic
.Client
.isIE());
2395 * Pixastic Lib - Mosaic filter - v0.1.0
2396 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
2397 * License: [http://www.pixastic.com/lib/license.txt]
2400 Pixastic
.Actions
.mosaic
= {
2402 process : function(params
) {
2403 var blockSize
= Math
.max(1,parseInt(params
.options
.blockSize
,10));
2405 if (Pixastic
.Client
.hasCanvasImageData()) {
2406 var rect
= params
.options
.rect
;
2408 var h
= rect
.height
;
2412 var ctx
= params
.canvas
.getContext("2d");
2414 var pixel
= document
.createElement("canvas");
2415 pixel
.width
= pixel
.height
= 1;
2416 var pixelCtx
= pixel
.getContext("2d");
2418 var copy
= document
.createElement("canvas");
2421 var copyCtx
= copy
.getContext("2d");
2422 copyCtx
.drawImage(params
.canvas
,rect
.left
,rect
.top
,w
,h
, 0,0,w
,h
);
2424 for (var y
=0;y
<h
;y
+=blockSize
) {
2425 for (var x
=0;x
<w
;x
+=blockSize
) {
2426 var blockSizeX
= blockSize
;
2427 var blockSizeY
= blockSize
;
2429 if (blockSizeX
+ x
> w
)
2431 if (blockSizeY
+ y
> h
)
2434 pixelCtx
.drawImage(copy
, x
, y
, blockSizeX
, blockSizeY
, 0, 0, 1, 1);
2435 var data
= pixelCtx
.getImageData(0,0,1,1).data
;
2436 ctx
.fillStyle
= "rgb(" + data
[0] + "," + data
[1] + "," + data
[2] + ")";
2437 ctx
.fillRect(rect
.left
+ x
, rect
.top
+ y
, blockSize
, blockSize
);
2440 params
.useData
= false;
2445 checkSupport : function() {
2446 return (Pixastic
.Client
.hasCanvasImageData());
2449 * Pixastic Lib - Noise filter - v0.1.0
2450 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
2451 * License: [http://www.pixastic.com/lib/license.txt]
2454 Pixastic
.Actions
.noise
= {
2456 process : function(params
) {
2461 if (typeof params
.options
.amount
!= "undefined")
2462 amount
= parseFloat(params
.options
.amount
)||0;
2463 if (typeof params
.options
.strength
!= "undefined")
2464 strength
= parseFloat(params
.options
.strength
)||0;
2465 if (typeof params
.options
.mono
!= "undefined")
2466 mono
= !!(params
.options
.mono
&& params
.options
.mono
!= "false");
2468 amount
= Math
.max(0,Math
.min(1,amount
));
2469 strength
= Math
.max(0,Math
.min(1,strength
));
2471 var noise
= 128 * strength
;
2472 var noise2
= noise
/ 2;
2474 if (Pixastic
.Client
.hasCanvasImageData()) {
2475 var data
= Pixastic
.prepareData(params
);
2476 var rect
= params
.options
.rect
;
2478 var h
= rect
.height
;
2481 var random
= Math
.random
;
2484 var offsetY
= (y
-1)*w4
;
2487 var offset
= offsetY
+ (x
-1)*4;
2488 if (random() < amount
) {
2490 var pixelNoise
= - noise2
+ random() * noise
;
2491 var r
= data
[offset
] + pixelNoise
;
2492 var g
= data
[offset
+1] + pixelNoise
;
2493 var b
= data
[offset
+2] + pixelNoise
;
2495 var r
= data
[offset
] - noise2
+ (random() * noise
);
2496 var g
= data
[offset
+1] - noise2
+ (random() * noise
);
2497 var b
= data
[offset
+2] - noise2
+ (random() * noise
);
2503 if (r
> 255 ) r
= 255;
2504 if (g
> 255 ) g
= 255;
2505 if (b
> 255 ) b
= 255;
2516 checkSupport : function() {
2517 return Pixastic
.Client
.hasCanvasImageData();
2522 * Pixastic Lib - Posterize effect - v0.1.0
2523 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
2524 * License: [http://www.pixastic.com/lib/license.txt]
2527 Pixastic
.Actions
.posterize
= {
2529 process : function(params
) {
2532 var numLevels
= 256;
2533 if (typeof params
.options
.levels
!= "undefined")
2534 numLevels
= parseInt(params
.options
.levels
,10)||1;
2536 if (Pixastic
.Client
.hasCanvasImageData()) {
2537 var data
= Pixastic
.prepareData(params
);
2539 numLevels
= Math
.max(2,Math
.min(256,numLevels
));
2541 var numAreas
= 256 / numLevels
;
2542 var numValues
= 256 / (numLevels
-1);
2544 var rect
= params
.options
.rect
;
2546 var h
= rect
.height
;
2550 var offsetY
= (y
-1)*w4
;
2553 var offset
= offsetY
+ (x
-1)*4;
2555 var r
= numValues
* ((data
[offset
] / numAreas
)>>0);
2556 var g
= numValues
* ((data
[offset
+1] / numAreas
)>>0);
2557 var b
= numValues
* ((data
[offset
+2] / numAreas
)>>0);
2559 if (r
> 255) r
= 255;
2560 if (g
> 255) g
= 255;
2561 if (b
> 255) b
= 255;
2572 checkSupport : function() {
2573 return Pixastic
.Client
.hasCanvasImageData();
2579 * Pixastic Lib - Pointillize filter - v0.1.0
2580 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
2581 * License: [http://www.pixastic.com/lib/license.txt]
2584 Pixastic
.Actions
.pointillize
= {
2586 process : function(params
) {
2587 var radius
= Math
.max(1,parseInt(params
.options
.radius
,10));
2588 var density
= Math
.min(5,Math
.max(0,parseFloat(params
.options
.density
)||0));
2589 var noise
= Math
.max(0,parseFloat(params
.options
.noise
)||0);
2590 var transparent
= !!(params
.options
.transparent
&& params
.options
.transparent
!= "false");
2592 if (Pixastic
.Client
.hasCanvasImageData()) {
2593 var rect
= params
.options
.rect
;
2595 var h
= rect
.height
;
2599 var ctx
= params
.canvas
.getContext("2d");
2600 var canvasWidth
= params
.canvas
.width
;
2601 var canvasHeight
= params
.canvas
.height
;
2603 var pixel
= document
.createElement("canvas");
2604 pixel
.width
= pixel
.height
= 1;
2605 var pixelCtx
= pixel
.getContext("2d");
2607 var copy
= document
.createElement("canvas");
2610 var copyCtx
= copy
.getContext("2d");
2611 copyCtx
.drawImage(params
.canvas
,rect
.left
,rect
.top
,w
,h
, 0,0,w
,h
);
2613 var diameter
= radius
* 2;
2616 ctx
.clearRect(rect
.left
, rect
.top
, rect
.width
, rect
.height
);
2618 var noiseRadius
= radius
* noise
;
2620 var dist
= 1 / density
;
2622 for (var y
=0;y
<h
+radius
;y
+=diameter
*dist
) {
2623 for (var x
=0;x
<w
+radius
;x
+=diameter
*dist
) {
2624 rndX
= noise
? (x
+((Math
.random()*2-1) * noiseRadius
))>>0 : x
;
2625 rndY
= noise
? (y
+((Math
.random()*2-1) * noiseRadius
))>>0 : y
;
2627 var pixX
= rndX
- radius
;
2628 var pixY
= rndY
- radius
;
2629 if (pixX
< 0) pixX
= 0;
2630 if (pixY
< 0) pixY
= 0;
2632 var cx
= rndX
+ rect
.left
;
2633 var cy
= rndY
+ rect
.top
;
2635 if (cx
> canvasWidth
) cx
= canvasWidth
;
2637 if (cy
> canvasHeight
) cy
= canvasHeight
;
2639 var diameterX
= diameter
;
2640 var diameterY
= diameter
;
2642 if (diameterX
+ pixX
> w
)
2643 diameterX
= w
- pixX
;
2644 if (diameterY
+ pixY
> h
)
2645 diameterY
= h
- pixY
;
2646 if (diameterX
< 1) diameterX
= 1;
2647 if (diameterY
< 1) diameterY
= 1;
2649 pixelCtx
.drawImage(copy
, pixX
, pixY
, diameterX
, diameterY
, 0, 0, 1, 1);
2650 var data
= pixelCtx
.getImageData(0,0,1,1).data
;
2652 ctx
.fillStyle
= "rgb(" + data
[0] + "," + data
[1] + "," + data
[2] + ")";
2654 ctx
.arc(cx
, cy
, radius
, 0, Math
.PI
*2, true);
2660 params
.useData
= false;
2665 checkSupport : function() {
2666 return (Pixastic
.Client
.hasCanvasImageData());
2669 * Pixastic Lib - Resize - v0.1.0
2670 * Copyright (c) 2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
2671 * License: [http://www.pixastic.com/lib/license.txt]
2674 Pixastic
.Actions
.resize
= {
2675 process : function(params
) {
2676 if (Pixastic
.Client
.hasCanvas()) {
2677 var width
= parseInt(params
.options
.width
,10);
2678 var height
= parseInt(params
.options
.height
,10);
2679 var canvas
= params
.canvas
;
2681 if (width
< 1) width
= 1;
2682 if (width
< 2) width
= 2;
2684 var copy
= document
.createElement("canvas");
2686 copy
.height
= height
;
2688 copy
.getContext("2d").drawImage(canvas
,0,0,width
,height
);
2689 canvas
.width
= width
;
2690 canvas
.height
= height
;
2692 canvas
.getContext("2d").drawImage(copy
,0,0);
2694 params
.useData
= false;
2698 checkSupport : function() {
2699 return Pixastic
.Client
.hasCanvas();
2705 * Pixastic Lib - Remove noise - v0.1.0
2706 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
2707 * License: [http://www.pixastic.com/lib/license.txt]
2710 Pixastic
.Actions
.removenoise
= {
2711 process : function(params
) {
2713 if (Pixastic
.Client
.hasCanvasImageData()) {
2714 var data
= Pixastic
.prepareData(params
);
2716 var rect
= params
.options
.rect
;
2718 var h
= rect
.height
;
2723 var offsetY
= (y
-1)*w4
;
2725 var nextY
= (y
== h
) ? y
- 1 : y
;
2726 var prevY
= (y
== 1) ? 0 : y
-2;
2728 var offsetYPrev
= prevY
*w
*4;
2729 var offsetYNext
= nextY
*w
*4;
2733 var offset
= offsetY
+ (x
*4-4);
2735 var offsetPrev
= offsetYPrev
+ ((x
== 1) ? 0 : x
-2) * 4;
2736 var offsetNext
= offsetYNext
+ ((x
== w
) ? x
-1 : x
) * 4;
2738 var minR
, maxR
, minG
, maxG
, minB
, maxB
;
2740 minR
= maxR
= data
[offsetPrev
];
2741 var r1
= data
[offset
-4], r2
= data
[offset
+4], r3
= data
[offsetNext
];
2742 if (r1
< minR
) minR
= r1
;
2743 if (r2
< minR
) minR
= r2
;
2744 if (r3
< minR
) minR
= r3
;
2745 if (r1
> maxR
) maxR
= r1
;
2746 if (r2
> maxR
) maxR
= r2
;
2747 if (r3
> maxR
) maxR
= r3
;
2749 minG
= maxG
= data
[offsetPrev
+1];
2750 var g1
= data
[offset
-3], g2
= data
[offset
+5], g3
= data
[offsetNext
+1];
2751 if (g1
< minG
) minG
= g1
;
2752 if (g2
< minG
) minG
= g2
;
2753 if (g3
< minG
) minG
= g3
;
2754 if (g1
> maxG
) maxG
= g1
;
2755 if (g2
> maxG
) maxG
= g2
;
2756 if (g3
> maxG
) maxG
= g3
;
2758 minB
= maxB
= data
[offsetPrev
+2];
2759 var b1
= data
[offset
-2], b2
= data
[offset
+6], b3
= data
[offsetNext
+2];
2760 if (b1
< minB
) minB
= b1
;
2761 if (b2
< minB
) minB
= b2
;
2762 if (b3
< minB
) minB
= b3
;
2763 if (b1
> maxB
) maxB
= b1
;
2764 if (b2
> maxB
) maxB
= b2
;
2765 if (b3
> maxB
) maxB
= b3
;
2767 if (data
[offset
] > maxR
) {
2768 data
[offset
] = maxR
;
2769 } else if (data
[offset
] < minR
) {
2770 data
[offset
] = minR
;
2772 if (data
[offset
+1] > maxG
) {
2773 data
[offset
+1] = maxG
;
2774 } else if (data
[offset
+1] < minG
) {
2775 data
[offset
+1] = minG
;
2777 if (data
[offset
+2] > maxB
) {
2778 data
[offset
+2] = maxB
;
2779 } else if (data
[offset
+2] < minB
) {
2780 data
[offset
+2] = minB
;
2789 checkSupport : function() {
2790 return Pixastic
.Client
.hasCanvasImageData();
2793 * Pixastic Lib - Rotate - v0.1.0
2794 * Copyright (c) 2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
2795 * License: [http://www.pixastic.com/lib/license.txt]
2798 Pixastic
.Actions
.rotate
= {
2799 process : function(params
) {
2800 if (Pixastic
.Client
.hasCanvas()) {
2801 var canvas
= params
.canvas
;
2803 var width
= params
.width
;
2804 var height
= params
.height
;
2806 var copy
= document
.createElement("canvas");
2808 copy
.height
= height
;
2809 copy
.getContext("2d").drawImage(canvas
,0,0,width
,height
);
2811 var angle
= -parseFloat(params
.options
.angle
) * Math
.PI
/ 180;
2813 var dimAngle
= angle
;
2814 if (dimAngle
> Math
.PI
*0.5)
2815 dimAngle
= Math
.PI
- dimAngle
;
2816 if (dimAngle
< -Math
.PI
*0.5)
2817 dimAngle
= -Math
.PI
- dimAngle
;
2819 var diag
= Math
.sqrt(width
*width
+ height
*height
);
2821 var diagAngle1
= Math
.abs(dimAngle
) - Math
.abs(Math
.atan2(height
, width
));
2822 var diagAngle2
= Math
.abs(dimAngle
) + Math
.abs(Math
.atan2(height
, width
));
2824 var newWidth
= Math
.abs(Math
.cos(diagAngle1
) * diag
);
2825 var newHeight
= Math
.abs(Math
.sin(diagAngle2
) * diag
);
2827 canvas
.width
= newWidth
;
2828 canvas
.height
= newHeight
;
2830 var ctx
= canvas
.getContext("2d");
2831 ctx
.translate(newWidth
/2, newHeight/2);
2833 ctx
.drawImage(copy
,-width
/2,-height/2);
2835 params
.useData
= false;
2839 checkSupport : function() {
2840 return Pixastic
.Client
.hasCanvas();
2846 * Pixastic Lib - Sepia filter - v0.1.0
2847 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
2848 * License: [http://www.pixastic.com/lib/license.txt]
2851 Pixastic
.Actions
.sepia
= {
2853 process : function(params
) {
2854 var mode
= (parseInt(params
.options
.mode
,10)||0);
2855 if (mode
< 0) mode
= 0;
2856 if (mode
> 1) mode
= 1;
2858 if (Pixastic
.Client
.hasCanvasImageData()) {
2859 var data
= Pixastic
.prepareData(params
);
2860 var rect
= params
.options
.rect
;
2862 var h
= rect
.height
;
2866 var offsetY
= (y
-1)*w4
;
2869 var offset
= offsetY
+ (x
-1)*4;
2872 // a bit faster, but not as good
2873 var d
= data
[offset
] * 0.299 + data
[offset
+1] * 0.587 + data
[offset
+2] * 0.114;
2879 var or
= data
[offset
];
2880 var og
= data
[offset
+1];
2881 var ob
= data
[offset
+2];
2883 var r
= (or
* 0.393 + og
* 0.769 + ob
* 0.189);
2884 var g
= (or
* 0.349 + og
* 0.686 + ob
* 0.168);
2885 var b
= (or
* 0.272 + og
* 0.534 + ob
* 0.131);
2888 if (r
< 0) r
= 0; if (r
> 255) r
= 255;
2889 if (g
< 0) g
= 0; if (g
> 255) g
= 255;
2890 if (b
< 0) b
= 0; if (b
> 255) b
= 255;
2901 checkSupport : function() {
2902 return Pixastic
.Client
.hasCanvasImageData();
2905 * Pixastic Lib - Sharpen filter - v0.1.0
2906 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
2907 * License: [http://www.pixastic.com/lib/license.txt]
2910 Pixastic
.Actions
.sharpen
= {
2911 process : function(params
) {
2914 if (typeof params
.options
.amount
!= "undefined")
2915 strength
= parseFloat(params
.options
.amount
)||0;
2917 if (strength
< 0) strength
= 0;
2918 if (strength
> 1) strength
= 1;
2920 if (Pixastic
.Client
.hasCanvasImageData()) {
2921 var data
= Pixastic
.prepareData(params
);
2922 var dataCopy
= Pixastic
.prepareData(params
, true)
2925 var mulOther
= 1 + 3*strength
;
2929 [-mulOther
, mul
, -mulOther
],
2934 for (var i
=0;i
<3;i
++) {
2935 for (var j
=0;j
<3;j
++) {
2936 weight
+= kernel
[i
][j
];
2940 weight
= 1 / weight
;
2942 var rect
= params
.options
.rect
;
2944 var h
= rect
.height
;
2952 var offsetY
= (y
-1)*w4
;
2954 var nextY
= (y
== h
) ? y
- 1 : y
;
2955 var prevY
= (y
== 1) ? 0 : y
-2;
2957 var offsetYPrev
= prevY
*w4
;
2958 var offsetYNext
= nextY
*w4
;
2962 var offset
= offsetY
+ (x
*4-4);
2964 var offsetPrev
= offsetYPrev
+ ((x
== 1) ? 0 : x
-2) * 4;
2965 var offsetNext
= offsetYNext
+ ((x
== w
) ? x
-1 : x
) * 4;
2968 - dataCopy
[offsetPrev
]
2969 - dataCopy
[offset
-4]
2970 - dataCopy
[offset
+4]
2971 - dataCopy
[offsetNext
]) * mulOther
2972 + dataCopy
[offset
] * mul
2976 - dataCopy
[offsetPrev
+1]
2977 - dataCopy
[offset
-3]
2978 - dataCopy
[offset
+5]
2979 - dataCopy
[offsetNext
+1]) * mulOther
2980 + dataCopy
[offset
+1] * mul
2984 - dataCopy
[offsetPrev
+2]
2985 - dataCopy
[offset
-2]
2986 - dataCopy
[offset
+6]
2987 - dataCopy
[offsetNext
+2]) * mulOther
2988 + dataCopy
[offset
+2] * mul
2995 if (r
> 255 ) r
= 255;
2996 if (g
> 255 ) g
= 255;
2997 if (b
> 255 ) b
= 255;
3010 checkSupport : function() {
3011 return Pixastic
.Client
.hasCanvasImageData();
3015 * Pixastic Lib - Solarize filter - v0.1.0
3016 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
3017 * License: [http://www.pixastic.com/lib/license.txt]
3020 Pixastic
.Actions
.solarize
= {
3022 process : function(params
) {
3023 var useAverage
= !!(params
.options
.average
&& params
.options
.average
!= "false");
3025 if (Pixastic
.Client
.hasCanvasImageData()) {
3026 var data
= Pixastic
.prepareData(params
);
3027 var rect
= params
.options
.rect
;
3029 var h
= rect
.height
;
3033 var offsetY
= (y
-1)*w4
;
3036 var offset
= offsetY
+ (x
-1)*4;
3038 var r
= data
[offset
];
3039 var g
= data
[offset
+1];
3040 var b
= data
[offset
+2];
3042 if (r
> 127) r
= 255 - r
;
3043 if (g
> 127) g
= 255 - g
;
3044 if (b
> 127) b
= 255 - b
;
3055 checkSupport : function() {
3056 return (Pixastic
.Client
.hasCanvasImageData());
3059 * Pixastic Lib - USM - v0.1.0
3060 * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
3061 * License: [http://www.pixastic.com/lib/license.txt]
3065 Pixastic
.Actions
.unsharpmask
= {
3066 process : function(params
) {
3068 var amount
= (parseFloat(params
.options
.amount
)||0);
3069 var blurAmount
= parseFloat(params
.options
.radius
)||0;
3070 var threshold
= parseFloat(params
.options
.threshold
)||0;
3072 amount
= Math
.min(500,Math
.max(0,amount
)) / 2;
3073 blurAmount
= Math
.min(5,Math
.max(0,blurAmount
)) / 10;
3074 threshold
= Math
.min(255,Math
.max(0,threshold
));
3077 var thresholdNeg
= -threshold
;
3082 if (Pixastic
.Client
.hasCanvasImageData()) {
3083 var rect
= params
.options
.rect
;
3085 var blurCanvas
= document
.createElement("canvas");
3086 blurCanvas
.width
= params
.width
;
3087 blurCanvas
.height
= params
.height
;
3088 var blurCtx
= blurCanvas
.getContext("2d");
3089 blurCtx
.drawImage(params
.canvas
,0,0);
3092 var smallWidth
= Math
.round(params
.width
/ scale
);
3093 var smallHeight
= Math
.round(params
.height
/ scale
);
3095 var copy
= document
.createElement("canvas");
3096 copy
.width
= smallWidth
;
3097 copy
.height
= smallHeight
;
3099 var steps
= Math
.round(blurAmount
* 20);
3101 var copyCtx
= copy
.getContext("2d");
3102 for (var i
=0;i
<steps
;i
++) {
3103 var scaledWidth
= Math
.max(1,Math
.round(smallWidth
- i
));
3104 var scaledHeight
= Math
.max(1,Math
.round(smallHeight
- i
));
3106 copyCtx
.clearRect(0,0,smallWidth
,smallHeight
);
3110 0,0,params
.width
,params
.height
,
3111 0,0,scaledWidth
,scaledHeight
3114 blurCtx
.clearRect(0,0,params
.width
,params
.height
);
3118 0,0,scaledWidth
,scaledHeight
,
3119 0,0,params
.width
,params
.height
3123 var data
= Pixastic
.prepareData(params
);
3124 var blurData
= Pixastic
.prepareData({canvas
:blurCanvas
,options
:params
.options
});
3126 var h
= rect
.height
;
3130 var offsetY
= (y
-1)*w4
;
3133 var offset
= offsetY
+ (x
*4-4);
3135 var difR
= data
[offset
] - blurData
[offset
];
3136 if (difR
> threshold
|| difR
< thresholdNeg
) {
3137 var blurR
= blurData
[offset
];
3138 blurR
= amount
* difR
+ blurR
;
3139 data
[offset
] = blurR
> 255 ? 255 : (blurR
< 0 ? 0 : blurR
);
3142 var difG
= data
[offset
+1] - blurData
[offset
+1];
3143 if (difG
> threshold
|| difG
< thresholdNeg
) {
3144 var blurG
= blurData
[offset
+1];
3145 blurG
= amount
* difG
+ blurG
;
3146 data
[offset
+1] = blurG
> 255 ? 255 : (blurG
< 0 ? 0 : blurG
);
3149 var difB
= data
[offset
+2] - blurData
[offset
+2];
3150 if (difB
> threshold
|| difB
< thresholdNeg
) {
3151 var blurB
= blurData
[offset
+2];
3152 blurB
= amount
* difB
+ blurB
;
3153 data
[offset
+2] = blurB
> 255 ? 255 : (blurB
< 0 ? 0 : blurB
);
3162 checkSupport : function() {
3163 return Pixastic
.Client
.hasCanvasImageData();