Commit RELEASE-NOTES line for the wgCategories js variable I added some time ago.
[lhc/web/wiklou.git] / js2 / mwEmbed / libClipEdit / pixastic-editor / pixastic.all.js
1 /*
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]
5 */
6
7 var Pixastic = (function() {
8
9
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);
15 }
16
17 function onready(handler) {
18 var handlerDone = false;
19 var execHandler = function() {
20 if (!handlerDone) {
21 handlerDone = true;
22 handler();
23 }
24 }
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);
30 execHandler();
31 }
32 }
33 if (document.addEventListener)
34 document.addEventListener("DOMContentLoaded", execHandler, false);
35 addEvent(window, "load", execHandler);
36 }
37
38 function init() {
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++) {
44 (function() {
45
46 var el = elements[i];
47 var actions = [];
48 var classes = el.className.split(" ");
49 for (var c=0;c<classes.length;c++) {
50 var cls = classes[c];
51 if (cls.substring(0,9) == "pixastic-") {
52 var actionName = cls.substring(9);
53 if (actionName != "")
54 actions.push(actionName);
55 }
56 }
57 if (actions.length) {
58 if (el.tagName.toLowerCase() == "img") {
59 var dataImg = new Image();
60 dataImg.src = el.src;
61 if (dataImg.complete) {
62 for (var a=0;a<actions.length;a++) {
63 var res = Pixastic.applyAction(el, el, actions[a], null);
64 if (res)
65 el = res;
66 }
67 } else {
68 dataImg.onload = function() {
69 for (var a=0;a<actions.length;a++) {
70 var res = Pixastic.applyAction(el, el, actions[a], null)
71 if (res)
72 el = res;
73 }
74 }
75 }
76 } else {
77 setTimeout(function() {
78 for (var a=0;a<actions.length;a++) {
79 var res = Pixastic.applyAction(
80 el, el, actions[a], null
81 );
82 if (res)
83 el = res;
84 }
85 },1);
86 }
87 }
88
89 })();
90 }
91 }
92
93 // if (typeof pixastic_no_onready == "undefined") // yuck.
94 // onready(init);
95
96 // getElementsByClass by Dustin Diaz, http://www.dustindiaz.com/getelementsbyclass/
97 function getElementsByClass(searchClass,node,tag) {
98 var classElements = new Array();
99 if ( node == null )
100 node = document;
101 if ( tag == null )
102 tag = '*';
103
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];
110 j++;
111 }
112 }
113 return classElements;
114 }
115
116 var debugElement;
117
118 function writeDebug(text, level) {
119 if (!Pixastic.debug) return;
120 try {
121 switch (level) {
122 case "warn" :
123 console.warn("Pixastic:", text);
124 break;
125 case "error" :
126 console.error("Pixastic:", text);
127 break;
128 default:
129 console.log("Pixastic:", text);
130 }
131 } catch(e) {
132 }
133 if (!debugElement) {
134
135 }
136 }
137
138
139 return {
140
141 parseOnLoad : false,
142
143 debug : false,
144
145 applyAction : function(img, dataImg, actionName, options) {
146
147 options = options || {};
148
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.");
152 return false;
153 }
154
155 var canvas, ctx;
156 if (Pixastic.Client.hasCanvas()) {
157 canvas = document.createElement("canvas");
158 ctx = canvas.getContext("2d");
159 }
160
161 var w = parseInt(img.offsetWidth);
162 var h = parseInt(img.offsetHeight);
163
164 if (imageIsCanvas) {
165 w = img.width;
166 h = img.height;
167 }
168
169 if (actionName.indexOf("(") > -1) {
170 var tmp = actionName;
171 actionName = tmp.substr(0, tmp.indexOf("("));
172 var arg = tmp.match(/\((.*?)\)/);
173 if (arg[1]) {
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
185 }
186 } else {
187 options[thisArg[0]] = thisArg[1];
188 }
189 }
190 }
191 }
192 }
193
194 if (!options.rect) {
195 options.rect = {
196 left : 0, top : 0, width : w, height : h
197 };
198 }
199 var validAction = false;
200 if (Pixastic.Actions[actionName] && typeof Pixastic.Actions[actionName].process == "function") {
201 validAction = true;
202 }
203 if (!validAction) {
204 if (Pixastic.debug) writeDebug("Invalid action \"" + actionName + "\". Maybe file not included?");
205 return false;
206 }
207 if (!Pixastic.Actions[actionName].checkSupport()) {
208 if (Pixastic.debug) writeDebug("Action \"" + actionName + "\" not supported by this browser.");
209 return false;
210 }
211
212 if (Pixastic.Client.hasCanvas()) {
213 canvas.width = w;
214 canvas.height = h;
215 canvas.style.width = w+"px";
216 canvas.style.height = h+"px";
217 ctx.drawImage(dataImg,0,0,w,h);
218
219 if (!img.__pixastic_org_image) {
220 canvas.__pixastic_org_image = img;
221 canvas.__pixastic_org_width = w;
222 canvas.__pixastic_org_height = h;
223 } else {
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;
227 }
228
229 } else if (Pixastic.Client.isIE() && typeof img.__pixastic_org_style == "undefined") {
230 img.__pixastic_org_style = img.style.cssText;
231 }
232
233 var params = {
234 image : img,
235 canvas : canvas,
236 width : w,
237 height : h,
238 useData : true,
239 options : options
240 }
241
242 // Ok, let's do it!
243
244 var res = Pixastic.Actions[actionName].process(params);
245
246 if (!res) {
247 return false;
248 }
249
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);
254
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);
257 }
258 }
259
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;
270 canvas.id = img.id;
271 if (img.parentNode && img.parentNode.replaceChild) {
272 img.parentNode.replaceChild(canvas, img);
273 }
274 }
275
276 options.resultCanvas = canvas;
277
278 return canvas;
279 }
280
281 return img;
282 },
283
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;
290 return data;
291 },
292
293 // load the image file
294 process : function(img, actionName, options, callback)
295 {
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);
302 return res;
303 } else {
304 dataImg.onload = function() {
305 var res = Pixastic.applyAction(img, dataImg, actionName, options)
306 if (callback) callback(res);
307 }
308 }
309 }
310 if (img.tagName.toLowerCase() == "canvas") {
311 var res = Pixastic.applyAction(img, img, actionName, options);
312 if (callback) callback(res);
313 return res;
314 }
315 },
316
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);
323
324 if (img.parentNode && img.parentNode.replaceChild) {
325 img.parentNode.replaceChild(img.__pixastic_org_image, img);
326 }
327
328 return img;
329 }
330 } else if (Pixastic.Client.isIE() && typeof img.__pixastic_org_style != "undefined") {
331 img.style.cssText = img.__pixastic_org_style;
332 }
333 },
334
335 Client : {
336 hasCanvas : (function() {
337 var c = document.createElement("canvas");
338 var val = false;
339 try {
340 val = !!((typeof c.getContext == "function") && c.getContext("2d"));
341 } catch(e) {}
342 return function() {
343 return val;
344 }
345 })(),
346
347 hasCanvasImageData : (function() {
348 var c = document.createElement("canvas");
349 var val = false;
350 var ctx;
351 try {
352 if (typeof c.getContext == "function" && (ctx = c.getContext("2d"))) {
353 val = (typeof ctx.getImageData == "function");
354 }
355 } catch(e) {}
356 return function() {
357 return val;
358 }
359 })(),
360
361 isIE : function() {
362 return !!document.all && !!window.attachEvent && !window.opera;
363 }
364 },
365
366 Actions : {}
367 }
368
369
370 })();
371 /*
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]
375 */
376
377 if (typeof jQuery != "undefined" && jQuery && jQuery.fn) {
378 jQuery.fn.pixastic = function(action, options) {
379 var newElements = [];
380 this.each(
381 function () {
382 if (this.tagName.toLowerCase() == "img" && !this.complete) {
383 return;
384 }
385 var res = Pixastic.process(this, action, options);
386 if (res) {
387 newElements.push(res);
388 }
389 }
390 );
391 if (newElements.length > 0)
392 return jQuery(newElements);
393 else
394 return this;
395 };
396
397 };
398 /*
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]
402 */
403
404 Pixastic.Actions.blend = {
405
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;
410
411 amount = Math.max(0,Math.min(1,amount));
412
413 if (!image) return false;
414
415 if (Pixastic.Client.hasCanvasImageData()) {
416 var rect = params.options.rect;
417 var data = Pixastic.prepareData(params);
418 var w = rect.width;
419 var h = rect.height;
420
421 params.useData = false;
422
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);
428
429 var params2 = {canvas:otherCanvas,options:params.options};
430 var data2 = Pixastic.prepareData(params2);
431 var dataDesc2 = params2.canvasData;
432
433 var p = w*h;
434 var pix = p*4;
435 var pix1, pix2;
436 var r1, g1, b1;
437 var r2, g2, b2;
438 var r3, g3, b3;
439 var r4, g4, b4;
440
441 var dataChanged = false;
442
443 switch (mode) {
444 case "normal" :
445 //while (p--) {
446 // data2[pix-=4] = data2[pix];
447 // data2[pix1=pix+1] = data2[pix1];
448 // data2[pix2=pix+2] = data2[pix2];
449 //}
450 break;
451
452 case "multiply" :
453 while (p--) {
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;
457 }
458 dataChanged = true;
459 break;
460
461 case "lighten" :
462 while (p--) {
463 if ((r1 = data[pix-=4]) > data2[pix])
464 data2[pix] = r1;
465 if ((g1 = data[pix1=pix+1]) > data2[pix1])
466 data2[pix1] = g1;
467 if ((b1 = data[pix2=pix+2]) > data2[pix2])
468 data2[pix2] = b1;
469 }
470 dataChanged = true;
471 break;
472
473 case "darken" :
474 while (p--) {
475 if ((r1 = data[pix-=4]) < data2[pix])
476 data2[pix] = r1;
477 if ((g1 = data[pix1=pix+1]) < data2[pix1])
478 data2[pix1] = g1;
479 if ((b1 = data[pix2=pix+2]) < data2[pix2])
480 data2[pix2] = b1;
481
482 }
483 dataChanged = true;
484 break;
485
486 case "darkercolor" :
487 while (p--) {
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)) {
489 data2[pix] = r1;
490 data2[pix1] = g1;
491 data2[pix2] = b1;
492 }
493 }
494 dataChanged = true;
495 break;
496
497 case "lightercolor" :
498 while (p--) {
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)) {
500 data2[pix] = r1;
501 data2[pix1] = g1;
502 data2[pix2] = b1;
503 }
504 }
505 dataChanged = true;
506 break;
507
508 case "lineardodge" :
509 otherCtx.globalCompositeOperation = "source-over";
510 otherCtx.drawImage(params.canvas, 0, 0);
511 otherCtx.globalCompositeOperation = "lighter";
512 otherCtx.drawImage(image, 0, 0);
513
514 /*
515 while (p--) {
516 if ((r3 = data[pix-=4] + data2[pix]) > 255)
517 data2[pix] = 255;
518 else
519 data2[pix] = r3;
520 if ((g3 = data[pix1=pix+1] + data2[pix1]) > 255)
521 data2[pix1] = 255;
522 else
523 data2[pix1] = g3;
524 if ((b3 = data[pix2=pix+2] + data2[pix2]) > 255)
525 data2[pix2] = 255;
526 else
527 data2[pix2] = b3;
528 }
529 dataChanged = true;
530 */
531
532 break;
533
534 case "linearburn" :
535 while (p--) {
536 if ((r3 = data[pix-=4] + data2[pix]) < 255)
537 data2[pix] = 0;
538 else
539 data2[pix] = (r3 - 255);
540 if ((g3 = data[pix1=pix+1] + data2[pix1]) < 255)
541 data2[pix1] = 0;
542 else
543 data2[pix1] = (g3 - 255);
544 if ((b3 = data[pix2=pix+2] + data2[pix2]) < 255)
545 data2[pix2] = 0;
546 else
547 data2[pix2] = (b3 - 255);
548 }
549 dataChanged = true;
550 break;
551
552 case "difference" :
553 while (p--) {
554 if ((r3 = data[pix-=4] - data2[pix]) < 0)
555 data2[pix] = -r3;
556 else
557 data2[pix] = r3;
558 if ((g3 = data[pix1=pix+1] - data2[pix1]) < 0)
559 data2[pix1] = -g3;
560 else
561 data2[pix1] = g3;
562 if ((b3 = data[pix2=pix+2] - data2[pix2]) < 0)
563 data2[pix2] = -b3;
564 else
565 data2[pix2] = b3;
566 }
567 dataChanged = true;
568 break;
569
570 case "screen" :
571 while (p--) {
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));
575 }
576 dataChanged = true;
577 break;
578
579 case "exclusion" :
580 var div_2_255 = 2 / 255;
581 while (p--) {
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];
585 }
586 dataChanged = true;
587 break;
588
589 case "overlay" :
590 var div_2_255 = 2 / 255;
591 while (p--) {
592 if ((r1 = data[pix-=4]) < 128)
593 data2[pix] = data2[pix]*r1*div_2_255;
594 else
595 data2[pix] = 255 - (255-data2[pix])*(255-r1)*div_2_255;
596
597 if ((g1 = data[pix1=pix+1]) < 128)
598 data2[pix1] = data2[pix1]*g1*div_2_255;
599 else
600 data2[pix1] = 255 - (255-data2[pix1])*(255-g1)*div_2_255;
601
602 if ((b1 = data[pix2=pix+2]) < 128)
603 data2[pix2] = data2[pix2]*b1*div_2_255;
604 else
605 data2[pix2] = 255 - (255-data2[pix2])*(255-b1)*div_2_255;
606
607 }
608 dataChanged = true;
609 break;
610
611 case "softlight" :
612 var div_2_255 = 2 / 255;
613 while (p--) {
614 if ((r1 = data[pix-=4]) < 128)
615 data2[pix] = ((data2[pix]>>1) + 64) * r1 * div_2_255;
616 else
617 data2[pix] = 255 - (191 - (data2[pix]>>1)) * (255-r1) * div_2_255;
618
619 if ((g1 = data[pix1=pix+1]) < 128)
620 data2[pix1] = ((data2[pix1]>>1)+64) * g1 * div_2_255;
621 else
622 data2[pix1] = 255 - (191 - (data2[pix1]>>1)) * (255-g1) * div_2_255;
623
624 if ((b1 = data[pix2=pix+2]) < 128)
625 data2[pix2] = ((data2[pix2]>>1)+64) * b1 * div_2_255;
626 else
627 data2[pix2] = 255 - (191 - (data2[pix2]>>1)) * (255-b1) * div_2_255;
628
629 }
630 dataChanged = true;
631 break;
632
633 case "hardlight" :
634 var div_2_255 = 2 / 255;
635 while (p--) {
636 if ((r2 = data2[pix-=4]) < 128)
637 data2[pix] = data[pix] * r2 * div_2_255;
638 else
639 data2[pix] = 255 - (255-data[pix]) * (255-r2) * div_2_255;
640
641 if ((g2 = data2[pix1=pix+1]) < 128)
642 data2[pix1] = data[pix1] * g2 * div_2_255;
643 else
644 data2[pix1] = 255 - (255-data[pix1]) * (255-g2) * div_2_255;
645
646 if ((b2 = data2[pix2=pix+2]) < 128)
647 data2[pix2] = data[pix2] * b2 * div_2_255;
648 else
649 data2[pix2] = 255 - (255-data[pix2]) * (255-b2) * div_2_255;
650
651 }
652 dataChanged = true;
653 break;
654
655 case "colordodge" :
656 while (p--) {
657 if ((r3 = (data[pix-=4]<<8)/(255-(r2 = data2[pix]))) > 255 || r2 == 255)
658 data2[pix] = 255;
659 else
660 data2[pix] = r3;
661
662 if ((g3 = (data[pix1=pix+1]<<8)/(255-(g2 = data2[pix1]))) > 255 || g2 == 255)
663 data2[pix1] = 255;
664 else
665 data2[pix1] = g3;
666
667 if ((b3 = (data[pix2=pix+2]<<8)/(255-(b2 = data2[pix2]))) > 255 || b2 == 255)
668 data2[pix2] = 255;
669 else
670 data2[pix2] = b3;
671 }
672 dataChanged = true;
673 break;
674
675 case "colorburn" :
676 while (p--) {
677 if ((r3 = 255-((255-data[pix-=4])<<8)/data2[pix]) < 0 || data2[pix] == 0)
678 data2[pix] = 0;
679 else
680 data2[pix] = r3;
681
682 if ((g3 = 255-((255-data[pix1=pix+1])<<8)/data2[pix1]) < 0 || data2[pix1] == 0)
683 data2[pix1] = 0;
684 else
685 data2[pix1] = g3;
686
687 if ((b3 = 255-((255-data[pix2=pix+2])<<8)/data2[pix2]) < 0 || data2[pix2] == 0)
688 data2[pix2] = 0;
689 else
690 data2[pix2] = b3;
691 }
692 dataChanged = true;
693 break;
694
695 case "linearlight" :
696 while (p--) {
697 if ( ((r3 = 2*(r2=data2[pix-=4])+data[pix]-256) < 0) || (r2 < 128 && r3 < 0)) {
698 data2[pix] = 0
699 } else {
700 if (r3 > 255)
701 data2[pix] = 255;
702 else
703 data2[pix] = r3;
704 }
705 if ( ((g3 = 2*(g2=data2[pix1=pix+1])+data[pix1]-256) < 0) || (g2 < 128 && g3 < 0)) {
706 data2[pix1] = 0
707 } else {
708 if (g3 > 255)
709 data2[pix1] = 255;
710 else
711 data2[pix1] = g3;
712 }
713 if ( ((b3 = 2*(b2=data2[pix2=pix+2])+data[pix2]-256) < 0) || (b2 < 128 && b3 < 0)) {
714 data2[pix2] = 0
715 } else {
716 if (b3 > 255)
717 data2[pix2] = 255;
718 else
719 data2[pix2] = b3;
720 }
721 }
722 dataChanged = true;
723 break;
724
725 case "vividlight" :
726 while (p--) {
727 if ((r2=data2[pix-=4]) < 128) {
728 if (r2) {
729 if ((r3 = 255 - ((255-data[pix])<<8) / (2*r2)) < 0)
730 data2[pix] = 0;
731 else
732 data2[pix] = r3
733 } else {
734 data2[pix] = 0;
735 }
736 } else if ((r3 = (r4=2*r2-256)) < 255) {
737 if ((r3 = (data[pix]<<8)/(255-r4)) > 255)
738 data2[pix] = 255;
739 else
740 data2[pix] = r3;
741 } else {
742 if (r3 < 0)
743 data2[pix] = 0;
744 else
745 data2[pix] = r3
746 }
747
748 if ((g2=data2[pix1=pix+1]) < 128) {
749 if (g2) {
750 if ((g3 = 255 - ((255-data[pix1])<<8) / (2*g2)) < 0)
751 data2[pix1] = 0;
752 else
753 data2[pix1] = g3;
754 } else {
755 data2[pix1] = 0;
756 }
757 } else if ((g3 = (g4=2*g2-256)) < 255) {
758 if ((g3 = (data[pix1]<<8)/(255-g4)) > 255)
759 data2[pix1] = 255;
760 else
761 data2[pix1] = g3;
762 } else {
763 if (g3 < 0)
764 data2[pix1] = 0;
765 else
766 data2[pix1] = g3;
767 }
768
769 if ((b2=data2[pix2=pix+2]) < 128) {
770 if (b2) {
771 if ((b3 = 255 - ((255-data[pix2])<<8) / (2*b2)) < 0)
772 data2[pix2] = 0;
773 else
774 data2[pix2] = b3;
775 } else {
776 data2[pix2] = 0;
777 }
778 } else if ((b3 = (b4=2*b2-256)) < 255) {
779 if ((b3 = (data[pix2]<<8)/(255-b4)) > 255)
780 data2[pix2] = 255;
781 else
782 data2[pix2] = b3;
783 } else {
784 if (b3 < 0)
785 data2[pix2] = 0;
786 else
787 data2[pix2] = b3;
788 }
789 }
790 dataChanged = true;
791 break;
792
793 case "pinlight" :
794 while (p--) {
795 if ((r2=data2[pix-=4]) < 128)
796 if ((r1=data[pix]) < (r4=2*r2))
797 data2[pix] = r1;
798 else
799 data2[pix] = r4;
800 else
801 if ((r1=data[pix]) > (r4=2*r2-256))
802 data2[pix] = r1;
803 else
804 data2[pix] = r4;
805
806 if ((g2=data2[pix1=pix+1]) < 128)
807 if ((g1=data[pix1]) < (g4=2*g2))
808 data2[pix1] = g1;
809 else
810 data2[pix1] = g4;
811 else
812 if ((g1=data[pix1]) > (g4=2*g2-256))
813 data2[pix1] = g1;
814 else
815 data2[pix1] = g4;
816
817 if ((r2=data2[pix2=pix+2]) < 128)
818 if ((r1=data[pix2]) < (r4=2*r2))
819 data2[pix2] = r1;
820 else
821 data2[pix2] = r4;
822 else
823 if ((r1=data[pix2]) > (r4=2*r2-256))
824 data2[pix2] = r1;
825 else
826 data2[pix2] = r4;
827 }
828 dataChanged = true;
829 break;
830
831 case "hardmix" :
832 while (p--) {
833 if ((r2 = data2[pix-=4]) < 128)
834 if (255 - ((255-data[pix])<<8)/(2*r2) < 128 || r2 == 0)
835 data2[pix] = 0;
836 else
837 data2[pix] = 255;
838 else if ((r4=2*r2-256) < 255 && (data[pix]<<8)/(255-r4) < 128)
839 data2[pix] = 0;
840 else
841 data2[pix] = 255;
842
843 if ((g2 = data2[pix1=pix+1]) < 128)
844 if (255 - ((255-data[pix1])<<8)/(2*g2) < 128 || g2 == 0)
845 data2[pix1] = 0;
846 else
847 data2[pix1] = 255;
848 else if ((g4=2*g2-256) < 255 && (data[pix1]<<8)/(255-g4) < 128)
849 data2[pix1] = 0;
850 else
851 data2[pix1] = 255;
852
853 if ((b2 = data2[pix2=pix+2]) < 128)
854 if (255 - ((255-data[pix2])<<8)/(2*b2) < 128 || b2 == 0)
855 data2[pix2] = 0;
856 else
857 data2[pix2] = 255;
858 else if ((b4=2*b2-256) < 255 && (data[pix2]<<8)/(255-b4) < 128)
859 data2[pix2] = 0;
860 else
861 data2[pix2] = 255;
862 }
863 dataChanged = true;
864 break;
865 }
866
867 if (dataChanged)
868 otherCtx.putImageData(dataDesc2,0,0);
869
870 var ctx = params.canvas.getContext("2d");
871 ctx.save();
872 ctx.globalAlpha = amount;
873 ctx.drawImage(
874 otherCanvas,
875 0,0,rect.width,rect.height,
876 rect.left,rect.top,rect.width,rect.height
877 );
878 ctx.globalAlpha = 1;
879 ctx.restore();
880
881 return true;
882 }
883 },
884 checkSupport : function() {
885 return Pixastic.Client.hasCanvasImageData();
886 }
887 }/*
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]
891 */
892
893 Pixastic.Actions.blur = {
894 process : function(params) {
895
896 if (typeof params.options.fixMargin == "undefined")
897 params.options.fixMargin = true;
898
899 if (Pixastic.Client.hasCanvasImageData()) {
900 var data = Pixastic.prepareData(params);
901 var dataCopy = Pixastic.prepareData(params, true)
902
903 /*
904 var kernel = [
905 [0.5, 1, 0.5],
906 [1, 2, 1],
907 [0.5, 1, 0.5]
908 ];
909 */
910
911 var kernel = [
912 [0, 1, 0],
913 [1, 2, 1],
914 [0, 1, 0]
915 ];
916
917 var weight = 0;
918 for (var i=0;i<3;i++) {
919 for (var j=0;j<3;j++) {
920 weight += kernel[i][j];
921 }
922 }
923
924 weight = 1 / (weight*2);
925
926 var rect = params.options.rect;
927 var w = rect.width;
928 var h = rect.height;
929
930 var w4 = w*4;
931 var y = h;
932 do {
933 var offsetY = (y-1)*w4;
934
935 var prevY = (y == 1) ? 0 : y-2;
936 var nextY = (y == h) ? y - 1 : y;
937
938 var offsetYPrev = prevY*w*4;
939 var offsetYNext = nextY*w*4;
940
941 var x = w;
942 do {
943 var offset = offsetY + (x*4-4);
944
945 var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
946 var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
947
948 data[offset] = (
949 /*
950 dataCopy[offsetPrev - 4]
951 + dataCopy[offsetPrev+4]
952 + dataCopy[offsetNext - 4]
953 + dataCopy[offsetNext+4]
954 +
955 */
956 (dataCopy[offsetPrev]
957 + dataCopy[offset-4]
958 + dataCopy[offset+4]
959 + dataCopy[offsetNext]) * 2
960 + dataCopy[offset] * 4
961 ) * weight;
962
963 data[offset+1] = (
964 /*
965 dataCopy[offsetPrev - 3]
966 + dataCopy[offsetPrev+5]
967 + dataCopy[offsetNext - 3]
968 + dataCopy[offsetNext+5]
969 +
970 */
971 (dataCopy[offsetPrev+1]
972 + dataCopy[offset-3]
973 + dataCopy[offset+5]
974 + dataCopy[offsetNext+1]) * 2
975 + dataCopy[offset+1] * 4
976 ) * weight;
977
978 data[offset+2] = (
979 /*
980 dataCopy[offsetPrev - 2]
981 + dataCopy[offsetPrev+6]
982 + dataCopy[offsetNext - 2]
983 + dataCopy[offsetNext+6]
984 +
985 */
986 (dataCopy[offsetPrev+2]
987 + dataCopy[offset-2]
988 + dataCopy[offset+6]
989 + dataCopy[offsetNext+2]) * 2
990 + dataCopy[offset+2] * 4
991 ) * weight;
992
993 } while (--x);
994 } while (--y);
995
996 return true;
997
998 } else if (Pixastic.Client.isIE()) {
999 params.image.style.filter += " progid:DXImageTransform.Microsoft.Blur(pixelradius=1.5)";
1000
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";
1004 }
1005
1006 return true;
1007 }
1008 },
1009 checkSupport : function() {
1010 return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
1011 }
1012 }/*
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]
1016 */
1017
1018 Pixastic.Actions.blurfast = {
1019 process : function(params) {
1020
1021 var amount = parseFloat(params.options.amount)||0;
1022 var clear = !!(params.options.clear && params.options.clear != "false");
1023
1024 amount = Math.max(0,Math.min(5,amount));
1025
1026 if (Pixastic.Client.hasCanvas()) {
1027 var rect = params.options.rect;
1028
1029 var ctx = params.canvas.getContext("2d");
1030 ctx.save();
1031 ctx.beginPath();
1032 ctx.rect(rect.left, rect.top, rect.width, rect.height);
1033 ctx.clip();
1034
1035 var scale = 2;
1036 var smallWidth = Math.round(params.width / scale);
1037 var smallHeight = Math.round(params.height / scale);
1038
1039 var copy = document.createElement("canvas");
1040 copy.width = smallWidth;
1041 copy.height = smallHeight;
1042
1043 var clear = false;
1044 var steps = Math.round(amount * 20);
1045
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));
1050
1051 copyCtx.clearRect(0,0,smallWidth,smallHeight);
1052
1053 copyCtx.drawImage(
1054 params.canvas,
1055 0,0,params.width,params.height,
1056 0,0,scaledWidth,scaledHeight
1057 );
1058
1059 if (clear)
1060 ctx.clearRect(rect.left,rect.top,rect.width,rect.height);
1061
1062 ctx.drawImage(
1063 copy,
1064 0,0,scaledWidth,scaledHeight,
1065 0,0,params.width,params.height
1066 );
1067 }
1068
1069 ctx.restore();
1070
1071 params.useData = false;
1072 return true;
1073 } else if (Pixastic.Client.isIE()) {
1074 var radius = 10 * amount;
1075 params.image.style.filter += " progid:DXImageTransform.Microsoft.Blur(pixelradius=" + radius + ")";
1076
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";
1080 }
1081
1082 return true;
1083 }
1084 },
1085 checkSupport : function() {
1086 return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
1087 }
1088 }
1089 /*
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]
1093 */
1094
1095 Pixastic.Actions.brightness = {
1096
1097 process : function(params) {
1098
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");
1102
1103 if (legacy) {
1104 brightness = Math.min(150,Math.max(-150,brightness));
1105 } else {
1106 var brightMul = 1 + Math.min(150,Math.max(-150,brightness)) / 150;
1107 }
1108 contrast = Math.max(0,contrast+1);
1109
1110 if (Pixastic.Client.hasCanvasImageData()) {
1111 var data = Pixastic.prepareData(params);
1112 var rect = params.options.rect;
1113 var w = rect.width;
1114 var h = rect.height;
1115
1116 var p = w*h;
1117 var pix = p*4, pix1, pix2;
1118
1119 var mul, add;
1120 if (contrast != 1) {
1121 if (legacy) {
1122 mul = contrast;
1123 add = (brightness - 128) * contrast + 128;
1124 } else {
1125 mul = brightMul * contrast;
1126 add = - contrast * 128 + 128;
1127 }
1128 } else { // this if-then is not necessary anymore, is it?
1129 if (legacy) {
1130 mul = 1;
1131 add = brightness;
1132 } else {
1133 mul = brightMul;
1134 add = 0;
1135 }
1136 }
1137 var r, g, b;
1138 while (p--) {
1139 if ((r = data[pix-=4] * mul + add) > 255 )
1140 data[pix] = 255;
1141 else if (r < 0)
1142 data[pix] = 0;
1143 else
1144 data[pix] = r;
1145
1146 if ((g = data[pix1=pix+1] * mul + add) > 255 )
1147 data[pix1] = 255;
1148 else if (g < 0)
1149 data[pix1] = 0;
1150 else
1151 data[pix1] = g;
1152
1153 if ((b = data[pix2=pix+2] * mul + add) > 255 )
1154 data[pix2] = 255;
1155 else if (b < 0)
1156 data[pix2] = 0;
1157 else
1158 data[pix2] = b;
1159 }
1160 return true;
1161 }
1162 },
1163 checkSupport : function() {
1164 return Pixastic.Client.hasCanvasImageData();
1165 }
1166 }
1167
1168 /*
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]
1172 */
1173
1174 Pixastic.Actions.coloradjust = {
1175
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;
1180
1181 red = Math.round(red*255);
1182 green = Math.round(green*255);
1183 blue = Math.round(blue*255);
1184
1185 if (Pixastic.Client.hasCanvasImageData()) {
1186 var data = Pixastic.prepareData(params);
1187 var rect = params.options.rect;
1188
1189 var p = rect.width*rect.height;
1190 var pix = p*4, pix1, pix2;
1191
1192 var r, g, b;
1193 while (p--) {
1194 pix -= 4;
1195
1196 if (red) {
1197 if ((r = data[pix] + red) < 0 )
1198 data[pix] = 0;
1199 else if (r > 255 )
1200 data[pix] = 255;
1201 else
1202 data[pix] = r;
1203 }
1204
1205 if (green) {
1206 if ((g = data[pix1=pix+1] + green) < 0 )
1207 data[pix1] = 0;
1208 else if (g > 255 )
1209 data[pix1] = 255;
1210 else
1211 data[pix1] = g;
1212 }
1213
1214 if (blue) {
1215 if ((b = data[pix2=pix+2] + blue) < 0 )
1216 data[pix2] = 0;
1217 else if (b > 255 )
1218 data[pix2] = 255;
1219 else
1220 data[pix2] = b;
1221 }
1222 }
1223 return true;
1224 }
1225 },
1226 checkSupport : function() {
1227 return (Pixastic.Client.hasCanvasImageData());
1228 }
1229 }
1230 /*
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]
1234 */
1235
1236
1237 Pixastic.Actions.colorhistogram = {
1238
1239 array256 : function(default_value) {
1240 arr = [];
1241 for (var i=0; i<256; i++) { arr[i] = default_value; }
1242 return arr
1243 },
1244
1245 process : function(params) {
1246 var values = [];
1247 if (typeof params.options.returnValue != "object") {
1248 params.options.returnValue = {rvals:[], gvals:[], bvals:[]};
1249 }
1250 var paint = !!(params.options.paint);
1251
1252 var returnValue = params.options.returnValue;
1253 if (typeof returnValue.values != "array") {
1254 returnValue.rvals = [];
1255 returnValue.gvals = [];
1256 returnValue.bvals = [];
1257 }
1258
1259 if (Pixastic.Client.hasCanvasImageData()) {
1260 var data = Pixastic.prepareData(params);
1261 params.useData = false;
1262
1263 var rvals = this.array256(0);
1264 var gvals = this.array256(0);
1265 var bvals = this.array256(0);
1266
1267 var rect = params.options.rect;
1268
1269 var p = rect.width*rect.height;
1270 var pix = p*4;
1271 while (p--) {
1272 rvals[data[pix-=4]]++;
1273 gvals[data[pix+1]]++;
1274 bvals[data[pix+2]]++;
1275 }
1276
1277 returnValue.rvals = rvals;
1278 returnValue.gvals = gvals;
1279 returnValue.bvals = bvals;
1280
1281 if (paint) {
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;
1286 var maxValue = 0;
1287 for (var i=0;i<256;i++) {
1288 if (vals[v][i] > maxValue)
1289 maxValue = vals[v][i];
1290 }
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++) {
1297 ctx.fillRect(
1298 i * widthScale, params.height - heightScale * vals[v][i] - params.height + yoff,
1299 widthScale, vals[v][i] * heightScale
1300 );
1301 }
1302 }
1303 }
1304 return true;
1305 }
1306 },
1307
1308 checkSupport : function() {
1309 return Pixastic.Client.hasCanvasImageData();
1310 }
1311 }/*
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]
1315 */
1316
1317 Pixastic.Actions.crop = {
1318 process : function(params) {
1319 if (Pixastic.Client.hasCanvas()) {
1320 var rect = params.options.rect;
1321
1322 var width = rect.width;
1323 var height = rect.height;
1324 var top = rect.top;
1325 var left = rect.left;
1326
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);
1335
1336 if (left < 0) left = 0;
1337 if (left > params.width-1) left = params.width-1;
1338
1339 if (top < 0) top = 0;
1340 if (top > params.height-1) top = params.height-1;
1341
1342 if (width < 1) width = 1;
1343 if (left + width > params.width)
1344 width = params.width - left;
1345
1346 if (height < 1) height = 1;
1347 if (top + height > params.height)
1348 height = params.height - top;
1349
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);
1354
1355 params.canvas.width = width;
1356 params.canvas.height = height;
1357 params.canvas.getContext("2d").clearRect(0,0,width,height);
1358
1359 params.canvas.getContext("2d").drawImage(copy,
1360 left,top,width,height,
1361 0,0,width,height
1362 );
1363
1364 params.useData = false;
1365 return true;
1366 }
1367 },
1368 checkSupport : function() {
1369 return Pixastic.Client.hasCanvas();
1370 }
1371 }
1372
1373
1374 /*
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]
1378 */
1379
1380 Pixastic.Actions.desaturate = {
1381
1382 process : function(params) {
1383 var useAverage = !!(params.options.average && params.options.average != "false");
1384
1385 if (Pixastic.Client.hasCanvasImageData()) {
1386 var data = Pixastic.prepareData(params);
1387 var rect = params.options.rect;
1388 var w = rect.width;
1389 var h = rect.height;
1390
1391 var p = w*h;
1392 var pix = p*4, pix1, pix2;
1393
1394 if (useAverage) {
1395 while (p--)
1396 data[pix-=4] = data[pix1=pix+1] = data[pix2=pix+2] = (data[pix]+data[pix1]+data[pix2])/3
1397 } else {
1398 while (p--)
1399 data[pix-=4] = data[pix1=pix+1] = data[pix2=pix+2] = (data[pix]*0.3 + data[pix1]*0.59 + data[pix2]*0.11);
1400 }
1401 return true;
1402 } else if (Pixastic.Client.isIE()) {
1403 params.image.style.filter += " gray";
1404 return true;
1405 }
1406 },
1407 checkSupport : function() {
1408 return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
1409 }
1410 }/*
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]
1414 */
1415
1416 Pixastic.Actions.edges = {
1417 process : function(params) {
1418
1419 var mono = !!(params.options.mono && params.options.mono != "false");
1420 var invert = !!(params.options.invert && params.options.invert != "false");
1421
1422 if (Pixastic.Client.hasCanvasImageData()) {
1423 var data = Pixastic.prepareData(params);
1424 var dataCopy = Pixastic.prepareData(params, true)
1425
1426 var c = -1/8;
1427 var kernel = [
1428 [c, c, c],
1429 [c, 1, c],
1430 [c, c, c]
1431 ];
1432
1433 weight = 1/c;
1434
1435 var rect = params.options.rect;
1436 var w = rect.width;
1437 var h = rect.height;
1438
1439 var w4 = w*4;
1440 var y = h;
1441 do {
1442 var offsetY = (y-1)*w4;
1443
1444 var nextY = (y == h) ? y - 1 : y;
1445 var prevY = (y == 1) ? 0 : y-2;
1446
1447 var offsetYPrev = prevY*w*4;
1448 var offsetYNext = nextY*w*4;
1449
1450 var x = w;
1451 do {
1452 var offset = offsetY + (x*4-4);
1453
1454 var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
1455 var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
1456
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
1465 + dataCopy[offset]
1466 )
1467 * weight;
1468
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])
1478 * weight;
1479
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])
1489 * weight;
1490
1491 if (mono) {
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;
1497 } else {
1498 if (invert) {
1499 r = 255 - r;
1500 g = 255 - g;
1501 b = 255 - b;
1502 }
1503 if (r < 0 ) r = 0;
1504 if (g < 0 ) g = 0;
1505 if (b < 0 ) b = 0;
1506 if (r > 255 ) r = 255;
1507 if (g > 255 ) g = 255;
1508 if (b > 255 ) b = 255;
1509 }
1510
1511 data[offset] = r;
1512 data[offset+1] = g;
1513 data[offset+2] = b;
1514
1515 } while (--x);
1516 } while (--y);
1517
1518 return true;
1519 }
1520 },
1521 checkSupport : function() {
1522 return Pixastic.Client.hasCanvasImageData();
1523 }
1524 }/*
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]
1528 *
1529 * Contribution by Oliver Hunt (http://nerget.com/, http://nerget.com/canvas/edgeDetection.js). Thanks Oliver!
1530 *
1531 */
1532
1533 Pixastic.Actions.edges2 = {
1534 process : function(params) {
1535
1536 if (Pixastic.Client.hasCanvasImageData()) {
1537 var data = Pixastic.prepareData(params);
1538 var dataCopy = Pixastic.prepareData(params, true)
1539
1540 var rect = params.options.rect;
1541 var w = rect.width;
1542 var h = rect.height;
1543
1544 var w4 = w * 4;
1545 var pixel = w4 + 4; // Start at (1,1)
1546 var hm1 = h - 1;
1547 var wm1 = w - 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;
1553
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];
1557
1558 var rp = dataCopy[priorRow += 2];
1559 var gp = dataCopy[++priorRow];
1560 var bp = dataCopy[++priorRow];
1561
1562 var rc = dataCopy[centerRow += 2];
1563 var gc = dataCopy[++centerRow];
1564 var bc = dataCopy[++centerRow];
1565
1566 var rn = dataCopy[nextRow += 2];
1567 var gn = dataCopy[++nextRow];
1568 var bn = dataCopy[++nextRow];
1569
1570 var r2 = - rp - rc - rn;
1571 var g2 = - gp - gc - gn;
1572 var b2 = - bp - bc - bn;
1573
1574 // Main convolution loop
1575 for (var x = 1; x < wm1; ++x) {
1576 centerRow = pixel + 4;
1577 priorRow = centerRow - w4;
1578 nextRow = centerRow + w4;
1579
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;
1583
1584 r1 = r2;
1585 g1 = g2;
1586 b1 = b2;
1587
1588 rp = dataCopy[ priorRow];
1589 gp = dataCopy[++priorRow];
1590 bp = dataCopy[++priorRow];
1591
1592 rc = dataCopy[ centerRow];
1593 gc = dataCopy[++centerRow];
1594 bc = dataCopy[++centerRow];
1595
1596 rn = dataCopy[ nextRow];
1597 gn = dataCopy[++nextRow];
1598 bn = dataCopy[++nextRow];
1599
1600 r += (r2 = - rp - rc - rn);
1601 g += (g2 = - gp - gc - gn);
1602 b += (b2 = - bp - bc - bn);
1603
1604 if (r > 255) r = 255;
1605 if (g > 255) g = 255;
1606 if (b > 255) b = 255;
1607 if (r < 0) r = 0;
1608 if (g < 0) g = 0;
1609 if (b < 0) b = 0;
1610
1611 data[pixel] = r;
1612 data[++pixel] = g;
1613 data[++pixel] = b;
1614 //data[++pixel] = 255; // alpha
1615
1616 pixel+=2;
1617 }
1618 pixel += 8;
1619 }
1620 return true;
1621 }
1622 },
1623 checkSupport : function() {
1624 return Pixastic.Client.hasCanvasImageData();
1625 }
1626 }/*
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]
1630 */
1631
1632 Pixastic.Actions.emboss = {
1633 process : function(params) {
1634
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");
1639
1640 var dirY = 0;
1641 var dirX = 0;
1642
1643 switch (direction) {
1644 case "topleft": // top left
1645 dirY = -1;
1646 dirX = -1;
1647 break;
1648 case "top": // top
1649 dirY = -1;
1650 dirX = 0;
1651 break;
1652 case "topright": // top right
1653 dirY = -1;
1654 dirX = 1;
1655 break;
1656 case "right": // right
1657 dirY = 0;
1658 dirX = 1;
1659 break;
1660 case "bottomright": // bottom right
1661 dirY = 1;
1662 dirX = 1;
1663 break;
1664 case "bottom": // bottom
1665 dirY = 1;
1666 dirX = 0;
1667 break;
1668 case "bottomleft": // bottom left
1669 dirY = 1;
1670 dirX = -1;
1671 break;
1672 case "left": // left
1673 dirY = 0;
1674 dirX = -1;
1675 break;
1676 }
1677
1678 if (Pixastic.Client.hasCanvasImageData()) {
1679 var data = Pixastic.prepareData(params);
1680 var dataCopy = Pixastic.prepareData(params, true)
1681
1682 var invertAlpha = !!params.options.invertAlpha;
1683 var rect = params.options.rect;
1684 var w = rect.width;
1685 var h = rect.height;
1686
1687 var w4 = w*4;
1688 var y = h;
1689 do {
1690 var offsetY = (y-1)*w4;
1691
1692 var otherY = dirY;
1693 if (y + otherY < 1) otherY = 0;
1694 if (y + otherY > h) otherY = 0;
1695
1696 var offsetYOther = (y-1+otherY)*w*4;
1697
1698 var x = w;
1699 do {
1700 var offset = offsetY + (x-1)*4;
1701
1702 var otherX = dirX;
1703 if (x + otherX < 1) otherX = 0;
1704 if (x + otherX > w) otherX = 0;
1705
1706 var offsetOther = offsetYOther + (x-1+otherX)*4;
1707
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];
1711
1712 var dif = dR;
1713 var absDif = dif > 0 ? dif : -dif;
1714
1715 var absG = dG > 0 ? dG : -dG;
1716 var absB = dB > 0 ? dB : -dB;
1717
1718 if (absG > absDif) {
1719 dif = dG;
1720 }
1721 if (absB > absDif) {
1722 dif = dB;
1723 }
1724
1725 dif *= strength;
1726
1727 if (blend) {
1728 var r = data[offset] + dif;
1729 var g = data[offset+1] + dif;
1730 var b = data[offset+2] + dif;
1731
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);
1735 } else {
1736 var grey = greyLevel - dif;
1737 if (grey < 0) {
1738 grey = 0;
1739 } else if (grey > 255) {
1740 grey = 255;
1741 }
1742
1743 data[offset] = data[offset+1] = data[offset+2] = grey;
1744 }
1745
1746 } while (--x);
1747 } while (--y);
1748 return true;
1749
1750 } else if (Pixastic.Client.isIE()) {
1751 params.image.style.filter += " progid:DXImageTransform.Microsoft.emboss()";
1752 return true;
1753 }
1754 },
1755 checkSupport : function() {
1756 return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
1757 }
1758
1759 }
1760 /*
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]
1764 */
1765
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);
1773
1774 var ctx = params.canvas.getContext("2d");
1775 ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
1776
1777 if (params.options.axis == "horizontal") {
1778 ctx.scale(-1,1);
1779 ctx.drawImage(copyCanvas, -rect.left-rect.width, rect.top, rect.width, rect.height)
1780 } else {
1781 ctx.scale(1,-1);
1782 ctx.drawImage(copyCanvas, rect.left, -rect.top-rect.height, rect.width, rect.height)
1783 }
1784
1785 params.useData = false;
1786
1787 return true;
1788 },
1789 checkSupport : function() {
1790 return Pixastic.Client.hasCanvas();
1791 }
1792 }
1793
1794 /*
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]
1798 */
1799
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);
1808
1809 var ctx = params.canvas.getContext("2d");
1810 ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
1811 ctx.scale(-1,1);
1812 ctx.drawImage(copyCanvas, -rect.left-rect.width, rect.top, rect.width, rect.height)
1813 params.useData = false;
1814
1815 return true;
1816
1817 } else if (Pixastic.Client.isIE()) {
1818 params.image.style.filter += " fliph";
1819 return true;
1820 }
1821 },
1822 checkSupport : function() {
1823 return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
1824 }
1825 }
1826
1827 /*
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]
1831 */
1832
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);
1841
1842 var ctx = params.canvas.getContext("2d");
1843 ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
1844 ctx.scale(1,-1);
1845 ctx.drawImage(copyCanvas, rect.left, -rect.top-rect.height, rect.width, rect.height)
1846 params.useData = false;
1847
1848 return true;
1849
1850 } else if (Pixastic.Client.isIE()) {
1851 params.image.style.filter += " flipv";
1852 return true;
1853 }
1854 },
1855 checkSupport : function() {
1856 return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
1857 }
1858 }
1859
1860 /*
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]
1864 */
1865
1866
1867 Pixastic.Actions.glow = {
1868 process : function(params) {
1869
1870 var amount = (parseFloat(params.options.amount)||0);
1871 var blurAmount = parseFloat(params.options.radius)||0;
1872
1873 amount = Math.min(1,Math.max(0,amount));
1874 blurAmount = Math.min(5,Math.max(0,blurAmount));
1875
1876 if (Pixastic.Client.hasCanvasImageData()) {
1877 var rect = params.options.rect;
1878
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);
1884
1885 var scale = 2;
1886 var smallWidth = Math.round(params.width / scale);
1887 var smallHeight = Math.round(params.height / scale);
1888
1889 var copy = document.createElement("canvas");
1890 copy.width = smallWidth;
1891 copy.height = smallHeight;
1892
1893 var clear = true;
1894 var steps = Math.round(blurAmount * 20);
1895
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));
1900
1901 copyCtx.clearRect(0,0,smallWidth,smallHeight);
1902
1903 copyCtx.drawImage(
1904 blurCanvas,
1905 0,0,params.width,params.height,
1906 0,0,scaledWidth,scaledHeight
1907 );
1908
1909 blurCtx.clearRect(0,0,params.width,params.height);
1910
1911 blurCtx.drawImage(
1912 copy,
1913 0,0,scaledWidth,scaledHeight,
1914 0,0,params.width,params.height
1915 );
1916 }
1917
1918 var data = Pixastic.prepareData(params);
1919 var blurData = Pixastic.prepareData({canvas:blurCanvas,options:params.options});
1920 var w = rect.width;
1921 var h = rect.height;
1922 var w4 = w*4;
1923 var y = h;
1924 do {
1925 var offsetY = (y-1)*w4;
1926 var x = w;
1927 do {
1928 var offset = offsetY + (x*4-4);
1929
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];
1933
1934 if (r > 255) r = 255;
1935 if (g > 255) g = 255;
1936 if (b > 255) b = 255;
1937 if (r < 0) r = 0;
1938 if (g < 0) g = 0;
1939 if (b < 0) b = 0;
1940
1941 data[offset] = r;
1942 data[offset+1] = g;
1943 data[offset+2] = b;
1944
1945 } while (--x);
1946 } while (--y);
1947
1948 return true;
1949 }
1950 },
1951 checkSupport : function() {
1952 return Pixastic.Client.hasCanvasImageData();
1953 }
1954 }
1955
1956
1957
1958 /*
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]
1962 */
1963
1964 Pixastic.Actions.histogram = {
1965 process : function(params) {
1966
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)";
1970 var values = [];
1971 if (typeof params.options.returnValue != "object") {
1972 params.options.returnValue = {values:[]};
1973 }
1974 var returnValue = params.options.returnValue;
1975 if (typeof returnValue.values != "array") {
1976 returnValue.values = [];
1977 }
1978 values = returnValue.values;
1979
1980 if (Pixastic.Client.hasCanvasImageData()) {
1981 var data = Pixastic.prepareData(params);
1982 params.useData = false;
1983
1984 for (var i=0;i<256;i++) {
1985 values[i] = 0;
1986 }
1987
1988 var rect = params.options.rect;
1989 var w = rect.width;
1990 var h = rect.height;
1991 var w4 = w*4;
1992 var y = h;
1993 do {
1994 var offsetY = (y-1)*w4;
1995 var x = w;
1996 do {
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]++;
2002
2003 } while (--x);
2004 } while (--y);
2005
2006 if (paint) {
2007 var maxValue = 0;
2008 for (var i=0;i<256;i++) {
2009 if (values[i] > maxValue) {
2010 maxValue = values[i];
2011 }
2012 }
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++) {
2018 ctx.fillRect(
2019 i * widthScale, params.height - heightScale * values[i],
2020 widthScale, values[i] * heightScale
2021 );
2022 }
2023 }
2024
2025 returnValue.values = values;
2026
2027 return true;
2028 }
2029 },
2030 checkSupport : function() {
2031 return Pixastic.Client.hasCanvasImageData();
2032 }
2033 }
2034 /*
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]
2038 */
2039
2040 Pixastic.Actions.hsl = {
2041 process : function(params) {
2042
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;
2046
2047
2048 // this seems to give the same result as Photoshop
2049 if (saturation < 0) {
2050 var satMul = 1+saturation;
2051 } else {
2052 var satMul = 1+saturation*2;
2053 }
2054
2055 hue = (hue%360) / 360;
2056 var hue6 = hue * 6;
2057
2058 var rgbDiv = 1 / 255;
2059
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);
2065
2066 var rect = params.options.rect;
2067 var w = rect.width;
2068 var h = rect.height;
2069
2070 var w4 = w*4;
2071 var y = h;
2072
2073 do {
2074 var offsetY = (y-1)*w4;
2075 var x = w;
2076 do {
2077 var offset = offsetY + (x*4-4);
2078
2079 var r = data[offset];
2080 var g = data[offset+1];
2081 var b = data[offset+2];
2082
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.
2087 var vs = r;
2088 if (g > vs) vs = g;
2089 if (b > vs) vs = b;
2090 var ms = r;
2091 if (g < ms) ms = g;
2092 if (b < ms) ms = b;
2093 var vm = (vs-ms);
2094 var l = (ms+vs)/255 * 0.5;
2095 if (l > 0) {
2096 if (vm > 0) {
2097 if (l <= 0.5) {
2098 var s = vm / (vs+ms) * satMul;
2099 if (s > 1) s = 1;
2100 var v = (l * (1+s));
2101 } else {
2102 var s = vm / (510-vs-ms) * satMul;
2103 if (s > 1) s = 1;
2104 var v = (l+s - l*s);
2105 }
2106 if (r == vs) {
2107 if (g == ms)
2108 var h = 5 + ((vs-b)/vm) + hue6;
2109 else
2110 var h = 1 - ((vs-g)/vm) + hue6;
2111 } else if (g == vs) {
2112 if (b == ms)
2113 var h = 1 + ((vs-r)/vm) + hue6;
2114 else
2115 var h = 3 - ((vs-b)/vm) + hue6;
2116 } else {
2117 if (r == ms)
2118 var h = 3 + ((vs-g)/vm) + hue6;
2119 else
2120 var h = 5 - ((vs-r)/vm) + hue6;
2121 }
2122 if (h < 0) h+=6;
2123 if (h >= 6) h-=6;
2124 var m = (l+l-v);
2125 var sextant = h>>0;
2126 switch (sextant) {
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;
2133 }
2134 }
2135 }
2136 }
2137
2138 if (lightness < 0) {
2139 r *= lightp1;
2140 g *= lightp1;
2141 b *= lightp1;
2142 } else if (lightness > 0) {
2143 r = r * lightm1 + light255;
2144 g = g * lightm1 + light255;
2145 b = b * lightm1 + light255;
2146 }
2147
2148 if (r < 0) r = 0;
2149 if (g < 0) g = 0;
2150 if (b < 0) b = 0;
2151 if (r > 255) r = 255;
2152 if (g > 255) g = 255;
2153 if (b > 255) b = 255;
2154
2155 data[offset] = r;
2156 data[offset+1] = g;
2157 data[offset+2] = b;
2158
2159 } while (--x);
2160 } while (--y);
2161 return true;
2162 }
2163 },
2164 checkSupport : function() {
2165 return Pixastic.Client.hasCanvasImageData();
2166 }
2167
2168 }
2169 /*
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]
2173 */
2174
2175 Pixastic.Actions.invert = {
2176 process : function(params) {
2177 if (Pixastic.Client.hasCanvasImageData()) {
2178 var data = Pixastic.prepareData(params);
2179
2180 var invertAlpha = !!params.options.invertAlpha;
2181 var rect = params.options.rect;
2182 var w = rect.width;
2183 var h = rect.height;
2184
2185 var w4 = w*4;
2186 var y = h;
2187 do {
2188 var offsetY = (y-1)*w4;
2189 var x = w;
2190 do {
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];
2196 } while (--x);
2197 } while (--y);
2198
2199 return true;
2200 } else if (Pixastic.Client.isIE()) {
2201 params.image.style.filter += " invert";
2202 return true;
2203 }
2204 },
2205 checkSupport : function() {
2206 return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
2207 }
2208 }
2209 /*
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]
2213 */
2214
2215 Pixastic.Actions.laplace = {
2216 process : function(params) {
2217
2218 var strength = 1.0;
2219 var invert = !!(params.options.invert && params.options.invert != "false");
2220 var contrast = parseFloat(params.options.edgeStrength)||0;
2221
2222 var greyLevel = parseInt(params.options.greyLevel)||0;
2223
2224 contrast = -contrast;
2225
2226 if (Pixastic.Client.hasCanvasImageData()) {
2227 var data = Pixastic.prepareData(params);
2228 var dataCopy = Pixastic.prepareData(params, true)
2229
2230 var kernel = [
2231 [-1, -1, -1],
2232 [-1, 8, -1],
2233 [-1, -1, -1]
2234 ];
2235
2236 var weight = 1/8;
2237
2238 var rect = params.options.rect;
2239 var w = rect.width;
2240 var h = rect.height;
2241
2242 var w4 = w*4;
2243 var y = h;
2244 do {
2245 var offsetY = (y-1)*w4;
2246
2247 var nextY = (y == h) ? y - 1 : y;
2248 var prevY = (y == 1) ? 0 : y-2;
2249
2250 var offsetYPrev = prevY*w*4;
2251 var offsetYNext = nextY*w*4;
2252
2253 var x = w;
2254 do {
2255 var offset = offsetY + (x*4-4);
2256
2257 var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
2258 var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
2259
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)
2269 * weight;
2270
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)
2280 * weight;
2281
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)
2291 * weight;
2292
2293 var brightness = ((r + g + b)/3) + greyLevel;
2294
2295 if (contrast != 0) {
2296 if (brightness > 127) {
2297 brightness += ((brightness + 1) - 128) * contrast;
2298 } else if (brightness < 127) {
2299 brightness -= (brightness + 1) * contrast;
2300 }
2301 }
2302 if (invert) {
2303 brightness = 255 - brightness;
2304 }
2305 if (brightness < 0 ) brightness = 0;
2306 if (brightness > 255 ) brightness = 255;
2307
2308 data[offset] = data[offset+1] = data[offset+2] = brightness;
2309
2310 } while (--x);
2311 } while (--y);
2312
2313 return true;
2314 }
2315 },
2316 checkSupport : function() {
2317 return Pixastic.Client.hasCanvasImageData();
2318 }
2319 }
2320
2321 /*
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]
2325 */
2326
2327 Pixastic.Actions.lighten = {
2328
2329 process : function(params) {
2330 var amount = parseFloat(params.options.amount) || 0;
2331
2332 if (Pixastic.Client.hasCanvasImageData()) {
2333 var data = Pixastic.prepareData(params);
2334 var rect = params.options.rect;
2335 var w = rect.width;
2336 var h = rect.height;
2337 var w4 = w*4;
2338 var y = h;
2339 do {
2340 var offsetY = (y-1)*w4;
2341 var x = w;
2342 do {
2343 var offset = offsetY + (x-1)*4;
2344
2345 var r = data[offset];
2346 var g = data[offset+1];
2347 var b = data[offset+2];
2348
2349 r += r*amount;
2350 g += g*amount;
2351 b += b*amount;
2352
2353 if (r < 0 ) r = 0;
2354 if (g < 0 ) g = 0;
2355 if (b < 0 ) b = 0;
2356 if (r > 255 ) r = 255;
2357 if (g > 255 ) g = 255;
2358 if (b > 255 ) b = 255;
2359
2360 data[offset] = r;
2361 data[offset+1] = g;
2362 data[offset+2] = b;
2363
2364 } while (--x);
2365 } while (--y);
2366 return true;
2367
2368 } else if (Pixastic.Client.isIE()) {
2369 var img = params.image;
2370 if (amount < 0) {
2371 img.style.filter += " light()";
2372 img.filters[img.filters.length-1].addAmbient(
2373 255,255,255,
2374 100 * -amount
2375 );
2376 } else if (amount > 0) {
2377 img.style.filter += " light()";
2378 img.filters[img.filters.length-1].addAmbient(
2379 255,255,255,
2380 100
2381 );
2382 img.filters[img.filters.length-1].addAmbient(
2383 255,255,255,
2384 100 * amount
2385 );
2386 }
2387 return true;
2388 }
2389 },
2390 checkSupport : function() {
2391 return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
2392 }
2393 }
2394 /*
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]
2398 */
2399
2400 Pixastic.Actions.mosaic = {
2401
2402 process : function(params) {
2403 var blockSize = Math.max(1,parseInt(params.options.blockSize,10));
2404
2405 if (Pixastic.Client.hasCanvasImageData()) {
2406 var rect = params.options.rect;
2407 var w = rect.width;
2408 var h = rect.height;
2409 var w4 = w*4;
2410 var y = h;
2411
2412 var ctx = params.canvas.getContext("2d");
2413
2414 var pixel = document.createElement("canvas");
2415 pixel.width = pixel.height = 1;
2416 var pixelCtx = pixel.getContext("2d");
2417
2418 var copy = document.createElement("canvas");
2419 copy.width = w;
2420 copy.height = h;
2421 var copyCtx = copy.getContext("2d");
2422 copyCtx.drawImage(params.canvas,rect.left,rect.top,w,h, 0,0,w,h);
2423
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;
2428
2429 if (blockSizeX + x > w)
2430 blockSizeX = w - x;
2431 if (blockSizeY + y > h)
2432 blockSizeY = h - y;
2433
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);
2438 }
2439 }
2440 params.useData = false;
2441
2442 return true;
2443 }
2444 },
2445 checkSupport : function() {
2446 return (Pixastic.Client.hasCanvasImageData());
2447 }
2448 }/*
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]
2452 */
2453
2454 Pixastic.Actions.noise = {
2455
2456 process : function(params) {
2457 var amount = 0;
2458 var strength = 0;
2459 var mono = false;
2460
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");
2467
2468 amount = Math.max(0,Math.min(1,amount));
2469 strength = Math.max(0,Math.min(1,strength));
2470
2471 var noise = 128 * strength;
2472 var noise2 = noise / 2;
2473
2474 if (Pixastic.Client.hasCanvasImageData()) {
2475 var data = Pixastic.prepareData(params);
2476 var rect = params.options.rect;
2477 var w = rect.width;
2478 var h = rect.height;
2479 var w4 = w*4;
2480 var y = h;
2481 var random = Math.random;
2482
2483 do {
2484 var offsetY = (y-1)*w4;
2485 var x = w;
2486 do {
2487 var offset = offsetY + (x-1)*4;
2488 if (random() < amount) {
2489 if (mono) {
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;
2494 } else {
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);
2498 }
2499
2500 if (r < 0 ) r = 0;
2501 if (g < 0 ) g = 0;
2502 if (b < 0 ) b = 0;
2503 if (r > 255 ) r = 255;
2504 if (g > 255 ) g = 255;
2505 if (b > 255 ) b = 255;
2506
2507 data[offset] = r;
2508 data[offset+1] = g;
2509 data[offset+2] = b;
2510 }
2511 } while (--x);
2512 } while (--y);
2513 return true;
2514 }
2515 },
2516 checkSupport : function() {
2517 return Pixastic.Client.hasCanvasImageData();
2518 }
2519 }
2520
2521 /*
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]
2525 */
2526
2527 Pixastic.Actions.posterize = {
2528
2529 process : function(params) {
2530
2531
2532 var numLevels = 256;
2533 if (typeof params.options.levels != "undefined")
2534 numLevels = parseInt(params.options.levels,10)||1;
2535
2536 if (Pixastic.Client.hasCanvasImageData()) {
2537 var data = Pixastic.prepareData(params);
2538
2539 numLevels = Math.max(2,Math.min(256,numLevels));
2540
2541 var numAreas = 256 / numLevels;
2542 var numValues = 256 / (numLevels-1);
2543
2544 var rect = params.options.rect;
2545 var w = rect.width;
2546 var h = rect.height;
2547 var w4 = w*4;
2548 var y = h;
2549 do {
2550 var offsetY = (y-1)*w4;
2551 var x = w;
2552 do {
2553 var offset = offsetY + (x-1)*4;
2554
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);
2558
2559 if (r > 255) r = 255;
2560 if (g > 255) g = 255;
2561 if (b > 255) b = 255;
2562
2563 data[offset] = r;
2564 data[offset+1] = g;
2565 data[offset+2] = b;
2566
2567 } while (--x);
2568 } while (--y);
2569 return true;
2570 }
2571 },
2572 checkSupport : function() {
2573 return Pixastic.Client.hasCanvasImageData();
2574 }
2575 }
2576
2577
2578 /*
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]
2582 */
2583
2584 Pixastic.Actions.pointillize = {
2585
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");
2591
2592 if (Pixastic.Client.hasCanvasImageData()) {
2593 var rect = params.options.rect;
2594 var w = rect.width;
2595 var h = rect.height;
2596 var w4 = w*4;
2597 var y = h;
2598
2599 var ctx = params.canvas.getContext("2d");
2600 var canvasWidth = params.canvas.width;
2601 var canvasHeight = params.canvas.height;
2602
2603 var pixel = document.createElement("canvas");
2604 pixel.width = pixel.height = 1;
2605 var pixelCtx = pixel.getContext("2d");
2606
2607 var copy = document.createElement("canvas");
2608 copy.width = w;
2609 copy.height = h;
2610 var copyCtx = copy.getContext("2d");
2611 copyCtx.drawImage(params.canvas,rect.left,rect.top,w,h, 0,0,w,h);
2612
2613 var diameter = radius * 2;
2614
2615 if (transparent)
2616 ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
2617
2618 var noiseRadius = radius * noise;
2619
2620 var dist = 1 / density;
2621
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;
2626
2627 var pixX = rndX - radius;
2628 var pixY = rndY - radius;
2629 if (pixX < 0) pixX = 0;
2630 if (pixY < 0) pixY = 0;
2631
2632 var cx = rndX + rect.left;
2633 var cy = rndY + rect.top;
2634 if (cx < 0) cx = 0;
2635 if (cx > canvasWidth) cx = canvasWidth;
2636 if (cy < 0) cy = 0;
2637 if (cy > canvasHeight) cy = canvasHeight;
2638
2639 var diameterX = diameter;
2640 var diameterY = diameter;
2641
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;
2648
2649 pixelCtx.drawImage(copy, pixX, pixY, diameterX, diameterY, 0, 0, 1, 1);
2650 var data = pixelCtx.getImageData(0,0,1,1).data;
2651
2652 ctx.fillStyle = "rgb(" + data[0] + "," + data[1] + "," + data[2] + ")";
2653 ctx.beginPath();
2654 ctx.arc(cx, cy, radius, 0, Math.PI*2, true);
2655 ctx.closePath();
2656 ctx.fill();
2657 }
2658 }
2659
2660 params.useData = false;
2661
2662 return true;
2663 }
2664 },
2665 checkSupport : function() {
2666 return (Pixastic.Client.hasCanvasImageData());
2667 }
2668 }/*
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]
2672 */
2673
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;
2680
2681 if (width < 1) width = 1;
2682 if (width < 2) width = 2;
2683
2684 var copy = document.createElement("canvas");
2685 copy.width = width;
2686 copy.height = height;
2687
2688 copy.getContext("2d").drawImage(canvas,0,0,width,height);
2689 canvas.width = width;
2690 canvas.height = height;
2691
2692 canvas.getContext("2d").drawImage(copy,0,0);
2693
2694 params.useData = false;
2695 return true;
2696 }
2697 },
2698 checkSupport : function() {
2699 return Pixastic.Client.hasCanvas();
2700 }
2701 }
2702
2703
2704 /*
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]
2708 */
2709
2710 Pixastic.Actions.removenoise = {
2711 process : function(params) {
2712
2713 if (Pixastic.Client.hasCanvasImageData()) {
2714 var data = Pixastic.prepareData(params);
2715
2716 var rect = params.options.rect;
2717 var w = rect.width;
2718 var h = rect.height;
2719
2720 var w4 = w*4;
2721 var y = h;
2722 do {
2723 var offsetY = (y-1)*w4;
2724
2725 var nextY = (y == h) ? y - 1 : y;
2726 var prevY = (y == 1) ? 0 : y-2;
2727
2728 var offsetYPrev = prevY*w*4;
2729 var offsetYNext = nextY*w*4;
2730
2731 var x = w;
2732 do {
2733 var offset = offsetY + (x*4-4);
2734
2735 var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
2736 var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
2737
2738 var minR, maxR, minG, maxG, minB, maxB;
2739
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;
2748
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;
2757
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;
2766
2767 if (data[offset] > maxR) {
2768 data[offset] = maxR;
2769 } else if (data[offset] < minR) {
2770 data[offset] = minR;
2771 }
2772 if (data[offset+1] > maxG) {
2773 data[offset+1] = maxG;
2774 } else if (data[offset+1] < minG) {
2775 data[offset+1] = minG;
2776 }
2777 if (data[offset+2] > maxB) {
2778 data[offset+2] = maxB;
2779 } else if (data[offset+2] < minB) {
2780 data[offset+2] = minB;
2781 }
2782
2783 } while (--x);
2784 } while (--y);
2785
2786 return true;
2787 }
2788 },
2789 checkSupport : function() {
2790 return Pixastic.Client.hasCanvasImageData();
2791 }
2792 }/*
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]
2796 */
2797
2798 Pixastic.Actions.rotate = {
2799 process : function(params) {
2800 if (Pixastic.Client.hasCanvas()) {
2801 var canvas = params.canvas;
2802
2803 var width = params.width;
2804 var height = params.height;
2805
2806 var copy = document.createElement("canvas");
2807 copy.width = width;
2808 copy.height = height;
2809 copy.getContext("2d").drawImage(canvas,0,0,width,height);
2810
2811 var angle = -parseFloat(params.options.angle) * Math.PI / 180;
2812
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;
2818
2819 var diag = Math.sqrt(width*width + height*height);
2820
2821 var diagAngle1 = Math.abs(dimAngle) - Math.abs(Math.atan2(height, width));
2822 var diagAngle2 = Math.abs(dimAngle) + Math.abs(Math.atan2(height, width));
2823
2824 var newWidth = Math.abs(Math.cos(diagAngle1) * diag);
2825 var newHeight = Math.abs(Math.sin(diagAngle2) * diag);
2826
2827 canvas.width = newWidth;
2828 canvas.height = newHeight;
2829
2830 var ctx = canvas.getContext("2d");
2831 ctx.translate(newWidth/2, newHeight/2);
2832 ctx.rotate(angle);
2833 ctx.drawImage(copy,-width/2,-height/2);
2834
2835 params.useData = false;
2836 return true;
2837 }
2838 },
2839 checkSupport : function() {
2840 return Pixastic.Client.hasCanvas();
2841 }
2842 }
2843
2844
2845 /*
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]
2849 */
2850
2851 Pixastic.Actions.sepia = {
2852
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;
2857
2858 if (Pixastic.Client.hasCanvasImageData()) {
2859 var data = Pixastic.prepareData(params);
2860 var rect = params.options.rect;
2861 var w = rect.width;
2862 var h = rect.height;
2863 var w4 = w*4;
2864 var y = h;
2865 do {
2866 var offsetY = (y-1)*w4;
2867 var x = w;
2868 do {
2869 var offset = offsetY + (x-1)*4;
2870
2871 if (mode) {
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;
2874 var r = (d + 39);
2875 var g = (d + 14);
2876 var b = (d - 36);
2877 } else {
2878 // Microsoft
2879 var or = data[offset];
2880 var og = data[offset+1];
2881 var ob = data[offset+2];
2882
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);
2886 }
2887
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;
2891
2892 data[offset] = r;
2893 data[offset+1] = g;
2894 data[offset+2] = b;
2895
2896 } while (--x);
2897 } while (--y);
2898 return true;
2899 }
2900 },
2901 checkSupport : function() {
2902 return Pixastic.Client.hasCanvasImageData();
2903 }
2904 }/*
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]
2908 */
2909
2910 Pixastic.Actions.sharpen = {
2911 process : function(params) {
2912
2913 var strength = 0;
2914 if (typeof params.options.amount != "undefined")
2915 strength = parseFloat(params.options.amount)||0;
2916
2917 if (strength < 0) strength = 0;
2918 if (strength > 1) strength = 1;
2919
2920 if (Pixastic.Client.hasCanvasImageData()) {
2921 var data = Pixastic.prepareData(params);
2922 var dataCopy = Pixastic.prepareData(params, true)
2923
2924 var mul = 15;
2925 var mulOther = 1 + 3*strength;
2926
2927 var kernel = [
2928 [0, -mulOther, 0],
2929 [-mulOther, mul, -mulOther],
2930 [0, -mulOther, 0]
2931 ];
2932
2933 var weight = 0;
2934 for (var i=0;i<3;i++) {
2935 for (var j=0;j<3;j++) {
2936 weight += kernel[i][j];
2937 }
2938 }
2939
2940 weight = 1 / weight;
2941
2942 var rect = params.options.rect;
2943 var w = rect.width;
2944 var h = rect.height;
2945
2946 mul *= weight;
2947 mulOther *= weight;
2948
2949 var w4 = w*4;
2950 var y = h;
2951 do {
2952 var offsetY = (y-1)*w4;
2953
2954 var nextY = (y == h) ? y - 1 : y;
2955 var prevY = (y == 1) ? 0 : y-2;
2956
2957 var offsetYPrev = prevY*w4;
2958 var offsetYNext = nextY*w4;
2959
2960 var x = w;
2961 do {
2962 var offset = offsetY + (x*4-4);
2963
2964 var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
2965 var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
2966
2967 var r = ((
2968 - dataCopy[offsetPrev]
2969 - dataCopy[offset-4]
2970 - dataCopy[offset+4]
2971 - dataCopy[offsetNext]) * mulOther
2972 + dataCopy[offset] * mul
2973 );
2974
2975 var g = ((
2976 - dataCopy[offsetPrev+1]
2977 - dataCopy[offset-3]
2978 - dataCopy[offset+5]
2979 - dataCopy[offsetNext+1]) * mulOther
2980 + dataCopy[offset+1] * mul
2981 );
2982
2983 var b = ((
2984 - dataCopy[offsetPrev+2]
2985 - dataCopy[offset-2]
2986 - dataCopy[offset+6]
2987 - dataCopy[offsetNext+2]) * mulOther
2988 + dataCopy[offset+2] * mul
2989 );
2990
2991
2992 if (r < 0 ) r = 0;
2993 if (g < 0 ) g = 0;
2994 if (b < 0 ) b = 0;
2995 if (r > 255 ) r = 255;
2996 if (g > 255 ) g = 255;
2997 if (b > 255 ) b = 255;
2998
2999 data[offset] = r;
3000 data[offset+1] = g;
3001 data[offset+2] = b;
3002
3003 } while (--x);
3004 } while (--y);
3005
3006 return true;
3007
3008 }
3009 },
3010 checkSupport : function() {
3011 return Pixastic.Client.hasCanvasImageData();
3012 }
3013 }
3014 /*
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]
3018 */
3019
3020 Pixastic.Actions.solarize = {
3021
3022 process : function(params) {
3023 var useAverage = !!(params.options.average && params.options.average != "false");
3024
3025 if (Pixastic.Client.hasCanvasImageData()) {
3026 var data = Pixastic.prepareData(params);
3027 var rect = params.options.rect;
3028 var w = rect.width;
3029 var h = rect.height;
3030 var w4 = w*4;
3031 var y = h;
3032 do {
3033 var offsetY = (y-1)*w4;
3034 var x = w;
3035 do {
3036 var offset = offsetY + (x-1)*4;
3037
3038 var r = data[offset];
3039 var g = data[offset+1];
3040 var b = data[offset+2];
3041
3042 if (r > 127) r = 255 - r;
3043 if (g > 127) g = 255 - g;
3044 if (b > 127) b = 255 - b;
3045
3046 data[offset] = r;
3047 data[offset+1] = g;
3048 data[offset+2] = b;
3049
3050 } while (--x);
3051 } while (--y);
3052 return true;
3053 }
3054 },
3055 checkSupport : function() {
3056 return (Pixastic.Client.hasCanvasImageData());
3057 }
3058 }/*
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]
3062 */
3063
3064
3065 Pixastic.Actions.unsharpmask = {
3066 process : function(params) {
3067
3068 var amount = (parseFloat(params.options.amount)||0);
3069 var blurAmount = parseFloat(params.options.radius)||0;
3070 var threshold = parseFloat(params.options.threshold)||0;
3071
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));
3075
3076 threshold--;
3077 var thresholdNeg = -threshold;
3078
3079 amount *= 0.016;
3080 amount++;
3081
3082 if (Pixastic.Client.hasCanvasImageData()) {
3083 var rect = params.options.rect;
3084
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);
3090
3091 var scale = 2;
3092 var smallWidth = Math.round(params.width / scale);
3093 var smallHeight = Math.round(params.height / scale);
3094
3095 var copy = document.createElement("canvas");
3096 copy.width = smallWidth;
3097 copy.height = smallHeight;
3098
3099 var steps = Math.round(blurAmount * 20);
3100
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));
3105
3106 copyCtx.clearRect(0,0,smallWidth,smallHeight);
3107
3108 copyCtx.drawImage(
3109 blurCanvas,
3110 0,0,params.width,params.height,
3111 0,0,scaledWidth,scaledHeight
3112 );
3113
3114 blurCtx.clearRect(0,0,params.width,params.height);
3115
3116 blurCtx.drawImage(
3117 copy,
3118 0,0,scaledWidth,scaledHeight,
3119 0,0,params.width,params.height
3120 );
3121 }
3122
3123 var data = Pixastic.prepareData(params);
3124 var blurData = Pixastic.prepareData({canvas:blurCanvas,options:params.options});
3125 var w = rect.width;
3126 var h = rect.height;
3127 var w4 = w*4;
3128 var y = h;
3129 do {
3130 var offsetY = (y-1)*w4;
3131 var x = w;
3132 do {
3133 var offset = offsetY + (x*4-4);
3134
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);
3140 }
3141
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);
3147 }
3148
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);
3154 }
3155
3156 } while (--x);
3157 } while (--y);
3158
3159 return true;
3160 }
3161 },
3162 checkSupport : function() {
3163 return Pixastic.Client.hasCanvasImageData();
3164 }
3165 }
3166
3167
3168
3169