r52052 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r52051‎ | r52052 | r52053 >
Date:16:51, 17 June 2009
Author:dale
Status:deferred
Tags:
Comment:
pixastic-editor library import
mvFirefog sp fix
Modified paths:
  • /branches/new-upload/phase3/js2/mwEmbed/jquery/jquery.ui-1.7.1/themes/base/images/ui-bg_diagonals-thick_20_666666_40x40.png (added) (history)
  • /branches/new-upload/phase3/js2/mwEmbed/libAddMedia/mvBaseUploadInterface.js (modified) (history)
  • /branches/new-upload/phase3/js2/mwEmbed/libAddMedia/mvFirefogg.js (modified) (history)
  • /branches/new-upload/phase3/js2/mwEmbed/libClipEdit/pixastic-editor (added) (history)
  • /branches/new-upload/phase3/js2/mwEmbed/libClipEdit/pixastic-editor/editor.js (added) (history)
  • /branches/new-upload/phase3/js2/mwEmbed/libClipEdit/pixastic-editor/pixastic.all.js (added) (history)
  • /branches/new-upload/phase3/js2/mwEmbed/libClipEdit/pixastic-editor/pixastic.css (added) (history)
  • /branches/new-upload/phase3/js2/mwEmbed/libClipEdit/pixastic-editor/uidata.js (added) (history)
  • /branches/new-upload/phase3/js2/mwEmbed/skins/mvpcf/images/ui-bg_diagonals-thick_20_666666_40x40.png (added) (history)

Diff [purge]

Index: branches/new-upload/phase3/js2/mwEmbed/jquery/jquery.ui-1.7.1/themes/base/images/ui-bg_diagonals-thick_20_666666_40x40.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/new-upload/phase3/js2/mwEmbed/jquery/jquery.ui-1.7.1/themes/base/images/ui-bg_diagonals-thick_20_666666_40x40.png
___________________________________________________________________
Added: svn:mime-type
11 + application/octet-stream
Index: branches/new-upload/phase3/js2/mwEmbed/libAddMedia/mvFirefogg.js
@@ -564,7 +564,7 @@
565565 },
566566 cancel_action:function( dlElm ){
567567 js_log('firefogg:cancel')
568 - if( confirm( gM('mv-canecl-confim') )){
 568+ if( confirm( gM('mv-cancel-confim') )){
569569 if(navigator.oscpu && navigator.oscpu.search('Win') >= 0){
570570 alert( 'sorry we do not yet support cancel on windows' );
571571 }else{
Index: branches/new-upload/phase3/js2/mwEmbed/libAddMedia/mvBaseUploadInterface.js
@@ -15,7 +15,7 @@
1616 "mv_upload_done" : "Your upload <i>should be</i> accessible <a href=\"$1\">here</a>",
1717 "upload-unknown-size": "Unknown size",
1818
19 - "mv-canecl-confim" : "Are you sure you want to cancel?",
 19+ "mv-cancel-confim" : "Are you sure you want to cancel?",
2020
2121 "successfulupload" : "Successful Upload",
2222 "uploaderror" : "Upload error",
@@ -547,7 +547,7 @@
548548 },
549549 cancel_action:function(dlElm){
550550 //confirm:
551 - if( confirm( gM('mv-canecl-confim') )){
 551+ if( confirm( gM('mv-cancel-confim') )){
552552 //@@todo (cancel the encode / upload)
553553 //$j(dlElm).dialog('close');
554554 alert('(sorry we do not yet support cancel)');
Index: branches/new-upload/phase3/js2/mwEmbed/libClipEdit/pixastic-editor/pixastic.css
@@ -0,0 +1,423 @@
 2+/* http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/ */
 3+
 4+html, body, div, span, applet, object, iframe,
 5+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
 6+a, abbr, acronym, address, big, cite, code,
 7+del, dfn, em, font, img, ins, kbd, q, s, samp,
 8+small, strike, strong, sub, sup, tt, var,
 9+dl, dt, dd, ol, ul, li,
 10+fieldset, form, label, legend,
 11+table, caption, tbody, tfoot, thead, tr, th, td {
 12+ margin: 0;
 13+ padding: 0;
 14+ border: 0;
 15+ outline: 0;
 16+ font-weight: inherit;
 17+ font-style: inherit;
 18+ font-size: 100%;
 19+ font-family: inherit;
 20+ vertical-align: baseline;
 21+}
 22+/* remember to define focus styles! */
 23+:focus {
 24+ outline: 0;
 25+}
 26+body {
 27+ line-height: 1;
 28+ color: black;
 29+ background: white;
 30+}
 31+ol, ul {
 32+ list-style: none;
 33+}
 34+/* tables still need 'cellspacing="0"' in the markup */
 35+table {
 36+ border-collapse: separate;
 37+ border-spacing: 0;
 38+}
 39+caption, th, td {
 40+ text-align: left;
 41+ font-weight: normal;
 42+}
 43+blockquote:before, blockquote:after,
 44+q:before, q:after {
 45+ content: "";
 46+}
 47+blockquote, q {
 48+ quotes: "" "";
 49+}
 50+/* end reset */
 51+
 52+/* -----------------------
 53+ * Base
 54+ * -----------------------
 55+ */
 56+
 57+/* main container element for editor app */
 58+#pixastic-editor {
 59+ margin : 0;
 60+ position : absolute;
 61+ left : 0;
 62+ top : 0;
 63+ padding: 0px;
 64+ width: 100%;
 65+ height: 100%;
 66+ font-family : Helvetica,Arial,sans-serif;
 67+ overflow : hidden;
 68+ z-index : 10000000;
 69+}
 70+
 71+
 72+/* -----------------------
 73+ * Loading screen
 74+ * -----------------------
 75+ */
 76+
 77+/* container for loading screen */
 78+#loading-screen {
 79+ margin : 0;
 80+ position : absolute;
 81+ left : 0;
 82+ top : 0;
 83+ padding: 0px;
 84+ width: 100%;
 85+ height: 100%;
 86+ font-family : Helvetica,Arial,sans-serif;
 87+ overflow : hidden;
 88+ z-index : 10000000;
 89+ background-color : #111;
 90+ opacity : 0.9;
 91+ display : table;
 92+ text-align : center;
 93+}
 94+
 95+/* container for spinner in loading screen */
 96+#loading-screen-cell {
 97+ display : table-cell;
 98+ vertical-align : middle;
 99+ text-align : center;
 100+}
 101+
 102+
 103+/* -----------------------
 104+ * Misc
 105+ * -----------------------
 106+ */
 107+
 108+
 109+// UI error dialog
 110+.ui-dialog .error-dialog {
 111+ background-color : #544;
 112+}
 113+
 114+/* loading spinner */
 115+.spinner {
 116+ width : 31px;
 117+ height : 31px;
 118+ display : inline-block;
 119+ background: url(spinner.gif);
 120+ overflow : hidden;
 121+}
 122+
 123+canvas.display-canvas,
 124+canvas.undo-canvas {
 125+ /*
 126+ background : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC1JREFUeNpiPHPmDAM2YGxsjFWciYFEMKqBGMD4//9/rBJnz54dDSX6aQAIMABCtQiAsDRF+wAAAABJRU5ErkJggg==');
 127+ */
 128+ background : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC5JREFUeNpiPHPmTAMDHmBsbIxPmoGJgUIwasBgMICFUDyfPXt2NBCHvwEAAQYAICIGn294LYEAAAAASUVORK5CYII=');
 129+
 130+}
 131+
 132+.far-far-away {
 133+ position : absolute;
 134+ left : -9999px;
 135+ top : -9999px;
 136+}
 137+
 138+#powered-by-pixastic {
 139+ position : absolute;
 140+ bottom : 0px;
 141+ margin-bottom : 23px;
 142+ margin-left : 42px;
 143+}
 144+#powered-by-pixastic a {
 145+ font-size : 12px;
 146+ font-family : Helvetica,Arial,sans-serif;
 147+ letter-spacing : 0.1em;
 148+ color : rgb(100,100,100);
 149+ color : rgba(255,255,255,0.2);
 150+ text-decoration : none;
 151+}
 152+
 153+#powered-by-pixastic a:hover {
 154+ color : rgb(200,200,200);
 155+ color : rgba(255,255,255,0.7);
 156+ text-decoration : underline;
 157+}
 158+
 159+
 160+/* -----------------------
 161+ * Skeleton structure
 162+ * -----------------------
 163+ */
 164+
 165+/* editor background underlay */
 166+#background {
 167+ background-color : #111;
 168+ opacity : 0.9;
 169+ width : 100%;
 170+ height : 100%;
 171+ position : absolute;
 172+ z-index : -1;
 173+}
 174+
 175+#image-area {
 176+ position : relative;
 177+ background-color : #222;
 178+ border : 1px solid #444;
 179+ width : 100%;
 180+ height : 100%;
 181+ -moz-box-sizing:border-box;
 182+ overflow : auto;
 183+ text-align : center;
 184+}
 185+
 186+#image-area-sub {
 187+}
 188+
 189+#image-container {
 190+}
 191+
 192+#image-overlay-container {
 193+ -moz-box-sizing:border-box;
 194+ width:100%;
 195+ height:100%;
 196+ position:absolute;
 197+ top:0;
 198+ left:0;
 199+}
 200+
 201+#image-overlay {
 202+}
 203+
 204+
 205+/* structure elements */
 206+#edit-ctr-1 {
 207+ position : absolute;
 208+ top : 0;
 209+ left : 0;
 210+ width : 100%;
 211+ height : 100%;
 212+}
 213+
 214+#edit-ctr-2 {
 215+ -moz-box-sizing : border-box;
 216+ box-sizing : border-box;
 217+ padding-left:40px;
 218+ padding-right:420px;
 219+ padding-top:70px;
 220+ padding-bottom : 40px;
 221+ height : 100%;
 222+ width : 100%;
 223+}
 224+
 225+
 226+/* main menu bar */
 227+#main-bar {
 228+ position : absolute;
 229+ width : 100%;
 230+ text-align : right;
 231+ margin-top : 20px;
 232+ margin-right : 30px;
 233+}
 234+
 235+/* area on the right with accordion widgets and undo bar */
 236+#controls-bar {
 237+ margin-right : -385px;
 238+ width : 372px;
 239+ float : right;
 240+ height : 100%;
 241+}
 242+
 243+/* accordion area */
 244+#action-bar {
 245+ padding : 10px;
 246+ width : 290px;
 247+ background-color : #222;
 248+ border : 1px solid #444;
 249+ -moz-box-sizing : border-box;
 250+ box-sizing : border-box;
 251+ height : 100%;
 252+ overflow-x : hidden;
 253+ overflow-y : auto;
 254+ float: right;
 255+ position : relative;
 256+}
 257+
 258+#action-bar-overlay {
 259+ position : absolute;
 260+ z-index : 1000000;
 261+ width : 100%;
 262+ height : 100%;
 263+ left : 0;
 264+ top : 0;
 265+ background-color : #444;
 266+ opacity : 0.2;
 267+ display : none;
 268+}
 269+
 270+
 271+/* vertical bar with undo image states */
 272+#undo-bar {
 273+ -moz-box-sizing : border-box;
 274+ box-sizing : border-box;
 275+ background-color : #222;
 276+ border : 1px solid #444;
 277+ width: 70px;
 278+ height: 100%;
 279+ overflow: hidden;
 280+ padding-top : 3px;
 281+}
 282+
 283+
 284+
 285+/* -----------------------
 286+ * Main menu styles
 287+ * -----------------------
 288+ */
 289+
 290+.main-tab {
 291+ color : #999;
 292+ display : inline-block;
 293+ width : 150px;
 294+ text-transform : lowercase;
 295+ font-size : 22px;
 296+ cursor : pointer;
 297+ text-align : center;
 298+ text-decoration : none;
 299+ padding-top : 4px;
 300+ padding-bottom : 5px;
 301+ outline : 0;
 302+}
 303+
 304+.main-tab.hover {
 305+ color : white !important;
 306+}
 307+
 308+.main-tab.active {
 309+ color : white;
 310+}
 311+
 312+
 313+
 314+/* -----------------------
 315+ * Undo list
 316+ * -----------------------
 317+ */
 318+
 319+
 320+.undo-canvas-small {
 321+ width : 60px;
 322+ height : 40px;
 323+ cursor : pointer;
 324+}
 325+
 326+.undo-link {
 327+ width : 60px;
 328+ height : 40px;
 329+ display : block;
 330+ margin : 4px;
 331+ cursor : pointer;
 332+ opacity : 0.8;
 333+}
 334+
 335+.undo-link.hover {
 336+ opacity : 1;
 337+}
 338+
 339+
 340+
 341+/* -----------------------
 342+ * Action UI controls
 343+ * -----------------------
 344+ */
 345+
 346+
 347+.ui-slider-label,
 348+.ui-checkbox-label,
 349+.ui-textinput-label,
 350+.ui-select-label {
 351+ width : 70px;
 352+ text-align : right;
 353+ margin-right : 5px;
 354+ display : inline-block;
 355+}
 356+
 357+.ui-textinput-label-right {
 358+ margin-left : 5px;
 359+}
 360+
 361+.ui-textinput {
 362+}
 363+
 364+.ui-numericinput {
 365+ width : 35px;
 366+}
 367+
 368+.ui-slider {
 369+ width : 125px;
 370+ display : inline-block;
 371+ margin-left : 3px;
 372+ background-color : #222;
 373+}
 374+
 375+.ui-slider-value {
 376+ font-size : 11px;
 377+ width : 25px;
 378+ display : inline-block;
 379+ margin-left : 10px;
 380+}
 381+
 382+.ui-action-output {
 383+ margin-bottom : 10px;
 384+}
 385+
 386+.ui-accordion .ui-accordion-content-active {
 387+ font-size : 11px;
 388+ overflow : hidden;
 389+}
 390+
 391+.ui-slider-horizontal {
 392+}
 393+
 394+.ui-slider-container,
 395+.ui-checkbox-container,
 396+.ui-textinput-container,
 397+.ui-select-container {
 398+ margin-top : 0px;
 399+ margin-bottom : 10px;
 400+ white-space : nowrap;
 401+}
 402+
 403+.ui-preview-checkbox-container {
 404+ display : inline-block;
 405+}
 406+
 407+.ui-checkbox {
 408+ margin-bottom:3px;
 409+ margin-left:5px;
 410+ margin-right:5px;
 411+ margin-top:0px;
 412+ vertical-align:middle;
 413+}
 414+
 415+input::-moz-focus-inner { border: 0; }
 416+
 417+.action-output-text {
 418+ margin-bottom : 5px;
 419+}
 420+
 421+button {
 422+ margin-right : 5px;
 423+}
 424+
Index: branches/new-upload/phase3/js2/mwEmbed/libClipEdit/pixastic-editor/editor.js
@@ -0,0 +1,967 @@
 2+
 3+var PixasticEditor = (function () {
 4+
 5+ var $frame; // iframe container element
 6+ var $editor; // editor container element
 7+
 8+ // various UI structures
 9+ var accordionElements = {};
 10+ var tabElements = {};
 11+ var activeTabId;
 12+ var $activeTabContent;
 13+
 14+ var isRunning = false;
 15+
 16+ var $loadingScreen;
 17+
 18+ var $imageCanvas; // the canvas holding the current state of the image
 19+ var $displayCanvas; // the canvas element displayed on the screen, also the working canvas (where preview operations are performed)
 20+ var imageCtx;
 21+
 22+ var imageWidth = 0; // dimensions of the current image state
 23+ var imageHeight = 0;
 24+
 25+ var undoImages = []; // canvas elements holding previous image states
 26+ var undoLevels = 10;
 27+
 28+ var doc;
 29+
 30+ var $;
 31+
 32+ // test for valid file formats for toDataURL()
 33+ // we do that by calling it with each of the mime types in testFormats
 34+ // and then doing string checking on the resulting data: URI to see if it succeeded
 35+ var saveFormats = [];
 36+ var testFormats = [["image/jpeg", "JPEG"], ["image/png", "PNG"]];
 37+ var testCanvas = document.createElement("canvas");
 38+ if (testCanvas.toDataURL) {
 39+ testCanvas.width = testCanvas.height = 1;
 40+ for (var i=0;i<testFormats.length;i++) {
 41+ var data = testCanvas.toDataURL(testFormats[i][0]);
 42+ if (data.substr(0, 5 + testFormats[i][0].length) == "data:" + testFormats[i][0])
 43+ saveFormats.push({mime:testFormats[i][0], name:testFormats[i][1]});
 44+ }
 45+ }
 46+
 47+
 48+ // pops up an error dialog with the specified text (errTxt),
 49+ // if no context is provided, the name of the calling function is used.
 50+ // The final message is returned for easy throwing of actual errors
 51+ function errorDialog(errTxt, context) {
 52+ if (!($editor && $editor.get && $editor.get(0)))
 53+ throw new Error("errorDialog(): $editor doesn't exist");
 54+
 55+ var caller = errorDialog.caller.toString().split(" ")[1];
 56+ caller = caller.substring(0, caller.indexOf("("));
 57+ context = context || caller;
 58+ errTxt = context + "(): " + errTxt;
 59+ var dialog = $("<div></div>", doc)
 60+ .addClass("error-dialog")
 61+ .attr("title", "Oops!")
 62+ .html(errTxt)
 63+ .dialog();
 64+ // the dialog is added outside the Pixastic container, so get it back in.
 65+ var dialogParent = $(dialog.get(0).parentNode);
 66+ dialogParent.appendTo($editor);
 67+
 68+ return errTxt;
 69+ }
 70+
 71+ function enableTab(id, refresh) {
 72+ if (id == activeTabId && !refresh)
 73+ return;
 74+
 75+ activeTabId = id;
 76+
 77+ var activeIndex = 0;
 78+
 79+ if ($activeTabContent) {
 80+ if ($activeTabContent.get(0)) {
 81+ var $parent = $($activeTabContent.get(0).parentNode);
 82+ activeIndex = $parent.data("accordionindex");
 83+ if ($parent.data("ondeactivate")) {
 84+ $parent.data("ondeactivate")();
 85+ }
 86+ if ($parent.data("previewCheckbox"))
 87+ $parent.data("previewCheckbox").attr("checked", false);
 88+ $parent.data("uidesc").previewEnabled = false;
 89+ if ($parent.data("uidesc").forcePreview)
 90+ $parent.data("uidesc").previewEnabled = true;
 91+ }
 92+ }
 93+
 94+
 95+ for (var a in accordionElements) {
 96+ if (accordionElements.hasOwnProperty(a)) {
 97+ accordionElements[a].accordion("option", "animated", false);
 98+ accordionElements[a].accordion("activate", -1);
 99+ accordionElements[a].hide();
 100+ tabElements[a].removeClass("active");
 101+
 102+ }
 103+ }
 104+
 105+ accordionElements[id].accordion("option", "animated", false);
 106+ accordionElements[id].accordion("activate", refresh ? activeIndex : 0);
 107+ tabElements[id].addClass("active");
 108+ accordionElements[id].show();
 109+ accordionElements[id].accordion("option", "animated", "slide");
 110+ resetDisplayCanvas();
 111+ }
 112+
 113+ // revert to a previous image state
 114+ function undo(idx) {
 115+ var undoImage = undoImages[idx];
 116+
 117+ if (!undoImage)
 118+ throw new Error(errorDialog("Invalid undo state"));
 119+ if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))
 120+ throw new Error(errorDialog("$imageCanvas doesn't exist"));
 121+
 122+ var canvas = $imageCanvas.get(0);
 123+ addUndo(canvas);
 124+ canvas.width = imageWidth = undoImage.width;
 125+ canvas.height = imageHeight = undoImage.height;
 126+ canvas.getContext("2d").drawImage(undoImage,0,0);
 127+
 128+ enableTab(activeTabId, true);
 129+ resetDisplayCanvas();
 130+ }
 131+
 132+ function addUndo(canvasElement) {
 133+ if (!canvasElement)
 134+ throw new Error(errorDialog("No undo image state provided"));
 135+
 136+ if (undoImages.length == undoLevels) {
 137+ undoImages.shift();
 138+ }
 139+ var undoCanvas = document.createElement("canvas");
 140+ undoCanvas.width = canvasElement.width;
 141+ undoCanvas.height = canvasElement.height;
 142+ undoCanvas.getContext("2d").drawImage(canvasElement,0,0);
 143+ $(undoCanvas).addClass("undo-canvas");
 144+ undoImages.push(undoCanvas);
 145+ updateUndoList();
 146+ }
 147+
 148+ function updateUndoList() {
 149+ var $listCtr = $("#undo-bar", doc)
 150+ .html("");
 151+
 152+ var ctrHeight = $listCtr.height();
 153+
 154+ var $testCanvas = $("<canvas></canvas>", doc)
 155+ .addClass("undo-canvas-small")
 156+ .addClass("far-far-away")
 157+ .appendTo("body");
 158+
 159+ var canvasHeight = $testCanvas.height();
 160+ var canvasWidth = $testCanvas.width();
 161+ var canvasCSSHeight = canvasHeight + parseInt($testCanvas.css("margin-top"),10) + parseInt($testCanvas.css("margin-bottom"),10);
 162+
 163+ $testCanvas.remove();
 164+
 165+ var undoRatio = canvasWidth / canvasHeight;
 166+
 167+ for (var i=undoImages.length-1;i>=0;i--) {
 168+ (function(){
 169+ var canvas = document.createElement("canvas");
 170+ $(canvas)
 171+ .addClass("undo-canvas-small")
 172+ .attr("width", canvasWidth)
 173+ .attr("height", canvasHeight);
 174+
 175+ var image = undoImages[i];
 176+ $(image).show();
 177+
 178+ var undoWidth, undoHeight;
 179+ var imageRatio = image.width / image.height;
 180+
 181+ if (imageRatio > undoRatio) { // image too wide
 182+ undoWidth = canvasWidth;
 183+ undoHeight = canvasWidth / imageRatio;
 184+ } else {
 185+ undoWidth = canvasHeight * imageRatio;
 186+ undoHeight = canvasHeight;
 187+ }
 188+
 189+ var restWidth = canvasWidth - undoWidth;
 190+ var restHeight = canvasHeight - undoHeight;
 191+
 192+ canvas.getContext("2d").drawImage(
 193+ image,
 194+ 0,0,image.width,image.height,
 195+ restWidth*0.5, restHeight*0.5,
 196+ undoWidth, undoHeight
 197+ );
 198+
 199+
 200+ $link = $("<a href='#'></a>", doc)
 201+ .addClass("undo-link")
 202+ .appendTo($listCtr)
 203+ .mouseover(function(){ $(this).addClass("hover") })
 204+ .mouseout(function(){ $(this).removeClass("hover") });
 205+ $(canvas).appendTo($link);
 206+
 207+ var displayShowing;
 208+ var undoIndex = i;
 209+ $link.click(function() {
 210+ $(image).hide();
 211+ $(image).remove();
 212+ undo(undoIndex);
 213+ if (displayShowing)
 214+ $displayCanvas.show();
 215+ $(".jcrop-holder", doc).show();
 216+ });
 217+
 218+ $link.mouseover(function() {
 219+ displayShowing = $displayCanvas.css("display") != "none";
 220+ var $imagectr = $("#image-container", doc);
 221+
 222+ $(".jcrop-holder", doc).hide();
 223+ $displayCanvas.hide();
 224+ $(image).appendTo($imagectr);
 225+
 226+ var h1 = $("#image-area", doc).height();
 227+ var h2 = image.height;
 228+ var m = Math.max(0, (h1 - h2) / 2);
 229+ $imagectr.css("marginTop", m);
 230+
 231+ $imagectr.height(image.height);
 232+ });
 233+
 234+ $link.mouseout(function() {
 235+ $(image).remove();
 236+ if (displayShowing)
 237+ $displayCanvas.show();
 238+ $(".jcrop-holder", doc).show();
 239+ updateDisplayCanvas();
 240+ });
 241+
 242+
 243+ $(canvas).attr("title", "Click to revert to this previous image");
 244+
 245+ })();
 246+ }
 247+ }
 248+
 249+
 250+ function applyAction(id, options, afteraction) {
 251+ if (!Pixastic.Actions[id])
 252+ throw new Error("applyAction(): unknown action [" + id + "]");
 253+
 254+ $("#action-bar-overlay", doc).show();
 255+
 256+ setTimeout(function() {
 257+ options.leaveDOM = true;
 258+ var canvasElement = $imageCanvas.get(0);
 259+ addUndo(canvasElement)
 260+
 261+ var res = Pixastic.process(
 262+ canvasElement, id, options,
 263+ function(resCanvas) {
 264+ canvasElement.width = imageWidth = resCanvas.width;
 265+ canvasElement.height = imageHeight = resCanvas.height;
 266+
 267+ var ctx = canvasElement.getContext("2d");
 268+ ctx.clearRect(0,0,imageWidth,imageHeight);
 269+ ctx.drawImage(resCanvas,0,0);
 270+ $imageCanvas = $(canvasElement);
 271+ resetDisplayCanvas();
 272+
 273+ $("#action-bar-overlay", doc).hide();
 274+
 275+ if (afteraction)
 276+ afteraction();
 277+ }
 278+ );
 279+ if (!res)
 280+ throw new Error("applyAction(): Pixastic.process() failed for action [" + id + "]");
 281+ },1);
 282+ }
 283+
 284+
 285+ function previewAction(id, options, afteraction) {
 286+ if (!Pixastic.Actions[id])
 287+ throw new Error("applyAction(): unknown action [" + id + "]");
 288+
 289+ $("#action-bar-overlay", doc).show();
 290+
 291+ resetDisplayCanvas();
 292+
 293+ options.leaveDOM = true;
 294+ var canvasElement = $displayCanvas.get(0);
 295+
 296+ var res = Pixastic.process(
 297+ canvasElement, id, options,
 298+ function(resCanvas) {
 299+
 300+ canvasElement.width = resCanvas.width;
 301+ canvasElement.height = resCanvas.height;
 302+
 303+ var ctx = canvasElement.getContext("2d");
 304+ ctx.clearRect(0,0,canvasElement.width,canvasElement.height);
 305+ ctx.drawImage(resCanvas,0,0);
 306+ updateDisplayCanvas();
 307+ updateOverlay();
 308+
 309+ $("#action-bar-overlay", doc).hide();
 310+
 311+ if (afteraction)
 312+ afteraction();
 313+ }
 314+ );
 315+ }
 316+
 317+ var onwindowresize = function() {
 318+ updateDisplayCanvas();
 319+ updateOverlay();
 320+ }
 321+
 322+ var baseUrl = ""
 323+
 324+ function buildEditor() {
 325+ var styles = [
 326+ "jquery-ui-1.7.1.custom.css",
 327+ "jquery.Jcrop.css",
 328+ "pixastic.css"
 329+ ];
 330+
 331+ for (var i=0;i<styles.length;i++) {
 332+ var s = doc.createElement("link");
 333+ s.href = baseUrl + styles[i];
 334+ s.type = "text/css";
 335+ s.rel = "stylesheet";
 336+ doc.getElementsByTagName("head")[0].appendChild( s );
 337+ }
 338+
 339+ undoImages = [];
 340+ accordionElements = {};
 341+ tabElements = {};
 342+ activeTabId = -1;
 343+ $activeTabContent = null;
 344+
 345+ // setup DOM UI skeleton
 346+ $editor = $("<div />", doc)
 347+ .attr("id", "pixastic-editor")
 348+ .appendTo($(doc.body));
 349+
 350+ $editor.append(
 351+ $("<div id='background' />", doc),
 352+ $("<div id='edit-ctr-1' />", doc).append(
 353+ $("<div id='edit-ctr-2' />", doc).append(
 354+ $("<div id='controls-bar' />", doc).append(
 355+ $("<div id='action-bar' />", doc).append(
 356+ $("<div id='action-bar-overlay' />", doc)
 357+ ),
 358+ $("<div id='undo-bar' />", doc)
 359+ ),
 360+ $("<div id='image-area' />", doc).append(
 361+ $("<div id='image-area-sub' />", doc).append(
 362+ $("<div id='image-container' />", doc),
 363+ $("<div id='image-overlay-container' />", doc).append(
 364+ $("<div id='image-overlay' />", doc)
 365+ )
 366+ )
 367+ )
 368+ )
 369+ ),
 370+ $("<div id='main-bar' />", doc),
 371+ $("<div id='powered-by-pixastic'><a href=\"http://www.pixastic.com/\" target=\"_blank\">Powered by Pixastic</a></div>", doc)
 372+ );
 373+
 374+ $("#image-container", doc).append(
 375+ $displayCanvas = $("<canvas />", doc)
 376+ .addClass("display-canvas")
 377+ );
 378+
 379+ // loop through all defined UI action controls
 380+ var tabs = PixasticEditor.UI.data.tabs;
 381+
 382+ for (var i=0;i<tabs.length;i++) {
 383+ (function() {
 384+
 385+ var tab = tabs[i];
 386+
 387+ var $tabElement = $("<a href=\"#\">" + tab.title + "</a>", doc)
 388+ .attr("id", "main-tab-button-" + tab.id)
 389+ .addClass("main-tab")
 390+ .click(function() {
 391+ enableTab(tab.id);
 392+ })
 393+ .mouseover(function(){ $(this).addClass("hover") })
 394+ .mouseout(function(){ $(this).removeClass("hover") });
 395+
 396+ $("#main-bar", doc).append($tabElement);
 397+
 398+ tabElements[tab.id] = $tabElement;
 399+
 400+ var $menu = $("<div/>", doc);
 401+ accordionElements[tab.id] = $menu;
 402+
 403+ for (var j=0;j<tab.actions.length;j++) {
 404+ (function() {
 405+
 406+ var action = tab.actions[j];
 407+
 408+ var $actionElement = $("<div><h3><a href=\"#\">" + action.title + "</a></h3></div>", doc)
 409+
 410+ $menu.append($actionElement);
 411+
 412+ var $content = $("<div></div>", doc)
 413+ .attr("id", "pixastic-action-tab-content-" + action.id)
 414+ .appendTo($actionElement);
 415+
 416+ var controlOptions = [];
 417+
 418+ action.previewEnabled = false;
 419+ if (action.forcePreview)
 420+ action.previewEnabled = true;
 421+
 422+ function togglePreview(enable, doAction) {
 423+ if (enable && !action.previewEnabled && doAction)
 424+ doAction(true);
 425+ if (!enable && action.previewEnabled)
 426+ resetDisplayCanvas();
 427+
 428+ action.previewEnabled = enable;
 429+ }
 430+
 431+ var reset = function() {
 432+ for (var i in controlOptions) {
 433+ if (controlOptions.hasOwnProperty(i)) {
 434+ controlOptions[i].reset();
 435+ }
 436+ }
 437+ if (action.previewEnabled)
 438+ doAction(true);
 439+ }
 440+ var doAction = function(isPreview) {
 441+ var options = {};
 442+ for (var i in controlOptions) {
 443+ if (controlOptions.hasOwnProperty(i)) {
 444+ options[i] = controlOptions[i].valueField.val();
 445+ }
 446+ }
 447+
 448+ var afteraction = function() {
 449+ if (action.onafteraction)
 450+ action.onafteraction(action, isPreview);
 451+ if (!isPreview)
 452+ resetDisplayCanvas();
 453+
 454+ if (!isPreview && !action.forcePreview) {
 455+ $("#pixastic-input-preview-" + action.id, doc).attr("checked", false);
 456+ togglePreview(false);
 457+ reset();
 458+ }
 459+ }
 460+
 461+ if (isPreview) {
 462+ previewAction(action.id, options, afteraction);
 463+ } else {
 464+ applyAction(action.id, options, afteraction);
 465+ }
 466+
 467+ }
 468+
 469+ var hadInputs = false;
 470+
 471+ if (action.controls) {
 472+ var onChange = function() {};
 473+ if (action.isAction && action.preview) {
 474+ onChange = function() {
 475+ if (action.previewEnabled)
 476+ doAction(true)
 477+ };
 478+ }
 479+
 480+ for (var k=0;k<action.controls.length;k++) {
 481+ var control = action.controls[k];
 482+ if (typeof control.defaultValue != "function") {
 483+ (function(){
 484+ var defVal = control.defaultValue;
 485+ control.defaultValue = function() {
 486+ return defVal;
 487+ }
 488+ })();
 489+ }
 490+ var controlId = action.id + "-" + control.option;
 491+
 492+ if (control.type != "output")
 493+ hadInputs = true;
 494+
 495+ switch (control.type) {
 496+ case "number" :
 497+ switch (control.ui) {
 498+ case "slider" :
 499+ var slider = PixasticEditor.UI.makeSlider(
 500+ control.label, controlId,
 501+ control.range[0], control.range[1], control.step, control.defaultValue, onChange
 502+ );
 503+
 504+ slider.container.appendTo($content);
 505+ controlOptions[control.option] = slider;
 506+ break;
 507+ case "text" :
 508+ var text = PixasticEditor.UI.makeNumericInput(
 509+ control.label, control.labelRight, controlId,
 510+ control.range[0], control.range[1], control.step, control.defaultValue, onChange
 511+ );
 512+ text.container.appendTo($content);
 513+ controlOptions[control.option] = text;
 514+ break;
 515+ }
 516+ break;
 517+ case "boolean" :
 518+ switch (control.ui) {
 519+ case "checkbox" :
 520+ var checkbox = PixasticEditor.UI.makeCheckbox(
 521+ control.label, controlId, control.defaultValue, onChange
 522+ );
 523+
 524+ checkbox.container.appendTo($content);
 525+ controlOptions[control.option] = checkbox;
 526+ break;
 527+ }
 528+ case "string" :
 529+ switch (control.ui) {
 530+ case "select" :
 531+ var select = PixasticEditor.UI.makeSelect(
 532+ control.label, controlId, control.values, control.defaultValue, onChange
 533+ );
 534+
 535+ select.container.appendTo($content);
 536+ controlOptions[control.option] = select;
 537+ break;
 538+ }
 539+ break;
 540+ case "output" :
 541+ var outputText = $("<div></div>", doc)
 542+ .addClass("ui-action-output")
 543+ .html(control.content)
 544+ .appendTo($content);
 545+ break;
 546+ }
 547+ }
 548+ }
 549+
 550+ if (action.isAction) {
 551+
 552+ var $applyButton = PixasticEditor.UI.makeButton("Apply")
 553+ .addClass("pixastic-option-button-apply")
 554+ .click(function() {doAction();});
 555+
 556+ $content.append($applyButton);
 557+
 558+ if (hadInputs) {
 559+ var $resetButton = PixasticEditor.UI.makeButton("Reset")
 560+ .addClass("pixastic-option-button-reset")
 561+ .click(reset);
 562+
 563+ $content.append($resetButton)
 564+ }
 565+
 566+ if (action.preview && !action.forcePreview) {
 567+ var $checkctr = $("<div></div>", doc)
 568+ .addClass("ui-checkbox-container")
 569+ .addClass("ui-preview-checkbox-container");
 570+
 571+ var $label = $("<label></label>", doc)
 572+ .addClass("ui-checkbox-label")
 573+ .attr("for", "pixastic-input-preview-" + action.id)
 574+ .html("Preview:")
 575+ .appendTo($checkctr);
 576+
 577+ var $checkbox = $("<input type=\"checkbox\"></input>", doc)
 578+ .addClass("ui-checkbox")
 579+ .attr("id", "pixastic-input-preview-" + action.id)
 580+ .appendTo($checkctr)
 581+ .change(function() {
 582+ togglePreview(this.checked, doAction)
 583+ });
 584+
 585+ $content.append($checkctr);
 586+
 587+ $content.data("previewCheckbox", $checkbox);
 588+ }
 589+
 590+ }
 591+
 592+
 593+ if (typeof action.content == "function") {
 594+ action.content($content);
 595+ }
 596+
 597+ // stupid hack to make it possible to get $content in change event (below)
 598+ $("<span></span>", doc).appendTo($content);
 599+
 600+ $content.data("controlOptions", controlOptions);
 601+ $content.data("onactivate", action.onactivate);
 602+ $content.data("ondeactivate", action.ondeactivate);
 603+ $content.data("onoverlayupdate", action.onoverlayupdate);
 604+ $content.data("accordionindex", j);
 605+ $content.data("uidesc", action);
 606+
 607+ })();
 608+ }
 609+
 610+ $("#action-bar", doc).append($menu);
 611+
 612+ $menu.hide().accordion({
 613+ header: "h3",
 614+ autoHeight : false,
 615+ collapsible : true,
 616+ active: -1
 617+ })
 618+ .bind("accordionchange",
 619+ function(event, ui) {
 620+ resetDisplayCanvas();
 621+
 622+ // oldContent / newContent are arrays of whatever elements are present in the content area
 623+ // We need the parent element (the one holding the content) but if there is no content, how do we get it?
 624+ // fixed above by always appending a <span> but that's ugly and needs to be done in some other way
 625+ if (ui.oldContent.get(0)) {
 626+ var $parent = $(ui.oldContent.get(0).parentNode);
 627+ if ($parent.data("ondeactivate")) {
 628+ $parent.data("ondeactivate")();
 629+ }
 630+ }
 631+ $activeTabContent = ui.newContent;
 632+
 633+ if (ui.newContent.get(0)) {
 634+ var $parent = $(ui.newContent.get(0).parentNode);
 635+ if ($parent.data("previewCheckbox"))
 636+ $parent.data("previewCheckbox").attr("checked", false);
 637+ $parent.data("uidesc").previewEnabled = false;
 638+ if ($parent.data("uidesc").forcePreview)
 639+ $parent.data("uidesc").previewEnabled = true;
 640+
 641+ var controlOptions = $parent.data("controlOptions");
 642+ for (var i in controlOptions) {
 643+ if (controlOptions.hasOwnProperty(i)) {
 644+ controlOptions[i].reset();
 645+ }
 646+ }
 647+ if ($parent.data("onactivate")) {
 648+ $parent.data("onactivate")();
 649+ }
 650+ }
 651+ updateDisplayCanvas();
 652+
 653+ }
 654+ );
 655+
 656+
 657+ })();
 658+ }
 659+
 660+ $(window).bind("resize", onwindowresize);
 661+ }
 662+
 663+ function showLoadingScreen() {
 664+ if ($loadingScreen) {
 665+ $loadingScreen.show();
 666+ return;
 667+ }
 668+ $loadingScreen = $("<div id=\"loading-screen\" />")
 669+ var $ctr = $("<div id=\"loading-screen-cell\" />");
 670+ $("<div />")
 671+ .addClass("spinner")
 672+ .appendTo($ctr);
 673+ $loadingScreen.append($ctr);
 674+ $loadingScreen.appendTo("body");
 675+ }
 676+
 677+ function hideLoadingScreen() {
 678+ setTimeout(function() {
 679+ $loadingScreen.hide();
 680+ }, 1);
 681+ }
 682+
 683+ var oldScrollLeft;
 684+ var oldScrollTop;
 685+ var oldOverflow;
 686+
 687+ // fire it up
 688+ function init(callback) {
 689+ isRunning = true;
 690+
 691+ showLoadingScreen();
 692+
 693+ oldScrollLeft = document.body.scrollLeft;
 694+ oldScrollTop = document.body.scrollTop;
 695+ oldOverflow = document.body.style.overflow;
 696+
 697+ document.body.scrollLeft = 0;
 698+ document.body.scrollTop = 0;
 699+ document.body.style.overflow = "hidden";
 700+
 701+ $frame = $("<iframe />");
 702+ $frame.hide();
 703+ $frame.css({
 704+ position : "absolute",
 705+ left : document.body.scrollLeft + "px",
 706+ top : document.body.scrollTop + "px",
 707+ width : "100%",
 708+ height : "100%"
 709+ });
 710+ $frame.load(function(){
 711+ doc = $frame.get(0).contentDocument;
 712+
 713+ buildEditor();
 714+ callback();
 715+ $frame.show();
 716+ hideLoadingScreen();
 717+ setTimeout(function(){
 718+ updateDisplayCanvas();
 719+ },10);
 720+ });
 721+ $frame.appendTo("body");
 722+ }
 723+
 724+ // unload the editor, remove all elements added to the page and restore whatever properties we messed with
 725+ function unload() {
 726+ $(window).unbind("resize", onwindowresize);
 727+ $frame.hide();
 728+ $editor.hide();
 729+ $editor.remove();
 730+ $frame.remove();
 731+
 732+ document.body.scrollLeft = oldScrollLeft;
 733+ document.body.scrollTop = oldScrollTop;
 734+ document.body.style.overflow = oldOverflow;
 735+
 736+ isRunning = false;
 737+ }
 738+
 739+
 740+ // resets the display canvas (clears the canvas and repaints the current state)
 741+ // then updates display and overlay
 742+ function resetDisplayCanvas() {
 743+ if (!($displayCanvas && $displayCanvas.get)) throw new Error(errorDialog("$displayCanvas doesn't exist"));
 744+ if (!($imageCanvas && $imageCanvas.get)) throw new Error(errorDialog("$imageCanvas doesn't exist"));
 745+
 746+ var display = $displayCanvas.get(0);
 747+ var image = $imageCanvas.get(0);
 748+
 749+ if (!display) throw new Error(errorDialog("resetDisplayCanvas(): No elements in $displayCanvas"));
 750+ if (!image) throw new Error(errorDialog("resetDisplayCanvas(): No elements in $imageCanvas"));
 751+
 752+ display.width = imageWidth;
 753+ display.height = imageHeight;
 754+ display.getContext("2d").drawImage( image, 0, 0 );
 755+
 756+ updateDisplayCanvas();
 757+ updateOverlay();
 758+ }
 759+
 760+ // updates the display by resetting the height and margin of the image container
 761+ // this is mainly to keep vertical centering
 762+ function updateDisplayCanvas() {
 763+ var $imageCtr = $("#image-container", doc);
 764+ var $editArea = $("#image-area", doc);
 765+
 766+ if (!$imageCtr.get(0)) throw new Error(errorDialog("updateDisplayCanvas(): $imageCtr doesn't exist"));
 767+ if (!$displayCanvas.get(0)) throw new Error(errorDialog("updateDisplayCanvas(): $displayCanvas doesn't exist"));
 768+ if (!$editArea.get(0)) throw new Error(errorDialog("updateDisplayCanvas(): $editArea doesn't exist"));
 769+
 770+ var h2 = $displayCanvas.get(0).height;
 771+ var h1 = $("#image-area", doc).height();
 772+ var m = Math.max(0, (h1 - h2) / 2);
 773+ $imageCtr.height(h2);
 774+ $imageCtr.css("marginTop", m);
 775+ }
 776+
 777+ // basically the same as updateDisplayCanvas but for the image overlay
 778+ function updateOverlay() {
 779+ var $overlay = $("#image-overlay-container", doc);
 780+ var $imagectr = $("#image-container", doc);
 781+ $overlay.height($imagectr.height());
 782+ $overlay.css("marginTop", $imagectr.css("marginTop"));
 783+
 784+ if ($activeTabContent && $activeTabContent.get(0)) {
 785+ var $tabContent = $($activeTabContent.get(0).parentNode);
 786+ if (typeof $tabContent.data("onoverlayupdate") == "function")
 787+ $tabContent.data("onoverlayupdate")();
 788+ }
 789+ }
 790+
 791+ var imageIsLoading = false;
 792+ var originalImageElement;
 793+ var $tmpImg;
 794+
 795+ function loadImage(imgEl) {
 796+ if (imageIsLoading)
 797+ return;
 798+
 799+ imageIsLoading = true;
 800+
 801+ originalImageElement = imgEl;
 802+
 803+ $imageCanvas = $("<canvas />", doc);
 804+ imageCtx = $imageCanvas.get(0).getContext("2d");
 805+
 806+ imageWidth = 0;
 807+ imageHeight = 0;
 808+ $imageCanvas.attr("width", 0);
 809+ $imageCanvas.attr("height", 0);
 810+
 811+ if (imgEl.tagName.toLowerCase() == "img" && !imgEl._pixasticCanvas) {
 812+ var onload = function(el) {
 813+ imageWidth = el.offsetWidth;
 814+ imageHeight = el.offsetHeight;
 815+ $imageCanvas.attr("width", imageWidth);
 816+ $imageCanvas.attr("height", imageHeight);
 817+ imageCtx.drawImage(el,0,0);
 818+ $tmpImg.remove();
 819+ imageIsLoading = false;
 820+ enableTab("reshape");
 821+ setTimeout(function() {
 822+ resetDisplayCanvas();
 823+ }, 10);
 824+ }
 825+ $tmpImg = $("<img />", doc)
 826+ .css("position", "absolute")
 827+ .css("left", "-9999px")
 828+ .css("top", "-9999px")
 829+ .appendTo("body")
 830+ .load(function(){onload(this);})
 831+ .error(function(){
 832+ throw new Error("Could not load temporary copy image. Is provided image valid?");
 833+ unload();
 834+ })
 835+ .attr("src", imgEl.src);
 836+ if ($tmpImg.attr("complete")) {
 837+ onload($tmpImg.get(0));
 838+ }
 839+ } else {
 840+ var $canvas = imgEl._pixasticCanvas || imgEl;
 841+ imageWidth = $canvas.attr("width");
 842+ imageHeight = $canvas.attr("height");
 843+ $imageCanvas.attr("width", imageWidth);
 844+ $imageCanvas.attr("height", imageHeight);
 845+ imageCtx.drawImage($canvas.get(0), 0, 0);
 846+ imageIsLoading = false;
 847+ enableTab("reshape");
 848+ resetDisplayCanvas();
 849+ }
 850+ }
 851+
 852+ // return public interface
 853+ return {
 854+ /*
 855+ // don't call. For now we must load the image immediately via load()
 856+ loadImage : function(imgEl) {
 857+ if (!isRunning) return false;
 858+ loadImage(imgEl);
 859+ },
 860+ */
 861+ saveToPage : function() {
 862+ if (!isRunning) throw new Error("PixasticEditor::saveToPage(): Editor is not running");
 863+
 864+ var $canvas = PixasticEditor.getImageCanvas();
 865+ var img = PixasticEditor.getOriginalImage();
 866+ if (img.tagName.toLowerCase() == "canvas") {
 867+ img.width = $canvas.attr("width");
 868+ img.height = $canvas.attr("height");
 869+ img.getContext("2d").drawImage($canvas.get(0), 0, 0);
 870+ } else {
 871+ img.src = PixasticEditor.getDataURI();
 872+ }
 873+ img._pixasticCanvas = PixasticEditor.getImageCanvas();
 874+ },
 875+ load : function(img, customBaseUrl) {
 876+ if (isRunning) return false;
 877+
 878+ if (!img)
 879+ throw new Error("Must be called with an image or canvas as its first argument", "PixasticEditor::load")
 880+
 881+ $ = PixasticEditor.jQuery;
 882+
 883+ baseUrl = customBaseUrl || "http://www.pixastic.com/editor-test/";
 884+
 885+ init(function() {
 886+ if (img && img.tagName.toLowerCase() == "img" || img.tagName.toLowerCase() == "canvas") {
 887+ loadImage(img);
 888+ }
 889+ });
 890+ },
 891+
 892+ unload : function() {
 893+ if (!isRunning) throw new Error("PixasticEditor::unload(): Editor is not running");
 894+ unload();
 895+ },
 896+
 897+ getDocument : function() {
 898+ if (!isRunning) throw new Error("PixasticEditor::getDocument(): Editor is not running");
 899+
 900+ return doc;
 901+ },
 902+
 903+ validSaveFormats : function() {
 904+ return saveFormats;
 905+ },
 906+
 907+ getOriginalImage : function() {
 908+ if (!isRunning) throw new Error("PixasticEditor::getOriginalImage(): Editor is not running");
 909+ return originalImageElement;
 910+ },
 911+
 912+ getDataURI : function(mime) {
 913+ if (!isRunning) throw new Error("PixasticEditor::getDataURI(): Editor is not running");
 914+
 915+ if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))
 916+ throw new Error(errorDialog("$imageCanvas doesn't exist", "getImageCanvas"));
 917+
 918+ return $imageCanvas.get(0).toDataURL(mime||"image/png");
 919+ },
 920+
 921+ getImageCanvas : function() {
 922+ if (!isRunning) throw new Error("PixasticEditor::getImageCanvas(): Editor is not running");
 923+
 924+ if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))
 925+ throw new Error(errorDialog("$imageCanvas doesn't exist", "getImageCanvas"));
 926+
 927+ return $imageCanvas;
 928+ },
 929+ getOverlay : function() {
 930+ if (!isRunning) throw new Error("PixasticEditor::getOverlay(): Editor is not running");
 931+
 932+ return $("#image-overlay", doc);
 933+ },
 934+ getDisplayCanvas : function() {
 935+ if (!isRunning) throw new Error("PixasticEditor::getDisplayCanvas(): Editor is not running");
 936+
 937+ if (!($displayCanvas && $displayCanvas.get && $displayCanvas.get(0)))
 938+ throw new Error(errorDialog("$displayCanvas doesn't exist", "getDisplayCanvas"));
 939+ return $displayCanvas;
 940+ },
 941+ getDisplayWidth : function() {
 942+ if (!isRunning) throw new Error("PixasticEditor::getDisplayWidth(): Editor is not running");
 943+
 944+ return displayWidth;
 945+ },
 946+ getDisplayHeight : function() {
 947+ if (!isRunning) throw new Error("PixasticEditor::getDisplayHeight(): Editor is not running");
 948+
 949+ return displayHeight;
 950+ },
 951+ getImageWidth : function() {
 952+ if (!isRunning) throw new Error("PixasticEditor::getImageWidth(): Editor is not running");
 953+
 954+ return imageWidth;
 955+ },
 956+ getImageHeight : function() {
 957+ if (!isRunning) throw new Error("PixasticEditor::getImageHeight(): Editor is not running");
 958+
 959+ return imageHeight;
 960+ },
 961+ errorDialog : function() {
 962+ if (!isRunning) throw new Error("PixasticEditor::errorDialog(): Editor is not running");
 963+
 964+ return errorDialog.apply(null, arguments);
 965+ }
 966+ }
 967+
 968+})();
\ No newline at end of file
Index: branches/new-upload/phase3/js2/mwEmbed/libClipEdit/pixastic-editor/uidata.js
@@ -0,0 +1,966 @@
 2+(function($) {
 3+
 4+var PE = PixasticEditor;
 5+
 6+PE.UI.data = {
 7+ tabs : [
 8+ {
 9+ title : "Reshape",
 10+ id : "reshape",
 11+ actions : [
 12+ {
 13+ title : "Resize",
 14+ id : "resize",
 15+ isAction : true,
 16+ controls : [
 17+ {
 18+ type : "output",
 19+ content : "Enter new dimensions below."
 20+ },
 21+ {
 22+ label : "Width",
 23+ labelRight : "px",
 24+ option : "width",
 25+ type : "number",
 26+ range : [1,10000],
 27+ step : 1,
 28+ defaultValue : function() { return PE.getImageWidth(); },
 29+ ui : "text"
 30+ },
 31+ {
 32+ label : "Height",
 33+ labelRight : "px",
 34+ option : "height",
 35+ type : "number",
 36+ range : [1,10000],
 37+ step : 1,
 38+ defaultValue : function() { return PE.getImageHeight(); },
 39+ ui : "text"
 40+ }
 41+ ]
 42+ },
 43+ {
 44+ title : "Crop",
 45+ id : "crop",
 46+ isAction : true,
 47+ controls : [
 48+ {
 49+ type : "output",
 50+ content : "Enter new crop values below or use mouse to select crop area."
 51+ },
 52+ {
 53+ label : "X",
 54+ labelRight : "px",
 55+ option : "left",
 56+ type : "number",
 57+ range : [0,10000],
 58+ step : 1,
 59+ defaultValue : 0,
 60+ ui : "text"
 61+ },
 62+ {
 63+ label : "Y",
 64+ labelRight : "px",
 65+ option : "top",
 66+ type : "number",
 67+ range : [0,10000],
 68+ step : 1,
 69+ defaultValue : 0,
 70+ ui : "text"
 71+ },
 72+ {
 73+ label : "Width",
 74+ labelRight : "px",
 75+ option : "width",
 76+ type : "number",
 77+ range : [1,10000],
 78+ step : 1,
 79+ defaultValue : function() { return PE.getImageWidth(); },
 80+ ui : "text"
 81+ },
 82+ {
 83+ label : "Height",
 84+ labelRight : "px",
 85+ option : "height",
 86+ type : "number",
 87+ range : [1,10000],
 88+ step : 1,
 89+ defaultValue : function() { return PE.getImageHeight(); },
 90+ ui : "text"
 91+ }
 92+ ],
 93+ onactivate : function() {
 94+ var $canvas = PE.getDisplayCanvas();
 95+ var onchange = function(c) {
 96+ var doc = PE.getDocument();
 97+ $("#input-numeric-crop-left", doc).val(c.x).change();
 98+ $("#input-numeric-crop-top", doc).val(c.y).change();
 99+ $("#input-numeric-crop-width", doc).val(c.w).change();
 100+ $("#input-numeric-crop-height", doc).val(c.h).change();
 101+ $("#input-hidden-crop-left", doc).val(c.x).change();
 102+ $("#input-hidden-crop-top", doc).val(c.y).change();
 103+ $("#input-hidden-crop-width", doc).val(c.w).change();
 104+ $("#input-hidden-crop-height", doc).val(c.h).change();
 105+ }
 106+ $canvas.data("Jcrop-onchange", onchange);
 107+ $canvas.Jcrop({onChange:onchange}, PE.getDocument());
 108+ },
 109+ ondeactivate : function() {
 110+ var $canvas = PE.getDisplayCanvas();
 111+ if ($canvas.data("Jcrop") && $canvas.data("Jcrop").destroy)
 112+ $canvas.data("Jcrop").destroy();
 113+ },
 114+ onafteraction : function(action, isPreview) {
 115+ action.ondeactivate();
 116+ action.onactivate();
 117+ /*
 118+ var $canvas = PE.getDisplayCanvas();
 119+ if ($canvas.data("Jcrop") && $canvas.data("Jcrop").destroy)
 120+ $canvas.data("Jcrop").destroy();
 121+ var onchange = $canvas.data("Jcrop-onchange");
 122+ $canvas.Jcrop({onChange:onchange});
 123+ */
 124+ }
 125+ },
 126+ {
 127+ title : "Rotate",
 128+ id : "rotate",
 129+ isAction : true,
 130+ preview : true,
 131+ forcePreview : true,
 132+ controls : [
 133+ {
 134+ type : "output",
 135+ content : "Enter the angle (-180&deg; to 180&deg;) you want to rotate the picture. Use negative values for clockwise rotation, positive for counterclockwise."
 136+ },
 137+ {
 138+ label : "Angle",
 139+ labelRight : "&deg;",
 140+ option : "angle",
 141+ type : "number",
 142+ range : [-180,180],
 143+ step : 1,
 144+ defaultValue : 0,
 145+ ui : "text"
 146+ }
 147+ ],
 148+ onactivate : function() {
 149+ var doc = PE.getDocument();
 150+ var $displayCanvas = PE.getDisplayCanvas();
 151+ var dim = Math.min($displayCanvas.attr("height"), 200);
 152+ var $canvas = $("<canvas></canvas>", doc);
 153+ PE.getOverlay().append($canvas);
 154+
 155+ $canvas.attr("width", dim);
 156+ $canvas.attr("height", dim);
 157+ $canvas.width(dim);
 158+ $canvas.height(dim);
 159+
 160+ $canvas.css("marginTop", (($displayCanvas.attr("height") - dim) * 0.5) + "px");
 161+
 162+ var lineWidth = 20;
 163+ var radius = dim/2 - lineWidth;
 164+ if (radius < 1) radius = 1;
 165+
 166+ var ctx = $canvas.get(0).getContext("2d");
 167+ ctx.beginPath()
 168+ ctx.arc(dim/2, dim/2, radius, 0, Math.PI*2, true);
 169+ ctx.closePath();
 170+ ctx.fillStyle = "rgba(200,200,200,0.2)";
 171+ ctx.fill();
 172+ ctx.strokeStyle = "rgba(200,200,200,0.5)";
 173+ ctx.lineWidth = 20;
 174+ ctx.stroke();
 175+
 176+ $("#image-area", doc).css("cursor", "move");
 177+
 178+ $overlay = PE.getOverlay();
 179+
 180+ $canvas.get(0).ondragstart = function() {return false;}
 181+ $canvas.get(0).onselectstart = function() {return false;}
 182+
 183+ var mx = 0, my = 0;
 184+ var startMouseAngle = 0;
 185+ var startAngle = 0;
 186+ var deltaAngle = 0;
 187+ var angle = 0;
 188+
 189+ var mouseIsDown = false;
 190+ var onmousedown = function(e) {
 191+ mouseIsDown = true;
 192+ var offset = $displayCanvas.offset();
 193+ mx = (e.pageX - offset.left) - $displayCanvas.attr("width")*0.5;
 194+ my = (e.pageY - offset.top) - $displayCanvas.attr("height")*0.5;
 195+ startMouseAngle = Math.atan2(my, mx);
 196+ startAngle = parseInt($("#input-numeric-rotate-angle", doc).val(), 10) * Math.PI / 180;
 197+ }
 198+ var onmousemove = function(e) {
 199+ if (!mouseIsDown) return;
 200+
 201+ var offset = $displayCanvas.offset();
 202+ mx = (e.pageX - offset.left) - $displayCanvas.attr("width")*0.5;
 203+ my = (e.pageY - offset.top) - $displayCanvas.attr("height")*0.5;
 204+ deltaAngle = Math.atan2(my, mx) - startMouseAngle;
 205+ angle = startAngle - deltaAngle;
 206+ if (angle < -Math.PI) angle += 2*Math.PI;
 207+ if (angle > Math.PI) angle -= 2*Math.PI;
 208+ $("#input-numeric-rotate-angle", doc).val(Math.round(angle * 180 / Math.PI));
 209+ $("#input-numeric-rotate-angle", doc).change();
 210+ }
 211+ var onmouseup = function() {
 212+ mouseIsDown = false;
 213+ }
 214+
 215+ $("#image-area", doc).bind("mousedown", onmousedown);
 216+ $("#image-area", doc).bind("mousemove", onmousemove);
 217+ $("#image-area", doc).bind("mouseup", onmouseup);
 218+ $canvas.data("onmousedown", onmousedown);
 219+ $canvas.data("onmousemove", onmousemove);
 220+ $canvas.data("onmouseup", onmouseup);
 221+ $displayCanvas.data("rotateCanvas", $canvas);
 222+ },
 223+ ondeactivate : function() {
 224+ var doc = PE.getDocument();
 225+ var $displayCanvas = PE.getDisplayCanvas();
 226+ $overlay = PE.getOverlay();
 227+ $("#image-area", doc).css("cursor", "default");
 228+
 229+ var $canvas = $displayCanvas.data("rotateCanvas");
 230+
 231+ $("#image-area", doc).unbind("mousedown", $canvas.data("onmousedown"));
 232+ $("#image-area", doc).unbind("mousemove", $canvas.data("onmousemove"));
 233+ $("#image-area", doc).unbind("mouseup", $canvas.data("onmouseup"));
 234+ $displayCanvas.removeData("rotateCanvas");
 235+ $canvas.remove();
 236+ },
 237+ onafteraction : function(action, isPreview) {
 238+ if (!isPreview) { // rebuild the rotate widget
 239+ action.ondeactivate();
 240+ action.onactivate();
 241+ }
 242+ },
 243+ onoverlayupdate : function() {
 244+ var $canvas = PE.getDisplayCanvas().data("rotateCanvas");
 245+ if ($canvas) {
 246+ $canvas.css("marginTop", ((PE.getDisplayCanvas().get(0).height - $canvas.get(0).height) * 0.5) + "px");
 247+ }
 248+ }
 249+ },
 250+ {
 251+ title : "Flip",
 252+ id : "flip",
 253+ isAction : true,
 254+ controls : [
 255+ {
 256+ label : "Axis",
 257+ option : "axis",
 258+ type : "string",
 259+ values : [
 260+ {name:"Horizontal", value:"horizontal"},
 261+ {name:"Vertical", value:"vertical"}
 262+ ],
 263+ defaultValue : "vertical",
 264+ ui : "select"
 265+ }
 266+ ]
 267+ }
 268+ ]
 269+ },
 270+ {
 271+ title : "Develop",
 272+ id : "develop",
 273+ actions : [
 274+ {
 275+ title : "Brightness & Contrast",
 276+ id : "brightness",
 277+ isAction : true,
 278+ preview : true,
 279+ controls : [
 280+ {
 281+ type : "output",
 282+ content : "Use the sliders below to adjust the brightness and/or contrast of the image."
 283+ },
 284+ {
 285+ label : "Brightness",
 286+ option : "brightness",
 287+ type : "number",
 288+ range : [-100,100],
 289+ defaultValue : 0,
 290+ ui : "slider",
 291+ step : 1
 292+ },
 293+ {
 294+ label : "Contrast",
 295+ option : "contrast",
 296+ type : "number",
 297+ range : [-1,1],
 298+ defaultValue : 0,
 299+ ui : "slider",
 300+ step : 0.01
 301+ },
 302+ {
 303+ label : "Legacy mode",
 304+ option : "legacy",
 305+ type : "boolean",
 306+ defaultValue : false,
 307+ ui : "checkbox"
 308+ }
 309+ ]
 310+ },
 311+ {
 312+ title : "Hue/Saturation/Lightness",
 313+ id : "hsl",
 314+ isAction : true,
 315+ preview : true,
 316+ controls : [
 317+ {
 318+ type : "output",
 319+ content : "Use the sliders below to adjust the hue, saturation and/or lightness of the image."
 320+ },
 321+ {
 322+ label : "Hue",
 323+ option : "hue",
 324+ type : "number",
 325+ range : [-180,180],
 326+ defaultValue : 0,
 327+ ui : "slider",
 328+ step : 1
 329+ },
 330+ {
 331+ label : "Saturation",
 332+ option : "saturation",
 333+ type : "number",
 334+ range : [-100,100],
 335+ defaultValue : 0,
 336+ ui : "slider",
 337+ step : 1
 338+ },
 339+ {
 340+ label : "Lightness",
 341+ option : "lightness",
 342+ type : "number",
 343+ range : [-100,100],
 344+ defaultValue : 0,
 345+ ui : "slider",
 346+ step : 1
 347+ }
 348+ ]
 349+ },
 350+ {
 351+ title : "Adjust colors",
 352+ id : "coloradjust",
 353+ isAction : true,
 354+ preview : true,
 355+ controls : [
 356+ {
 357+ type : "output",
 358+ content : "Use the sliders below to shift the R, G and B channels of the image."
 359+ },
 360+ {
 361+ label : "Red",
 362+ option : "red",
 363+ type : "number",
 364+ range : [-1,1],
 365+ defaultValue : 0,
 366+ ui : "slider",
 367+ step : 0.01
 368+ },
 369+ {
 370+ label : "Green",
 371+ option : "green",
 372+ type : "number",
 373+ range : [-1,1],
 374+ defaultValue : 0,
 375+ ui : "slider",
 376+ step : 0.01
 377+ },
 378+ {
 379+ label : "Blue",
 380+ option : "blue",
 381+ type : "number",
 382+ range : [-1,1],
 383+ defaultValue : 0,
 384+ ui : "slider",
 385+ step : 0.01
 386+ }
 387+ ]
 388+ },
 389+ {
 390+ title : "Desaturate",
 391+ id : "desaturate",
 392+ isAction : true,
 393+ preview : true,
 394+ controls : [
 395+ {
 396+ type : "output",
 397+ content : "This will desaturate the image. Select \"Use average\" to use the average value of the R, G and B channels rather than the default mix of 30% red, 59% green and 11% blue."
 398+ },
 399+ {
 400+ label : "Use average",
 401+ option : "average",
 402+ type : "boolean",
 403+ defaultValue : false,
 404+ ui : "checkbox"
 405+ }
 406+ ]
 407+ },
 408+ {
 409+ title : "Sepia toning",
 410+ id : "sepia",
 411+ isAction : true,
 412+ preview : true,
 413+ controls : [
 414+ {
 415+ type : "output",
 416+ content : "Applies a sepia toning effect to the image."
 417+ }
 418+ ]
 419+ },
 420+ {
 421+ title : "Invert",
 422+ id : "invert",
 423+ isAction : true,
 424+ preview : true,
 425+ controls : [
 426+ {
 427+ type : "output",
 428+ content : "This will invert the colors of the image."
 429+ }
 430+ ]
 431+ },
 432+ {
 433+ title : "Lighten",
 434+ id : "lighten",
 435+ isAction : true,
 436+ preview : true,
 437+ controls : [
 438+ {
 439+ type : "output",
 440+ content : "Use the slider below to lighten or darken the image."
 441+ },
 442+ {
 443+ label : "Amount",
 444+ option : "amount",
 445+ type : "number",
 446+ range : [-1,1],
 447+ defaultValue : 0,
 448+ ui : "slider",
 449+ step : 0.01
 450+ }
 451+ ]
 452+ },
 453+ {
 454+ title : "Unsharp mask",
 455+ id : "unsharpmask",
 456+ isAction : true,
 457+ preview : true,
 458+ controls : [
 459+ {
 460+ type : "output",
 461+ content : "Use the sliders below to adjust the unsharp mask parameters."
 462+ },
 463+ {
 464+ label : "Amount",
 465+ option : "amount",
 466+ type : "number",
 467+ range : [0,500],
 468+ defaultValue : 200,
 469+ ui : "slider",
 470+ step : 2
 471+ },
 472+ {
 473+ label : "Radius",
 474+ option : "radius",
 475+ type : "number",
 476+ range : [0,5],
 477+ defaultValue : 2,
 478+ ui : "slider",
 479+ step : 0.1
 480+ },
 481+ {
 482+ label : "Threshold",
 483+ option : "amount",
 484+ type : "number",
 485+ range : [0,255],
 486+ defaultValue : 25,
 487+ ui : "slider",
 488+ step : 1
 489+ }
 490+ ]
 491+ }
 492+
 493+ ]
 494+ },
 495+ {
 496+ title : "Effects",
 497+ id : "effects",
 498+ actions : [
 499+ {
 500+ title : "Blur",
 501+ id : "blurfast",
 502+ isAction : true,
 503+ preview : true,
 504+ controls : [
 505+ {
 506+ type : "output",
 507+ content : "Use the slider to set the blur amount."
 508+ },
 509+ {
 510+ label : "Amount",
 511+ option : "amount",
 512+ type : "number",
 513+ range : [0,1],
 514+ defaultValue : 0.5,
 515+ ui : "slider",
 516+ step : 0.01
 517+ }
 518+ ]
 519+
 520+ },
 521+ {
 522+ title : "Edge detection",
 523+ id : "edges",
 524+ isAction : true,
 525+ preview : true,
 526+ controls : [
 527+ {
 528+ type : "output",
 529+ content : "Performs edge detection on the image."
 530+ },
 531+ {
 532+ label : "Greyscale",
 533+ option : "mono",
 534+ type : "boolean",
 535+ defaultValue : false,
 536+ ui : "checkbox"
 537+ },
 538+ {
 539+ label : "Invert",
 540+ option : "invert",
 541+ type : "boolean",
 542+ defaultValue : false,
 543+ ui : "checkbox"
 544+ }
 545+ ]
 546+ },
 547+ {
 548+ title : "Emboss",
 549+ id : "emboss",
 550+ isAction : true,
 551+ preview : true,
 552+ controls : [
 553+ {
 554+ type : "output",
 555+ content : "Adds an emboss-like effect to the image. Use the controls below to control the appearance of the effect. Choose \"Blend\" to blend the effect with the original image."
 556+ },
 557+ {
 558+ label : "Strength",
 559+ option : "strength",
 560+ type : "number",
 561+ range : [0,10],
 562+ defaultValue : 1,
 563+ ui : "slider",
 564+ step : 0.1
 565+ },
 566+ {
 567+ label : "Grey level",
 568+ option : "greyLevel",
 569+ type : "number",
 570+ range : [0,255],
 571+ defaultValue : 180,
 572+ ui : "slider",
 573+ step : 1
 574+ },
 575+ {
 576+ label : "Direction",
 577+ option : "direction",
 578+ type : "string",
 579+ values : [
 580+ {name:"Top left", value:"topleft"},
 581+ {name:"Top", value:"top"},
 582+ {name:"Top right", value:"topright"},
 583+ {name:"Right", value:"right"},
 584+ {name:"Bottom right", value:"bottomright"},
 585+ {name:"Bottom", value:"bottom"},
 586+ {name:"Bottom left", value:"bottomleft"},
 587+ {name:"Left", value:"left"}
 588+ ],
 589+ defaultValue : "topleft",
 590+ ui : "select"
 591+ },
 592+ {
 593+ label : "Blend",
 594+ option : "blend",
 595+ type : "boolean",
 596+ defaultValue : false,
 597+ ui : "checkbox"
 598+ }
 599+ ]
 600+
 601+ },
 602+ {
 603+ title : "Glow",
 604+ id : "glow",
 605+ isAction : true,
 606+ preview : true,
 607+ controls : [
 608+ {
 609+ type : "output",
 610+ content : "Creates a glowing effect on the image."
 611+ },
 612+ {
 613+ label : "Amount",
 614+ option : "amount",
 615+ type : "number",
 616+ range : [0,1],
 617+ defaultValue : 0.5,
 618+ ui : "slider",
 619+ step : 0.01
 620+ },
 621+ {
 622+ label : "Radius",
 623+ option : "radius",
 624+ type : "number",
 625+ range : [0,1],
 626+ defaultValue : 0.5,
 627+ ui : "slider",
 628+ step : 0.01
 629+ }
 630+ ]
 631+ },
 632+ {
 633+ title : "Add noise",
 634+ id : "noise",
 635+ isAction : true,
 636+ preview : true,
 637+ controls : [
 638+ {
 639+ type : "output",
 640+ content : "Add random noise to the image."
 641+ },
 642+ {
 643+ label : "Amount",
 644+ option : "amount",
 645+ type : "number",
 646+ range : [0,1],
 647+ defaultValue : 0.5,
 648+ ui : "slider",
 649+ step : 0.01
 650+ },
 651+ {
 652+ label : "Strength",
 653+ option : "strength",
 654+ type : "number",
 655+ range : [0,1],
 656+ defaultValue : 0.5,
 657+ ui : "slider",
 658+ step : 0.01
 659+ },
 660+ {
 661+ label : "Greyscale",
 662+ option : "mono",
 663+ type : "boolean",
 664+ defaultValue : false,
 665+ ui : "checkbox"
 666+ }
 667+ ]
 668+ },
 669+ {
 670+ title : "Remove noise",
 671+ id : "removenoise",
 672+ isAction : true,
 673+ preview : true,
 674+ controls : [
 675+ {
 676+ type : "output",
 677+ content : "Attempts to remove noise from the image. Works best for getting rid of single pixels that stand out."
 678+ }
 679+ ]
 680+ },
 681+ {
 682+ title : "Pointillize",
 683+ id : "pointillize",
 684+ isAction : true,
 685+ preview : true,
 686+ controls : [
 687+ {
 688+ type : "output",
 689+ content : "Paints the picture with circular points."
 690+ },
 691+ {
 692+ label : "Point radius",
 693+ option : "radius",
 694+ type : "number",
 695+ range : [1,50],
 696+ defaultValue : 5,
 697+ ui : "slider",
 698+ step : 1
 699+ },
 700+ {
 701+ label : "Density",
 702+ option : "density",
 703+ type : "number",
 704+ range : [0,5],
 705+ defaultValue : 1,
 706+ ui : "slider",
 707+ step : 0.01
 708+ },
 709+ {
 710+ label : "Noise",
 711+ option : "noise",
 712+ type : "number",
 713+ range : [0,2],
 714+ defaultValue : 1,
 715+ ui : "slider",
 716+ step : 0.01
 717+ },
 718+ {
 719+ label : "Transparent",
 720+ option : "transparent",
 721+ type : "boolean",
 722+ defaultValue : false,
 723+ ui : "checkbox"
 724+ }
 725+ ]
 726+ },
 727+ {
 728+ title : "Posterize",
 729+ id : "posterize",
 730+ isAction : true,
 731+ preview : true,
 732+ controls : [
 733+ {
 734+ type : "output",
 735+ content : "Reduces the number of colours to a specified number of levels."
 736+ },
 737+ {
 738+ label : "Levels",
 739+ option : "levels",
 740+ type : "number",
 741+ range : [1,32],
 742+ defaultValue : 5,
 743+ ui : "slider",
 744+ step : 1
 745+ }
 746+ ]
 747+ },
 748+ {
 749+ title : "Solarize",
 750+ id : "solarize",
 751+ isAction : true,
 752+ preview : true,
 753+ controls : [
 754+ {
 755+ type : "output",
 756+ content : "Applies a solarize effect to the image."
 757+ }
 758+ ]
 759+ },
 760+ {
 761+ title : "Mosaic",
 762+ id : "mosaic",
 763+ isAction : true,
 764+ preview : true,
 765+ controls : [
 766+ {
 767+ type : "output",
 768+ content : "Creates a pixelated look."
 769+ },
 770+ {
 771+ label : "Block size",
 772+ option : "blockSize",
 773+ type : "number",
 774+ range : [1,100],
 775+ defaultValue : 5,
 776+ ui : "slider",
 777+ step : 1
 778+ }
 779+ ]
 780+ }
 781+
 782+
 783+ ]
 784+ },
 785+ {
 786+ title : "Done",
 787+ id : "done",
 788+ actions : [
 789+ {
 790+ title : "Save to page",
 791+ id : "savepage",
 792+ content : function($ctr) {
 793+ var doc = PE.getDocument();
 794+ $("<div></div>", doc)
 795+ .addClass("action-output-text")
 796+ .html("This will save the image to the page.")
 797+ .appendTo($ctr);
 798+
 799+ var $buttonCtr = $("<div></div>", doc).appendTo($ctr);
 800+ var $saveButton = $("<button></button>", doc)
 801+ .html("Save image")
 802+ .appendTo($buttonCtr)
 803+ .click(function() {
 804+ PE.saveToPage();
 805+ });
 806+
 807+ }
 808+ },
 809+ {
 810+ title : "Save to file",
 811+ id : "savefile",
 812+ content : function(ctr) {
 813+ var doc = PE.getDocument();
 814+ $("<div></div>", doc)
 815+ .addClass("action-output-text")
 816+ .html("This will save the image to your local computer.")
 817+ .appendTo(ctr);
 818+
 819+ var formats = PE.validSaveFormats();
 820+
 821+ var selectHtml = "<select>";
 822+ for (var i=0;i<formats.length;i++) {
 823+ selectHtml += "<option value='" + formats[i].mime + "'>" + formats[i].name + "</option>";
 824+ }
 825+ selectHtml += "</select>";
 826+
 827+ var selectCtr = $("<div></div>", doc)
 828+ .addClass("ui-select-container");
 829+
 830+
 831+ var label = $("<div></div>", doc)
 832+ .addClass("ui-select-label")
 833+ .html("Format:")
 834+ .appendTo(selectCtr);
 835+
 836+ var formatSelect = $(selectHtml, doc).appendTo(selectCtr);
 837+
 838+
 839+ selectCtr.appendTo(ctr);
 840+
 841+ var buttonCtr = $("<div></div>", doc).appendTo(ctr);
 842+ var saveButton = $("<button></button>", doc)
 843+ .html("Save file")
 844+ .appendTo(buttonCtr)
 845+
 846+ saveButton.click(function() {
 847+ var selectElement = formatSelect.get(0);
 848+ var formatMime = selectElement.options[selectElement.selectedIndex].value;
 849+ var dataString = PE.getDataURI(formatMime);
 850+
 851+ var dialog = $("<div></div>", doc)
 852+ .attr("id", "save-dialog")
 853+ .attr("title", "Download file")
 854+ .html(
 855+ "Right click the link below and select \"Save as...\" to save your file.<br/>"
 856+ + "<br/>"
 857+ + "<a href=\"" + dataString + "\">Image Link</a>"
 858+ )
 859+ .dialog();
 860+
 861+ // the dialog is added outside the Pixastic container, so get it back in.
 862+ var dialogParent = $(dialog.get(0).parentNode);
 863+ $("#pixastic-editor", doc).append(dialogParent);
 864+ });
 865+ }
 866+ },
 867+ /*
 868+ {
 869+ title : "Upload to Flickr",
 870+ id : "flickrupload",
 871+ content : function($ctr) {
 872+ var doc = PE.getDocument();
 873+
 874+ function flickrAuthed() {
 875+ var $text = $("<div />", doc)
 876+ .addClass("action-output-text")
 877+ .html("Authorized as: " + PE.Flickr.getAuthName());
 878+
 879+ var $buttonCtr = $("<div></div>", doc);
 880+ var $uploadButton = $("<button></button>", doc)
 881+ .html("Upload image")
 882+ .appendTo($buttonCtr)
 883+
 884+ $uploadButton.click(function() {
 885+ PE.Flickr.uploadImage(PE.getDataURI());
 886+ });
 887+
 888+ $ctr.append($text, $buttonCtr);
 889+ }
 890+
 891+ var $authCtr = $("<div />", doc).appendTo($ctr);
 892+
 893+ $("<div />", doc)
 894+ .addClass("action-output-text")
 895+ .html("If you have a Flickr account you can now upload your image to Flickr. You will need to give access to your account first. Click the button below to open an authorization window.")
 896+ .appendTo($authCtr);
 897+
 898+ var $buttonCtr = $("<div></div>", doc).appendTo($authCtr);
 899+ var $authButton = $("<button></button>", doc)
 900+ .html("Authenticate")
 901+ .appendTo($buttonCtr)
 902+
 903+ var checkButtonAdded = false;
 904+ $authButton.click(function() {
 905+ PE.Flickr.auth();
 906+ if (!checkButtonAdded) {
 907+ checkButtonAdded = true;
 908+
 909+ var $text = $("<div />", doc)
 910+ .addClass("action-output-text")
 911+ .html("Now click the button below when you have authorized access to your Flickr account.");
 912+
 913+ var $buttonCtr = $("<div></div>", doc);
 914+
 915+ $authCtr.append($text, $buttonCtr);
 916+
 917+ var $checkButton = $("<button></button>", doc)
 918+ .html("I have authenticated!")
 919+ .appendTo($buttonCtr);
 920+
 921+ $checkButton.click(function() {
 922+ PE.Flickr.checkAuth(function(res) {
 923+ if (res.stat == "ok") {
 924+ $authCtr.remove();
 925+ flickrAuthed();
 926+ }
 927+ });
 928+ });
 929+ }
 930+
 931+ });
 932+ }
 933+ },
 934+ */
 935+ {
 936+ title : "Quit",
 937+ id : "quit",
 938+ content : function(ctr) {
 939+ var doc = PE.getDocument();
 940+
 941+ $("<div>Are you sure you want to quit?</div>", doc)
 942+ .addClass("action-output-text")
 943+ .appendTo(ctr);
 944+ var $buttonCtr = $("<div></div>", doc).appendTo(ctr);
 945+
 946+ var $quitButton = PE.UI.makeButton("Yes, quit now!")
 947+ .appendTo($buttonCtr)
 948+
 949+ $quitButton.click(function() {
 950+ PE.unload();
 951+ });
 952+
 953+ var $saveButton = PE.UI.makeButton("Save to page and quit")
 954+ .appendTo($buttonCtr)
 955+ .click(function() {
 956+ PE.saveToPage();
 957+ PE.unload();
 958+ });
 959+ }
 960+ }
 961+ ]
 962+ }
 963+ ]
 964+};
 965+
 966+
 967+})(PixasticEditor.jQuery);
\ No newline at end of file
Index: branches/new-upload/phase3/js2/mwEmbed/libClipEdit/pixastic-editor/pixastic.all.js
@@ -0,0 +1,3169 @@
 2+/*
 3+ * Pixastic Lib - Core Functions - v0.1.3
 4+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 5+ * License: [http://www.pixastic.com/lib/license.txt]
 6+ */
 7+
 8+var Pixastic = (function() {
 9+
 10+
 11+ function addEvent(el, event, handler) {
 12+ if (el.addEventListener)
 13+ el.addEventListener(event, handler, false);
 14+ else if (el.attachEvent)
 15+ el.attachEvent("on" + event, handler);
 16+ }
 17+
 18+ function onready(handler) {
 19+ var handlerDone = false;
 20+ var execHandler = function() {
 21+ if (!handlerDone) {
 22+ handlerDone = true;
 23+ handler();
 24+ }
 25+ }
 26+ document.write("<"+"script defer src=\"//:\" id=\"__onload_ie_sumbox__\"></"+"script>");
 27+ var script = document.getElementById("__onload_ie_sumbox__");
 28+ script.onreadystatechange = function() {
 29+ if (script.readyState == "complete") {
 30+ script.parentNode.removeChild(script);
 31+ execHandler();
 32+ }
 33+ }
 34+ if (document.addEventListener)
 35+ document.addEventListener("DOMContentLoaded", execHandler, false);
 36+ addEvent(window, "load", execHandler);
 37+ }
 38+
 39+ function init() {
 40+ if (!Pixastic.parseOnLoad) return;
 41+ var imgEls = getElementsByClass("pixastic", null, "img");
 42+ var canvasEls = getElementsByClass("pixastic", null, "canvas");
 43+ var elements = imgEls.concat(canvasEls);
 44+ for (var i=0;i<elements.length;i++) {
 45+ (function() {
 46+
 47+ var el = elements[i];
 48+ var actions = [];
 49+ var classes = el.className.split(" ");
 50+ for (var c=0;c<classes.length;c++) {
 51+ var cls = classes[c];
 52+ if (cls.substring(0,9) == "pixastic-") {
 53+ var actionName = cls.substring(9);
 54+ if (actionName != "")
 55+ actions.push(actionName);
 56+ }
 57+ }
 58+ if (actions.length) {
 59+ if (el.tagName.toLowerCase() == "img") {
 60+ var dataImg = new Image();
 61+ dataImg.src = el.src;
 62+ if (dataImg.complete) {
 63+ for (var a=0;a<actions.length;a++) {
 64+ var res = Pixastic.applyAction(el, el, actions[a], null);
 65+ if (res)
 66+ el = res;
 67+ }
 68+ } else {
 69+ dataImg.onload = function() {
 70+ for (var a=0;a<actions.length;a++) {
 71+ var res = Pixastic.applyAction(el, el, actions[a], null)
 72+ if (res)
 73+ el = res;
 74+ }
 75+ }
 76+ }
 77+ } else {
 78+ setTimeout(function() {
 79+ for (var a=0;a<actions.length;a++) {
 80+ var res = Pixastic.applyAction(
 81+ el, el, actions[a], null
 82+ );
 83+ if (res)
 84+ el = res;
 85+ }
 86+ },1);
 87+ }
 88+ }
 89+
 90+ })();
 91+ }
 92+ }
 93+
 94+// if (typeof pixastic_no_onready == "undefined") // yuck.
 95+// onready(init);
 96+
 97+ // getElementsByClass by Dustin Diaz, http://www.dustindiaz.com/getelementsbyclass/
 98+ function getElementsByClass(searchClass,node,tag) {
 99+ var classElements = new Array();
 100+ if ( node == null )
 101+ node = document;
 102+ if ( tag == null )
 103+ tag = '*';
 104+
 105+ var els = node.getElementsByTagName(tag);
 106+ var elsLen = els.length;
 107+ var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
 108+ for (i = 0, j = 0; i < elsLen; i++) {
 109+ if ( pattern.test(els[i].className) ) {
 110+ classElements[j] = els[i];
 111+ j++;
 112+ }
 113+ }
 114+ return classElements;
 115+ }
 116+
 117+ var debugElement;
 118+
 119+ function writeDebug(text, level) {
 120+ if (!Pixastic.debug) return;
 121+ try {
 122+ switch (level) {
 123+ case "warn" :
 124+ console.warn("Pixastic:", text);
 125+ break;
 126+ case "error" :
 127+ console.error("Pixastic:", text);
 128+ break;
 129+ default:
 130+ console.log("Pixastic:", text);
 131+ }
 132+ } catch(e) {
 133+ }
 134+ if (!debugElement) {
 135+
 136+ }
 137+ }
 138+
 139+
 140+ return {
 141+
 142+ parseOnLoad : false,
 143+
 144+ debug : false,
 145+
 146+ applyAction : function(img, dataImg, actionName, options) {
 147+
 148+ options = options || {};
 149+
 150+ var imageIsCanvas = (img.tagName.toLowerCase() == "canvas");
 151+ if (imageIsCanvas && Pixastic.Client.isIE()) {
 152+ if (Pixastic.debug) writeDebug("Tried to process a canvas element but browser is IE.");
 153+ return false;
 154+ }
 155+
 156+ var canvas, ctx;
 157+ if (Pixastic.Client.hasCanvas()) {
 158+ canvas = document.createElement("canvas");
 159+ ctx = canvas.getContext("2d");
 160+ }
 161+
 162+ var w = parseInt(img.offsetWidth);
 163+ var h = parseInt(img.offsetHeight);
 164+
 165+ if (imageIsCanvas) {
 166+ w = img.width;
 167+ h = img.height;
 168+ }
 169+
 170+ if (actionName.indexOf("(") > -1) {
 171+ var tmp = actionName;
 172+ actionName = tmp.substr(0, tmp.indexOf("("));
 173+ var arg = tmp.match(/\((.*?)\)/);
 174+ if (arg[1]) {
 175+ arg = arg[1].split(";");
 176+ for (var a=0;a<arg.length;a++) {
 177+ thisArg = arg[a].split("=");
 178+ if (thisArg.length == 2) {
 179+ if (thisArg[0] == "rect") {
 180+ var rectVal = thisArg[1].split(",");
 181+ options[thisArg[0]] = {
 182+ left : parseInt(rectVal[0],10)||0,
 183+ top : parseInt(rectVal[1],10)||0,
 184+ width : parseInt(rectVal[2],10)||0,
 185+ height : parseInt(rectVal[3],10)||0
 186+ }
 187+ } else {
 188+ options[thisArg[0]] = thisArg[1];
 189+ }
 190+ }
 191+ }
 192+ }
 193+ }
 194+
 195+ if (!options.rect) {
 196+ options.rect = {
 197+ left : 0, top : 0, width : w, height : h
 198+ };
 199+ }
 200+ var validAction = false;
 201+ if (Pixastic.Actions[actionName] && typeof Pixastic.Actions[actionName].process == "function") {
 202+ validAction = true;
 203+ }
 204+ if (!validAction) {
 205+ if (Pixastic.debug) writeDebug("Invalid action \"" + actionName + "\". Maybe file not included?");
 206+ return false;
 207+ }
 208+ if (!Pixastic.Actions[actionName].checkSupport()) {
 209+ if (Pixastic.debug) writeDebug("Action \"" + actionName + "\" not supported by this browser.");
 210+ return false;
 211+ }
 212+
 213+ if (Pixastic.Client.hasCanvas()) {
 214+ canvas.width = w;
 215+ canvas.height = h;
 216+ canvas.style.width = w+"px";
 217+ canvas.style.height = h+"px";
 218+ ctx.drawImage(dataImg,0,0,w,h);
 219+
 220+ if (!img.__pixastic_org_image) {
 221+ canvas.__pixastic_org_image = img;
 222+ canvas.__pixastic_org_width = w;
 223+ canvas.__pixastic_org_height = h;
 224+ } else {
 225+ canvas.__pixastic_org_image = img.__pixastic_org_image;
 226+ canvas.__pixastic_org_width = img.__pixastic_org_width;
 227+ canvas.__pixastic_org_height = img.__pixastic_org_height;
 228+ }
 229+
 230+ } else if (Pixastic.Client.isIE() && typeof img.__pixastic_org_style == "undefined") {
 231+ img.__pixastic_org_style = img.style.cssText;
 232+ }
 233+
 234+ var params = {
 235+ image : img,
 236+ canvas : canvas,
 237+ width : w,
 238+ height : h,
 239+ useData : true,
 240+ options : options
 241+ }
 242+
 243+ // Ok, let's do it!
 244+
 245+ var res = Pixastic.Actions[actionName].process(params);
 246+
 247+ if (!res) {
 248+ return false;
 249+ }
 250+
 251+ if (Pixastic.Client.hasCanvas()) {
 252+ if (params.useData) {
 253+ if (Pixastic.Client.hasCanvasImageData()) {
 254+ canvas.getContext("2d").putImageData(params.canvasData, options.rect.left, options.rect.top);
 255+
 256+ // Opera doesn't seem to update the canvas until we draw something on it, lets draw a 0x0 rectangle.
 257+ canvas.getContext("2d").fillRect(0,0,0,0);
 258+ }
 259+ }
 260+
 261+ if (!options.leaveDOM) {
 262+ // copy properties and stuff from the source image
 263+ canvas.title = img.title;
 264+ canvas.imgsrc = img.imgsrc;
 265+ if (!imageIsCanvas) canvas.alt = img.alt;
 266+ if (!imageIsCanvas) canvas.imgsrc = img.src;
 267+ canvas.className = img.className;
 268+ canvas.style.cssText = img.style.cssText;
 269+ canvas.name = img.name;
 270+ canvas.tabIndex = img.tabIndex;
 271+ canvas.id = img.id;
 272+ if (img.parentNode && img.parentNode.replaceChild) {
 273+ img.parentNode.replaceChild(canvas, img);
 274+ }
 275+ }
 276+
 277+ options.resultCanvas = canvas;
 278+
 279+ return canvas;
 280+ }
 281+
 282+ return img;
 283+ },
 284+
 285+ prepareData : function(params, getCopy) {
 286+ var ctx = params.canvas.getContext("2d");
 287+ var rect = params.options.rect;
 288+ var dataDesc = ctx.getImageData(rect.left, rect.top, rect.width, rect.height);
 289+ var data = dataDesc.data;
 290+ if (!getCopy) params.canvasData = dataDesc;
 291+ return data;
 292+ },
 293+
 294+ // load the image file
 295+ process : function(img, actionName, options, callback)
 296+ {
 297+ if (img.tagName.toLowerCase() == "img") {
 298+ var dataImg = new Image();
 299+ dataImg.src = img.src;
 300+ if (dataImg.complete) {
 301+ var res = Pixastic.applyAction(img, dataImg, actionName, options);
 302+ if (callback) callback(res);
 303+ return res;
 304+ } else {
 305+ dataImg.onload = function() {
 306+ var res = Pixastic.applyAction(img, dataImg, actionName, options)
 307+ if (callback) callback(res);
 308+ }
 309+ }
 310+ }
 311+ if (img.tagName.toLowerCase() == "canvas") {
 312+ var res = Pixastic.applyAction(img, img, actionName, options);
 313+ if (callback) callback(res);
 314+ return res;
 315+ }
 316+ },
 317+
 318+ revert : function(img) {
 319+ if (Pixastic.Client.hasCanvas()) {
 320+ if (img.tagName.toLowerCase() == "canvas" && img.__pixastic_org_image) {
 321+ img.width = img.__pixastic_org_width;
 322+ img.height = img.__pixastic_org_height;
 323+ img.getContext("2d").drawImage(img.__pixastic_org_image, 0, 0);
 324+
 325+ if (img.parentNode && img.parentNode.replaceChild) {
 326+ img.parentNode.replaceChild(img.__pixastic_org_image, img);
 327+ }
 328+
 329+ return img;
 330+ }
 331+ } else if (Pixastic.Client.isIE() && typeof img.__pixastic_org_style != "undefined") {
 332+ img.style.cssText = img.__pixastic_org_style;
 333+ }
 334+ },
 335+
 336+ Client : {
 337+ hasCanvas : (function() {
 338+ var c = document.createElement("canvas");
 339+ var val = false;
 340+ try {
 341+ val = !!((typeof c.getContext == "function") && c.getContext("2d"));
 342+ } catch(e) {}
 343+ return function() {
 344+ return val;
 345+ }
 346+ })(),
 347+
 348+ hasCanvasImageData : (function() {
 349+ var c = document.createElement("canvas");
 350+ var val = false;
 351+ var ctx;
 352+ try {
 353+ if (typeof c.getContext == "function" && (ctx = c.getContext("2d"))) {
 354+ val = (typeof ctx.getImageData == "function");
 355+ }
 356+ } catch(e) {}
 357+ return function() {
 358+ return val;
 359+ }
 360+ })(),
 361+
 362+ isIE : function() {
 363+ return !!document.all && !!window.attachEvent && !window.opera;
 364+ }
 365+ },
 366+
 367+ Actions : {}
 368+ }
 369+
 370+
 371+})();
 372+/*
 373+ * Pixastic Lib - jQuery plugin
 374+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 375+ * License: [http://www.pixastic.com/lib/license.txt]
 376+ */
 377+
 378+if (typeof jQuery != "undefined" && jQuery && jQuery.fn) {
 379+ jQuery.fn.pixastic = function(action, options) {
 380+ var newElements = [];
 381+ this.each(
 382+ function () {
 383+ if (this.tagName.toLowerCase() == "img" && !this.complete) {
 384+ return;
 385+ }
 386+ var res = Pixastic.process(this, action, options);
 387+ if (res) {
 388+ newElements.push(res);
 389+ }
 390+ }
 391+ );
 392+ if (newElements.length > 0)
 393+ return jQuery(newElements);
 394+ else
 395+ return this;
 396+ };
 397+
 398+};
 399+/*
 400+ * Pixastic Lib - Blend - v0.1.1
 401+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 402+ * License: [http://www.pixastic.com/lib/license.txt]
 403+ */
 404+
 405+Pixastic.Actions.blend = {
 406+
 407+ process : function(params) {
 408+ var amount = parseFloat(params.options.amount);
 409+ var mode = (params.options.mode || "normal").toLowerCase();
 410+ var image = params.options.image;
 411+
 412+ amount = Math.max(0,Math.min(1,amount));
 413+
 414+ if (!image) return false;
 415+
 416+ if (Pixastic.Client.hasCanvasImageData()) {
 417+ var rect = params.options.rect;
 418+ var data = Pixastic.prepareData(params);
 419+ var w = rect.width;
 420+ var h = rect.height;
 421+
 422+ params.useData = false;
 423+
 424+ var otherCanvas = document.createElement("canvas");
 425+ otherCanvas.width = params.canvas.width;
 426+ otherCanvas.height = params.canvas.height;
 427+ var otherCtx = otherCanvas.getContext("2d");
 428+ otherCtx.drawImage(image,0,0);
 429+
 430+ var params2 = {canvas:otherCanvas,options:params.options};
 431+ var data2 = Pixastic.prepareData(params2);
 432+ var dataDesc2 = params2.canvasData;
 433+
 434+ var p = w*h;
 435+ var pix = p*4;
 436+ var pix1, pix2;
 437+ var r1, g1, b1;
 438+ var r2, g2, b2;
 439+ var r3, g3, b3;
 440+ var r4, g4, b4;
 441+
 442+ var dataChanged = false;
 443+
 444+ switch (mode) {
 445+ case "normal" :
 446+ //while (p--) {
 447+ // data2[pix-=4] = data2[pix];
 448+ // data2[pix1=pix+1] = data2[pix1];
 449+ // data2[pix2=pix+2] = data2[pix2];
 450+ //}
 451+ break;
 452+
 453+ case "multiply" :
 454+ while (p--) {
 455+ data2[pix-=4] = data[pix] * data2[pix] / 255;
 456+ data2[pix1=pix+1] = data[pix1] * data2[pix1] / 255;
 457+ data2[pix2=pix+2] = data[pix2] * data2[pix2] / 255;
 458+ }
 459+ dataChanged = true;
 460+ break;
 461+
 462+ case "lighten" :
 463+ while (p--) {
 464+ if ((r1 = data[pix-=4]) > data2[pix])
 465+ data2[pix] = r1;
 466+ if ((g1 = data[pix1=pix+1]) > data2[pix1])
 467+ data2[pix1] = g1;
 468+ if ((b1 = data[pix2=pix+2]) > data2[pix2])
 469+ data2[pix2] = b1;
 470+ }
 471+ dataChanged = true;
 472+ break;
 473+
 474+ case "darken" :
 475+ while (p--) {
 476+ if ((r1 = data[pix-=4]) < data2[pix])
 477+ data2[pix] = r1;
 478+ if ((g1 = data[pix1=pix+1]) < data2[pix1])
 479+ data2[pix1] = g1;
 480+ if ((b1 = data[pix2=pix+2]) < data2[pix2])
 481+ data2[pix2] = b1;
 482+
 483+ }
 484+ dataChanged = true;
 485+ break;
 486+
 487+ case "darkercolor" :
 488+ while (p--) {
 489+ 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)) {
 490+ data2[pix] = r1;
 491+ data2[pix1] = g1;
 492+ data2[pix2] = b1;
 493+ }
 494+ }
 495+ dataChanged = true;
 496+ break;
 497+
 498+ case "lightercolor" :
 499+ while (p--) {
 500+ 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)) {
 501+ data2[pix] = r1;
 502+ data2[pix1] = g1;
 503+ data2[pix2] = b1;
 504+ }
 505+ }
 506+ dataChanged = true;
 507+ break;
 508+
 509+ case "lineardodge" :
 510+ otherCtx.globalCompositeOperation = "source-over";
 511+ otherCtx.drawImage(params.canvas, 0, 0);
 512+ otherCtx.globalCompositeOperation = "lighter";
 513+ otherCtx.drawImage(image, 0, 0);
 514+
 515+ /*
 516+ while (p--) {
 517+ if ((r3 = data[pix-=4] + data2[pix]) > 255)
 518+ data2[pix] = 255;
 519+ else
 520+ data2[pix] = r3;
 521+ if ((g3 = data[pix1=pix+1] + data2[pix1]) > 255)
 522+ data2[pix1] = 255;
 523+ else
 524+ data2[pix1] = g3;
 525+ if ((b3 = data[pix2=pix+2] + data2[pix2]) > 255)
 526+ data2[pix2] = 255;
 527+ else
 528+ data2[pix2] = b3;
 529+ }
 530+ dataChanged = true;
 531+ */
 532+
 533+ break;
 534+
 535+ case "linearburn" :
 536+ while (p--) {
 537+ if ((r3 = data[pix-=4] + data2[pix]) < 255)
 538+ data2[pix] = 0;
 539+ else
 540+ data2[pix] = (r3 - 255);
 541+ if ((g3 = data[pix1=pix+1] + data2[pix1]) < 255)
 542+ data2[pix1] = 0;
 543+ else
 544+ data2[pix1] = (g3 - 255);
 545+ if ((b3 = data[pix2=pix+2] + data2[pix2]) < 255)
 546+ data2[pix2] = 0;
 547+ else
 548+ data2[pix2] = (b3 - 255);
 549+ }
 550+ dataChanged = true;
 551+ break;
 552+
 553+ case "difference" :
 554+ while (p--) {
 555+ if ((r3 = data[pix-=4] - data2[pix]) < 0)
 556+ data2[pix] = -r3;
 557+ else
 558+ data2[pix] = r3;
 559+ if ((g3 = data[pix1=pix+1] - data2[pix1]) < 0)
 560+ data2[pix1] = -g3;
 561+ else
 562+ data2[pix1] = g3;
 563+ if ((b3 = data[pix2=pix+2] - data2[pix2]) < 0)
 564+ data2[pix2] = -b3;
 565+ else
 566+ data2[pix2] = b3;
 567+ }
 568+ dataChanged = true;
 569+ break;
 570+
 571+ case "screen" :
 572+ while (p--) {
 573+ data2[pix-=4] = (255 - ( ((255-data2[pix])*(255-data[pix])) >> 8));
 574+ data2[pix1=pix+1] = (255 - ( ((255-data2[pix1])*(255-data[pix1])) >> 8));
 575+ data2[pix2=pix+2] = (255 - ( ((255-data2[pix2])*(255-data[pix2])) >> 8));
 576+ }
 577+ dataChanged = true;
 578+ break;
 579+
 580+ case "exclusion" :
 581+ var div_2_255 = 2 / 255;
 582+ while (p--) {
 583+ data2[pix-=4] = (r1 = data[pix]) - (r1 * div_2_255 - 1) * data2[pix];
 584+ data2[pix1=pix+1] = (g1 = data[pix1]) - (g1 * div_2_255 - 1) * data2[pix1];
 585+ data2[pix2=pix+2] = (b1 = data[pix2]) - (b1 * div_2_255 - 1) * data2[pix2];
 586+ }
 587+ dataChanged = true;
 588+ break;
 589+
 590+ case "overlay" :
 591+ var div_2_255 = 2 / 255;
 592+ while (p--) {
 593+ if ((r1 = data[pix-=4]) < 128)
 594+ data2[pix] = data2[pix]*r1*div_2_255;
 595+ else
 596+ data2[pix] = 255 - (255-data2[pix])*(255-r1)*div_2_255;
 597+
 598+ if ((g1 = data[pix1=pix+1]) < 128)
 599+ data2[pix1] = data2[pix1]*g1*div_2_255;
 600+ else
 601+ data2[pix1] = 255 - (255-data2[pix1])*(255-g1)*div_2_255;
 602+
 603+ if ((b1 = data[pix2=pix+2]) < 128)
 604+ data2[pix2] = data2[pix2]*b1*div_2_255;
 605+ else
 606+ data2[pix2] = 255 - (255-data2[pix2])*(255-b1)*div_2_255;
 607+
 608+ }
 609+ dataChanged = true;
 610+ break;
 611+
 612+ case "softlight" :
 613+ var div_2_255 = 2 / 255;
 614+ while (p--) {
 615+ if ((r1 = data[pix-=4]) < 128)
 616+ data2[pix] = ((data2[pix]>>1) + 64) * r1 * div_2_255;
 617+ else
 618+ data2[pix] = 255 - (191 - (data2[pix]>>1)) * (255-r1) * div_2_255;
 619+
 620+ if ((g1 = data[pix1=pix+1]) < 128)
 621+ data2[pix1] = ((data2[pix1]>>1)+64) * g1 * div_2_255;
 622+ else
 623+ data2[pix1] = 255 - (191 - (data2[pix1]>>1)) * (255-g1) * div_2_255;
 624+
 625+ if ((b1 = data[pix2=pix+2]) < 128)
 626+ data2[pix2] = ((data2[pix2]>>1)+64) * b1 * div_2_255;
 627+ else
 628+ data2[pix2] = 255 - (191 - (data2[pix2]>>1)) * (255-b1) * div_2_255;
 629+
 630+ }
 631+ dataChanged = true;
 632+ break;
 633+
 634+ case "hardlight" :
 635+ var div_2_255 = 2 / 255;
 636+ while (p--) {
 637+ if ((r2 = data2[pix-=4]) < 128)
 638+ data2[pix] = data[pix] * r2 * div_2_255;
 639+ else
 640+ data2[pix] = 255 - (255-data[pix]) * (255-r2) * div_2_255;
 641+
 642+ if ((g2 = data2[pix1=pix+1]) < 128)
 643+ data2[pix1] = data[pix1] * g2 * div_2_255;
 644+ else
 645+ data2[pix1] = 255 - (255-data[pix1]) * (255-g2) * div_2_255;
 646+
 647+ if ((b2 = data2[pix2=pix+2]) < 128)
 648+ data2[pix2] = data[pix2] * b2 * div_2_255;
 649+ else
 650+ data2[pix2] = 255 - (255-data[pix2]) * (255-b2) * div_2_255;
 651+
 652+ }
 653+ dataChanged = true;
 654+ break;
 655+
 656+ case "colordodge" :
 657+ while (p--) {
 658+ if ((r3 = (data[pix-=4]<<8)/(255-(r2 = data2[pix]))) > 255 || r2 == 255)
 659+ data2[pix] = 255;
 660+ else
 661+ data2[pix] = r3;
 662+
 663+ if ((g3 = (data[pix1=pix+1]<<8)/(255-(g2 = data2[pix1]))) > 255 || g2 == 255)
 664+ data2[pix1] = 255;
 665+ else
 666+ data2[pix1] = g3;
 667+
 668+ if ((b3 = (data[pix2=pix+2]<<8)/(255-(b2 = data2[pix2]))) > 255 || b2 == 255)
 669+ data2[pix2] = 255;
 670+ else
 671+ data2[pix2] = b3;
 672+ }
 673+ dataChanged = true;
 674+ break;
 675+
 676+ case "colorburn" :
 677+ while (p--) {
 678+ if ((r3 = 255-((255-data[pix-=4])<<8)/data2[pix]) < 0 || data2[pix] == 0)
 679+ data2[pix] = 0;
 680+ else
 681+ data2[pix] = r3;
 682+
 683+ if ((g3 = 255-((255-data[pix1=pix+1])<<8)/data2[pix1]) < 0 || data2[pix1] == 0)
 684+ data2[pix1] = 0;
 685+ else
 686+ data2[pix1] = g3;
 687+
 688+ if ((b3 = 255-((255-data[pix2=pix+2])<<8)/data2[pix2]) < 0 || data2[pix2] == 0)
 689+ data2[pix2] = 0;
 690+ else
 691+ data2[pix2] = b3;
 692+ }
 693+ dataChanged = true;
 694+ break;
 695+
 696+ case "linearlight" :
 697+ while (p--) {
 698+ if ( ((r3 = 2*(r2=data2[pix-=4])+data[pix]-256) < 0) || (r2 < 128 && r3 < 0)) {
 699+ data2[pix] = 0
 700+ } else {
 701+ if (r3 > 255)
 702+ data2[pix] = 255;
 703+ else
 704+ data2[pix] = r3;
 705+ }
 706+ if ( ((g3 = 2*(g2=data2[pix1=pix+1])+data[pix1]-256) < 0) || (g2 < 128 && g3 < 0)) {
 707+ data2[pix1] = 0
 708+ } else {
 709+ if (g3 > 255)
 710+ data2[pix1] = 255;
 711+ else
 712+ data2[pix1] = g3;
 713+ }
 714+ if ( ((b3 = 2*(b2=data2[pix2=pix+2])+data[pix2]-256) < 0) || (b2 < 128 && b3 < 0)) {
 715+ data2[pix2] = 0
 716+ } else {
 717+ if (b3 > 255)
 718+ data2[pix2] = 255;
 719+ else
 720+ data2[pix2] = b3;
 721+ }
 722+ }
 723+ dataChanged = true;
 724+ break;
 725+
 726+ case "vividlight" :
 727+ while (p--) {
 728+ if ((r2=data2[pix-=4]) < 128) {
 729+ if (r2) {
 730+ if ((r3 = 255 - ((255-data[pix])<<8) / (2*r2)) < 0)
 731+ data2[pix] = 0;
 732+ else
 733+ data2[pix] = r3
 734+ } else {
 735+ data2[pix] = 0;
 736+ }
 737+ } else if ((r3 = (r4=2*r2-256)) < 255) {
 738+ if ((r3 = (data[pix]<<8)/(255-r4)) > 255)
 739+ data2[pix] = 255;
 740+ else
 741+ data2[pix] = r3;
 742+ } else {
 743+ if (r3 < 0)
 744+ data2[pix] = 0;
 745+ else
 746+ data2[pix] = r3
 747+ }
 748+
 749+ if ((g2=data2[pix1=pix+1]) < 128) {
 750+ if (g2) {
 751+ if ((g3 = 255 - ((255-data[pix1])<<8) / (2*g2)) < 0)
 752+ data2[pix1] = 0;
 753+ else
 754+ data2[pix1] = g3;
 755+ } else {
 756+ data2[pix1] = 0;
 757+ }
 758+ } else if ((g3 = (g4=2*g2-256)) < 255) {
 759+ if ((g3 = (data[pix1]<<8)/(255-g4)) > 255)
 760+ data2[pix1] = 255;
 761+ else
 762+ data2[pix1] = g3;
 763+ } else {
 764+ if (g3 < 0)
 765+ data2[pix1] = 0;
 766+ else
 767+ data2[pix1] = g3;
 768+ }
 769+
 770+ if ((b2=data2[pix2=pix+2]) < 128) {
 771+ if (b2) {
 772+ if ((b3 = 255 - ((255-data[pix2])<<8) / (2*b2)) < 0)
 773+ data2[pix2] = 0;
 774+ else
 775+ data2[pix2] = b3;
 776+ } else {
 777+ data2[pix2] = 0;
 778+ }
 779+ } else if ((b3 = (b4=2*b2-256)) < 255) {
 780+ if ((b3 = (data[pix2]<<8)/(255-b4)) > 255)
 781+ data2[pix2] = 255;
 782+ else
 783+ data2[pix2] = b3;
 784+ } else {
 785+ if (b3 < 0)
 786+ data2[pix2] = 0;
 787+ else
 788+ data2[pix2] = b3;
 789+ }
 790+ }
 791+ dataChanged = true;
 792+ break;
 793+
 794+ case "pinlight" :
 795+ while (p--) {
 796+ if ((r2=data2[pix-=4]) < 128)
 797+ if ((r1=data[pix]) < (r4=2*r2))
 798+ data2[pix] = r1;
 799+ else
 800+ data2[pix] = r4;
 801+ else
 802+ if ((r1=data[pix]) > (r4=2*r2-256))
 803+ data2[pix] = r1;
 804+ else
 805+ data2[pix] = r4;
 806+
 807+ if ((g2=data2[pix1=pix+1]) < 128)
 808+ if ((g1=data[pix1]) < (g4=2*g2))
 809+ data2[pix1] = g1;
 810+ else
 811+ data2[pix1] = g4;
 812+ else
 813+ if ((g1=data[pix1]) > (g4=2*g2-256))
 814+ data2[pix1] = g1;
 815+ else
 816+ data2[pix1] = g4;
 817+
 818+ if ((r2=data2[pix2=pix+2]) < 128)
 819+ if ((r1=data[pix2]) < (r4=2*r2))
 820+ data2[pix2] = r1;
 821+ else
 822+ data2[pix2] = r4;
 823+ else
 824+ if ((r1=data[pix2]) > (r4=2*r2-256))
 825+ data2[pix2] = r1;
 826+ else
 827+ data2[pix2] = r4;
 828+ }
 829+ dataChanged = true;
 830+ break;
 831+
 832+ case "hardmix" :
 833+ while (p--) {
 834+ if ((r2 = data2[pix-=4]) < 128)
 835+ if (255 - ((255-data[pix])<<8)/(2*r2) < 128 || r2 == 0)
 836+ data2[pix] = 0;
 837+ else
 838+ data2[pix] = 255;
 839+ else if ((r4=2*r2-256) < 255 && (data[pix]<<8)/(255-r4) < 128)
 840+ data2[pix] = 0;
 841+ else
 842+ data2[pix] = 255;
 843+
 844+ if ((g2 = data2[pix1=pix+1]) < 128)
 845+ if (255 - ((255-data[pix1])<<8)/(2*g2) < 128 || g2 == 0)
 846+ data2[pix1] = 0;
 847+ else
 848+ data2[pix1] = 255;
 849+ else if ((g4=2*g2-256) < 255 && (data[pix1]<<8)/(255-g4) < 128)
 850+ data2[pix1] = 0;
 851+ else
 852+ data2[pix1] = 255;
 853+
 854+ if ((b2 = data2[pix2=pix+2]) < 128)
 855+ if (255 - ((255-data[pix2])<<8)/(2*b2) < 128 || b2 == 0)
 856+ data2[pix2] = 0;
 857+ else
 858+ data2[pix2] = 255;
 859+ else if ((b4=2*b2-256) < 255 && (data[pix2]<<8)/(255-b4) < 128)
 860+ data2[pix2] = 0;
 861+ else
 862+ data2[pix2] = 255;
 863+ }
 864+ dataChanged = true;
 865+ break;
 866+ }
 867+
 868+ if (dataChanged)
 869+ otherCtx.putImageData(dataDesc2,0,0);
 870+
 871+ var ctx = params.canvas.getContext("2d");
 872+ ctx.save();
 873+ ctx.globalAlpha = amount;
 874+ ctx.drawImage(
 875+ otherCanvas,
 876+ 0,0,rect.width,rect.height,
 877+ rect.left,rect.top,rect.width,rect.height
 878+ );
 879+ ctx.globalAlpha = 1;
 880+ ctx.restore();
 881+
 882+ return true;
 883+ }
 884+ },
 885+ checkSupport : function() {
 886+ return Pixastic.Client.hasCanvasImageData();
 887+ }
 888+}/*
 889+ * Pixastic Lib - Blur filter - v0.1.0
 890+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 891+ * License: [http://www.pixastic.com/lib/license.txt]
 892+ */
 893+
 894+Pixastic.Actions.blur = {
 895+ process : function(params) {
 896+
 897+ if (typeof params.options.fixMargin == "undefined")
 898+ params.options.fixMargin = true;
 899+
 900+ if (Pixastic.Client.hasCanvasImageData()) {
 901+ var data = Pixastic.prepareData(params);
 902+ var dataCopy = Pixastic.prepareData(params, true)
 903+
 904+ /*
 905+ var kernel = [
 906+ [0.5, 1, 0.5],
 907+ [1, 2, 1],
 908+ [0.5, 1, 0.5]
 909+ ];
 910+ */
 911+
 912+ var kernel = [
 913+ [0, 1, 0],
 914+ [1, 2, 1],
 915+ [0, 1, 0]
 916+ ];
 917+
 918+ var weight = 0;
 919+ for (var i=0;i<3;i++) {
 920+ for (var j=0;j<3;j++) {
 921+ weight += kernel[i][j];
 922+ }
 923+ }
 924+
 925+ weight = 1 / (weight*2);
 926+
 927+ var rect = params.options.rect;
 928+ var w = rect.width;
 929+ var h = rect.height;
 930+
 931+ var w4 = w*4;
 932+ var y = h;
 933+ do {
 934+ var offsetY = (y-1)*w4;
 935+
 936+ var prevY = (y == 1) ? 0 : y-2;
 937+ var nextY = (y == h) ? y - 1 : y;
 938+
 939+ var offsetYPrev = prevY*w*4;
 940+ var offsetYNext = nextY*w*4;
 941+
 942+ var x = w;
 943+ do {
 944+ var offset = offsetY + (x*4-4);
 945+
 946+ var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
 947+ var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
 948+
 949+ data[offset] = (
 950+ /*
 951+ dataCopy[offsetPrev - 4]
 952+ + dataCopy[offsetPrev+4]
 953+ + dataCopy[offsetNext - 4]
 954+ + dataCopy[offsetNext+4]
 955+ +
 956+ */
 957+ (dataCopy[offsetPrev]
 958+ + dataCopy[offset-4]
 959+ + dataCopy[offset+4]
 960+ + dataCopy[offsetNext]) * 2
 961+ + dataCopy[offset] * 4
 962+ ) * weight;
 963+
 964+ data[offset+1] = (
 965+ /*
 966+ dataCopy[offsetPrev - 3]
 967+ + dataCopy[offsetPrev+5]
 968+ + dataCopy[offsetNext - 3]
 969+ + dataCopy[offsetNext+5]
 970+ +
 971+ */
 972+ (dataCopy[offsetPrev+1]
 973+ + dataCopy[offset-3]
 974+ + dataCopy[offset+5]
 975+ + dataCopy[offsetNext+1]) * 2
 976+ + dataCopy[offset+1] * 4
 977+ ) * weight;
 978+
 979+ data[offset+2] = (
 980+ /*
 981+ dataCopy[offsetPrev - 2]
 982+ + dataCopy[offsetPrev+6]
 983+ + dataCopy[offsetNext - 2]
 984+ + dataCopy[offsetNext+6]
 985+ +
 986+ */
 987+ (dataCopy[offsetPrev+2]
 988+ + dataCopy[offset-2]
 989+ + dataCopy[offset+6]
 990+ + dataCopy[offsetNext+2]) * 2
 991+ + dataCopy[offset+2] * 4
 992+ ) * weight;
 993+
 994+ } while (--x);
 995+ } while (--y);
 996+
 997+ return true;
 998+
 999+ } else if (Pixastic.Client.isIE()) {
 1000+ params.image.style.filter += " progid:DXImageTransform.Microsoft.Blur(pixelradius=1.5)";
 1001+
 1002+ if (params.options.fixMargin) {
 1003+ params.image.style.marginLeft = (parseInt(params.image.style.marginLeft,10)||0) - 2 + "px";
 1004+ params.image.style.marginTop = (parseInt(params.image.style.marginTop,10)||0) - 2 + "px";
 1005+ }
 1006+
 1007+ return true;
 1008+ }
 1009+ },
 1010+ checkSupport : function() {
 1011+ return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
 1012+ }
 1013+}/*
 1014+ * Pixastic Lib - Blur Fast - v0.1.1
 1015+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 1016+ * License: [http://www.pixastic.com/lib/license.txt]
 1017+ */
 1018+
 1019+Pixastic.Actions.blurfast = {
 1020+ process : function(params) {
 1021+
 1022+ var amount = parseFloat(params.options.amount)||0;
 1023+ var clear = !!(params.options.clear && params.options.clear != "false");
 1024+
 1025+ amount = Math.max(0,Math.min(5,amount));
 1026+
 1027+ if (Pixastic.Client.hasCanvas()) {
 1028+ var rect = params.options.rect;
 1029+
 1030+ var ctx = params.canvas.getContext("2d");
 1031+ ctx.save();
 1032+ ctx.beginPath();
 1033+ ctx.rect(rect.left, rect.top, rect.width, rect.height);
 1034+ ctx.clip();
 1035+
 1036+ var scale = 2;
 1037+ var smallWidth = Math.round(params.width / scale);
 1038+ var smallHeight = Math.round(params.height / scale);
 1039+
 1040+ var copy = document.createElement("canvas");
 1041+ copy.width = smallWidth;
 1042+ copy.height = smallHeight;
 1043+
 1044+ var clear = false;
 1045+ var steps = Math.round(amount * 20);
 1046+
 1047+ var copyCtx = copy.getContext("2d");
 1048+ for (var i=0;i<steps;i++) {
 1049+ var scaledWidth = Math.max(1,Math.round(smallWidth - i));
 1050+ var scaledHeight = Math.max(1,Math.round(smallHeight - i));
 1051+
 1052+ copyCtx.clearRect(0,0,smallWidth,smallHeight);
 1053+
 1054+ copyCtx.drawImage(
 1055+ params.canvas,
 1056+ 0,0,params.width,params.height,
 1057+ 0,0,scaledWidth,scaledHeight
 1058+ );
 1059+
 1060+ if (clear)
 1061+ ctx.clearRect(rect.left,rect.top,rect.width,rect.height);
 1062+
 1063+ ctx.drawImage(
 1064+ copy,
 1065+ 0,0,scaledWidth,scaledHeight,
 1066+ 0,0,params.width,params.height
 1067+ );
 1068+ }
 1069+
 1070+ ctx.restore();
 1071+
 1072+ params.useData = false;
 1073+ return true;
 1074+ } else if (Pixastic.Client.isIE()) {
 1075+ var radius = 10 * amount;
 1076+ params.image.style.filter += " progid:DXImageTransform.Microsoft.Blur(pixelradius=" + radius + ")";
 1077+
 1078+ if (params.options.fixMargin || 1) {
 1079+ params.image.style.marginLeft = (parseInt(params.image.style.marginLeft,10)||0) - Math.round(radius) + "px";
 1080+ params.image.style.marginTop = (parseInt(params.image.style.marginTop,10)||0) - Math.round(radius) + "px";
 1081+ }
 1082+
 1083+ return true;
 1084+ }
 1085+ },
 1086+ checkSupport : function() {
 1087+ return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
 1088+ }
 1089+}
 1090+/*
 1091+ * Pixastic Lib - Brightness/Contrast filter - v0.1.1
 1092+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 1093+ * License: [http://www.pixastic.com/lib/license.txt]
 1094+ */
 1095+
 1096+Pixastic.Actions.brightness = {
 1097+
 1098+ process : function(params) {
 1099+
 1100+ var brightness = parseInt(params.options.brightness,10) || 0;
 1101+ var contrast = parseFloat(params.options.contrast)||0;
 1102+ var legacy = !!(params.options.legacy && params.options.legacy != "false");
 1103+
 1104+ if (legacy) {
 1105+ brightness = Math.min(150,Math.max(-150,brightness));
 1106+ } else {
 1107+ var brightMul = 1 + Math.min(150,Math.max(-150,brightness)) / 150;
 1108+ }
 1109+ contrast = Math.max(0,contrast+1);
 1110+
 1111+ if (Pixastic.Client.hasCanvasImageData()) {
 1112+ var data = Pixastic.prepareData(params);
 1113+ var rect = params.options.rect;
 1114+ var w = rect.width;
 1115+ var h = rect.height;
 1116+
 1117+ var p = w*h;
 1118+ var pix = p*4, pix1, pix2;
 1119+
 1120+ var mul, add;
 1121+ if (contrast != 1) {
 1122+ if (legacy) {
 1123+ mul = contrast;
 1124+ add = (brightness - 128) * contrast + 128;
 1125+ } else {
 1126+ mul = brightMul * contrast;
 1127+ add = - contrast * 128 + 128;
 1128+ }
 1129+ } else { // this if-then is not necessary anymore, is it?
 1130+ if (legacy) {
 1131+ mul = 1;
 1132+ add = brightness;
 1133+ } else {
 1134+ mul = brightMul;
 1135+ add = 0;
 1136+ }
 1137+ }
 1138+ var r, g, b;
 1139+ while (p--) {
 1140+ if ((r = data[pix-=4] * mul + add) > 255 )
 1141+ data[pix] = 255;
 1142+ else if (r < 0)
 1143+ data[pix] = 0;
 1144+ else
 1145+ data[pix] = r;
 1146+
 1147+ if ((g = data[pix1=pix+1] * mul + add) > 255 )
 1148+ data[pix1] = 255;
 1149+ else if (g < 0)
 1150+ data[pix1] = 0;
 1151+ else
 1152+ data[pix1] = g;
 1153+
 1154+ if ((b = data[pix2=pix+2] * mul + add) > 255 )
 1155+ data[pix2] = 255;
 1156+ else if (b < 0)
 1157+ data[pix2] = 0;
 1158+ else
 1159+ data[pix2] = b;
 1160+ }
 1161+ return true;
 1162+ }
 1163+ },
 1164+ checkSupport : function() {
 1165+ return Pixastic.Client.hasCanvasImageData();
 1166+ }
 1167+}
 1168+
 1169+/*
 1170+ * Pixastic Lib - Color adjust filter - v0.1.1
 1171+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 1172+ * License: [http://www.pixastic.com/lib/license.txt]
 1173+ */
 1174+
 1175+Pixastic.Actions.coloradjust = {
 1176+
 1177+ process : function(params) {
 1178+ var red = parseFloat(params.options.red) || 0;
 1179+ var green = parseFloat(params.options.green) || 0;
 1180+ var blue = parseFloat(params.options.blue) || 0;
 1181+
 1182+ red = Math.round(red*255);
 1183+ green = Math.round(green*255);
 1184+ blue = Math.round(blue*255);
 1185+
 1186+ if (Pixastic.Client.hasCanvasImageData()) {
 1187+ var data = Pixastic.prepareData(params);
 1188+ var rect = params.options.rect;
 1189+
 1190+ var p = rect.width*rect.height;
 1191+ var pix = p*4, pix1, pix2;
 1192+
 1193+ var r, g, b;
 1194+ while (p--) {
 1195+ pix -= 4;
 1196+
 1197+ if (red) {
 1198+ if ((r = data[pix] + red) < 0 )
 1199+ data[pix] = 0;
 1200+ else if (r > 255 )
 1201+ data[pix] = 255;
 1202+ else
 1203+ data[pix] = r;
 1204+ }
 1205+
 1206+ if (green) {
 1207+ if ((g = data[pix1=pix+1] + green) < 0 )
 1208+ data[pix1] = 0;
 1209+ else if (g > 255 )
 1210+ data[pix1] = 255;
 1211+ else
 1212+ data[pix1] = g;
 1213+ }
 1214+
 1215+ if (blue) {
 1216+ if ((b = data[pix2=pix+2] + blue) < 0 )
 1217+ data[pix2] = 0;
 1218+ else if (b > 255 )
 1219+ data[pix2] = 255;
 1220+ else
 1221+ data[pix2] = b;
 1222+ }
 1223+ }
 1224+ return true;
 1225+ }
 1226+ },
 1227+ checkSupport : function() {
 1228+ return (Pixastic.Client.hasCanvasImageData());
 1229+ }
 1230+}
 1231+/*
 1232+ * Pixastic Lib - Histogram - v0.1.0
 1233+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 1234+ * License: [http://www.pixastic.com/lib/license.txt]
 1235+ */
 1236+
 1237+
 1238+Pixastic.Actions.colorhistogram = {
 1239+
 1240+ array256 : function(default_value) {
 1241+ arr = [];
 1242+ for (var i=0; i<256; i++) { arr[i] = default_value; }
 1243+ return arr
 1244+ },
 1245+
 1246+ process : function(params) {
 1247+ var values = [];
 1248+ if (typeof params.options.returnValue != "object") {
 1249+ params.options.returnValue = {rvals:[], gvals:[], bvals:[]};
 1250+ }
 1251+ var paint = !!(params.options.paint);
 1252+
 1253+ var returnValue = params.options.returnValue;
 1254+ if (typeof returnValue.values != "array") {
 1255+ returnValue.rvals = [];
 1256+ returnValue.gvals = [];
 1257+ returnValue.bvals = [];
 1258+ }
 1259+
 1260+ if (Pixastic.Client.hasCanvasImageData()) {
 1261+ var data = Pixastic.prepareData(params);
 1262+ params.useData = false;
 1263+
 1264+ var rvals = this.array256(0);
 1265+ var gvals = this.array256(0);
 1266+ var bvals = this.array256(0);
 1267+
 1268+ var rect = params.options.rect;
 1269+
 1270+ var p = rect.width*rect.height;
 1271+ var pix = p*4;
 1272+ while (p--) {
 1273+ rvals[data[pix-=4]]++;
 1274+ gvals[data[pix+1]]++;
 1275+ bvals[data[pix+2]]++;
 1276+ }
 1277+
 1278+ returnValue.rvals = rvals;
 1279+ returnValue.gvals = gvals;
 1280+ returnValue.bvals = bvals;
 1281+
 1282+ if (paint) {
 1283+ var ctx = params.canvas.getContext("2d");
 1284+ var vals = [rvals, gvals, bvals];
 1285+ for (var v=0;v<3;v++) {
 1286+ var yoff = (v+1) * params.height / 3;
 1287+ var maxValue = 0;
 1288+ for (var i=0;i<256;i++) {
 1289+ if (vals[v][i] > maxValue)
 1290+ maxValue = vals[v][i];
 1291+ }
 1292+ var heightScale = params.height / 3 / maxValue;
 1293+ var widthScale = params.width / 256;
 1294+ if (v==0) ctx.fillStyle = "rgba(255,0,0,0.5)";
 1295+ else if (v==1) ctx.fillStyle = "rgba(0,255,0,0.5)";
 1296+ else if (v==2) ctx.fillStyle = "rgba(0,0,255,0.5)";
 1297+ for (var i=0;i<256;i++) {
 1298+ ctx.fillRect(
 1299+ i * widthScale, params.height - heightScale * vals[v][i] - params.height + yoff,
 1300+ widthScale, vals[v][i] * heightScale
 1301+ );
 1302+ }
 1303+ }
 1304+ }
 1305+ return true;
 1306+ }
 1307+ },
 1308+
 1309+ checkSupport : function() {
 1310+ return Pixastic.Client.hasCanvasImageData();
 1311+ }
 1312+}/*
 1313+ * Pixastic Lib - Crop - v0.1.1
 1314+ * Copyright (c) 2008-2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 1315+ * License: [http://www.pixastic.com/lib/license.txt]
 1316+ */
 1317+
 1318+Pixastic.Actions.crop = {
 1319+ process : function(params) {
 1320+ if (Pixastic.Client.hasCanvas()) {
 1321+ var rect = params.options.rect;
 1322+
 1323+ var width = rect.width;
 1324+ var height = rect.height;
 1325+ var top = rect.top;
 1326+ var left = rect.left;
 1327+
 1328+ if (typeof params.options.left != "undefined")
 1329+ left = parseInt(params.options.left,10);
 1330+ if (typeof params.options.top != "undefined")
 1331+ top = parseInt(params.options.top,10);
 1332+ if (typeof params.options.height != "undefined")
 1333+ width = parseInt(params.options.width,10);
 1334+ if (typeof params.options.height != "undefined")
 1335+ height = parseInt(params.options.height,10);
 1336+
 1337+ if (left < 0) left = 0;
 1338+ if (left > params.width-1) left = params.width-1;
 1339+
 1340+ if (top < 0) top = 0;
 1341+ if (top > params.height-1) top = params.height-1;
 1342+
 1343+ if (width < 1) width = 1;
 1344+ if (left + width > params.width)
 1345+ width = params.width - left;
 1346+
 1347+ if (height < 1) height = 1;
 1348+ if (top + height > params.height)
 1349+ height = params.height - top;
 1350+
 1351+ var copy = document.createElement("canvas");
 1352+ copy.width = params.width;
 1353+ copy.height = params.height;
 1354+ copy.getContext("2d").drawImage(params.canvas,0,0);
 1355+
 1356+ params.canvas.width = width;
 1357+ params.canvas.height = height;
 1358+ params.canvas.getContext("2d").clearRect(0,0,width,height);
 1359+
 1360+ params.canvas.getContext("2d").drawImage(copy,
 1361+ left,top,width,height,
 1362+ 0,0,width,height
 1363+ );
 1364+
 1365+ params.useData = false;
 1366+ return true;
 1367+ }
 1368+ },
 1369+ checkSupport : function() {
 1370+ return Pixastic.Client.hasCanvas();
 1371+ }
 1372+}
 1373+
 1374+
 1375+/*
 1376+ * Pixastic Lib - Desaturation filter - v0.1.1
 1377+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 1378+ * License: [http://www.pixastic.com/lib/license.txt]
 1379+ */
 1380+
 1381+Pixastic.Actions.desaturate = {
 1382+
 1383+ process : function(params) {
 1384+ var useAverage = !!(params.options.average && params.options.average != "false");
 1385+
 1386+ if (Pixastic.Client.hasCanvasImageData()) {
 1387+ var data = Pixastic.prepareData(params);
 1388+ var rect = params.options.rect;
 1389+ var w = rect.width;
 1390+ var h = rect.height;
 1391+
 1392+ var p = w*h;
 1393+ var pix = p*4, pix1, pix2;
 1394+
 1395+ if (useAverage) {
 1396+ while (p--)
 1397+ data[pix-=4] = data[pix1=pix+1] = data[pix2=pix+2] = (data[pix]+data[pix1]+data[pix2])/3
 1398+ } else {
 1399+ while (p--)
 1400+ data[pix-=4] = data[pix1=pix+1] = data[pix2=pix+2] = (data[pix]*0.3 + data[pix1]*0.59 + data[pix2]*0.11);
 1401+ }
 1402+ return true;
 1403+ } else if (Pixastic.Client.isIE()) {
 1404+ params.image.style.filter += " gray";
 1405+ return true;
 1406+ }
 1407+ },
 1408+ checkSupport : function() {
 1409+ return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
 1410+ }
 1411+}/*
 1412+ * Pixastic Lib - Edge detection filter - v0.1.1
 1413+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 1414+ * License: [http://www.pixastic.com/lib/license.txt]
 1415+ */
 1416+
 1417+Pixastic.Actions.edges = {
 1418+ process : function(params) {
 1419+
 1420+ var mono = !!(params.options.mono && params.options.mono != "false");
 1421+ var invert = !!(params.options.invert && params.options.invert != "false");
 1422+
 1423+ if (Pixastic.Client.hasCanvasImageData()) {
 1424+ var data = Pixastic.prepareData(params);
 1425+ var dataCopy = Pixastic.prepareData(params, true)
 1426+
 1427+ var c = -1/8;
 1428+ var kernel = [
 1429+ [c, c, c],
 1430+ [c, 1, c],
 1431+ [c, c, c]
 1432+ ];
 1433+
 1434+ weight = 1/c;
 1435+
 1436+ var rect = params.options.rect;
 1437+ var w = rect.width;
 1438+ var h = rect.height;
 1439+
 1440+ var w4 = w*4;
 1441+ var y = h;
 1442+ do {
 1443+ var offsetY = (y-1)*w4;
 1444+
 1445+ var nextY = (y == h) ? y - 1 : y;
 1446+ var prevY = (y == 1) ? 0 : y-2;
 1447+
 1448+ var offsetYPrev = prevY*w*4;
 1449+ var offsetYNext = nextY*w*4;
 1450+
 1451+ var x = w;
 1452+ do {
 1453+ var offset = offsetY + (x*4-4);
 1454+
 1455+ var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
 1456+ var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
 1457+
 1458+ var r = ((dataCopy[offsetPrev-4]
 1459+ + dataCopy[offsetPrev]
 1460+ + dataCopy[offsetPrev+4]
 1461+ + dataCopy[offset-4]
 1462+ + dataCopy[offset+4]
 1463+ + dataCopy[offsetNext-4]
 1464+ + dataCopy[offsetNext]
 1465+ + dataCopy[offsetNext+4]) * c
 1466+ + dataCopy[offset]
 1467+ )
 1468+ * weight;
 1469+
 1470+ var g = ((dataCopy[offsetPrev-3]
 1471+ + dataCopy[offsetPrev+1]
 1472+ + dataCopy[offsetPrev+5]
 1473+ + dataCopy[offset-3]
 1474+ + dataCopy[offset+5]
 1475+ + dataCopy[offsetNext-3]
 1476+ + dataCopy[offsetNext+1]
 1477+ + dataCopy[offsetNext+5]) * c
 1478+ + dataCopy[offset+1])
 1479+ * weight;
 1480+
 1481+ var b = ((dataCopy[offsetPrev-2]
 1482+ + dataCopy[offsetPrev+2]
 1483+ + dataCopy[offsetPrev+6]
 1484+ + dataCopy[offset-2]
 1485+ + dataCopy[offset+6]
 1486+ + dataCopy[offsetNext-2]
 1487+ + dataCopy[offsetNext+2]
 1488+ + dataCopy[offsetNext+6]) * c
 1489+ + dataCopy[offset+2])
 1490+ * weight;
 1491+
 1492+ if (mono) {
 1493+ var brightness = (r*0.3 + g*0.59 + b*0.11)||0;
 1494+ if (invert) brightness = 255 - brightness;
 1495+ if (brightness < 0 ) brightness = 0;
 1496+ if (brightness > 255 ) brightness = 255;
 1497+ r = g = b = brightness;
 1498+ } else {
 1499+ if (invert) {
 1500+ r = 255 - r;
 1501+ g = 255 - g;
 1502+ b = 255 - b;
 1503+ }
 1504+ if (r < 0 ) r = 0;
 1505+ if (g < 0 ) g = 0;
 1506+ if (b < 0 ) b = 0;
 1507+ if (r > 255 ) r = 255;
 1508+ if (g > 255 ) g = 255;
 1509+ if (b > 255 ) b = 255;
 1510+ }
 1511+
 1512+ data[offset] = r;
 1513+ data[offset+1] = g;
 1514+ data[offset+2] = b;
 1515+
 1516+ } while (--x);
 1517+ } while (--y);
 1518+
 1519+ return true;
 1520+ }
 1521+ },
 1522+ checkSupport : function() {
 1523+ return Pixastic.Client.hasCanvasImageData();
 1524+ }
 1525+}/*
 1526+ * Pixastic Lib - Edge detection 2 - v0.1.0
 1527+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 1528+ * License: [http://www.pixastic.com/lib/license.txt]
 1529+ *
 1530+ * Contribution by Oliver Hunt (http://nerget.com/, http://nerget.com/canvas/edgeDetection.js). Thanks Oliver!
 1531+ *
 1532+ */
 1533+
 1534+Pixastic.Actions.edges2 = {
 1535+ process : function(params) {
 1536+
 1537+ if (Pixastic.Client.hasCanvasImageData()) {
 1538+ var data = Pixastic.prepareData(params);
 1539+ var dataCopy = Pixastic.prepareData(params, true)
 1540+
 1541+ var rect = params.options.rect;
 1542+ var w = rect.width;
 1543+ var h = rect.height;
 1544+
 1545+ var w4 = w * 4;
 1546+ var pixel = w4 + 4; // Start at (1,1)
 1547+ var hm1 = h - 1;
 1548+ var wm1 = w - 1;
 1549+ for (var y = 1; y < hm1; ++y) {
 1550+ // Prepare initial cached values for current row
 1551+ var centerRow = pixel - 4;
 1552+ var priorRow = centerRow - w4;
 1553+ var nextRow = centerRow + w4;
 1554+
 1555+ var r1 = - dataCopy[priorRow] - dataCopy[centerRow] - dataCopy[nextRow];
 1556+ var g1 = - dataCopy[++priorRow] - dataCopy[++centerRow] - dataCopy[++nextRow];
 1557+ var b1 = - dataCopy[++priorRow] - dataCopy[++centerRow] - dataCopy[++nextRow];
 1558+
 1559+ var rp = dataCopy[priorRow += 2];
 1560+ var gp = dataCopy[++priorRow];
 1561+ var bp = dataCopy[++priorRow];
 1562+
 1563+ var rc = dataCopy[centerRow += 2];
 1564+ var gc = dataCopy[++centerRow];
 1565+ var bc = dataCopy[++centerRow];
 1566+
 1567+ var rn = dataCopy[nextRow += 2];
 1568+ var gn = dataCopy[++nextRow];
 1569+ var bn = dataCopy[++nextRow];
 1570+
 1571+ var r2 = - rp - rc - rn;
 1572+ var g2 = - gp - gc - gn;
 1573+ var b2 = - bp - bc - bn;
 1574+
 1575+ // Main convolution loop
 1576+ for (var x = 1; x < wm1; ++x) {
 1577+ centerRow = pixel + 4;
 1578+ priorRow = centerRow - w4;
 1579+ nextRow = centerRow + w4;
 1580+
 1581+ var r = 127 + r1 - rp - (rc * -8) - rn;
 1582+ var g = 127 + g1 - gp - (gc * -8) - gn;
 1583+ var b = 127 + b1 - bp - (bc * -8) - bn;
 1584+
 1585+ r1 = r2;
 1586+ g1 = g2;
 1587+ b1 = b2;
 1588+
 1589+ rp = dataCopy[ priorRow];
 1590+ gp = dataCopy[++priorRow];
 1591+ bp = dataCopy[++priorRow];
 1592+
 1593+ rc = dataCopy[ centerRow];
 1594+ gc = dataCopy[++centerRow];
 1595+ bc = dataCopy[++centerRow];
 1596+
 1597+ rn = dataCopy[ nextRow];
 1598+ gn = dataCopy[++nextRow];
 1599+ bn = dataCopy[++nextRow];
 1600+
 1601+ r += (r2 = - rp - rc - rn);
 1602+ g += (g2 = - gp - gc - gn);
 1603+ b += (b2 = - bp - bc - bn);
 1604+
 1605+ if (r > 255) r = 255;
 1606+ if (g > 255) g = 255;
 1607+ if (b > 255) b = 255;
 1608+ if (r < 0) r = 0;
 1609+ if (g < 0) g = 0;
 1610+ if (b < 0) b = 0;
 1611+
 1612+ data[pixel] = r;
 1613+ data[++pixel] = g;
 1614+ data[++pixel] = b;
 1615+ //data[++pixel] = 255; // alpha
 1616+
 1617+ pixel+=2;
 1618+ }
 1619+ pixel += 8;
 1620+ }
 1621+ return true;
 1622+ }
 1623+ },
 1624+ checkSupport : function() {
 1625+ return Pixastic.Client.hasCanvasImageData();
 1626+ }
 1627+}/*
 1628+ * Pixastic Lib - Emboss filter - v0.1.0
 1629+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 1630+ * License: [http://www.pixastic.com/lib/license.txt]
 1631+ */
 1632+
 1633+Pixastic.Actions.emboss = {
 1634+ process : function(params) {
 1635+
 1636+ var strength = parseFloat(params.options.strength)||1;
 1637+ var greyLevel = typeof params.options.greyLevel != "undefined" ? parseInt(params.options.greyLevel) : 180;
 1638+ var direction = params.options.direction||"topleft";
 1639+ var blend = !!(params.options.blend && params.options.blend != "false");
 1640+
 1641+ var dirY = 0;
 1642+ var dirX = 0;
 1643+
 1644+ switch (direction) {
 1645+ case "topleft": // top left
 1646+ dirY = -1;
 1647+ dirX = -1;
 1648+ break;
 1649+ case "top": // top
 1650+ dirY = -1;
 1651+ dirX = 0;
 1652+ break;
 1653+ case "topright": // top right
 1654+ dirY = -1;
 1655+ dirX = 1;
 1656+ break;
 1657+ case "right": // right
 1658+ dirY = 0;
 1659+ dirX = 1;
 1660+ break;
 1661+ case "bottomright": // bottom right
 1662+ dirY = 1;
 1663+ dirX = 1;
 1664+ break;
 1665+ case "bottom": // bottom
 1666+ dirY = 1;
 1667+ dirX = 0;
 1668+ break;
 1669+ case "bottomleft": // bottom left
 1670+ dirY = 1;
 1671+ dirX = -1;
 1672+ break;
 1673+ case "left": // left
 1674+ dirY = 0;
 1675+ dirX = -1;
 1676+ break;
 1677+ }
 1678+
 1679+ if (Pixastic.Client.hasCanvasImageData()) {
 1680+ var data = Pixastic.prepareData(params);
 1681+ var dataCopy = Pixastic.prepareData(params, true)
 1682+
 1683+ var invertAlpha = !!params.options.invertAlpha;
 1684+ var rect = params.options.rect;
 1685+ var w = rect.width;
 1686+ var h = rect.height;
 1687+
 1688+ var w4 = w*4;
 1689+ var y = h;
 1690+ do {
 1691+ var offsetY = (y-1)*w4;
 1692+
 1693+ var otherY = dirY;
 1694+ if (y + otherY < 1) otherY = 0;
 1695+ if (y + otherY > h) otherY = 0;
 1696+
 1697+ var offsetYOther = (y-1+otherY)*w*4;
 1698+
 1699+ var x = w;
 1700+ do {
 1701+ var offset = offsetY + (x-1)*4;
 1702+
 1703+ var otherX = dirX;
 1704+ if (x + otherX < 1) otherX = 0;
 1705+ if (x + otherX > w) otherX = 0;
 1706+
 1707+ var offsetOther = offsetYOther + (x-1+otherX)*4;
 1708+
 1709+ var dR = dataCopy[offset] - dataCopy[offsetOther];
 1710+ var dG = dataCopy[offset+1] - dataCopy[offsetOther+1];
 1711+ var dB = dataCopy[offset+2] - dataCopy[offsetOther+2];
 1712+
 1713+ var dif = dR;
 1714+ var absDif = dif > 0 ? dif : -dif;
 1715+
 1716+ var absG = dG > 0 ? dG : -dG;
 1717+ var absB = dB > 0 ? dB : -dB;
 1718+
 1719+ if (absG > absDif) {
 1720+ dif = dG;
 1721+ }
 1722+ if (absB > absDif) {
 1723+ dif = dB;
 1724+ }
 1725+
 1726+ dif *= strength;
 1727+
 1728+ if (blend) {
 1729+ var r = data[offset] + dif;
 1730+ var g = data[offset+1] + dif;
 1731+ var b = data[offset+2] + dif;
 1732+
 1733+ data[offset] = (r > 255) ? 255 : (r < 0 ? 0 : r);
 1734+ data[offset+1] = (g > 255) ? 255 : (g < 0 ? 0 : g);
 1735+ data[offset+2] = (b > 255) ? 255 : (b < 0 ? 0 : b);
 1736+ } else {
 1737+ var grey = greyLevel - dif;
 1738+ if (grey < 0) {
 1739+ grey = 0;
 1740+ } else if (grey > 255) {
 1741+ grey = 255;
 1742+ }
 1743+
 1744+ data[offset] = data[offset+1] = data[offset+2] = grey;
 1745+ }
 1746+
 1747+ } while (--x);
 1748+ } while (--y);
 1749+ return true;
 1750+
 1751+ } else if (Pixastic.Client.isIE()) {
 1752+ params.image.style.filter += " progid:DXImageTransform.Microsoft.emboss()";
 1753+ return true;
 1754+ }
 1755+ },
 1756+ checkSupport : function() {
 1757+ return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
 1758+ }
 1759+
 1760+}
 1761+/*
 1762+ * Pixastic Lib - Flip - v0.1.0
 1763+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 1764+ * License: [http://www.pixastic.com/lib/license.txt]
 1765+ */
 1766+
 1767+Pixastic.Actions.flip = {
 1768+ process : function(params) {
 1769+ var rect = params.options.rect;
 1770+ var copyCanvas = document.createElement("canvas");
 1771+ copyCanvas.width = rect.width;
 1772+ copyCanvas.height = rect.height;
 1773+ copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);
 1774+
 1775+ var ctx = params.canvas.getContext("2d");
 1776+ ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
 1777+
 1778+ if (params.options.axis == "horizontal") {
 1779+ ctx.scale(-1,1);
 1780+ ctx.drawImage(copyCanvas, -rect.left-rect.width, rect.top, rect.width, rect.height)
 1781+ } else {
 1782+ ctx.scale(1,-1);
 1783+ ctx.drawImage(copyCanvas, rect.left, -rect.top-rect.height, rect.width, rect.height)
 1784+ }
 1785+
 1786+ params.useData = false;
 1787+
 1788+ return true;
 1789+ },
 1790+ checkSupport : function() {
 1791+ return Pixastic.Client.hasCanvas();
 1792+ }
 1793+}
 1794+
 1795+/*
 1796+ * Pixastic Lib - Horizontal flip - v0.1.0
 1797+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 1798+ * License: [http://www.pixastic.com/lib/license.txt]
 1799+ */
 1800+
 1801+Pixastic.Actions.fliph = {
 1802+ process : function(params) {
 1803+ if (Pixastic.Client.hasCanvas()) {
 1804+ var rect = params.options.rect;
 1805+ var copyCanvas = document.createElement("canvas");
 1806+ copyCanvas.width = rect.width;
 1807+ copyCanvas.height = rect.height;
 1808+ copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);
 1809+
 1810+ var ctx = params.canvas.getContext("2d");
 1811+ ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
 1812+ ctx.scale(-1,1);
 1813+ ctx.drawImage(copyCanvas, -rect.left-rect.width, rect.top, rect.width, rect.height)
 1814+ params.useData = false;
 1815+
 1816+ return true;
 1817+
 1818+ } else if (Pixastic.Client.isIE()) {
 1819+ params.image.style.filter += " fliph";
 1820+ return true;
 1821+ }
 1822+ },
 1823+ checkSupport : function() {
 1824+ return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
 1825+ }
 1826+}
 1827+
 1828+/*
 1829+ * Pixastic Lib - Vertical flip - v0.1.0
 1830+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 1831+ * License: [http://www.pixastic.com/lib/license.txt]
 1832+ */
 1833+
 1834+Pixastic.Actions.flipv = {
 1835+ process : function(params) {
 1836+ if (Pixastic.Client.hasCanvas()) {
 1837+ var rect = params.options.rect;
 1838+ var copyCanvas = document.createElement("canvas");
 1839+ copyCanvas.width = rect.width;
 1840+ copyCanvas.height = rect.height;
 1841+ copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);
 1842+
 1843+ var ctx = params.canvas.getContext("2d");
 1844+ ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
 1845+ ctx.scale(1,-1);
 1846+ ctx.drawImage(copyCanvas, rect.left, -rect.top-rect.height, rect.width, rect.height)
 1847+ params.useData = false;
 1848+
 1849+ return true;
 1850+
 1851+ } else if (Pixastic.Client.isIE()) {
 1852+ params.image.style.filter += " flipv";
 1853+ return true;
 1854+ }
 1855+ },
 1856+ checkSupport : function() {
 1857+ return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
 1858+ }
 1859+}
 1860+
 1861+/*
 1862+ * Pixastic Lib - Glow - v0.1.0
 1863+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 1864+ * License: [http://www.pixastic.com/lib/license.txt]
 1865+ */
 1866+
 1867+
 1868+Pixastic.Actions.glow = {
 1869+ process : function(params) {
 1870+
 1871+ var amount = (parseFloat(params.options.amount)||0);
 1872+ var blurAmount = parseFloat(params.options.radius)||0;
 1873+
 1874+ amount = Math.min(1,Math.max(0,amount));
 1875+ blurAmount = Math.min(5,Math.max(0,blurAmount));
 1876+
 1877+ if (Pixastic.Client.hasCanvasImageData()) {
 1878+ var rect = params.options.rect;
 1879+
 1880+ var blurCanvas = document.createElement("canvas");
 1881+ blurCanvas.width = params.width;
 1882+ blurCanvas.height = params.height;
 1883+ var blurCtx = blurCanvas.getContext("2d");
 1884+ blurCtx.drawImage(params.canvas,0,0);
 1885+
 1886+ var scale = 2;
 1887+ var smallWidth = Math.round(params.width / scale);
 1888+ var smallHeight = Math.round(params.height / scale);
 1889+
 1890+ var copy = document.createElement("canvas");
 1891+ copy.width = smallWidth;
 1892+ copy.height = smallHeight;
 1893+
 1894+ var clear = true;
 1895+ var steps = Math.round(blurAmount * 20);
 1896+
 1897+ var copyCtx = copy.getContext("2d");
 1898+ for (var i=0;i<steps;i++) {
 1899+ var scaledWidth = Math.max(1,Math.round(smallWidth - i));
 1900+ var scaledHeight = Math.max(1,Math.round(smallHeight - i));
 1901+
 1902+ copyCtx.clearRect(0,0,smallWidth,smallHeight);
 1903+
 1904+ copyCtx.drawImage(
 1905+ blurCanvas,
 1906+ 0,0,params.width,params.height,
 1907+ 0,0,scaledWidth,scaledHeight
 1908+ );
 1909+
 1910+ blurCtx.clearRect(0,0,params.width,params.height);
 1911+
 1912+ blurCtx.drawImage(
 1913+ copy,
 1914+ 0,0,scaledWidth,scaledHeight,
 1915+ 0,0,params.width,params.height
 1916+ );
 1917+ }
 1918+
 1919+ var data = Pixastic.prepareData(params);
 1920+ var blurData = Pixastic.prepareData({canvas:blurCanvas,options:params.options});
 1921+ var w = rect.width;
 1922+ var h = rect.height;
 1923+ var w4 = w*4;
 1924+ var y = h;
 1925+ do {
 1926+ var offsetY = (y-1)*w4;
 1927+ var x = w;
 1928+ do {
 1929+ var offset = offsetY + (x*4-4);
 1930+
 1931+ var r = data[offset] + amount * blurData[offset];
 1932+ var g = data[offset+1] + amount * blurData[offset+1];
 1933+ var b = data[offset+2] + amount * blurData[offset+2];
 1934+
 1935+ if (r > 255) r = 255;
 1936+ if (g > 255) g = 255;
 1937+ if (b > 255) b = 255;
 1938+ if (r < 0) r = 0;
 1939+ if (g < 0) g = 0;
 1940+ if (b < 0) b = 0;
 1941+
 1942+ data[offset] = r;
 1943+ data[offset+1] = g;
 1944+ data[offset+2] = b;
 1945+
 1946+ } while (--x);
 1947+ } while (--y);
 1948+
 1949+ return true;
 1950+ }
 1951+ },
 1952+ checkSupport : function() {
 1953+ return Pixastic.Client.hasCanvasImageData();
 1954+ }
 1955+}
 1956+
 1957+
 1958+
 1959+/*
 1960+ * Pixastic Lib - Histogram - v0.1.0
 1961+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 1962+ * License: [http://www.pixastic.com/lib/license.txt]
 1963+ */
 1964+
 1965+Pixastic.Actions.histogram = {
 1966+ process : function(params) {
 1967+
 1968+ var average = !!(params.options.average && params.options.average != "false");
 1969+ var paint = !!(params.options.paint && params.options.paint != "false");
 1970+ var color = params.options.color || "rgba(255,255,255,0.5)";
 1971+ var values = [];
 1972+ if (typeof params.options.returnValue != "object") {
 1973+ params.options.returnValue = {values:[]};
 1974+ }
 1975+ var returnValue = params.options.returnValue;
 1976+ if (typeof returnValue.values != "array") {
 1977+ returnValue.values = [];
 1978+ }
 1979+ values = returnValue.values;
 1980+
 1981+ if (Pixastic.Client.hasCanvasImageData()) {
 1982+ var data = Pixastic.prepareData(params);
 1983+ params.useData = false;
 1984+
 1985+ for (var i=0;i<256;i++) {
 1986+ values[i] = 0;
 1987+ }
 1988+
 1989+ var rect = params.options.rect;
 1990+ var w = rect.width;
 1991+ var h = rect.height;
 1992+ var w4 = w*4;
 1993+ var y = h;
 1994+ do {
 1995+ var offsetY = (y-1)*w4;
 1996+ var x = w;
 1997+ do {
 1998+ var offset = offsetY + (x*4-4);
 1999+ var brightness = average ?
 2000+ Math.round((data[offset]+data[offset+1]+data[offset+2])/3)
 2001+ : Math.round(data[offset]*0.3 + data[offset+1]*0.59 + data[offset+2]*0.11);
 2002+ values[brightness]++;
 2003+
 2004+ } while (--x);
 2005+ } while (--y);
 2006+
 2007+ if (paint) {
 2008+ var maxValue = 0;
 2009+ for (var i=0;i<256;i++) {
 2010+ if (values[i] > maxValue) {
 2011+ maxValue = values[i];
 2012+ }
 2013+ }
 2014+ var heightScale = params.height / maxValue;
 2015+ var widthScale = params.width / 256;
 2016+ var ctx = params.canvas.getContext("2d");
 2017+ ctx.fillStyle = color;
 2018+ for (var i=0;i<256;i++) {
 2019+ ctx.fillRect(
 2020+ i * widthScale, params.height - heightScale * values[i],
 2021+ widthScale, values[i] * heightScale
 2022+ );
 2023+ }
 2024+ }
 2025+
 2026+ returnValue.values = values;
 2027+
 2028+ return true;
 2029+ }
 2030+ },
 2031+ checkSupport : function() {
 2032+ return Pixastic.Client.hasCanvasImageData();
 2033+ }
 2034+}
 2035+/*
 2036+ * Pixastic Lib - HSL Adjust - v0.1.0
 2037+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 2038+ * License: [http://www.pixastic.com/lib/license.txt]
 2039+ */
 2040+
 2041+Pixastic.Actions.hsl = {
 2042+ process : function(params) {
 2043+
 2044+ var hue = parseInt(params.options.hue,10)||0;
 2045+ var saturation = (parseInt(params.options.saturation,10)||0) / 100;
 2046+ var lightness = (parseInt(params.options.lightness,10)||0) / 100;
 2047+
 2048+
 2049+ // this seems to give the same result as Photoshop
 2050+ if (saturation < 0) {
 2051+ var satMul = 1+saturation;
 2052+ } else {
 2053+ var satMul = 1+saturation*2;
 2054+ }
 2055+
 2056+ hue = (hue%360) / 360;
 2057+ var hue6 = hue * 6;
 2058+
 2059+ var rgbDiv = 1 / 255;
 2060+
 2061+ var light255 = lightness * 255;
 2062+ var lightp1 = 1 + lightness;
 2063+ var lightm1 = 1 - lightness;
 2064+ if (Pixastic.Client.hasCanvasImageData()) {
 2065+ var data = Pixastic.prepareData(params);
 2066+
 2067+ var rect = params.options.rect;
 2068+ var w = rect.width;
 2069+ var h = rect.height;
 2070+
 2071+ var w4 = w*4;
 2072+ var y = h;
 2073+
 2074+ do {
 2075+ var offsetY = (y-1)*w4;
 2076+ var x = w;
 2077+ do {
 2078+ var offset = offsetY + (x*4-4);
 2079+
 2080+ var r = data[offset];
 2081+ var g = data[offset+1];
 2082+ var b = data[offset+2];
 2083+
 2084+ if (hue != 0 || saturation != 0) {
 2085+ // ok, here comes rgb to hsl + adjust + hsl to rgb, all in one jumbled mess.
 2086+ // It's not so pretty, but it's been optimized to get somewhat decent performance.
 2087+ // The transforms were originally adapted from the ones found in Graphics Gems, but have been heavily modified.
 2088+ var vs = r;
 2089+ if (g > vs) vs = g;
 2090+ if (b > vs) vs = b;
 2091+ var ms = r;
 2092+ if (g < ms) ms = g;
 2093+ if (b < ms) ms = b;
 2094+ var vm = (vs-ms);
 2095+ var l = (ms+vs)/255 * 0.5;
 2096+ if (l > 0) {
 2097+ if (vm > 0) {
 2098+ if (l <= 0.5) {
 2099+ var s = vm / (vs+ms) * satMul;
 2100+ if (s > 1) s = 1;
 2101+ var v = (l * (1+s));
 2102+ } else {
 2103+ var s = vm / (510-vs-ms) * satMul;
 2104+ if (s > 1) s = 1;
 2105+ var v = (l+s - l*s);
 2106+ }
 2107+ if (r == vs) {
 2108+ if (g == ms)
 2109+ var h = 5 + ((vs-b)/vm) + hue6;
 2110+ else
 2111+ var h = 1 - ((vs-g)/vm) + hue6;
 2112+ } else if (g == vs) {
 2113+ if (b == ms)
 2114+ var h = 1 + ((vs-r)/vm) + hue6;
 2115+ else
 2116+ var h = 3 - ((vs-b)/vm) + hue6;
 2117+ } else {
 2118+ if (r == ms)
 2119+ var h = 3 + ((vs-g)/vm) + hue6;
 2120+ else
 2121+ var h = 5 - ((vs-r)/vm) + hue6;
 2122+ }
 2123+ if (h < 0) h+=6;
 2124+ if (h >= 6) h-=6;
 2125+ var m = (l+l-v);
 2126+ var sextant = h>>0;
 2127+ switch (sextant) {
 2128+ case 0: r = v*255; g = (m+((v-m)*(h-sextant)))*255; b = m*255; break;
 2129+ case 1: r = (v-((v-m)*(h-sextant)))*255; g = v*255; b = m*255; break;
 2130+ case 2: r = m*255; g = v*255; b = (m+((v-m)*(h-sextant)))*255; break;
 2131+ case 3: r = m*255; g = (v-((v-m)*(h-sextant)))*255; b = v*255; break;
 2132+ case 4: r = (m+((v-m)*(h-sextant)))*255; g = m*255; b = v*255; break;
 2133+ case 5: r = v*255; g = m*255; b = (v-((v-m)*(h-sextant)))*255; break;
 2134+ }
 2135+ }
 2136+ }
 2137+ }
 2138+
 2139+ if (lightness < 0) {
 2140+ r *= lightp1;
 2141+ g *= lightp1;
 2142+ b *= lightp1;
 2143+ } else if (lightness > 0) {
 2144+ r = r * lightm1 + light255;
 2145+ g = g * lightm1 + light255;
 2146+ b = b * lightm1 + light255;
 2147+ }
 2148+
 2149+ if (r < 0) r = 0;
 2150+ if (g < 0) g = 0;
 2151+ if (b < 0) b = 0;
 2152+ if (r > 255) r = 255;
 2153+ if (g > 255) g = 255;
 2154+ if (b > 255) b = 255;
 2155+
 2156+ data[offset] = r;
 2157+ data[offset+1] = g;
 2158+ data[offset+2] = b;
 2159+
 2160+ } while (--x);
 2161+ } while (--y);
 2162+ return true;
 2163+ }
 2164+ },
 2165+ checkSupport : function() {
 2166+ return Pixastic.Client.hasCanvasImageData();
 2167+ }
 2168+
 2169+}
 2170+/*
 2171+ * Pixastic Lib - Invert filter - v0.1.0
 2172+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 2173+ * License: [http://www.pixastic.com/lib/license.txt]
 2174+ */
 2175+
 2176+Pixastic.Actions.invert = {
 2177+ process : function(params) {
 2178+ if (Pixastic.Client.hasCanvasImageData()) {
 2179+ var data = Pixastic.prepareData(params);
 2180+
 2181+ var invertAlpha = !!params.options.invertAlpha;
 2182+ var rect = params.options.rect;
 2183+ var w = rect.width;
 2184+ var h = rect.height;
 2185+
 2186+ var w4 = w*4;
 2187+ var y = h;
 2188+ do {
 2189+ var offsetY = (y-1)*w4;
 2190+ var x = w;
 2191+ do {
 2192+ var offset = offsetY + (x-1)*4;
 2193+ data[offset] = 255 - data[offset];
 2194+ data[offset+1] = 255 - data[offset+1];
 2195+ data[offset+2] = 255 - data[offset+2];
 2196+ if (invertAlpha) data[offset+3] = 255 - data[offset+3];
 2197+ } while (--x);
 2198+ } while (--y);
 2199+
 2200+ return true;
 2201+ } else if (Pixastic.Client.isIE()) {
 2202+ params.image.style.filter += " invert";
 2203+ return true;
 2204+ }
 2205+ },
 2206+ checkSupport : function() {
 2207+ return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
 2208+ }
 2209+}
 2210+/*
 2211+ * Pixastic Lib - Laplace filter - v0.1.0
 2212+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 2213+ * License: [http://www.pixastic.com/lib/license.txt]
 2214+ */
 2215+
 2216+Pixastic.Actions.laplace = {
 2217+ process : function(params) {
 2218+
 2219+ var strength = 1.0;
 2220+ var invert = !!(params.options.invert && params.options.invert != "false");
 2221+ var contrast = parseFloat(params.options.edgeStrength)||0;
 2222+
 2223+ var greyLevel = parseInt(params.options.greyLevel)||0;
 2224+
 2225+ contrast = -contrast;
 2226+
 2227+ if (Pixastic.Client.hasCanvasImageData()) {
 2228+ var data = Pixastic.prepareData(params);
 2229+ var dataCopy = Pixastic.prepareData(params, true)
 2230+
 2231+ var kernel = [
 2232+ [-1, -1, -1],
 2233+ [-1, 8, -1],
 2234+ [-1, -1, -1]
 2235+ ];
 2236+
 2237+ var weight = 1/8;
 2238+
 2239+ var rect = params.options.rect;
 2240+ var w = rect.width;
 2241+ var h = rect.height;
 2242+
 2243+ var w4 = w*4;
 2244+ var y = h;
 2245+ do {
 2246+ var offsetY = (y-1)*w4;
 2247+
 2248+ var nextY = (y == h) ? y - 1 : y;
 2249+ var prevY = (y == 1) ? 0 : y-2;
 2250+
 2251+ var offsetYPrev = prevY*w*4;
 2252+ var offsetYNext = nextY*w*4;
 2253+
 2254+ var x = w;
 2255+ do {
 2256+ var offset = offsetY + (x*4-4);
 2257+
 2258+ var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
 2259+ var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
 2260+
 2261+ var r = ((-dataCopy[offsetPrev-4]
 2262+ - dataCopy[offsetPrev]
 2263+ - dataCopy[offsetPrev+4]
 2264+ - dataCopy[offset-4]
 2265+ - dataCopy[offset+4]
 2266+ - dataCopy[offsetNext-4]
 2267+ - dataCopy[offsetNext]
 2268+ - dataCopy[offsetNext+4])
 2269+ + dataCopy[offset] * 8)
 2270+ * weight;
 2271+
 2272+ var g = ((-dataCopy[offsetPrev-3]
 2273+ - dataCopy[offsetPrev+1]
 2274+ - dataCopy[offsetPrev+5]
 2275+ - dataCopy[offset-3]
 2276+ - dataCopy[offset+5]
 2277+ - dataCopy[offsetNext-3]
 2278+ - dataCopy[offsetNext+1]
 2279+ - dataCopy[offsetNext+5])
 2280+ + dataCopy[offset+1] * 8)
 2281+ * weight;
 2282+
 2283+ var b = ((-dataCopy[offsetPrev-2]
 2284+ - dataCopy[offsetPrev+2]
 2285+ - dataCopy[offsetPrev+6]
 2286+ - dataCopy[offset-2]
 2287+ - dataCopy[offset+6]
 2288+ - dataCopy[offsetNext-2]
 2289+ - dataCopy[offsetNext+2]
 2290+ - dataCopy[offsetNext+6])
 2291+ + dataCopy[offset+2] * 8)
 2292+ * weight;
 2293+
 2294+ var brightness = ((r + g + b)/3) + greyLevel;
 2295+
 2296+ if (contrast != 0) {
 2297+ if (brightness > 127) {
 2298+ brightness += ((brightness + 1) - 128) * contrast;
 2299+ } else if (brightness < 127) {
 2300+ brightness -= (brightness + 1) * contrast;
 2301+ }
 2302+ }
 2303+ if (invert) {
 2304+ brightness = 255 - brightness;
 2305+ }
 2306+ if (brightness < 0 ) brightness = 0;
 2307+ if (brightness > 255 ) brightness = 255;
 2308+
 2309+ data[offset] = data[offset+1] = data[offset+2] = brightness;
 2310+
 2311+ } while (--x);
 2312+ } while (--y);
 2313+
 2314+ return true;
 2315+ }
 2316+ },
 2317+ checkSupport : function() {
 2318+ return Pixastic.Client.hasCanvasImageData();
 2319+ }
 2320+}
 2321+
 2322+/*
 2323+ * Pixastic Lib - Lighten filter - v0.1.0
 2324+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 2325+ * License: [http://www.pixastic.com/lib/license.txt]
 2326+ */
 2327+
 2328+Pixastic.Actions.lighten = {
 2329+
 2330+ process : function(params) {
 2331+ var amount = parseFloat(params.options.amount) || 0;
 2332+
 2333+ if (Pixastic.Client.hasCanvasImageData()) {
 2334+ var data = Pixastic.prepareData(params);
 2335+ var rect = params.options.rect;
 2336+ var w = rect.width;
 2337+ var h = rect.height;
 2338+ var w4 = w*4;
 2339+ var y = h;
 2340+ do {
 2341+ var offsetY = (y-1)*w4;
 2342+ var x = w;
 2343+ do {
 2344+ var offset = offsetY + (x-1)*4;
 2345+
 2346+ var r = data[offset];
 2347+ var g = data[offset+1];
 2348+ var b = data[offset+2];
 2349+
 2350+ r += r*amount;
 2351+ g += g*amount;
 2352+ b += b*amount;
 2353+
 2354+ if (r < 0 ) r = 0;
 2355+ if (g < 0 ) g = 0;
 2356+ if (b < 0 ) b = 0;
 2357+ if (r > 255 ) r = 255;
 2358+ if (g > 255 ) g = 255;
 2359+ if (b > 255 ) b = 255;
 2360+
 2361+ data[offset] = r;
 2362+ data[offset+1] = g;
 2363+ data[offset+2] = b;
 2364+
 2365+ } while (--x);
 2366+ } while (--y);
 2367+ return true;
 2368+
 2369+ } else if (Pixastic.Client.isIE()) {
 2370+ var img = params.image;
 2371+ if (amount < 0) {
 2372+ img.style.filter += " light()";
 2373+ img.filters[img.filters.length-1].addAmbient(
 2374+ 255,255,255,
 2375+ 100 * -amount
 2376+ );
 2377+ } else if (amount > 0) {
 2378+ img.style.filter += " light()";
 2379+ img.filters[img.filters.length-1].addAmbient(
 2380+ 255,255,255,
 2381+ 100
 2382+ );
 2383+ img.filters[img.filters.length-1].addAmbient(
 2384+ 255,255,255,
 2385+ 100 * amount
 2386+ );
 2387+ }
 2388+ return true;
 2389+ }
 2390+ },
 2391+ checkSupport : function() {
 2392+ return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
 2393+ }
 2394+}
 2395+/*
 2396+ * Pixastic Lib - Mosaic filter - v0.1.0
 2397+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 2398+ * License: [http://www.pixastic.com/lib/license.txt]
 2399+ */
 2400+
 2401+Pixastic.Actions.mosaic = {
 2402+
 2403+ process : function(params) {
 2404+ var blockSize = Math.max(1,parseInt(params.options.blockSize,10));
 2405+
 2406+ if (Pixastic.Client.hasCanvasImageData()) {
 2407+ var rect = params.options.rect;
 2408+ var w = rect.width;
 2409+ var h = rect.height;
 2410+ var w4 = w*4;
 2411+ var y = h;
 2412+
 2413+ var ctx = params.canvas.getContext("2d");
 2414+
 2415+ var pixel = document.createElement("canvas");
 2416+ pixel.width = pixel.height = 1;
 2417+ var pixelCtx = pixel.getContext("2d");
 2418+
 2419+ var copy = document.createElement("canvas");
 2420+ copy.width = w;
 2421+ copy.height = h;
 2422+ var copyCtx = copy.getContext("2d");
 2423+ copyCtx.drawImage(params.canvas,rect.left,rect.top,w,h, 0,0,w,h);
 2424+
 2425+ for (var y=0;y<h;y+=blockSize) {
 2426+ for (var x=0;x<w;x+=blockSize) {
 2427+ var blockSizeX = blockSize;
 2428+ var blockSizeY = blockSize;
 2429+
 2430+ if (blockSizeX + x > w)
 2431+ blockSizeX = w - x;
 2432+ if (blockSizeY + y > h)
 2433+ blockSizeY = h - y;
 2434+
 2435+ pixelCtx.drawImage(copy, x, y, blockSizeX, blockSizeY, 0, 0, 1, 1);
 2436+ var data = pixelCtx.getImageData(0,0,1,1).data;
 2437+ ctx.fillStyle = "rgb(" + data[0] + "," + data[1] + "," + data[2] + ")";
 2438+ ctx.fillRect(rect.left + x, rect.top + y, blockSize, blockSize);
 2439+ }
 2440+ }
 2441+ params.useData = false;
 2442+
 2443+ return true;
 2444+ }
 2445+ },
 2446+ checkSupport : function() {
 2447+ return (Pixastic.Client.hasCanvasImageData());
 2448+ }
 2449+}/*
 2450+ * Pixastic Lib - Noise filter - v0.1.0
 2451+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 2452+ * License: [http://www.pixastic.com/lib/license.txt]
 2453+ */
 2454+
 2455+Pixastic.Actions.noise = {
 2456+
 2457+ process : function(params) {
 2458+ var amount = 0;
 2459+ var strength = 0;
 2460+ var mono = false;
 2461+
 2462+ if (typeof params.options.amount != "undefined")
 2463+ amount = parseFloat(params.options.amount)||0;
 2464+ if (typeof params.options.strength != "undefined")
 2465+ strength = parseFloat(params.options.strength)||0;
 2466+ if (typeof params.options.mono != "undefined")
 2467+ mono = !!(params.options.mono && params.options.mono != "false");
 2468+
 2469+ amount = Math.max(0,Math.min(1,amount));
 2470+ strength = Math.max(0,Math.min(1,strength));
 2471+
 2472+ var noise = 128 * strength;
 2473+ var noise2 = noise / 2;
 2474+
 2475+ if (Pixastic.Client.hasCanvasImageData()) {
 2476+ var data = Pixastic.prepareData(params);
 2477+ var rect = params.options.rect;
 2478+ var w = rect.width;
 2479+ var h = rect.height;
 2480+ var w4 = w*4;
 2481+ var y = h;
 2482+ var random = Math.random;
 2483+
 2484+ do {
 2485+ var offsetY = (y-1)*w4;
 2486+ var x = w;
 2487+ do {
 2488+ var offset = offsetY + (x-1)*4;
 2489+ if (random() < amount) {
 2490+ if (mono) {
 2491+ var pixelNoise = - noise2 + random() * noise;
 2492+ var r = data[offset] + pixelNoise;
 2493+ var g = data[offset+1] + pixelNoise;
 2494+ var b = data[offset+2] + pixelNoise;
 2495+ } else {
 2496+ var r = data[offset] - noise2 + (random() * noise);
 2497+ var g = data[offset+1] - noise2 + (random() * noise);
 2498+ var b = data[offset+2] - noise2 + (random() * noise);
 2499+ }
 2500+
 2501+ if (r < 0 ) r = 0;
 2502+ if (g < 0 ) g = 0;
 2503+ if (b < 0 ) b = 0;
 2504+ if (r > 255 ) r = 255;
 2505+ if (g > 255 ) g = 255;
 2506+ if (b > 255 ) b = 255;
 2507+
 2508+ data[offset] = r;
 2509+ data[offset+1] = g;
 2510+ data[offset+2] = b;
 2511+ }
 2512+ } while (--x);
 2513+ } while (--y);
 2514+ return true;
 2515+ }
 2516+ },
 2517+ checkSupport : function() {
 2518+ return Pixastic.Client.hasCanvasImageData();
 2519+ }
 2520+}
 2521+
 2522+/*
 2523+ * Pixastic Lib - Posterize effect - v0.1.0
 2524+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 2525+ * License: [http://www.pixastic.com/lib/license.txt]
 2526+ */
 2527+
 2528+Pixastic.Actions.posterize = {
 2529+
 2530+ process : function(params) {
 2531+
 2532+
 2533+ var numLevels = 256;
 2534+ if (typeof params.options.levels != "undefined")
 2535+ numLevels = parseInt(params.options.levels,10)||1;
 2536+
 2537+ if (Pixastic.Client.hasCanvasImageData()) {
 2538+ var data = Pixastic.prepareData(params);
 2539+
 2540+ numLevels = Math.max(2,Math.min(256,numLevels));
 2541+
 2542+ var numAreas = 256 / numLevels;
 2543+ var numValues = 256 / (numLevels-1);
 2544+
 2545+ var rect = params.options.rect;
 2546+ var w = rect.width;
 2547+ var h = rect.height;
 2548+ var w4 = w*4;
 2549+ var y = h;
 2550+ do {
 2551+ var offsetY = (y-1)*w4;
 2552+ var x = w;
 2553+ do {
 2554+ var offset = offsetY + (x-1)*4;
 2555+
 2556+ var r = numValues * ((data[offset] / numAreas)>>0);
 2557+ var g = numValues * ((data[offset+1] / numAreas)>>0);
 2558+ var b = numValues * ((data[offset+2] / numAreas)>>0);
 2559+
 2560+ if (r > 255) r = 255;
 2561+ if (g > 255) g = 255;
 2562+ if (b > 255) b = 255;
 2563+
 2564+ data[offset] = r;
 2565+ data[offset+1] = g;
 2566+ data[offset+2] = b;
 2567+
 2568+ } while (--x);
 2569+ } while (--y);
 2570+ return true;
 2571+ }
 2572+ },
 2573+ checkSupport : function() {
 2574+ return Pixastic.Client.hasCanvasImageData();
 2575+ }
 2576+}
 2577+
 2578+
 2579+/*
 2580+ * Pixastic Lib - Pointillize filter - v0.1.0
 2581+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 2582+ * License: [http://www.pixastic.com/lib/license.txt]
 2583+ */
 2584+
 2585+Pixastic.Actions.pointillize = {
 2586+
 2587+ process : function(params) {
 2588+ var radius = Math.max(1,parseInt(params.options.radius,10));
 2589+ var density = Math.min(5,Math.max(0,parseFloat(params.options.density)||0));
 2590+ var noise = Math.max(0,parseFloat(params.options.noise)||0);
 2591+ var transparent = !!(params.options.transparent && params.options.transparent != "false");
 2592+
 2593+ if (Pixastic.Client.hasCanvasImageData()) {
 2594+ var rect = params.options.rect;
 2595+ var w = rect.width;
 2596+ var h = rect.height;
 2597+ var w4 = w*4;
 2598+ var y = h;
 2599+
 2600+ var ctx = params.canvas.getContext("2d");
 2601+ var canvasWidth = params.canvas.width;
 2602+ var canvasHeight = params.canvas.height;
 2603+
 2604+ var pixel = document.createElement("canvas");
 2605+ pixel.width = pixel.height = 1;
 2606+ var pixelCtx = pixel.getContext("2d");
 2607+
 2608+ var copy = document.createElement("canvas");
 2609+ copy.width = w;
 2610+ copy.height = h;
 2611+ var copyCtx = copy.getContext("2d");
 2612+ copyCtx.drawImage(params.canvas,rect.left,rect.top,w,h, 0,0,w,h);
 2613+
 2614+ var diameter = radius * 2;
 2615+
 2616+ if (transparent)
 2617+ ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
 2618+
 2619+ var noiseRadius = radius * noise;
 2620+
 2621+ var dist = 1 / density;
 2622+
 2623+ for (var y=0;y<h+radius;y+=diameter*dist) {
 2624+ for (var x=0;x<w+radius;x+=diameter*dist) {
 2625+ rndX = noise ? (x+((Math.random()*2-1) * noiseRadius))>>0 : x;
 2626+ rndY = noise ? (y+((Math.random()*2-1) * noiseRadius))>>0 : y;
 2627+
 2628+ var pixX = rndX - radius;
 2629+ var pixY = rndY - radius;
 2630+ if (pixX < 0) pixX = 0;
 2631+ if (pixY < 0) pixY = 0;
 2632+
 2633+ var cx = rndX + rect.left;
 2634+ var cy = rndY + rect.top;
 2635+ if (cx < 0) cx = 0;
 2636+ if (cx > canvasWidth) cx = canvasWidth;
 2637+ if (cy < 0) cy = 0;
 2638+ if (cy > canvasHeight) cy = canvasHeight;
 2639+
 2640+ var diameterX = diameter;
 2641+ var diameterY = diameter;
 2642+
 2643+ if (diameterX + pixX > w)
 2644+ diameterX = w - pixX;
 2645+ if (diameterY + pixY > h)
 2646+ diameterY = h - pixY;
 2647+ if (diameterX < 1) diameterX = 1;
 2648+ if (diameterY < 1) diameterY = 1;
 2649+
 2650+ pixelCtx.drawImage(copy, pixX, pixY, diameterX, diameterY, 0, 0, 1, 1);
 2651+ var data = pixelCtx.getImageData(0,0,1,1).data;
 2652+
 2653+ ctx.fillStyle = "rgb(" + data[0] + "," + data[1] + "," + data[2] + ")";
 2654+ ctx.beginPath();
 2655+ ctx.arc(cx, cy, radius, 0, Math.PI*2, true);
 2656+ ctx.closePath();
 2657+ ctx.fill();
 2658+ }
 2659+ }
 2660+
 2661+ params.useData = false;
 2662+
 2663+ return true;
 2664+ }
 2665+ },
 2666+ checkSupport : function() {
 2667+ return (Pixastic.Client.hasCanvasImageData());
 2668+ }
 2669+}/*
 2670+ * Pixastic Lib - Resize - v0.1.0
 2671+ * Copyright (c) 2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 2672+ * License: [http://www.pixastic.com/lib/license.txt]
 2673+ */
 2674+
 2675+Pixastic.Actions.resize = {
 2676+ process : function(params) {
 2677+ if (Pixastic.Client.hasCanvas()) {
 2678+ var width = parseInt(params.options.width,10);
 2679+ var height = parseInt(params.options.height,10);
 2680+ var canvas = params.canvas;
 2681+
 2682+ if (width < 1) width = 1;
 2683+ if (width < 2) width = 2;
 2684+
 2685+ var copy = document.createElement("canvas");
 2686+ copy.width = width;
 2687+ copy.height = height;
 2688+
 2689+ copy.getContext("2d").drawImage(canvas,0,0,width,height);
 2690+ canvas.width = width;
 2691+ canvas.height = height;
 2692+
 2693+ canvas.getContext("2d").drawImage(copy,0,0);
 2694+
 2695+ params.useData = false;
 2696+ return true;
 2697+ }
 2698+ },
 2699+ checkSupport : function() {
 2700+ return Pixastic.Client.hasCanvas();
 2701+ }
 2702+}
 2703+
 2704+
 2705+/*
 2706+ * Pixastic Lib - Remove noise - v0.1.0
 2707+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 2708+ * License: [http://www.pixastic.com/lib/license.txt]
 2709+ */
 2710+
 2711+Pixastic.Actions.removenoise = {
 2712+ process : function(params) {
 2713+
 2714+ if (Pixastic.Client.hasCanvasImageData()) {
 2715+ var data = Pixastic.prepareData(params);
 2716+
 2717+ var rect = params.options.rect;
 2718+ var w = rect.width;
 2719+ var h = rect.height;
 2720+
 2721+ var w4 = w*4;
 2722+ var y = h;
 2723+ do {
 2724+ var offsetY = (y-1)*w4;
 2725+
 2726+ var nextY = (y == h) ? y - 1 : y;
 2727+ var prevY = (y == 1) ? 0 : y-2;
 2728+
 2729+ var offsetYPrev = prevY*w*4;
 2730+ var offsetYNext = nextY*w*4;
 2731+
 2732+ var x = w;
 2733+ do {
 2734+ var offset = offsetY + (x*4-4);
 2735+
 2736+ var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
 2737+ var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
 2738+
 2739+ var minR, maxR, minG, maxG, minB, maxB;
 2740+
 2741+ minR = maxR = data[offsetPrev];
 2742+ var r1 = data[offset-4], r2 = data[offset+4], r3 = data[offsetNext];
 2743+ if (r1 < minR) minR = r1;
 2744+ if (r2 < minR) minR = r2;
 2745+ if (r3 < minR) minR = r3;
 2746+ if (r1 > maxR) maxR = r1;
 2747+ if (r2 > maxR) maxR = r2;
 2748+ if (r3 > maxR) maxR = r3;
 2749+
 2750+ minG = maxG = data[offsetPrev+1];
 2751+ var g1 = data[offset-3], g2 = data[offset+5], g3 = data[offsetNext+1];
 2752+ if (g1 < minG) minG = g1;
 2753+ if (g2 < minG) minG = g2;
 2754+ if (g3 < minG) minG = g3;
 2755+ if (g1 > maxG) maxG = g1;
 2756+ if (g2 > maxG) maxG = g2;
 2757+ if (g3 > maxG) maxG = g3;
 2758+
 2759+ minB = maxB = data[offsetPrev+2];
 2760+ var b1 = data[offset-2], b2 = data[offset+6], b3 = data[offsetNext+2];
 2761+ if (b1 < minB) minB = b1;
 2762+ if (b2 < minB) minB = b2;
 2763+ if (b3 < minB) minB = b3;
 2764+ if (b1 > maxB) maxB = b1;
 2765+ if (b2 > maxB) maxB = b2;
 2766+ if (b3 > maxB) maxB = b3;
 2767+
 2768+ if (data[offset] > maxR) {
 2769+ data[offset] = maxR;
 2770+ } else if (data[offset] < minR) {
 2771+ data[offset] = minR;
 2772+ }
 2773+ if (data[offset+1] > maxG) {
 2774+ data[offset+1] = maxG;
 2775+ } else if (data[offset+1] < minG) {
 2776+ data[offset+1] = minG;
 2777+ }
 2778+ if (data[offset+2] > maxB) {
 2779+ data[offset+2] = maxB;
 2780+ } else if (data[offset+2] < minB) {
 2781+ data[offset+2] = minB;
 2782+ }
 2783+
 2784+ } while (--x);
 2785+ } while (--y);
 2786+
 2787+ return true;
 2788+ }
 2789+ },
 2790+ checkSupport : function() {
 2791+ return Pixastic.Client.hasCanvasImageData();
 2792+ }
 2793+}/*
 2794+ * Pixastic Lib - Rotate - v0.1.0
 2795+ * Copyright (c) 2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 2796+ * License: [http://www.pixastic.com/lib/license.txt]
 2797+ */
 2798+
 2799+Pixastic.Actions.rotate = {
 2800+ process : function(params) {
 2801+ if (Pixastic.Client.hasCanvas()) {
 2802+ var canvas = params.canvas;
 2803+
 2804+ var width = params.width;
 2805+ var height = params.height;
 2806+
 2807+ var copy = document.createElement("canvas");
 2808+ copy.width = width;
 2809+ copy.height = height;
 2810+ copy.getContext("2d").drawImage(canvas,0,0,width,height);
 2811+
 2812+ var angle = -parseFloat(params.options.angle) * Math.PI / 180;
 2813+
 2814+ var dimAngle = angle;
 2815+ if (dimAngle > Math.PI*0.5)
 2816+ dimAngle = Math.PI - dimAngle;
 2817+ if (dimAngle < -Math.PI*0.5)
 2818+ dimAngle = -Math.PI - dimAngle;
 2819+
 2820+ var diag = Math.sqrt(width*width + height*height);
 2821+
 2822+ var diagAngle1 = Math.abs(dimAngle) - Math.abs(Math.atan2(height, width));
 2823+ var diagAngle2 = Math.abs(dimAngle) + Math.abs(Math.atan2(height, width));
 2824+
 2825+ var newWidth = Math.abs(Math.cos(diagAngle1) * diag);
 2826+ var newHeight = Math.abs(Math.sin(diagAngle2) * diag);
 2827+
 2828+ canvas.width = newWidth;
 2829+ canvas.height = newHeight;
 2830+
 2831+ var ctx = canvas.getContext("2d");
 2832+ ctx.translate(newWidth/2, newHeight/2);
 2833+ ctx.rotate(angle);
 2834+ ctx.drawImage(copy,-width/2,-height/2);
 2835+
 2836+ params.useData = false;
 2837+ return true;
 2838+ }
 2839+ },
 2840+ checkSupport : function() {
 2841+ return Pixastic.Client.hasCanvas();
 2842+ }
 2843+}
 2844+
 2845+
 2846+/*
 2847+ * Pixastic Lib - Sepia filter - v0.1.0
 2848+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 2849+ * License: [http://www.pixastic.com/lib/license.txt]
 2850+ */
 2851+
 2852+Pixastic.Actions.sepia = {
 2853+
 2854+ process : function(params) {
 2855+ var mode = (parseInt(params.options.mode,10)||0);
 2856+ if (mode < 0) mode = 0;
 2857+ if (mode > 1) mode = 1;
 2858+
 2859+ if (Pixastic.Client.hasCanvasImageData()) {
 2860+ var data = Pixastic.prepareData(params);
 2861+ var rect = params.options.rect;
 2862+ var w = rect.width;
 2863+ var h = rect.height;
 2864+ var w4 = w*4;
 2865+ var y = h;
 2866+ do {
 2867+ var offsetY = (y-1)*w4;
 2868+ var x = w;
 2869+ do {
 2870+ var offset = offsetY + (x-1)*4;
 2871+
 2872+ if (mode) {
 2873+ // a bit faster, but not as good
 2874+ var d = data[offset] * 0.299 + data[offset+1] * 0.587 + data[offset+2] * 0.114;
 2875+ var r = (d + 39);
 2876+ var g = (d + 14);
 2877+ var b = (d - 36);
 2878+ } else {
 2879+ // Microsoft
 2880+ var or = data[offset];
 2881+ var og = data[offset+1];
 2882+ var ob = data[offset+2];
 2883+
 2884+ var r = (or * 0.393 + og * 0.769 + ob * 0.189);
 2885+ var g = (or * 0.349 + og * 0.686 + ob * 0.168);
 2886+ var b = (or * 0.272 + og * 0.534 + ob * 0.131);
 2887+ }
 2888+
 2889+ if (r < 0) r = 0; if (r > 255) r = 255;
 2890+ if (g < 0) g = 0; if (g > 255) g = 255;
 2891+ if (b < 0) b = 0; if (b > 255) b = 255;
 2892+
 2893+ data[offset] = r;
 2894+ data[offset+1] = g;
 2895+ data[offset+2] = b;
 2896+
 2897+ } while (--x);
 2898+ } while (--y);
 2899+ return true;
 2900+ }
 2901+ },
 2902+ checkSupport : function() {
 2903+ return Pixastic.Client.hasCanvasImageData();
 2904+ }
 2905+}/*
 2906+ * Pixastic Lib - Sharpen filter - v0.1.0
 2907+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 2908+ * License: [http://www.pixastic.com/lib/license.txt]
 2909+ */
 2910+
 2911+Pixastic.Actions.sharpen = {
 2912+ process : function(params) {
 2913+
 2914+ var strength = 0;
 2915+ if (typeof params.options.amount != "undefined")
 2916+ strength = parseFloat(params.options.amount)||0;
 2917+
 2918+ if (strength < 0) strength = 0;
 2919+ if (strength > 1) strength = 1;
 2920+
 2921+ if (Pixastic.Client.hasCanvasImageData()) {
 2922+ var data = Pixastic.prepareData(params);
 2923+ var dataCopy = Pixastic.prepareData(params, true)
 2924+
 2925+ var mul = 15;
 2926+ var mulOther = 1 + 3*strength;
 2927+
 2928+ var kernel = [
 2929+ [0, -mulOther, 0],
 2930+ [-mulOther, mul, -mulOther],
 2931+ [0, -mulOther, 0]
 2932+ ];
 2933+
 2934+ var weight = 0;
 2935+ for (var i=0;i<3;i++) {
 2936+ for (var j=0;j<3;j++) {
 2937+ weight += kernel[i][j];
 2938+ }
 2939+ }
 2940+
 2941+ weight = 1 / weight;
 2942+
 2943+ var rect = params.options.rect;
 2944+ var w = rect.width;
 2945+ var h = rect.height;
 2946+
 2947+ mul *= weight;
 2948+ mulOther *= weight;
 2949+
 2950+ var w4 = w*4;
 2951+ var y = h;
 2952+ do {
 2953+ var offsetY = (y-1)*w4;
 2954+
 2955+ var nextY = (y == h) ? y - 1 : y;
 2956+ var prevY = (y == 1) ? 0 : y-2;
 2957+
 2958+ var offsetYPrev = prevY*w4;
 2959+ var offsetYNext = nextY*w4;
 2960+
 2961+ var x = w;
 2962+ do {
 2963+ var offset = offsetY + (x*4-4);
 2964+
 2965+ var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
 2966+ var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
 2967+
 2968+ var r = ((
 2969+ - dataCopy[offsetPrev]
 2970+ - dataCopy[offset-4]
 2971+ - dataCopy[offset+4]
 2972+ - dataCopy[offsetNext]) * mulOther
 2973+ + dataCopy[offset] * mul
 2974+ );
 2975+
 2976+ var g = ((
 2977+ - dataCopy[offsetPrev+1]
 2978+ - dataCopy[offset-3]
 2979+ - dataCopy[offset+5]
 2980+ - dataCopy[offsetNext+1]) * mulOther
 2981+ + dataCopy[offset+1] * mul
 2982+ );
 2983+
 2984+ var b = ((
 2985+ - dataCopy[offsetPrev+2]
 2986+ - dataCopy[offset-2]
 2987+ - dataCopy[offset+6]
 2988+ - dataCopy[offsetNext+2]) * mulOther
 2989+ + dataCopy[offset+2] * mul
 2990+ );
 2991+
 2992+
 2993+ if (r < 0 ) r = 0;
 2994+ if (g < 0 ) g = 0;
 2995+ if (b < 0 ) b = 0;
 2996+ if (r > 255 ) r = 255;
 2997+ if (g > 255 ) g = 255;
 2998+ if (b > 255 ) b = 255;
 2999+
 3000+ data[offset] = r;
 3001+ data[offset+1] = g;
 3002+ data[offset+2] = b;
 3003+
 3004+ } while (--x);
 3005+ } while (--y);
 3006+
 3007+ return true;
 3008+
 3009+ }
 3010+ },
 3011+ checkSupport : function() {
 3012+ return Pixastic.Client.hasCanvasImageData();
 3013+ }
 3014+}
 3015+/*
 3016+ * Pixastic Lib - Solarize filter - v0.1.0
 3017+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 3018+ * License: [http://www.pixastic.com/lib/license.txt]
 3019+ */
 3020+
 3021+Pixastic.Actions.solarize = {
 3022+
 3023+ process : function(params) {
 3024+ var useAverage = !!(params.options.average && params.options.average != "false");
 3025+
 3026+ if (Pixastic.Client.hasCanvasImageData()) {
 3027+ var data = Pixastic.prepareData(params);
 3028+ var rect = params.options.rect;
 3029+ var w = rect.width;
 3030+ var h = rect.height;
 3031+ var w4 = w*4;
 3032+ var y = h;
 3033+ do {
 3034+ var offsetY = (y-1)*w4;
 3035+ var x = w;
 3036+ do {
 3037+ var offset = offsetY + (x-1)*4;
 3038+
 3039+ var r = data[offset];
 3040+ var g = data[offset+1];
 3041+ var b = data[offset+2];
 3042+
 3043+ if (r > 127) r = 255 - r;
 3044+ if (g > 127) g = 255 - g;
 3045+ if (b > 127) b = 255 - b;
 3046+
 3047+ data[offset] = r;
 3048+ data[offset+1] = g;
 3049+ data[offset+2] = b;
 3050+
 3051+ } while (--x);
 3052+ } while (--y);
 3053+ return true;
 3054+ }
 3055+ },
 3056+ checkSupport : function() {
 3057+ return (Pixastic.Client.hasCanvasImageData());
 3058+ }
 3059+}/*
 3060+ * Pixastic Lib - USM - v0.1.0
 3061+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
 3062+ * License: [http://www.pixastic.com/lib/license.txt]
 3063+ */
 3064+
 3065+
 3066+Pixastic.Actions.unsharpmask = {
 3067+ process : function(params) {
 3068+
 3069+ var amount = (parseFloat(params.options.amount)||0);
 3070+ var blurAmount = parseFloat(params.options.radius)||0;
 3071+ var threshold = parseFloat(params.options.threshold)||0;
 3072+
 3073+ amount = Math.min(500,Math.max(0,amount)) / 2;
 3074+ blurAmount = Math.min(5,Math.max(0,blurAmount)) / 10;
 3075+ threshold = Math.min(255,Math.max(0,threshold));
 3076+
 3077+ threshold--;
 3078+ var thresholdNeg = -threshold;
 3079+
 3080+ amount *= 0.016;
 3081+ amount++;
 3082+
 3083+ if (Pixastic.Client.hasCanvasImageData()) {
 3084+ var rect = params.options.rect;
 3085+
 3086+ var blurCanvas = document.createElement("canvas");
 3087+ blurCanvas.width = params.width;
 3088+ blurCanvas.height = params.height;
 3089+ var blurCtx = blurCanvas.getContext("2d");
 3090+ blurCtx.drawImage(params.canvas,0,0);
 3091+
 3092+ var scale = 2;
 3093+ var smallWidth = Math.round(params.width / scale);
 3094+ var smallHeight = Math.round(params.height / scale);
 3095+
 3096+ var copy = document.createElement("canvas");
 3097+ copy.width = smallWidth;
 3098+ copy.height = smallHeight;
 3099+
 3100+ var steps = Math.round(blurAmount * 20);
 3101+
 3102+ var copyCtx = copy.getContext("2d");
 3103+ for (var i=0;i<steps;i++) {
 3104+ var scaledWidth = Math.max(1,Math.round(smallWidth - i));
 3105+ var scaledHeight = Math.max(1,Math.round(smallHeight - i));
 3106+
 3107+ copyCtx.clearRect(0,0,smallWidth,smallHeight);
 3108+
 3109+ copyCtx.drawImage(
 3110+ blurCanvas,
 3111+ 0,0,params.width,params.height,
 3112+ 0,0,scaledWidth,scaledHeight
 3113+ );
 3114+
 3115+ blurCtx.clearRect(0,0,params.width,params.height);
 3116+
 3117+ blurCtx.drawImage(
 3118+ copy,
 3119+ 0,0,scaledWidth,scaledHeight,
 3120+ 0,0,params.width,params.height
 3121+ );
 3122+ }
 3123+
 3124+ var data = Pixastic.prepareData(params);
 3125+ var blurData = Pixastic.prepareData({canvas:blurCanvas,options:params.options});
 3126+ var w = rect.width;
 3127+ var h = rect.height;
 3128+ var w4 = w*4;
 3129+ var y = h;
 3130+ do {
 3131+ var offsetY = (y-1)*w4;
 3132+ var x = w;
 3133+ do {
 3134+ var offset = offsetY + (x*4-4);
 3135+
 3136+ var difR = data[offset] - blurData[offset];
 3137+ if (difR > threshold || difR < thresholdNeg) {
 3138+ var blurR = blurData[offset];
 3139+ blurR = amount * difR + blurR;
 3140+ data[offset] = blurR > 255 ? 255 : (blurR < 0 ? 0 : blurR);
 3141+ }
 3142+
 3143+ var difG = data[offset+1] - blurData[offset+1];
 3144+ if (difG > threshold || difG < thresholdNeg) {
 3145+ var blurG = blurData[offset+1];
 3146+ blurG = amount * difG + blurG;
 3147+ data[offset+1] = blurG > 255 ? 255 : (blurG < 0 ? 0 : blurG);
 3148+ }
 3149+
 3150+ var difB = data[offset+2] - blurData[offset+2];
 3151+ if (difB > threshold || difB < thresholdNeg) {
 3152+ var blurB = blurData[offset+2];
 3153+ blurB = amount * difB + blurB;
 3154+ data[offset+2] = blurB > 255 ? 255 : (blurB < 0 ? 0 : blurB);
 3155+ }
 3156+
 3157+ } while (--x);
 3158+ } while (--y);
 3159+
 3160+ return true;
 3161+ }
 3162+ },
 3163+ checkSupport : function() {
 3164+ return Pixastic.Client.hasCanvasImageData();
 3165+ }
 3166+}
 3167+
 3168+
 3169+
 3170+
Index: branches/new-upload/phase3/js2/mwEmbed/skins/mvpcf/images/ui-bg_diagonals-thick_20_666666_40x40.png
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes on: branches/new-upload/phase3/js2/mwEmbed/skins/mvpcf/images/ui-bg_diagonals-thick_20_666666_40x40.png
___________________________________________________________________
Added: svn:mime-type
13171 + application/octet-stream

Status & tagging log