- Apache License\r
- Version 2.0, January 2004\r
- http://www.apache.org/licenses/\r
-\r
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\r
-\r
- 1. Definitions.\r
-\r
- "License" shall mean the terms and conditions for use, reproduction,\r
- and distribution as defined by Sections 1 through 9 of this document.\r
-\r
- "Licensor" shall mean the copyright owner or entity authorized by\r
- the copyright owner that is granting the License.\r
-\r
- "Legal Entity" shall mean the union of the acting entity and all\r
- other entities that control, are controlled by, or are under common\r
- control with that entity. For the purposes of this definition,\r
- "control" means (i) the power, direct or indirect, to cause the\r
- direction or management of such entity, whether by contract or\r
- otherwise, or (ii) ownership of fifty percent (50%) or more of the\r
- outstanding shares, or (iii) beneficial ownership of such entity.\r
-\r
- "You" (or "Your") shall mean an individual or Legal Entity\r
- exercising permissions granted by this License.\r
-\r
- "Source" form shall mean the preferred form for making modifications,\r
- including but not limited to software source code, documentation\r
- source, and configuration files.\r
-\r
- "Object" form shall mean any form resulting from mechanical\r
- transformation or translation of a Source form, including but\r
- not limited to compiled object code, generated documentation,\r
- and conversions to other media types.\r
-\r
- "Work" shall mean the work of authorship, whether in Source or\r
- Object form, made available under the License, as indicated by a\r
- copyright notice that is included in or attached to the work\r
- (an example is provided in the Appendix below).\r
-\r
- "Derivative Works" shall mean any work, whether in Source or Object\r
- form, that is based on (or derived from) the Work and for which the\r
- editorial revisions, annotations, elaborations, or other modifications\r
- represent, as a whole, an original work of authorship. For the purposes\r
- of this License, Derivative Works shall not include works that remain\r
- separable from, or merely link (or bind by name) to the interfaces of,\r
- the Work and Derivative Works thereof.\r
-\r
- "Contribution" shall mean any work of authorship, including\r
- the original version of the Work and any modifications or additions\r
- to that Work or Derivative Works thereof, that is intentionally\r
- submitted to Licensor for inclusion in the Work by the copyright owner\r
- or by an individual or Legal Entity authorized to submit on behalf of\r
- the copyright owner. For the purposes of this definition, "submitted"\r
- means any form of electronic, verbal, or written communication sent\r
- to the Licensor or its representatives, including but not limited to\r
- communication on electronic mailing lists, source code control systems,\r
- and issue tracking systems that are managed by, or on behalf of, the\r
- Licensor for the purpose of discussing and improving the Work, but\r
- excluding communication that is conspicuously marked or otherwise\r
- designated in writing by the copyright owner as "Not a Contribution."\r
-\r
- "Contributor" shall mean Licensor and any individual or Legal Entity\r
- on behalf of whom a Contribution has been received by Licensor and\r
- subsequently incorporated within the Work.\r
-\r
- 2. Grant of Copyright License. Subject to the terms and conditions of\r
- this License, each Contributor hereby grants to You a perpetual,\r
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
- copyright license to reproduce, prepare Derivative Works of,\r
- publicly display, publicly perform, sublicense, and distribute the\r
- Work and such Derivative Works in Source or Object form.\r
-\r
- 3. Grant of Patent License. Subject to the terms and conditions of\r
- this License, each Contributor hereby grants to You a perpetual,\r
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable\r
- (except as stated in this section) patent license to make, have made,\r
- use, offer to sell, sell, import, and otherwise transfer the Work,\r
- where such license applies only to those patent claims licensable\r
- by such Contributor that are necessarily infringed by their\r
- Contribution(s) alone or by combination of their Contribution(s)\r
- with the Work to which such Contribution(s) was submitted. If You\r
- institute patent litigation against any entity (including a\r
- cross-claim or counterclaim in a lawsuit) alleging that the Work\r
- or a Contribution incorporated within the Work constitutes direct\r
- or contributory patent infringement, then any patent licenses\r
- granted to You under this License for that Work shall terminate\r
- as of the date such litigation is filed.\r
-\r
- 4. Redistribution. You may reproduce and distribute copies of the\r
- Work or Derivative Works thereof in any medium, with or without\r
- modifications, and in Source or Object form, provided that You\r
- meet the following conditions:\r
-\r
- (a) You must give any other recipients of the Work or\r
- Derivative Works a copy of this License; and\r
-\r
- (b) You must cause any modified files to carry prominent notices\r
- stating that You changed the files; and\r
-\r
- (c) You must retain, in the Source form of any Derivative Works\r
- that You distribute, all copyright, patent, trademark, and\r
- attribution notices from the Source form of the Work,\r
- excluding those notices that do not pertain to any part of\r
- the Derivative Works; and\r
-\r
- (d) If the Work includes a "NOTICE" text file as part of its\r
- distribution, then any Derivative Works that You distribute must\r
- include a readable copy of the attribution notices contained\r
- within such NOTICE file, excluding those notices that do not\r
- pertain to any part of the Derivative Works, in at least one\r
- of the following places: within a NOTICE text file distributed\r
- as part of the Derivative Works; within the Source form or\r
- documentation, if provided along with the Derivative Works; or,\r
- within a display generated by the Derivative Works, if and\r
- wherever such third-party notices normally appear. The contents\r
- of the NOTICE file are for informational purposes only and\r
- do not modify the License. You may add Your own attribution\r
- notices within Derivative Works that You distribute, alongside\r
- or as an addendum to the NOTICE text from the Work, provided\r
- that such additional attribution notices cannot be construed\r
- as modifying the License.\r
-\r
- You may add Your own copyright statement to Your modifications and\r
- may provide additional or different license terms and conditions\r
- for use, reproduction, or distribution of Your modifications, or\r
- for any such Derivative Works as a whole, provided Your use,\r
- reproduction, and distribution of the Work otherwise complies with\r
- the conditions stated in this License.\r
-\r
- 5. Submission of Contributions. Unless You explicitly state otherwise,\r
- any Contribution intentionally submitted for inclusion in the Work\r
- by You to the Licensor shall be under the terms and conditions of\r
- this License, without any additional terms or conditions.\r
- Notwithstanding the above, nothing herein shall supersede or modify\r
- the terms of any separate license agreement you may have executed\r
- with Licensor regarding such Contributions.\r
-\r
- 6. Trademarks. This License does not grant permission to use the trade\r
- names, trademarks, service marks, or product names of the Licensor,\r
- except as required for reasonable and customary use in describing the\r
- origin of the Work and reproducing the content of the NOTICE file.\r
-\r
- 7. Disclaimer of Warranty. Unless required by applicable law or\r
- agreed to in writing, Licensor provides the Work (and each\r
- Contributor provides its Contributions) on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\r
- implied, including, without limitation, any warranties or conditions\r
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\r
- PARTICULAR PURPOSE. You are solely responsible for determining the\r
- appropriateness of using or redistributing the Work and assume any\r
- risks associated with Your exercise of permissions under this License.\r
-\r
- 8. Limitation of Liability. In no event and under no legal theory,\r
- whether in tort (including negligence), contract, or otherwise,\r
- unless required by applicable law (such as deliberate and grossly\r
- negligent acts) or agreed to in writing, shall any Contributor be\r
- liable to You for damages, including any direct, indirect, special,\r
- incidental, or consequential damages of any character arising as a\r
- result of this License or out of the use or inability to use the\r
- Work (including but not limited to damages for loss of goodwill,\r
- work stoppage, computer failure or malfunction, or any and all\r
- other commercial damages or losses), even if such Contributor\r
- has been advised of the possibility of such damages.\r
-\r
- 9. Accepting Warranty or Additional Liability. While redistributing\r
- the Work or Derivative Works thereof, You may choose to offer,\r
- and charge a fee for, acceptance of support, warranty, indemnity,\r
- or other liability obligations and/or rights consistent with this\r
- License. However, in accepting such obligations, You may act only\r
- on Your own behalf and on Your sole responsibility, not on behalf\r
- of any other Contributor, and only if You agree to indemnify,\r
- defend, and hold each Contributor harmless for any liability\r
- incurred by, or claims asserted against, such Contributor by reason\r
- of your accepting any such warranty or additional liability.\r
-\r
- END OF TERMS AND CONDITIONS\r
-\r
- APPENDIX: How to apply the Apache License to your work.\r
-\r
- To apply the Apache License to your work, attach the following\r
- boilerplate notice, with the fields enclosed by brackets "[]"\r
- replaced with your own identifying information. (Don't include\r
- the brackets!) The text should be enclosed in the appropriate\r
- comment syntax for the file format. We also recommend that a\r
- file or class name and description of purpose be included on the\r
- same "printed page" as the copyright notice for easier\r
- identification within third-party archives.\r
-\r
- Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-\r
- *** PRELIMINARY SOFTWARE ***\r
- \r
-Please note that this is a prerelease of the OMTK Flash library. No\r
-quality of this software can be guaranteed.\r
-\r
-\r
- *** haXe notes ***\r
- \r
-You need at least haXe 2.01 (with support for the new Flash 10 types)\r
-to compile the haXe source.\r
-\r
- *** Flash notes ***\r
- \r
-I am not able to create a .SWC library from the haXe .SWF file. It's\r
-therefore dynamically linked at runtime and hxmdct.swf must be placed\r
-in the same directory as the "real" Flash movie.\r
+
+ *** PRELIMINARY SOFTWARE ***
+
+Please note that this is a prerelease of the OMTK Flash library. No
+quality of this software can be guaranteed.
+
+
+ *** haXe notes ***
+
+You need at least haXe 2.01 (with support for the new Flash 10 types)
+to compile the haXe source.
+
+ *** Flash notes ***
+
+I am not able to create a .SWC library from the haXe .SWF file. It's
+therefore dynamically linked at runtime and hxmdct.swf must be placed
+in the same directory as the "real" Flash movie.
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package {\r
-\r
- import org.omtk.vorbis.VorbisSound;\r
- \r
- import flash.display.Shape;\r
- import flash.display.Sprite;\r
- import flash.display.StageAlign;\r
- import flash.display.StageQuality;\r
- import flash.display.StageScaleMode;\r
- import flash.net.*;\r
- import flash.events.Event;\r
- import flash.text.TextField;\r
- import flash.utils.ByteArray;\r
- import flash.utils.Endian;\r
- import flash.utils.getTimer;\r
- import flash.utils.setTimeout;\r
- import flash.utils.setInterval;\r
- import flash.external.ExternalInterface;\r
- \r
- [ SWF( backgroundColor = '#ffffff', width = '1', height = '1' ) ]\r
- \r
- public class Player extends Sprite {\r
- \r
- private var sound: VorbisSound;\r
- private var initialized: Boolean = false;\r
- \r
- public function Player() {\r
- if(stage != null) {\r
- stage.frameRate = 20;\r
- }\r
- \r
- setTimeout(registerJSCallbacks, 100);\r
- initialized = true;\r
- }\r
-\r
- private function registerJSCallbacks(): void {\r
- if (ExternalInterface.available) {\r
- ExternalInterface.addCallback("play", playJS);\r
- ExternalInterface.addCallback("getMetaData", getMetaDataJS);\r
- ExternalInterface.addCallback("getPosition", getPositionJS); \r
- }\r
- }\r
-\r
- public function playJS(url: String): void {\r
- if(sound != null) {\r
- sound.stop();\r
- }\r
- sound = new VorbisSound(new URLRequest(url));\r
- sound.addEventListener(Event.COMPLETE, complete); \r
- sound.addEventListener(VorbisSound.METADATA_UPDATE, metadataUpdate);\r
- sound.play();\r
- }\r
-\r
- public function getMetaDataJS(key: String): String {\r
- if(sound == null) {\r
- return null;\r
- }\r
- else {\r
- return sound.getMetaData(key);\r
- }\r
- }\r
- \r
- public function getPositionJS(): int {\r
- if(sound == null) {\r
- return -1;\r
- }\r
- else {\r
- return sound.position;\r
- }\r
- }\r
- \r
- private function complete(event: Event):void {\r
- trace("complete");\r
- if(ExternalInterface.available) {\r
- ExternalInterface.call("OMTK_P_complete");\r
- }\r
- }\r
-\r
- private function metadataUpdate(event: Event):void {\r
- trace("metadata update: " + sound.getMetaData("TITLE"));\r
- if(ExternalInterface.available) {\r
- ExternalInterface.call("OMTK_P_metadataUpdate");\r
- }\r
- }\r
-\r
- }\r
- \r
-}\r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package {
+
+ import org.omtk.vorbis.VorbisSound;
+
+ import flash.display.Shape;
+ import flash.display.Sprite;
+ import flash.display.StageAlign;
+ import flash.display.StageQuality;
+ import flash.display.StageScaleMode;
+ import flash.net.*;
+ import flash.events.Event;
+ import flash.text.TextField;
+ import flash.utils.ByteArray;
+ import flash.utils.Endian;
+ import flash.utils.getTimer;
+ import flash.utils.setTimeout;
+ import flash.utils.setInterval;
+ import flash.external.ExternalInterface;
+
+ [ SWF( backgroundColor = '#ffffff', width = '1', height = '1' ) ]
+
+ public class Player extends Sprite {
+
+ private var sound: VorbisSound;
+ private var initialized: Boolean = false;
+
+ public function Player() {
+ if(stage != null) {
+ stage.frameRate = 20;
+ }
+
+ setTimeout(registerJSCallbacks, 100);
+ initialized = true;
+ }
+
+ private function registerJSCallbacks(): void {
+ if (ExternalInterface.available) {
+ ExternalInterface.addCallback("play", playJS);
+ ExternalInterface.addCallback("getMetaData", getMetaDataJS);
+ ExternalInterface.addCallback("getPosition", getPositionJS);
+ }
+ }
+
+ public function playJS(url: String): void {
+ if(sound != null) {
+ sound.stop();
+ }
+ sound = new VorbisSound(new URLRequest(url));
+ sound.addEventListener(Event.COMPLETE, complete);
+ sound.addEventListener(VorbisSound.METADATA_UPDATE, metadataUpdate);
+ sound.play();
+ }
+
+ public function getMetaDataJS(key: String): String {
+ if(sound == null) {
+ return null;
+ }
+ else {
+ return sound.getMetaData(key);
+ }
+ }
+
+ public function getPositionJS(): int {
+ if(sound == null) {
+ return -1;
+ }
+ else {
+ return sound.position;
+ }
+ }
+
+ private function complete(event: Event):void {
+ trace("complete");
+ if(ExternalInterface.available) {
+ ExternalInterface.call("OMTK_P_complete");
+ }
+ }
+
+ private function metadataUpdate(event: Event):void {
+ trace("metadata update: " + sound.getMetaData("TITLE"));
+ if(ExternalInterface.available) {
+ ExternalInterface.call("OMTK_P_metadataUpdate");
+ }
+ }
+
+ }
+
+}
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.ogg {\r
-\r
- public class EndOfOggStreamError extends Error {\r
- \r
- public function EndOfOggStreamError(message:String = null) {\r
- super(message);\r
- }\r
- \r
- }\r
-\r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.ogg {
+
+ public class EndOfOggStreamError extends Error {
+
+ public function EndOfOggStreamError(message:String = null) {
+ super(message);
+ }
+
+ }
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.ogg {\r
-\r
- import org.omtk.util.BitByteArray; \r
- import flash.utils.Endian;\r
-\r
- public class LogicalOggStream {\r
- \r
- private var source:UncachedUrlStream;\r
- \r
- private var pageIndex:int;\r
- private var currentPage:OggPage;\r
- private var currentSegmentIndex:int;\r
- \r
- public function LogicalOggStream(source:UncachedUrlStream) {\r
- this.source = source;\r
- }\r
- \r
- public function getNextOggPacket(): OggPacket {\r
- \r
- var res:BitByteArray = new BitByteArray();\r
-\r
- var segmentLength:int = 0;\r
-\r
- if(currentPage == null) {\r
- currentPage = source.getNextOggPage();\r
- }\r
-\r
- do {\r
- if(currentSegmentIndex >= currentPage.segmentOffsets.length) {\r
- currentSegmentIndex=0;\r
-\r
- if(currentPage.eos) {\r
- throw new EndOfOggStreamError("End of OGG stream");\r
- }\r
- \r
- currentPage = source.getNextOggPage();\r
- }\r
-\r
- segmentLength = currentPage.segmentLengths[currentSegmentIndex];\r
- res.writeBytes(currentPage.data, currentPage.segmentOffsets[currentSegmentIndex], segmentLength);\r
- currentSegmentIndex++;\r
- }\r
- while(segmentLength==255);\r
- \r
- res.position = 0;\r
- \r
- var lastPacket: Boolean = currentPage.eos && currentSegmentIndex == currentPage.segmentOffsets.length;\r
- var lastGranulePosition: int = currentPage.absoluteGranulePosition;\r
- \r
- return new OggPacket(res, lastPacket, lastGranulePosition);\r
- }\r
- \r
- }\r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.ogg {
+
+ import org.omtk.util.BitByteArray;
+ import flash.utils.Endian;
+
+ public class LogicalOggStream {
+
+ private var source:UncachedUrlStream;
+
+ private var pageIndex:int;
+ private var currentPage:OggPage;
+ private var currentSegmentIndex:int;
+
+ public function LogicalOggStream(source:UncachedUrlStream) {
+ this.source = source;
+ }
+
+ public function getNextOggPacket(): OggPacket {
+
+ var res:BitByteArray = new BitByteArray();
+
+ var segmentLength:int = 0;
+
+ if(currentPage == null) {
+ currentPage = source.getNextOggPage();
+ }
+
+ do {
+ if(currentSegmentIndex >= currentPage.segmentOffsets.length) {
+ currentSegmentIndex=0;
+
+ if(currentPage.eos) {
+ throw new EndOfOggStreamError("End of OGG stream");
+ }
+
+ currentPage = source.getNextOggPage();
+ }
+
+ segmentLength = currentPage.segmentLengths[currentSegmentIndex];
+ res.writeBytes(currentPage.data, currentPage.segmentOffsets[currentSegmentIndex], segmentLength);
+ currentSegmentIndex++;
+ }
+ while(segmentLength==255);
+
+ res.position = 0;
+
+ var lastPacket: Boolean = currentPage.eos && currentSegmentIndex == currentPage.segmentOffsets.length;
+ var lastGranulePosition: int = currentPage.absoluteGranulePosition;
+
+ return new OggPacket(res, lastPacket, lastGranulePosition);
+ }
+
+ }
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.ogg {\r
-\r
- import org.omtk.util.BitByteArray;\r
-\r
- public class OggPacket {\r
- \r
- private var _data: BitByteArray;\r
- private var _lastPacket: Boolean;\r
- private var _lastGranulePosition: int;\r
- \r
- public function OggPacket(data: BitByteArray, lastPacket: Boolean, lastGranulePosition: int) {\r
- _data = data;\r
- _lastPacket = lastPacket;\r
- _lastGranulePosition = lastGranulePosition;\r
- }\r
- \r
- public function get data(): BitByteArray {\r
- return _data;\r
- }\r
- \r
- public function get lastPacket(): Boolean {\r
- return _lastPacket;\r
- }\r
- \r
- public function get lastGranulePosition(): int {\r
- return _lastGranulePosition;\r
- }\r
- \r
- }\r
- \r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.ogg {
+
+ import org.omtk.util.BitByteArray;
+
+ public class OggPacket {
+
+ private var _data: BitByteArray;
+ private var _lastPacket: Boolean;
+ private var _lastGranulePosition: int;
+
+ public function OggPacket(data: BitByteArray, lastPacket: Boolean, lastGranulePosition: int) {
+ _data = data;
+ _lastPacket = lastPacket;
+ _lastGranulePosition = lastGranulePosition;
+ }
+
+ public function get data(): BitByteArray {
+ return _data;
+ }
+
+ public function get lastPacket(): Boolean {
+ return _lastPacket;
+ }
+
+ public function get lastGranulePosition(): int {
+ return _lastGranulePosition;
+ }
+
+ }
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.ogg {\r
-\r
- import flash.net.*;\r
- import flash.utils.ByteArray;\r
- \r
- public class OggPage {\r
-\r
- private var _version:int;\r
- private var _continued:Boolean;\r
- private var _bos:Boolean;\r
- private var _eos:Boolean;\r
- private var _absoluteGranulePosition:int;\r
- private var _streamSerialNumber:int;\r
- private var _pageSequenceNumber:int;\r
- private var _pageCheckSum:int;\r
- private var _segmentOffsets:Array;\r
- private var _segmentLengths:Array;\r
- private var _totalLength:int;\r
- private var _data:ByteArray;\r
- \r
- public function OggPage(stream:URLStream) {\r
-\r
- var capture:int = stream.readInt();\r
- if(capture != 0x5367674f) {\r
- throw new Error("Ogg page does not start with 'OggS': "+capture);\r
- }\r
- \r
- _version = stream.readByte()&0xff;\r
- var tmp:int = stream.readByte();\r
- \r
- _continued = (tmp&1)!=0;;\r
- _bos = (tmp&2)!=0;\r
- _eos = (tmp&4)!=0;\r
- \r
- // absoluteGranulePosition is really 64 bits\r
- _absoluteGranulePosition = stream.readUnsignedInt();\r
- stream.readUnsignedInt(); // last 32 bits of _absoluteGranulePosition\r
- \r
- _streamSerialNumber = stream.readUnsignedInt();\r
- _pageSequenceNumber = stream.readUnsignedInt();\r
- _pageCheckSum = stream.readUnsignedInt();\r
- \r
- //trace("_pageSequenceNumber: " + _pageSequenceNumber);\r
- \r
- var pageSegments:int = stream.readUnsignedByte();\r
- \r
- //stream.waitFor(pageSegments);\r
- \r
- _segmentOffsets = [];\r
- _segmentLengths = [];\r
- _data = new ByteArray();\r
- \r
- var totalLength:int;\r
- \r
- var i:int;\r
- var l:int;\r
- \r
- for( i= 0 ; i < pageSegments ; i++ ) {\r
- l = stream.readUnsignedByte();\r
- _segmentLengths.push( l );\r
- _segmentOffsets.push( totalLength );\r
- totalLength += l;\r
- } \r
- \r
- stream.readBytes(_data, 0, totalLength);\r
- }\r
- \r
- public function get absoluteGranulePosition():int {\r
- return _absoluteGranulePosition;\r
- }\r
-\r
- public function get segmentOffsets():Array {\r
- return _segmentOffsets;\r
- }\r
- \r
- public function get segmentLengths():Array {\r
- return _segmentLengths;\r
- }\r
- \r
- public function get data():ByteArray {\r
- return _data;\r
- }\r
-\r
- public function get eos():Boolean {\r
- return _eos;\r
- }\r
- \r
- public function get bos():Boolean {\r
- return _bos;\r
- }\r
- \r
- public function get continued():Boolean {\r
- return _continued;\r
- }\r
- \r
- }\r
-\r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.ogg {
+
+ import flash.net.*;
+ import flash.utils.ByteArray;
+
+ public class OggPage {
+
+ private var _version:int;
+ private var _continued:Boolean;
+ private var _bos:Boolean;
+ private var _eos:Boolean;
+ private var _absoluteGranulePosition:int;
+ private var _streamSerialNumber:int;
+ private var _pageSequenceNumber:int;
+ private var _pageCheckSum:int;
+ private var _segmentOffsets:Array;
+ private var _segmentLengths:Array;
+ private var _totalLength:int;
+ private var _data:ByteArray;
+
+ public function OggPage(stream:URLStream) {
+
+ var capture:int = stream.readInt();
+ if(capture != 0x5367674f) {
+ throw new Error("Ogg page does not start with 'OggS': "+capture);
+ }
+
+ _version = stream.readByte()&0xff;
+ var tmp:int = stream.readByte();
+
+ _continued = (tmp&1)!=0;;
+ _bos = (tmp&2)!=0;
+ _eos = (tmp&4)!=0;
+
+ // absoluteGranulePosition is really 64 bits
+ _absoluteGranulePosition = stream.readUnsignedInt();
+ stream.readUnsignedInt(); // last 32 bits of _absoluteGranulePosition
+
+ _streamSerialNumber = stream.readUnsignedInt();
+ _pageSequenceNumber = stream.readUnsignedInt();
+ _pageCheckSum = stream.readUnsignedInt();
+
+ //trace("_pageSequenceNumber: " + _pageSequenceNumber);
+
+ var pageSegments:int = stream.readUnsignedByte();
+
+ //stream.waitFor(pageSegments);
+
+ _segmentOffsets = [];
+ _segmentLengths = [];
+ _data = new ByteArray();
+
+ var totalLength:int;
+
+ var i:int;
+ var l:int;
+
+ for( i= 0 ; i < pageSegments ; i++ ) {
+ l = stream.readUnsignedByte();
+ _segmentLengths.push( l );
+ _segmentOffsets.push( totalLength );
+ totalLength += l;
+ }
+
+ stream.readBytes(_data, 0, totalLength);
+ }
+
+ public function get absoluteGranulePosition():int {
+ return _absoluteGranulePosition;
+ }
+
+ public function get segmentOffsets():Array {
+ return _segmentOffsets;
+ }
+
+ public function get segmentLengths():Array {
+ return _segmentLengths;
+ }
+
+ public function get data():ByteArray {
+ return _data;
+ }
+
+ public function get eos():Boolean {
+ return _eos;
+ }
+
+ public function get bos():Boolean {
+ return _bos;
+ }
+
+ public function get continued():Boolean {
+ return _continued;
+ }
+
+ }
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.ogg {\r
-\r
- import flash.net.*;\r
- import flash.utils.Endian;\r
- import flash.events.HTTPStatusEvent;\r
- import flash.events.ProgressEvent;\r
- \r
- public class UncachedUrlStream {\r
- \r
- private var source:URLStream;\r
- \r
- public function UncachedUrlStream(source: URLStream) {\r
- this.source = source;\r
- }\r
- \r
- public function get bytesAvailable():int {\r
- return source.bytesAvailable;\r
- } \r
- \r
- public function addEventListener(type:String, listener:Function):void {\r
- source.addEventListener(type, listener);\r
- }\r
- \r
- public function getLogicalOggStream():LogicalOggStream {\r
- return new LogicalOggStream(this);\r
- }\r
- \r
- public function getNextOggPage():OggPage {\r
- return new OggPage(source);\r
- }\r
- \r
- }\r
-\r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.ogg {
+
+ import flash.net.*;
+ import flash.utils.Endian;
+ import flash.events.HTTPStatusEvent;
+ import flash.events.ProgressEvent;
+
+ public class UncachedUrlStream {
+
+ private var source:URLStream;
+
+ public function UncachedUrlStream(source: URLStream) {
+ this.source = source;
+ }
+
+ public function get bytesAvailable():int {
+ return source.bytesAvailable;
+ }
+
+ public function addEventListener(type:String, listener:Function):void {
+ source.addEventListener(type, listener);
+ }
+
+ public function getLogicalOggStream():LogicalOggStream {
+ return new LogicalOggStream(this);
+ }
+
+ public function getNextOggPage():OggPage {
+ return new OggPage(source);
+ }
+
+ }
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.util {\r
-\r
- import flash.utils.ByteArray;\r
- import flash.utils.Endian;\r
- import flash.errors.IllegalOperationError;\r
- \r
- public class BitByteArray extends ByteArray {\r
- \r
- private var currentByte:uint;\r
- private var bitIndex:int = 8;\r
- \r
- public function BitByteArray() {\r
- this.endian = Endian.LITTLE_ENDIAN;\r
- }\r
-\r
- public function readBit():Boolean {\r
- if (bitIndex > 7) {\r
- bitIndex = 0;\r
- currentByte = readUnsignedByte();\r
- }\r
- return (currentByte & (1 << (bitIndex++))) != 0;\r
- }\r
- \r
- public function readUnsignedBitwiseInt(bits:int):uint {\r
- \r
- var res:uint = 0;\r
- \r
- for (var i : int = 0; i < bits; i++) {\r
- if (bitIndex > 7) {\r
- bitIndex = 0;\r
- currentByte = readUnsignedByte();\r
- }\r
- if((currentByte & (1 << (bitIndex++))) != 0) {\r
- res |= (1 << i);\r
- }\r
- }\r
- \r
- return res;\r
- } \r
-\r
- public function readUnsignedHuffmanInt(root:HuffmanNode):uint {\r
-\r
- while (!root.hasValue) {\r
- if (bitIndex > 7) {\r
- bitIndex = 0;\r
- currentByte = readUnsignedByte();\r
- }\r
- root = (currentByte & (1 << (bitIndex++))) != 0 ? root._o1 : root._o0;\r
- }\r
- \r
- return root._value; \r
- }\r
- \r
- }\r
- \r
-\r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.util {
+
+ import flash.utils.ByteArray;
+ import flash.utils.Endian;
+ import flash.errors.IllegalOperationError;
+
+ public class BitByteArray extends ByteArray {
+
+ private var currentByte:uint;
+ private var bitIndex:int = 8;
+
+ public function BitByteArray() {
+ this.endian = Endian.LITTLE_ENDIAN;
+ }
+
+ public function readBit():Boolean {
+ if (bitIndex > 7) {
+ bitIndex = 0;
+ currentByte = readUnsignedByte();
+ }
+ return (currentByte & (1 << (bitIndex++))) != 0;
+ }
+
+ public function readUnsignedBitwiseInt(bits:int):uint {
+
+ var res:uint = 0;
+
+ for (var i : int = 0; i < bits; i++) {
+ if (bitIndex > 7) {
+ bitIndex = 0;
+ currentByte = readUnsignedByte();
+ }
+ if((currentByte & (1 << (bitIndex++))) != 0) {
+ res |= (1 << i);
+ }
+ }
+
+ return res;
+ }
+
+ public function readUnsignedHuffmanInt(root:HuffmanNode):uint {
+
+ while (!root.hasValue) {
+ if (bitIndex > 7) {
+ bitIndex = 0;
+ currentByte = readUnsignedByte();
+ }
+ root = (currentByte & (1 << (bitIndex++))) != 0 ? root._o1 : root._o0;
+ }
+
+ return root._value;
+ }
+
+ }
+
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-package org.omtk.util {\r
-\r
- public class HuffmanNode {\r
- \r
- private var _parent:HuffmanNode;\r
- \r
- public var _o0:HuffmanNode;\r
- public var _o1:HuffmanNode;\r
- \r
- private var _depth:int;\r
- \r
- public var _value:int;\r
- public var hasValue: Boolean;\r
- private var _full:Boolean = false;\r
- \r
- public function HuffmanNode(parent:HuffmanNode = null, value:int = -1) {\r
- _parent = parent;\r
- if(_parent != null) {\r
- _depth = _parent.depth+1;\r
- }\r
- _value = value; \r
- _full = value >= 0;\r
- hasValue = value >= 0;\r
- }\r
- \r
- public function setNewValue(depth:int, value:uint):Boolean {\r
- if (full) {\r
- return false;\r
- }\r
- if (depth == 1) {\r
- if (_o0 == null) {\r
- _o0 = new HuffmanNode(this, value);\r
- return true;\r
- } else if (_o1 == null) {\r
- _o1 = new HuffmanNode(this, value);\r
- return true;\r
- } else {\r
- return false;\r
- }\r
- } else {\r
- return o0.setNewValue(depth - 1, value)\r
- ? true : o1.setNewValue(depth - 1, value);\r
- }\r
- } \r
- \r
- public function get value():uint {\r
- return _value;\r
- }\r
- \r
- public function get o0():HuffmanNode {\r
- if(_o0 == null) {\r
- _o0 = new HuffmanNode(this);\r
- }\r
- return _o0;\r
- }\r
-\r
- public function get o1():HuffmanNode {\r
- if(_o1 == null) {\r
- _o1 = new HuffmanNode(this);\r
- }\r
- return _o1;\r
- }\r
- \r
- public function get depth():int {\r
- return _depth;\r
- }\r
- \r
- public function get full():Boolean {\r
- return _full ? true\r
- : (_full = (_o0 != null && _o0.full && _o1 != null && _o1.full));\r
- }\r
- \r
- }\r
- \r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+package org.omtk.util {
+
+ public class HuffmanNode {
+
+ private var _parent:HuffmanNode;
+
+ public var _o0:HuffmanNode;
+ public var _o1:HuffmanNode;
+
+ private var _depth:int;
+
+ public var _value:int;
+ public var hasValue: Boolean;
+ private var _full:Boolean = false;
+
+ public function HuffmanNode(parent:HuffmanNode = null, value:int = -1) {
+ _parent = parent;
+ if(_parent != null) {
+ _depth = _parent.depth+1;
+ }
+ _value = value;
+ _full = value >= 0;
+ hasValue = value >= 0;
+ }
+
+ public function setNewValue(depth:int, value:uint):Boolean {
+ if (full) {
+ return false;
+ }
+ if (depth == 1) {
+ if (_o0 == null) {
+ _o0 = new HuffmanNode(this, value);
+ return true;
+ } else if (_o1 == null) {
+ _o1 = new HuffmanNode(this, value);
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return o0.setNewValue(depth - 1, value)
+ ? true : o1.setNewValue(depth - 1, value);
+ }
+ }
+
+ public function get value():uint {
+ return _value;
+ }
+
+ public function get o0():HuffmanNode {
+ if(_o0 == null) {
+ _o0 = new HuffmanNode(this);
+ }
+ return _o0;
+ }
+
+ public function get o1():HuffmanNode {
+ if(_o1 == null) {
+ _o1 = new HuffmanNode(this);
+ }
+ return _o1;
+ }
+
+ public function get depth():int {
+ return _depth;
+ }
+
+ public function get full():Boolean {
+ return _full ? true
+ : (_full = (_o0 != null && _o0.full && _o1 != null && _o1.full));
+ }
+
+ }
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.vorbis {\r
-\r
- import flash.utils.getTimer;\r
- import flash.utils.ByteArray;\r
- import org.omtk.ogg.*;\r
- import org.omtk.util.BitByteArray;\r
-\r
- public class AudioPacket {\r
- \r
- private var modeNumber:int;\r
- private var mode:Mode;\r
- private var mapping:Mapping;\r
- private var n:int;\r
- \r
- private var blockFlag:Boolean;\r
- private var previousWindowFlag:Boolean;\r
- private var nextWindowFlag:Boolean;\r
-\r
- private var windowCenter:int;\r
- private var leftWindowStart:int;\r
- private var leftWindowEnd:int;\r
- private var leftN:int;\r
- private var rightWindowStart:int;\r
- private var rightWindowEnd:int;\r
- private var rightN:int;\r
- \r
- private var window:Vector.<Number>;\r
- private var freq0:Vector.<Number>;\r
- private var freq1:Vector.<Number>;\r
- private var pcm0:Vector.<Number>;\r
- private var pcm1:Vector.<Number>;\r
- \r
- private var channelFloors:Vector.<Floor>;\r
- private var noResidues:Vector.<Boolean>; \r
-\r
- private var _lastPacket: Boolean;\r
- private var _lastGranulePosition: int;\r
-\r
- public function AudioPacket(vorbis:VorbisStream, packet: OggPacket, currentGranulePosition: int) {\r
- \r
- var source: BitByteArray = packet.data;\r
- _lastPacket = packet.lastPacket;\r
- _lastGranulePosition = packet.lastGranulePosition;\r
- \r
- var i:int;\r
- var j:int;\r
- var k:int;\r
- \r
- var sHeader:SetupHeader = vorbis.setupHeader;\r
- var iHeader:IdentificationHeader = vorbis.identificationHeader;\r
- var modes:Vector.<Mode> = sHeader.modes;\r
- var mappings:Vector.<Mapping> = sHeader.mappings;\r
- var residues:Vector.<Residue> = sHeader.residues;\r
- var channels:int = iHeader.channels;\r
- \r
- if (source.readUnsignedBitwiseInt(1) != 0) {\r
- throw new Error("Packet type mismatch when trying to create an audio packet.");\r
- }\r
- \r
- modeNumber = source.readUnsignedBitwiseInt(Util.ilog(modes.length - 1));\r
- \r
- mode = modes[modeNumber];\r
- \r
- if(mode == null) {\r
- throw new Error("Reference to invalid mode in audio packet.");\r
- }\r
- \r
- mapping = mappings[mode.mapping];\r
- \r
- var magnitudes:Vector.<int> = mapping.magnitudes;\r
- var angles:Vector.<int> = mapping.angles;\r
- \r
- blockFlag = mode.blockFlag;\r
- \r
- var blockSize0:int = iHeader.blockSize0;\r
- var blockSize1:int = iHeader.blockSize1;\r
- \r
- n = blockFlag ? blockSize1 : blockSize0;\r
- \r
- if (blockFlag) {\r
- previousWindowFlag = source.readBit();\r
- nextWindowFlag = source.readBit();\r
- }\r
- \r
- windowCenter = n / 2;\r
- \r
- if (blockFlag && !previousWindowFlag) {\r
- leftWindowStart = n / 4 - blockSize0 / 4;\r
- leftWindowEnd = n / 4 + blockSize0 / 4;\r
- leftN = blockSize0 / 2;\r
- } else {\r
- leftWindowStart = 0;\r
- leftWindowEnd = n / 2;\r
- leftN = windowCenter;\r
- }\r
- \r
- if (blockFlag && !nextWindowFlag) {\r
- rightWindowStart = n * 3 / 4 - blockSize0 / 4;\r
- rightWindowEnd = n * 3 / 4 + blockSize0 / 4;\r
- rightN = blockSize0 / 2;\r
- } else {\r
- rightWindowStart = windowCenter;\r
- rightWindowEnd = n;\r
- rightN = n / 2;\r
- }\r
- \r
- window = getComputedWindow(vorbis);\r
- \r
- channelFloors = new Vector.<Floor>(channels, true);\r
- noResidues = new Vector.<Boolean>(channels, true);\r
- \r
- freq0 = new Vector.<Number>(n, true);\r
- freq1 = new Vector.<Number>(n, true);\r
- pcm0 = new Vector.<Number>(n, true);\r
- pcm1 = new Vector.<Number>(n, true);\r
-\r
- var allFloorsEmpty: Boolean = true;\r
- var submapNumber: int;\r
- var floorNumber: int;\r
- var decodedFloor: Floor;\r
- \r
- for(i = 0; i < channels; i++) {\r
- submapNumber = mapping.mux[i];\r
- floorNumber = mapping.submapFloors[submapNumber];\r
- decodedFloor = sHeader.floors[floorNumber].decodeFloor(vorbis, source);\r
- channelFloors[i] = decodedFloor;\r
- noResidues[i] = decodedFloor == null;\r
- if (decodedFloor != null) {\r
- allFloorsEmpty = false;\r
- }\r
- }\r
- \r
- if(allFloorsEmpty) {\r
- return;\r
- }\r
- \r
- var mag: int;\r
- var ang: int;\r
-\r
- for(i = 0; i < magnitudes.length; i++) {\r
- mag = magnitudes[i];\r
- ang = angles[i];\r
- if (!noResidues[mag] || !noResidues[ang]) {\r
- noResidues[mag] = false;\r
- noResidues[ang] = false;\r
- }\r
- }\r
- \r
- var ch: int;\r
- var doNotDecodeFlags: Vector.<Boolean>;\r
- var residue:Residue;\r
- \r
- for(i = 0; i < mapping.submaps; i++) {\r
- \r
- doNotDecodeFlags = new Vector.<Boolean>();\r
- \r
- for(j = 0; j < channels; j++) {\r
- if(mapping.mux[j] == i) {\r
- doNotDecodeFlags.push(noResidues[j]);\r
- }\r
- }\r
-\r
- residue = residues[mapping.submapResidues[i]];\r
- \r
- residue.decodeResidue(vorbis, source, mode, ch, doNotDecodeFlags, freq0, freq1);\r
- }\r
-\r
- var a: Number;\r
- var m: Number;\r
- \r
- for(i = mapping.couplingSteps - 1; i >= 0; i--) {\r
- \r
- mag = magnitudes[i];\r
- ang = angles[i];\r
- \r
- for (j = 0; j < freq0.length; j++) {\r
- \r
- a = ang == 0 ? freq0[j] : freq1[j];\r
- m = mag == 0 ? freq0[j] : freq1[j];\r
- \r
- if(a > 0) {\r
- if(ang == 0) {\r
- freq0[j] = m > 0 ? m - a : m + a;\r
- }\r
- else {\r
- freq1[j] = m > 0 ? m - a : m + a;\r
- }\r
- }\r
- else {\r
- if(mag == 0) {\r
- freq0[j] = m > 0 ? m + a : m - a;\r
- }\r
- else {\r
- freq1[j] = m > 0 ? m + a : m - a;\r
- }\r
- \r
- if(ang == 0) {\r
- freq0[j] = m;\r
- }\r
- else {\r
- freq1[j] = m;\r
- }\r
- }\r
- }\r
- }\r
- \r
- if(channelFloors[0] != null) {\r
- Floor(channelFloors[0]).computeFloor(freq0);\r
- }\r
- \r
- if(channelFloors[1] != null) {\r
- Floor(channelFloors[1]).computeFloor(freq1);\r
- }\r
-\r
- // perform an inverse mdct to all channels\r
- var mdct: Mdct = blockFlag ? iHeader.mdct1 : iHeader.mdct0;\r
- mdct.imdct(freq0, window, pcm0);\r
- mdct.imdct(freq1, window, pcm1);\r
-\r
- if(_lastPacket) {\r
- if(leftWindowEnd - leftWindowStart > _lastGranulePosition - currentGranulePosition) {\r
- leftWindowEnd = leftWindowStart + _lastGranulePosition - currentGranulePosition\r
- }\r
- if(rightWindowStart - leftWindowStart > _lastGranulePosition - currentGranulePosition) {\r
- rightWindowStart = leftWindowStart + _lastGranulePosition - currentGranulePosition\r
- }\r
- }\r
-\r
- } \r
- \r
- private function getComputedWindow(vorbis:VorbisStream):Vector.<Number> {\r
- \r
- var i:int;\r
- \r
- var ix:int = (blockFlag ? 4 : 0) + (previousWindowFlag ? 2 : 0) + (nextWindowFlag ? 1 : 0);\r
- var w:Vector.<Number> = vorbis.windows[ix];\r
- \r
- var x:Number;\r
- \r
- if (w == null) {\r
- w = new Vector.<Number>(n);\r
- \r
- for(i = 0; i < leftWindowStart; i++) {\r
- w[i] = 0;\r
- }\r
- \r
- for (i = 0; i < leftN; i++) {\r
- x = (i + .5) / leftN * Math.PI / 2.;\r
- x = Math.sin(x);\r
- x *= x;\r
- x *= Math.PI / 2.;\r
- x = Math.sin(x);\r
- w[i + leftWindowStart] = x;\r
- }\r
- \r
- for (i = leftWindowEnd; i < rightWindowStart; i++) {\r
- w[i] = 1;\r
- }\r
- \r
- for (i = 0; i < rightN; i++) {\r
- x = (rightN - i - .5) / rightN * Math.PI / 2.;\r
- x = Math.sin(x);\r
- x *= x;\r
- x *= Math.PI / 2.;\r
- x = Math.sin(x);\r
- w[i + rightWindowStart] = x;\r
- }\r
- \r
- for(i = rightN + rightWindowStart; i < n; i++) {\r
- w[i] = 0;\r
- }\r
-\r
- for(i = 0; i < w.length; i++) {\r
- w[i] *= 0.5;\r
- }\r
- \r
- vorbis.windows[ix] = w;\r
- }\r
- \r
- return w;\r
- } \r
- \r
- \r
- public function readPcm(previousPacket:AudioPacket, target: ByteArray): int {\r
- \r
- var j:int;\r
- var j2:int;\r
- var ppcm0:Vector.<Number> = previousPacket.pcm0;\r
- var ppcm1:Vector.<Number> = previousPacket.pcm1;\r
- \r
- j2 = previousPacket.rightWindowStart;\r
- \r
- for(j = leftWindowStart; j < leftWindowEnd; j++) {\r
- target.writeFloat(pcm0[j] + ppcm0[j2]);\r
- target.writeFloat(pcm1[j] + ppcm1[j2++]);\r
- }\r
-\r
- for (j = leftWindowEnd; j < rightWindowStart; j++) {\r
- target.writeFloat(pcm0[j]);\r
- target.writeFloat(pcm1[j]);\r
- }\r
-\r
- return numberOfSamples;\r
-\r
- }\r
-\r
- public function get numberOfSamples():int {\r
- return rightWindowStart - leftWindowStart;\r
- }\r
-\r
- public function get lastPacket(): Boolean {\r
- return lastPacket;\r
- }\r
- \r
- public function get lastGranulePosition(): int {\r
- return lastGranulePosition;\r
- }\r
- \r
- }\r
-\r
-\r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+ import flash.utils.getTimer;
+ import flash.utils.ByteArray;
+ import org.omtk.ogg.*;
+ import org.omtk.util.BitByteArray;
+
+ public class AudioPacket {
+
+ private var modeNumber:int;
+ private var mode:Mode;
+ private var mapping:Mapping;
+ private var n:int;
+
+ private var blockFlag:Boolean;
+ private var previousWindowFlag:Boolean;
+ private var nextWindowFlag:Boolean;
+
+ private var windowCenter:int;
+ private var leftWindowStart:int;
+ private var leftWindowEnd:int;
+ private var leftN:int;
+ private var rightWindowStart:int;
+ private var rightWindowEnd:int;
+ private var rightN:int;
+
+ private var window:Vector.<Number>;
+ private var freq0:Vector.<Number>;
+ private var freq1:Vector.<Number>;
+ private var pcm0:Vector.<Number>;
+ private var pcm1:Vector.<Number>;
+
+ private var channelFloors:Vector.<Floor>;
+ private var noResidues:Vector.<Boolean>;
+
+ private var _lastPacket: Boolean;
+ private var _lastGranulePosition: int;
+
+ public function AudioPacket(vorbis:VorbisStream, packet: OggPacket, currentGranulePosition: int) {
+
+ var source: BitByteArray = packet.data;
+ _lastPacket = packet.lastPacket;
+ _lastGranulePosition = packet.lastGranulePosition;
+
+ var i:int;
+ var j:int;
+ var k:int;
+
+ var sHeader:SetupHeader = vorbis.setupHeader;
+ var iHeader:IdentificationHeader = vorbis.identificationHeader;
+ var modes:Vector.<Mode> = sHeader.modes;
+ var mappings:Vector.<Mapping> = sHeader.mappings;
+ var residues:Vector.<Residue> = sHeader.residues;
+ var channels:int = iHeader.channels;
+
+ if (source.readUnsignedBitwiseInt(1) != 0) {
+ throw new Error("Packet type mismatch when trying to create an audio packet.");
+ }
+
+ modeNumber = source.readUnsignedBitwiseInt(Util.ilog(modes.length - 1));
+
+ mode = modes[modeNumber];
+
+ if(mode == null) {
+ throw new Error("Reference to invalid mode in audio packet.");
+ }
+
+ mapping = mappings[mode.mapping];
+
+ var magnitudes:Vector.<int> = mapping.magnitudes;
+ var angles:Vector.<int> = mapping.angles;
+
+ blockFlag = mode.blockFlag;
+
+ var blockSize0:int = iHeader.blockSize0;
+ var blockSize1:int = iHeader.blockSize1;
+
+ n = blockFlag ? blockSize1 : blockSize0;
+
+ if (blockFlag) {
+ previousWindowFlag = source.readBit();
+ nextWindowFlag = source.readBit();
+ }
+
+ windowCenter = n / 2;
+
+ if (blockFlag && !previousWindowFlag) {
+ leftWindowStart = n / 4 - blockSize0 / 4;
+ leftWindowEnd = n / 4 + blockSize0 / 4;
+ leftN = blockSize0 / 2;
+ } else {
+ leftWindowStart = 0;
+ leftWindowEnd = n / 2;
+ leftN = windowCenter;
+ }
+
+ if (blockFlag && !nextWindowFlag) {
+ rightWindowStart = n * 3 / 4 - blockSize0 / 4;
+ rightWindowEnd = n * 3 / 4 + blockSize0 / 4;
+ rightN = blockSize0 / 2;
+ } else {
+ rightWindowStart = windowCenter;
+ rightWindowEnd = n;
+ rightN = n / 2;
+ }
+
+ window = getComputedWindow(vorbis);
+
+ channelFloors = new Vector.<Floor>(channels, true);
+ noResidues = new Vector.<Boolean>(channels, true);
+
+ freq0 = new Vector.<Number>(n, true);
+ freq1 = new Vector.<Number>(n, true);
+ pcm0 = new Vector.<Number>(n, true);
+ pcm1 = new Vector.<Number>(n, true);
+
+ var allFloorsEmpty: Boolean = true;
+ var submapNumber: int;
+ var floorNumber: int;
+ var decodedFloor: Floor;
+
+ for(i = 0; i < channels; i++) {
+ submapNumber = mapping.mux[i];
+ floorNumber = mapping.submapFloors[submapNumber];
+ decodedFloor = sHeader.floors[floorNumber].decodeFloor(vorbis, source);
+ channelFloors[i] = decodedFloor;
+ noResidues[i] = decodedFloor == null;
+ if (decodedFloor != null) {
+ allFloorsEmpty = false;
+ }
+ }
+
+ if(allFloorsEmpty) {
+ return;
+ }
+
+ var mag: int;
+ var ang: int;
+
+ for(i = 0; i < magnitudes.length; i++) {
+ mag = magnitudes[i];
+ ang = angles[i];
+ if (!noResidues[mag] || !noResidues[ang]) {
+ noResidues[mag] = false;
+ noResidues[ang] = false;
+ }
+ }
+
+ var ch: int;
+ var doNotDecodeFlags: Vector.<Boolean>;
+ var residue:Residue;
+
+ for(i = 0; i < mapping.submaps; i++) {
+
+ doNotDecodeFlags = new Vector.<Boolean>();
+
+ for(j = 0; j < channels; j++) {
+ if(mapping.mux[j] == i) {
+ doNotDecodeFlags.push(noResidues[j]);
+ }
+ }
+
+ residue = residues[mapping.submapResidues[i]];
+
+ residue.decodeResidue(vorbis, source, mode, ch, doNotDecodeFlags, freq0, freq1);
+ }
+
+ var a: Number;
+ var m: Number;
+
+ for(i = mapping.couplingSteps - 1; i >= 0; i--) {
+
+ mag = magnitudes[i];
+ ang = angles[i];
+
+ for (j = 0; j < freq0.length; j++) {
+
+ a = ang == 0 ? freq0[j] : freq1[j];
+ m = mag == 0 ? freq0[j] : freq1[j];
+
+ if(a > 0) {
+ if(ang == 0) {
+ freq0[j] = m > 0 ? m - a : m + a;
+ }
+ else {
+ freq1[j] = m > 0 ? m - a : m + a;
+ }
+ }
+ else {
+ if(mag == 0) {
+ freq0[j] = m > 0 ? m + a : m - a;
+ }
+ else {
+ freq1[j] = m > 0 ? m + a : m - a;
+ }
+
+ if(ang == 0) {
+ freq0[j] = m;
+ }
+ else {
+ freq1[j] = m;
+ }
+ }
+ }
+ }
+
+ if(channelFloors[0] != null) {
+ Floor(channelFloors[0]).computeFloor(freq0);
+ }
+
+ if(channelFloors[1] != null) {
+ Floor(channelFloors[1]).computeFloor(freq1);
+ }
+
+ // perform an inverse mdct to all channels
+ var mdct: Mdct = blockFlag ? iHeader.mdct1 : iHeader.mdct0;
+ mdct.imdct(freq0, window, pcm0);
+ mdct.imdct(freq1, window, pcm1);
+
+ if(_lastPacket) {
+ if(leftWindowEnd - leftWindowStart > _lastGranulePosition - currentGranulePosition) {
+ leftWindowEnd = leftWindowStart + _lastGranulePosition - currentGranulePosition
+ }
+ if(rightWindowStart - leftWindowStart > _lastGranulePosition - currentGranulePosition) {
+ rightWindowStart = leftWindowStart + _lastGranulePosition - currentGranulePosition
+ }
+ }
+
+ }
+
+ private function getComputedWindow(vorbis:VorbisStream):Vector.<Number> {
+
+ var i:int;
+
+ var ix:int = (blockFlag ? 4 : 0) + (previousWindowFlag ? 2 : 0) + (nextWindowFlag ? 1 : 0);
+ var w:Vector.<Number> = vorbis.windows[ix];
+
+ var x:Number;
+
+ if (w == null) {
+ w = new Vector.<Number>(n);
+
+ for(i = 0; i < leftWindowStart; i++) {
+ w[i] = 0;
+ }
+
+ for (i = 0; i < leftN; i++) {
+ x = (i + .5) / leftN * Math.PI / 2.;
+ x = Math.sin(x);
+ x *= x;
+ x *= Math.PI / 2.;
+ x = Math.sin(x);
+ w[i + leftWindowStart] = x;
+ }
+
+ for (i = leftWindowEnd; i < rightWindowStart; i++) {
+ w[i] = 1;
+ }
+
+ for (i = 0; i < rightN; i++) {
+ x = (rightN - i - .5) / rightN * Math.PI / 2.;
+ x = Math.sin(x);
+ x *= x;
+ x *= Math.PI / 2.;
+ x = Math.sin(x);
+ w[i + rightWindowStart] = x;
+ }
+
+ for(i = rightN + rightWindowStart; i < n; i++) {
+ w[i] = 0;
+ }
+
+ for(i = 0; i < w.length; i++) {
+ w[i] *= 0.5;
+ }
+
+ vorbis.windows[ix] = w;
+ }
+
+ return w;
+ }
+
+
+ public function readPcm(previousPacket:AudioPacket, target: ByteArray): int {
+
+ var j:int;
+ var j2:int;
+ var ppcm0:Vector.<Number> = previousPacket.pcm0;
+ var ppcm1:Vector.<Number> = previousPacket.pcm1;
+
+ j2 = previousPacket.rightWindowStart;
+
+ for(j = leftWindowStart; j < leftWindowEnd; j++) {
+ target.writeFloat(pcm0[j] + ppcm0[j2]);
+ target.writeFloat(pcm1[j] + ppcm1[j2++]);
+ }
+
+ for (j = leftWindowEnd; j < rightWindowStart; j++) {
+ target.writeFloat(pcm0[j]);
+ target.writeFloat(pcm1[j]);
+ }
+
+ return numberOfSamples;
+
+ }
+
+ public function get numberOfSamples():int {
+ return rightWindowStart - leftWindowStart;
+ }
+
+ public function get lastPacket(): Boolean {
+ return lastPacket;
+ }
+
+ public function get lastGranulePosition(): int {
+ return lastGranulePosition;
+ }
+
+ }
+
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.vorbis {\r
-\r
- import flash.errors.IllegalOperationError;\r
- import org.omtk.util.*;\r
-\r
- public class CodeBook {\r
-\r
- private var entries:uint;\r
- private var entryLengths:Vector.<int>;\r
- private var valueVector:Vector.<Vector.<Number>>;\r
-\r
- private var codeBookLookupType:int = -1;\r
-\r
- public var huffmanRoot:HuffmanNode;\r
- public var dimensions:uint;\r
-\r
- public function CodeBook( source: BitByteArray ) {\r
-\r
- var i:int;\r
- var j:int;\r
- \r
- var syncPattern:uint = source.readUnsignedBitwiseInt(24);\r
- if(syncPattern !=0x564342) {\r
- throw new IllegalOperationError("Illegal codebook sync pattern: "+syncPattern);\r
- }\r
- \r
- dimensions = source.readUnsignedBitwiseInt(16);\r
- entries = source.readUnsignedBitwiseInt(24);\r
- \r
- entryLengths = new Vector.<int>(entries);\r
- \r
- var ordered:Boolean = source.readBit();\r
- \r
- if(ordered) {\r
- var cl:int = source.readUnsignedBitwiseInt(5)+1;\r
- for(i=0; i<entryLengths.length; ) {\r
- var num:int = source.readUnsignedBitwiseInt(Util.ilog(entryLengths.length-i));\r
- if(i+num>entryLengths.length) {\r
- throw new Error("The codebook entry length list is longer than the actual number of entry lengths.");\r
- }\r
- for(j=i; j<i+num; j++) {\r
- entryLengths[j] = cl;\r
- }\r
- //Arrays.fill(entryLengths, i, i+num, cl);\r
- cl++;\r
- i+=num;\r
- }\r
- }\r
- else {\r
- // !ordered\r
- var sparse:Boolean = source.readBit();\r
- \r
- if(sparse) {\r
- for(i=0; i<entryLengths.length; i++) {\r
- if(source.readBit()) {\r
- entryLengths[i]=source.readUnsignedBitwiseInt(5)+1;\r
- }\r
- else {\r
- entryLengths[i]=-1;\r
- }\r
- }\r
- }\r
- else {\r
- // !sparse\r
- //Alert.show("entryLengths.length: "+entryLengths.length, "CodeBook");\r
- for(i=0; i<entryLengths.length; i++) {\r
- entryLengths[i]=source.readUnsignedBitwiseInt(5)+1;\r
- }\r
- }\r
- \r
- }\r
- \r
- if (!createHuffmanTree(entryLengths)) {\r
- throw new Error("An exception was thrown when building the codebook Huffman tree.");\r
- } \r
-\r
- codeBookLookupType = source.readUnsignedBitwiseInt(4);\r
-\r
- switch(codeBookLookupType) {\r
- case 0:\r
- // codebook has no scalar vectors to be calculated\r
- break;\r
- case 1:\r
- case 2:\r
- var codeBookMinimumValue:Number = Util.float32unpack(source.readUnsignedBitwiseInt(32));\r
- var codeBookDeltaValue:Number = Util.float32unpack(source.readUnsignedBitwiseInt(32));\r
-\r
- var codeBookValueBits:uint = source.readUnsignedBitwiseInt(4)+1;\r
- var codeBookSequenceP:Boolean = source.readBit();\r
-\r
- var codeBookLookupValues:uint = 0;\r
-\r
- if(codeBookLookupType==1) {\r
- codeBookLookupValues=Util.lookup1Values(entries, dimensions);\r
- }\r
- else {\r
- codeBookLookupValues=entries*dimensions;\r
- }\r
-\r
- var codeBookMultiplicands:Vector.<int> = new Vector.<int>(codeBookLookupValues);\r
-\r
- for(i=0; i < codeBookMultiplicands.length; i++) {\r
- codeBookMultiplicands[i]=source.readUnsignedBitwiseInt(codeBookValueBits);\r
- }\r
-\r
- valueVector = new Vector.<Vector.<Number>>(entries);\r
-\r
- if(codeBookLookupType==1) {\r
- for(i=0; i<entries; i++) {\r
- valueVector[i] = new Vector.<Number>(dimensions);\r
- var last:Number = 0.0;\r
- var indexDivisor:uint = 1;\r
- for(j=0; j<dimensions; j++) {\r
- var multiplicandOffset:int = (i/indexDivisor)%codeBookLookupValues;\r
- valueVector[i][j]=\r
- codeBookMultiplicands[multiplicandOffset]*codeBookDeltaValue+codeBookMinimumValue+last;\r
- if(codeBookSequenceP) {\r
- last = valueVector[i][j];\r
- }\r
- indexDivisor*=codeBookLookupValues;\r
- }\r
- }\r
- }\r
- else {\r
- throw new Error("Unsupported codebook lookup type: "+codeBookLookupType);\r
- /** @todo implement */\r
- }\r
- break;\r
- default:\r
- throw new Error("Unsupported codebook lookup type: "+codeBookLookupType);\r
- }\r
- }\r
- \r
- private function createHuffmanTree(entryLengths:Vector.<int>):Boolean {\r
- \r
- var i:int;\r
- \r
- huffmanRoot = new HuffmanNode();\r
- for(i=0; i<entryLengths.length; i++) {\r
- var el:int = entryLengths[i];\r
- if(el>0) {\r
- if(!huffmanRoot.setNewValue(el, i)) {\r
- return false;\r
- }\r
- }\r
- }\r
- return true;\r
- }\r
-\r
-\r
- public function readVvAdd(a0:Vector.<Number>, a1:Vector.<Number>, left:Boolean, right:Boolean, source:BitByteArray, offset:int, length:int):void {\r
- \r
- var i:int;\r
- var j:int;\r
- \r
- if (!left && !right) {\r
- return;\r
- }\r
-\r
- // 1 or 2 channels \r
- var ch:int = \r
- left && right ? 2 : 1;\r
-\r
- var lim:int;\r
- var ix:int;\r
- var ve:Vector.<Number>;\r
- \r
- if(left && right) {\r
- lim = (offset + length) / 2;\r
- var chptr:int = 0;\r
- for (i = offset / 2; i < lim;) {\r
- ix = source.readUnsignedHuffmanInt(huffmanRoot);\r
- ve = valueVector[ix];\r
- for (j = 0; j < dimensions; j++) {\r
- if(chptr == 0) {\r
- a0[i] += ve[j];\r
- }\r
- else {\r
- a1[i] += ve[j];\r
- }\r
- chptr++;\r
- if(chptr == 2) {\r
- chptr = 0;\r
- i++;\r
- }\r
- }\r
- }\r
- }\r
- else {\r
- var a : Vector.<Number> = left ? a0 : a1;\r
- lim = offset + length;\r
- for (i = offset; i < lim;) {\r
- ve = valueVector[source.readUnsignedHuffmanInt(huffmanRoot)];\r
- for (j = 0; j < dimensions; j++) {\r
- a[i] += ve[j];\r
- i++;\r
- }\r
- }\r
- }\r
-\r
- }\r
- \r
- }\r
- \r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+ import flash.errors.IllegalOperationError;
+ import org.omtk.util.*;
+
+ public class CodeBook {
+
+ private var entries:uint;
+ private var entryLengths:Vector.<int>;
+ private var valueVector:Vector.<Vector.<Number>>;
+
+ private var codeBookLookupType:int = -1;
+
+ public var huffmanRoot:HuffmanNode;
+ public var dimensions:uint;
+
+ public function CodeBook( source: BitByteArray ) {
+
+ var i:int;
+ var j:int;
+
+ var syncPattern:uint = source.readUnsignedBitwiseInt(24);
+ if(syncPattern !=0x564342) {
+ throw new IllegalOperationError("Illegal codebook sync pattern: "+syncPattern);
+ }
+
+ dimensions = source.readUnsignedBitwiseInt(16);
+ entries = source.readUnsignedBitwiseInt(24);
+
+ entryLengths = new Vector.<int>(entries);
+
+ var ordered:Boolean = source.readBit();
+
+ if(ordered) {
+ var cl:int = source.readUnsignedBitwiseInt(5)+1;
+ for(i=0; i<entryLengths.length; ) {
+ var num:int = source.readUnsignedBitwiseInt(Util.ilog(entryLengths.length-i));
+ if(i+num>entryLengths.length) {
+ throw new Error("The codebook entry length list is longer than the actual number of entry lengths.");
+ }
+ for(j=i; j<i+num; j++) {
+ entryLengths[j] = cl;
+ }
+ //Arrays.fill(entryLengths, i, i+num, cl);
+ cl++;
+ i+=num;
+ }
+ }
+ else {
+ // !ordered
+ var sparse:Boolean = source.readBit();
+
+ if(sparse) {
+ for(i=0; i<entryLengths.length; i++) {
+ if(source.readBit()) {
+ entryLengths[i]=source.readUnsignedBitwiseInt(5)+1;
+ }
+ else {
+ entryLengths[i]=-1;
+ }
+ }
+ }
+ else {
+ // !sparse
+ //Alert.show("entryLengths.length: "+entryLengths.length, "CodeBook");
+ for(i=0; i<entryLengths.length; i++) {
+ entryLengths[i]=source.readUnsignedBitwiseInt(5)+1;
+ }
+ }
+
+ }
+
+ if (!createHuffmanTree(entryLengths)) {
+ throw new Error("An exception was thrown when building the codebook Huffman tree.");
+ }
+
+ codeBookLookupType = source.readUnsignedBitwiseInt(4);
+
+ switch(codeBookLookupType) {
+ case 0:
+ // codebook has no scalar vectors to be calculated
+ break;
+ case 1:
+ case 2:
+ var codeBookMinimumValue:Number = Util.float32unpack(source.readUnsignedBitwiseInt(32));
+ var codeBookDeltaValue:Number = Util.float32unpack(source.readUnsignedBitwiseInt(32));
+
+ var codeBookValueBits:uint = source.readUnsignedBitwiseInt(4)+1;
+ var codeBookSequenceP:Boolean = source.readBit();
+
+ var codeBookLookupValues:uint = 0;
+
+ if(codeBookLookupType==1) {
+ codeBookLookupValues=Util.lookup1Values(entries, dimensions);
+ }
+ else {
+ codeBookLookupValues=entries*dimensions;
+ }
+
+ var codeBookMultiplicands:Vector.<int> = new Vector.<int>(codeBookLookupValues);
+
+ for(i=0; i < codeBookMultiplicands.length; i++) {
+ codeBookMultiplicands[i]=source.readUnsignedBitwiseInt(codeBookValueBits);
+ }
+
+ valueVector = new Vector.<Vector.<Number>>(entries);
+
+ if(codeBookLookupType==1) {
+ for(i=0; i<entries; i++) {
+ valueVector[i] = new Vector.<Number>(dimensions);
+ var last:Number = 0.0;
+ var indexDivisor:uint = 1;
+ for(j=0; j<dimensions; j++) {
+ var multiplicandOffset:int = (i/indexDivisor)%codeBookLookupValues;
+ valueVector[i][j]=
+ codeBookMultiplicands[multiplicandOffset]*codeBookDeltaValue+codeBookMinimumValue+last;
+ if(codeBookSequenceP) {
+ last = valueVector[i][j];
+ }
+ indexDivisor*=codeBookLookupValues;
+ }
+ }
+ }
+ else {
+ throw new Error("Unsupported codebook lookup type: "+codeBookLookupType);
+ /** @todo implement */
+ }
+ break;
+ default:
+ throw new Error("Unsupported codebook lookup type: "+codeBookLookupType);
+ }
+ }
+
+ private function createHuffmanTree(entryLengths:Vector.<int>):Boolean {
+
+ var i:int;
+
+ huffmanRoot = new HuffmanNode();
+ for(i=0; i<entryLengths.length; i++) {
+ var el:int = entryLengths[i];
+ if(el>0) {
+ if(!huffmanRoot.setNewValue(el, i)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+
+ public function readVvAdd(a0:Vector.<Number>, a1:Vector.<Number>, left:Boolean, right:Boolean, source:BitByteArray, offset:int, length:int):void {
+
+ var i:int;
+ var j:int;
+
+ if (!left && !right) {
+ return;
+ }
+
+ // 1 or 2 channels
+ var ch:int =
+ left && right ? 2 : 1;
+
+ var lim:int;
+ var ix:int;
+ var ve:Vector.<Number>;
+
+ if(left && right) {
+ lim = (offset + length) / 2;
+ var chptr:int = 0;
+ for (i = offset / 2; i < lim;) {
+ ix = source.readUnsignedHuffmanInt(huffmanRoot);
+ ve = valueVector[ix];
+ for (j = 0; j < dimensions; j++) {
+ if(chptr == 0) {
+ a0[i] += ve[j];
+ }
+ else {
+ a1[i] += ve[j];
+ }
+ chptr++;
+ if(chptr == 2) {
+ chptr = 0;
+ i++;
+ }
+ }
+ }
+ }
+ else {
+ var a : Vector.<Number> = left ? a0 : a1;
+ lim = offset + length;
+ for (i = offset; i < lim;) {
+ ve = valueVector[source.readUnsignedHuffmanInt(huffmanRoot)];
+ for (j = 0; j < dimensions; j++) {
+ a[i] += ve[j];
+ i++;
+ }
+ }
+ }
+
+ }
+
+ }
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.vorbis {\r
-\r
- import flash.utils.ByteArray;\r
- import flash.utils.Endian;\r
- import flash.utils.Dictionary;\r
- import org.omtk.ogg.*;\r
-\r
- public class CommentHeader {\r
- \r
- private var _vendor:String;\r
- private var _comments:Dictionary = new Dictionary();\r
- \r
- public function CommentHeader(source:ByteArray)\r
- {\r
- init( source );\r
- }\r
- \r
- private function init( source: ByteArray ): void\r
- {\r
- source.readByte();\r
- source.readByte();\r
- source.readByte();\r
- source.readByte();\r
- source.readByte();\r
- source.readByte();\r
-\r
- _vendor = readUtf8String(source);\r
- \r
- var ucLength:int = source.readUnsignedInt();\r
- \r
- for(var i:int = 0; i < ucLength; i++) {\r
- var comment:String = readUtf8String(source);\r
- var ix:int = comment.indexOf('=');\r
- var key:String = comment.substring(0, ix);\r
- var value:String = comment.substring(ix+1);\r
- _comments[key.toUpperCase()]=value;\r
- }\r
- } \r
- \r
- private function readUtf8String(source:ByteArray):String {\r
- var length:uint = source.readUnsignedInt();\r
- return source.readUTFBytes(length);\r
- }\r
- \r
- public function get vendor():String {\r
- return _vendor;\r
- }\r
- \r
- public function get comments():Dictionary {\r
- return _comments;\r
- }\r
- \r
- public function get artist():String {\r
- return _comments["ARTIST"];\r
- }\r
- \r
- public function get title():String {\r
- return _comments["TITLE"];\r
- }\r
- \r
- }\r
-\r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+ import flash.utils.ByteArray;
+ import flash.utils.Endian;
+ import flash.utils.Dictionary;
+ import org.omtk.ogg.*;
+
+ public class CommentHeader {
+
+ private var _vendor:String;
+ private var _comments:Dictionary = new Dictionary();
+
+ public function CommentHeader(source:ByteArray)
+ {
+ init( source );
+ }
+
+ private function init( source: ByteArray ): void
+ {
+ source.readByte();
+ source.readByte();
+ source.readByte();
+ source.readByte();
+ source.readByte();
+ source.readByte();
+
+ _vendor = readUtf8String(source);
+
+ var ucLength:int = source.readUnsignedInt();
+
+ for(var i:int = 0; i < ucLength; i++) {
+ var comment:String = readUtf8String(source);
+ var ix:int = comment.indexOf('=');
+ var key:String = comment.substring(0, ix);
+ var value:String = comment.substring(ix+1);
+ _comments[key.toUpperCase()]=value;
+ }
+ }
+
+ private function readUtf8String(source:ByteArray):String {
+ var length:uint = source.readUnsignedInt();
+ return source.readUTFBytes(length);
+ }
+
+ public function get vendor():String {
+ return _vendor;
+ }
+
+ public function get comments():Dictionary {
+ return _comments;
+ }
+
+ public function get artist():String {
+ return _comments["ARTIST"];
+ }
+
+ public function get title():String {
+ return _comments["TITLE"];
+ }
+
+ }
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.vorbis {\r
-\r
- import flash.errors.IllegalOperationError;\r
- import org.omtk.util.BitByteArray;\r
- \r
- public class Floor {\r
- \r
- public static const DB_STATIC_TABLE:Vector.<Number> = Vector.<Number>([\r
- 1.0649863e-07, 1.1341951e-07, 1.2079015e-07, 1.2863978e-07,\r
- 1.3699951e-07, 1.4590251e-07, 1.5538408e-07, 1.6548181e-07,\r
- 1.7623575e-07, 1.8768855e-07, 1.9988561e-07, 2.128753e-07,\r
- 2.2670913e-07, 2.4144197e-07, 2.5713223e-07, 2.7384213e-07,\r
- 2.9163793e-07, 3.1059021e-07, 3.3077411e-07, 3.5226968e-07,\r
- 3.7516214e-07, 3.9954229e-07, 4.2550680e-07, 4.5315863e-07,\r
- 4.8260743e-07, 5.1396998e-07, 5.4737065e-07, 5.8294187e-07,\r
- 6.2082472e-07, 6.6116941e-07, 7.0413592e-07, 7.4989464e-07,\r
- 7.9862701e-07, 8.5052630e-07, 9.0579828e-07, 9.6466216e-07,\r
- 1.0273513e-06, 1.0941144e-06, 1.1652161e-06, 1.2409384e-06,\r
- 1.3215816e-06, 1.4074654e-06, 1.4989305e-06, 1.5963394e-06,\r
- 1.7000785e-06, 1.8105592e-06, 1.9282195e-06, 2.0535261e-06,\r
- 2.1869758e-06, 2.3290978e-06, 2.4804557e-06, 2.6416497e-06,\r
- 2.8133190e-06, 2.9961443e-06, 3.1908506e-06, 3.3982101e-06,\r
- 3.6190449e-06, 3.8542308e-06, 4.1047004e-06, 4.3714470e-06,\r
- 4.6555282e-06, 4.9580707e-06, 5.2802740e-06, 5.6234160e-06,\r
- 5.9888572e-06, 6.3780469e-06, 6.7925283e-06, 7.2339451e-06,\r
- 7.7040476e-06, 8.2047000e-06, 8.7378876e-06, 9.3057248e-06,\r
- 9.9104632e-06, 1.0554501e-05, 1.1240392e-05, 1.1970856e-05,\r
- 1.2748789e-05, 1.3577278e-05, 1.4459606e-05, 1.5399272e-05,\r
- 1.6400004e-05, 1.7465768e-05, 1.8600792e-05, 1.9809576e-05,\r
- 2.1096914e-05, 2.2467911e-05, 2.3928002e-05, 2.5482978e-05,\r
- 2.7139006e-05, 2.8902651e-05, 3.0780908e-05, 3.2781225e-05,\r
- 3.4911534e-05, 3.7180282e-05, 3.9596466e-05, 4.2169667e-05,\r
- 4.4910090e-05, 4.7828601e-05, 5.0936773e-05, 5.4246931e-05,\r
- 5.7772202e-05, 6.1526565e-05, 6.5524908e-05, 6.9783085e-05,\r
- 7.4317983e-05, 7.9147585e-05, 8.4291040e-05, 8.9768747e-05,\r
- 9.5602426e-05, 0.00010181521, 0.00010843174, 0.00011547824,\r
- 0.00012298267, 0.00013097477, 0.00013948625, 0.00014855085,\r
- 0.00015820453, 0.00016848555, 0.00017943469, 0.00019109536,\r
- 0.00020351382, 0.00021673929, 0.00023082423, 0.00024582449,\r
- 0.00026179955, 0.00027881276, 0.00029693158, 0.00031622787,\r
- 0.00033677814, 0.00035866388, 0.00038197188, 0.00040679456,\r
- 0.00043323036, 0.00046138411, 0.00049136745, 0.00052329927,\r
- 0.00055730621, 0.00059352311, 0.00063209358, 0.00067317058,\r
- 0.00071691700, 0.00076350630, 0.00081312324, 0.00086596457,\r
- 0.00092223983, 0.00098217216, 0.0010459992, 0.0011139742,\r
- 0.0011863665, 0.0012634633, 0.0013455702, 0.0014330129,\r
- 0.0015261382, 0.0016253153, 0.0017309374, 0.0018434235,\r
- 0.0019632195, 0.0020908006, 0.0022266726, 0.0023713743,\r
- 0.0025254795, 0.0026895994, 0.0028643847, 0.0030505286,\r
- 0.0032487691, 0.0034598925, 0.0036847358, 0.0039241906,\r
- 0.0041792066, 0.0044507950, 0.0047400328, 0.0050480668,\r
- 0.0053761186, 0.0057254891, 0.0060975636, 0.0064938176,\r
- 0.0069158225, 0.0073652516, 0.0078438871, 0.0083536271,\r
- 0.0088964928, 0.009474637, 0.010090352, 0.010746080,\r
- 0.011444421, 0.012188144, 0.012980198, 0.013823725,\r
- 0.014722068, 0.015678791, 0.016697687, 0.017782797,\r
- 0.018938423, 0.020169149, 0.021479854, 0.022875735,\r
- 0.024362330, 0.025945531, 0.027631618, 0.029427276,\r
- 0.031339626, 0.033376252, 0.035545228, 0.037855157,\r
- 0.040315199, 0.042935108, 0.045725273, 0.048696758,\r
- 0.051861348, 0.055231591, 0.058820850, 0.062643361,\r
- 0.066714279, 0.071049749, 0.075666962, 0.080584227,\r
- 0.085821044, 0.091398179, 0.097337747, 0.10366330,\r
- 0.11039993, 0.11757434, 0.12521498, 0.13335215,\r
- 0.14201813, 0.15124727, 0.16107617, 0.17154380,\r
- 0.18269168, 0.19456402, 0.20720788, 0.22067342,\r
- 0.23501402, 0.25028656, 0.26655159, 0.28387361,\r
- 0.30232132, 0.32196786, 0.34289114, 0.36517414,\r
- 0.38890521, 0.41417847, 0.44109412, 0.46975890,\r
- 0.50028648, 0.53279791, 0.56742212, 0.60429640,\r
- 0.64356699, 0.68538959, 0.72993007, 0.77736504,\r
- 0.82788260, 0.88168307, 0.9389798, 1.0]);\r
- \r
- public static function createInstance(source:BitByteArray, header:SetupHeader):Floor {\r
- \r
- var type:int = source.readUnsignedBitwiseInt(16);\r
- \r
- switch (type) {\r
- case 0:\r
- return new Floor0(source, header);\r
- case 1:\r
- return new Floor1(source, header);\r
- default:\r
- throw new Error("Floor type " + type + " is not supported.");\r
- }\r
- }\r
-\r
- public function get type():int {\r
- throw new IllegalOperationError("operation not implemented");\r
- }\r
- \r
- public function decodeFloor(vorbis:VorbisStream, source:BitByteArray):Floor1 {\r
- throw new IllegalOperationError("operation not implemented");\r
- }\r
- \r
- public function computeFloor(vector:Vector.<Number>):void {\r
- throw new IllegalOperationError("operation not implemented");\r
- }\r
- \r
-\r
- }\r
-\r
- \r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+ import flash.errors.IllegalOperationError;
+ import org.omtk.util.BitByteArray;
+
+ public class Floor {
+
+ public static const DB_STATIC_TABLE:Vector.<Number> = Vector.<Number>([
+ 1.0649863e-07, 1.1341951e-07, 1.2079015e-07, 1.2863978e-07,
+ 1.3699951e-07, 1.4590251e-07, 1.5538408e-07, 1.6548181e-07,
+ 1.7623575e-07, 1.8768855e-07, 1.9988561e-07, 2.128753e-07,
+ 2.2670913e-07, 2.4144197e-07, 2.5713223e-07, 2.7384213e-07,
+ 2.9163793e-07, 3.1059021e-07, 3.3077411e-07, 3.5226968e-07,
+ 3.7516214e-07, 3.9954229e-07, 4.2550680e-07, 4.5315863e-07,
+ 4.8260743e-07, 5.1396998e-07, 5.4737065e-07, 5.8294187e-07,
+ 6.2082472e-07, 6.6116941e-07, 7.0413592e-07, 7.4989464e-07,
+ 7.9862701e-07, 8.5052630e-07, 9.0579828e-07, 9.6466216e-07,
+ 1.0273513e-06, 1.0941144e-06, 1.1652161e-06, 1.2409384e-06,
+ 1.3215816e-06, 1.4074654e-06, 1.4989305e-06, 1.5963394e-06,
+ 1.7000785e-06, 1.8105592e-06, 1.9282195e-06, 2.0535261e-06,
+ 2.1869758e-06, 2.3290978e-06, 2.4804557e-06, 2.6416497e-06,
+ 2.8133190e-06, 2.9961443e-06, 3.1908506e-06, 3.3982101e-06,
+ 3.6190449e-06, 3.8542308e-06, 4.1047004e-06, 4.3714470e-06,
+ 4.6555282e-06, 4.9580707e-06, 5.2802740e-06, 5.6234160e-06,
+ 5.9888572e-06, 6.3780469e-06, 6.7925283e-06, 7.2339451e-06,
+ 7.7040476e-06, 8.2047000e-06, 8.7378876e-06, 9.3057248e-06,
+ 9.9104632e-06, 1.0554501e-05, 1.1240392e-05, 1.1970856e-05,
+ 1.2748789e-05, 1.3577278e-05, 1.4459606e-05, 1.5399272e-05,
+ 1.6400004e-05, 1.7465768e-05, 1.8600792e-05, 1.9809576e-05,
+ 2.1096914e-05, 2.2467911e-05, 2.3928002e-05, 2.5482978e-05,
+ 2.7139006e-05, 2.8902651e-05, 3.0780908e-05, 3.2781225e-05,
+ 3.4911534e-05, 3.7180282e-05, 3.9596466e-05, 4.2169667e-05,
+ 4.4910090e-05, 4.7828601e-05, 5.0936773e-05, 5.4246931e-05,
+ 5.7772202e-05, 6.1526565e-05, 6.5524908e-05, 6.9783085e-05,
+ 7.4317983e-05, 7.9147585e-05, 8.4291040e-05, 8.9768747e-05,
+ 9.5602426e-05, 0.00010181521, 0.00010843174, 0.00011547824,
+ 0.00012298267, 0.00013097477, 0.00013948625, 0.00014855085,
+ 0.00015820453, 0.00016848555, 0.00017943469, 0.00019109536,
+ 0.00020351382, 0.00021673929, 0.00023082423, 0.00024582449,
+ 0.00026179955, 0.00027881276, 0.00029693158, 0.00031622787,
+ 0.00033677814, 0.00035866388, 0.00038197188, 0.00040679456,
+ 0.00043323036, 0.00046138411, 0.00049136745, 0.00052329927,
+ 0.00055730621, 0.00059352311, 0.00063209358, 0.00067317058,
+ 0.00071691700, 0.00076350630, 0.00081312324, 0.00086596457,
+ 0.00092223983, 0.00098217216, 0.0010459992, 0.0011139742,
+ 0.0011863665, 0.0012634633, 0.0013455702, 0.0014330129,
+ 0.0015261382, 0.0016253153, 0.0017309374, 0.0018434235,
+ 0.0019632195, 0.0020908006, 0.0022266726, 0.0023713743,
+ 0.0025254795, 0.0026895994, 0.0028643847, 0.0030505286,
+ 0.0032487691, 0.0034598925, 0.0036847358, 0.0039241906,
+ 0.0041792066, 0.0044507950, 0.0047400328, 0.0050480668,
+ 0.0053761186, 0.0057254891, 0.0060975636, 0.0064938176,
+ 0.0069158225, 0.0073652516, 0.0078438871, 0.0083536271,
+ 0.0088964928, 0.009474637, 0.010090352, 0.010746080,
+ 0.011444421, 0.012188144, 0.012980198, 0.013823725,
+ 0.014722068, 0.015678791, 0.016697687, 0.017782797,
+ 0.018938423, 0.020169149, 0.021479854, 0.022875735,
+ 0.024362330, 0.025945531, 0.027631618, 0.029427276,
+ 0.031339626, 0.033376252, 0.035545228, 0.037855157,
+ 0.040315199, 0.042935108, 0.045725273, 0.048696758,
+ 0.051861348, 0.055231591, 0.058820850, 0.062643361,
+ 0.066714279, 0.071049749, 0.075666962, 0.080584227,
+ 0.085821044, 0.091398179, 0.097337747, 0.10366330,
+ 0.11039993, 0.11757434, 0.12521498, 0.13335215,
+ 0.14201813, 0.15124727, 0.16107617, 0.17154380,
+ 0.18269168, 0.19456402, 0.20720788, 0.22067342,
+ 0.23501402, 0.25028656, 0.26655159, 0.28387361,
+ 0.30232132, 0.32196786, 0.34289114, 0.36517414,
+ 0.38890521, 0.41417847, 0.44109412, 0.46975890,
+ 0.50028648, 0.53279791, 0.56742212, 0.60429640,
+ 0.64356699, 0.68538959, 0.72993007, 0.77736504,
+ 0.82788260, 0.88168307, 0.9389798, 1.0]);
+
+ public static function createInstance(source:BitByteArray, header:SetupHeader):Floor {
+
+ var type:int = source.readUnsignedBitwiseInt(16);
+
+ switch (type) {
+ case 0:
+ return new Floor0(source, header);
+ case 1:
+ return new Floor1(source, header);
+ default:
+ throw new Error("Floor type " + type + " is not supported.");
+ }
+ }
+
+ public function get type():int {
+ throw new IllegalOperationError("operation not implemented");
+ }
+
+ public function decodeFloor(vorbis:VorbisStream, source:BitByteArray):Floor1 {
+ throw new IllegalOperationError("operation not implemented");
+ }
+
+ public function computeFloor(vector:Vector.<Number>):void {
+ throw new IllegalOperationError("operation not implemented");
+ }
+
+
+ }
+
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.vorbis {\r
-\r
- import flash.errors.IllegalOperationError;\r
- import org.omtk.util.BitByteArray;\r
- \r
- public class Floor0 extends Floor {\r
-\r
- private var order:int;\r
- private var rate:int;\r
- private var barkMapSize:int;\r
- private var amplitudeBits:int;\r
- private var amplitudeOffset:int;\r
- \r
- private var bookList:Vector.<int>;\r
- \r
- public function Floor0(source:BitByteArray, header:SetupHeader) {\r
-\r
- order = source.readUnsignedBitwiseInt(8);\r
- rate = source.readUnsignedBitwiseInt(16);\r
- barkMapSize = source.readUnsignedBitwiseInt(16);\r
- amplitudeBits = source.readUnsignedBitwiseInt(6);\r
- amplitudeOffset = source.readUnsignedBitwiseInt(8);\r
- \r
- var bookCount:uint = source.readUnsignedBitwiseInt(4) + 1;\r
- bookList = new Vector.<int>(bookCount);\r
- \r
- var i:int;\r
- \r
- for (i = 0; i < bookList.length; i++) {\r
- bookList[i] = source.readUnsignedBitwiseInt(8);\r
- if (bookList[i] > header.codeBooks.length) {\r
- throw new Error("A floor0_book_list entry is higher than the code book count.");\r
- }\r
- }\r
- }\r
-\r
- }\r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+ import flash.errors.IllegalOperationError;
+ import org.omtk.util.BitByteArray;
+
+ public class Floor0 extends Floor {
+
+ private var order:int;
+ private var rate:int;
+ private var barkMapSize:int;
+ private var amplitudeBits:int;
+ private var amplitudeOffset:int;
+
+ private var bookList:Vector.<int>;
+
+ public function Floor0(source:BitByteArray, header:SetupHeader) {
+
+ order = source.readUnsignedBitwiseInt(8);
+ rate = source.readUnsignedBitwiseInt(16);
+ barkMapSize = source.readUnsignedBitwiseInt(16);
+ amplitudeBits = source.readUnsignedBitwiseInt(6);
+ amplitudeOffset = source.readUnsignedBitwiseInt(8);
+
+ var bookCount:uint = source.readUnsignedBitwiseInt(4) + 1;
+ bookList = new Vector.<int>(bookCount);
+
+ var i:int;
+
+ for (i = 0; i < bookList.length; i++) {
+ bookList[i] = source.readUnsignedBitwiseInt(8);
+ if (bookList[i] > header.codeBooks.length) {
+ throw new Error("A floor0_book_list entry is higher than the code book count.");
+ }
+ }
+ }
+
+ }
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.vorbis {\r
-\r
- import flash.errors.IllegalOperationError;\r
- import org.omtk.util.*;\r
- \r
- public class Floor1 extends Floor {\r
-\r
- private var partitionClassList:Vector.<int>;\r
- private var maximumClass:int;\r
- private var multiplier:int;\r
- private var rangeBits:int;\r
- private var classDimensions:Vector.<int>;\r
- private var classSubclasses:Vector.<int>;\r
- private var classMasterbooks:Vector.<int>;\r
- private var subclassBooks:Vector.<Vector.<int>>;\r
- private var xList:Vector.<int>;\r
- private var yList:Vector.<int>;\r
- private var lowNeighbours:Vector.<int>;\r
- private var highNeighbours:Vector.<int>;\r
- private static var RANGES:Vector.<int> = Vector.<int>([256, 128, 86, 64]);\r
-\r
- private var xList2:Vector.<int>;\r
- private var step2Flags:Vector.<Boolean>;\r
- \r
- public function Floor1(source:BitByteArray = null, header:SetupHeader = null) {\r
-\r
- if(source==null && header==null) {\r
- return;\r
- }\r
- \r
- var i:int;\r
- var j:int;\r
- \r
- maximumClass = -1;\r
- var partitions:int = source.readUnsignedBitwiseInt(5);\r
- partitionClassList = new Vector.<int>(partitions);\r
- \r
- for (i = 0; i < partitionClassList.length; i++) {\r
- partitionClassList[i] = source.readUnsignedBitwiseInt(4);\r
- if (partitionClassList[i] > maximumClass) {\r
- maximumClass = partitionClassList[i];\r
- }\r
- }\r
- \r
- classDimensions = new Vector.<int>(maximumClass + 1);\r
- classSubclasses = new Vector.<int>(maximumClass + 1);\r
- classMasterbooks = new Vector.<int>(maximumClass + 1);\r
- subclassBooks = new Vector.<Vector.<int>>(maximumClass + 1);\r
- \r
- var xListLength:int = 2;\r
- \r
- for (i = 0; i <= maximumClass; i++) {\r
- classDimensions[i] = source.readUnsignedBitwiseInt(3) + 1;\r
- xListLength += classDimensions[i];\r
- classSubclasses[i] = source.readUnsignedBitwiseInt(2);\r
- \r
- if (classDimensions[i] > header.codeBooks.length || classSubclasses[i] > header.codeBooks.length) {\r
- throw new Error("There is a class dimension or class subclasses entry higher than the number of codebooks in the setup header.");\r
- }\r
- if (classSubclasses[i] != 0) {\r
- classMasterbooks[i] = source.readUnsignedBitwiseInt(8);\r
- }\r
- subclassBooks[i] = new Vector.<int>(1 << classSubclasses[i]);\r
- for (j = 0; j < subclassBooks[i].length; j++) {\r
- subclassBooks[i][j] = source.readUnsignedBitwiseInt(8) - 1;\r
- }\r
- }\r
- \r
- multiplier = source.readUnsignedBitwiseInt(2) + 1;\r
- rangeBits = source.readUnsignedBitwiseInt(4);\r
- \r
- var floorValues:int = 0;\r
- \r
- xList = Vector.<int>([0, 1<<rangeBits]);\r
- \r
- for (i = 0; i < partitions; i++) {\r
- for (j = 0; j < classDimensions[partitionClassList[i]]; j++) {\r
- xList.push(source.readUnsignedBitwiseInt(rangeBits));\r
- }\r
- }\r
- \r
- lowNeighbours = new Vector.<int>(xList.length);\r
- highNeighbours = new Vector.<int>(xList.length);\r
- \r
- for (i = 0; i < xList.length; i++) {\r
- lowNeighbours[i] = Util.lowNeighbour(xList, i);\r
- highNeighbours[i] = Util.highNeighbour(xList, i);\r
- }\r
- \r
- xList2 = new Vector.<int>(xList.length, true);\r
- step2Flags = new Vector.<Boolean>(xList.length, true);\r
- }\r
-\r
- public override function get type():int {\r
- return 1;\r
- }\r
-\r
- public override function decodeFloor(vorbis:VorbisStream, source:BitByteArray):Floor1 {\r
-\r
- var i:int;\r
- var j:int;\r
- var offset:int;\r
-\r
- if (!source.readBit()) {\r
- return null;\r
- }\r
- \r
- var clone:Floor1 = clone();\r
- \r
- clone.yList = new Vector.<int>(xList.length);\r
- \r
- var range:int = RANGES[multiplier - 1];\r
- \r
- clone.yList[0] = source.readUnsignedBitwiseInt(Util.ilog(range - 1));\r
- clone.yList[1] = source.readUnsignedBitwiseInt(Util.ilog(range - 1));\r
- \r
- offset = 2;\r
- \r
- for (i = 0; i < partitionClassList.length; i++) {\r
- var cls:int = partitionClassList[i];\r
- var cdim:int = classDimensions[cls];\r
- var cbits:int = classSubclasses[cls];\r
- var csub:int = (1 << cbits) - 1;\r
- var cval:int = 0;\r
- if (cbits > 0) {\r
- cval = source.readUnsignedHuffmanInt(vorbis.setupHeader.codeBooks[classMasterbooks[cls]].huffmanRoot);\r
- }\r
-\r
- for (j = 0; j < cdim; j++) {\r
- var book:int = subclassBooks[cls][cval & csub];\r
- cval >>>= cbits;\r
- if (book >= 0) {\r
- clone.yList[j + offset] = source.readUnsignedHuffmanInt(vorbis.setupHeader.codeBooks[book].huffmanRoot);\r
- } else {\r
- clone.yList[j + offset] = 0;\r
- }\r
- }\r
- offset += cdim;\r
- }\r
- \r
- return clone;\r
- }\r
- \r
- public override function computeFloor(vector:Vector.<Number>):void {\r
-\r
- var i:int;\r
- var j:int;\r
-\r
- var n:int = vector.length;\r
- var values:int = xList.length;\r
- //var step2Flags:Vector.<Boolean> = new Vector.<Boolean>(values);\r
-\r
- var range:int = RANGES[multiplier - 1];\r
- \r
- for (i = 2; i < values; i++) {\r
-\r
- var lowNeighbourOffset:int = lowNeighbours[i];\r
- var highNeighbourOffset:int = highNeighbours[i];\r
- \r
- var predicted:int = Util.renderPoint(\r
- xList[lowNeighbourOffset], xList[highNeighbourOffset], \r
- yList[lowNeighbourOffset], yList[highNeighbourOffset], xList[i]);\r
- \r
- var val:int = yList[i];\r
- var highRoom:int = range - predicted;\r
- var lowRoom:int = predicted;\r
- var room:int = highRoom < lowRoom ? highRoom * 2 : lowRoom * 2;\r
- \r
- if (val != 0) {\r
- step2Flags[lowNeighbourOffset] = true;\r
- step2Flags[highNeighbourOffset] = true;\r
- step2Flags[i] = true;\r
- if (val >= room) {\r
- yList[i] = highRoom > lowRoom ? val - lowRoom + predicted\r
- : -val + highRoom + predicted - 1;\r
- } else {\r
- yList[i] = (val & 1) == 1 ? predicted - ((val + 1) >> 1)\r
- : predicted + (val >> 1);\r
- }\r
- } else {\r
- step2Flags[i] = false;\r
- yList[i] = predicted;\r
- }\r
- }\r
- \r
- for(i=0; i<xList.length; i++) {\r
- xList2[i] = xList[i];\r
- }\r
-\r
- sort(xList2, yList, step2Flags);\r
- \r
- var hx:int = 0;\r
- var hy:int = 0;\r
- var lx:int = 0;\r
- var ly:int = yList[0] * multiplier;\r
- \r
- for (i = 1; i < values; i++) {\r
- if (step2Flags[i]) {\r
- hy = yList[i] * multiplier;\r
- hx = xList2[i];\r
- Util.renderLine(lx, ly, hx, hy, vector);\r
- lx = hx;\r
- ly = hy;\r
- }\r
- }\r
- \r
- var r:Number = DB_STATIC_TABLE[hy];\r
-\r
- while(hx < n/2) {\r
- vector[hx++] = r;\r
- }\r
-\r
- }\r
-\r
- public function clone():Floor1 {\r
- var clone:Floor1 = new Floor1();\r
- clone.classDimensions = classDimensions;\r
- clone.classMasterbooks = classMasterbooks;\r
- clone.classSubclasses = classSubclasses;\r
- clone.maximumClass = maximumClass;\r
- clone.multiplier = multiplier;\r
- clone.partitionClassList = partitionClassList;\r
- clone.rangeBits = rangeBits;\r
- clone.subclassBooks = subclassBooks;\r
- clone.xList = xList;\r
- clone.yList = yList;\r
- clone.lowNeighbours = lowNeighbours;\r
- clone.highNeighbours = highNeighbours;\r
- clone.xList2 = xList2;\r
- clone.step2Flags = step2Flags;\r
- return clone;\r
- }\r
- \r
- private function sort(x:Vector.<int>, y:Vector.<int>, b:Vector.<Boolean>):void {\r
- var off:int = 0;\r
- var len:int = x.length;\r
- var lim:int = len + off;\r
- var itmp:int;\r
- var btmp:Boolean;\r
- var i:int;\r
- var j:int;\r
- // Insertion sort on smallest arrays\r
- for (i = off; i < lim; i++) {\r
- for (j = i; j > off && x[j - 1] > x[j]; j--) {\r
- itmp = x[j];\r
- x[j] = x[j - 1];\r
- x[j - 1] = itmp;\r
- itmp = y[j];\r
- y[j] = y[j - 1];\r
- y[j - 1] = itmp;\r
- btmp = b[j];\r
- b[j] = b[j - 1];\r
- b[j - 1] = btmp;\r
- }\r
- }\r
- }\r
-\r
- }\r
- \r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+ import flash.errors.IllegalOperationError;
+ import org.omtk.util.*;
+
+ public class Floor1 extends Floor {
+
+ private var partitionClassList:Vector.<int>;
+ private var maximumClass:int;
+ private var multiplier:int;
+ private var rangeBits:int;
+ private var classDimensions:Vector.<int>;
+ private var classSubclasses:Vector.<int>;
+ private var classMasterbooks:Vector.<int>;
+ private var subclassBooks:Vector.<Vector.<int>>;
+ private var xList:Vector.<int>;
+ private var yList:Vector.<int>;
+ private var lowNeighbours:Vector.<int>;
+ private var highNeighbours:Vector.<int>;
+ private static var RANGES:Vector.<int> = Vector.<int>([256, 128, 86, 64]);
+
+ private var xList2:Vector.<int>;
+ private var step2Flags:Vector.<Boolean>;
+
+ public function Floor1(source:BitByteArray = null, header:SetupHeader = null) {
+
+ if(source==null && header==null) {
+ return;
+ }
+
+ var i:int;
+ var j:int;
+
+ maximumClass = -1;
+ var partitions:int = source.readUnsignedBitwiseInt(5);
+ partitionClassList = new Vector.<int>(partitions);
+
+ for (i = 0; i < partitionClassList.length; i++) {
+ partitionClassList[i] = source.readUnsignedBitwiseInt(4);
+ if (partitionClassList[i] > maximumClass) {
+ maximumClass = partitionClassList[i];
+ }
+ }
+
+ classDimensions = new Vector.<int>(maximumClass + 1);
+ classSubclasses = new Vector.<int>(maximumClass + 1);
+ classMasterbooks = new Vector.<int>(maximumClass + 1);
+ subclassBooks = new Vector.<Vector.<int>>(maximumClass + 1);
+
+ var xListLength:int = 2;
+
+ for (i = 0; i <= maximumClass; i++) {
+ classDimensions[i] = source.readUnsignedBitwiseInt(3) + 1;
+ xListLength += classDimensions[i];
+ classSubclasses[i] = source.readUnsignedBitwiseInt(2);
+
+ if (classDimensions[i] > header.codeBooks.length || classSubclasses[i] > header.codeBooks.length) {
+ throw new Error("There is a class dimension or class subclasses entry higher than the number of codebooks in the setup header.");
+ }
+ if (classSubclasses[i] != 0) {
+ classMasterbooks[i] = source.readUnsignedBitwiseInt(8);
+ }
+ subclassBooks[i] = new Vector.<int>(1 << classSubclasses[i]);
+ for (j = 0; j < subclassBooks[i].length; j++) {
+ subclassBooks[i][j] = source.readUnsignedBitwiseInt(8) - 1;
+ }
+ }
+
+ multiplier = source.readUnsignedBitwiseInt(2) + 1;
+ rangeBits = source.readUnsignedBitwiseInt(4);
+
+ var floorValues:int = 0;
+
+ xList = Vector.<int>([0, 1<<rangeBits]);
+
+ for (i = 0; i < partitions; i++) {
+ for (j = 0; j < classDimensions[partitionClassList[i]]; j++) {
+ xList.push(source.readUnsignedBitwiseInt(rangeBits));
+ }
+ }
+
+ lowNeighbours = new Vector.<int>(xList.length);
+ highNeighbours = new Vector.<int>(xList.length);
+
+ for (i = 0; i < xList.length; i++) {
+ lowNeighbours[i] = Util.lowNeighbour(xList, i);
+ highNeighbours[i] = Util.highNeighbour(xList, i);
+ }
+
+ xList2 = new Vector.<int>(xList.length, true);
+ step2Flags = new Vector.<Boolean>(xList.length, true);
+ }
+
+ public override function get type():int {
+ return 1;
+ }
+
+ public override function decodeFloor(vorbis:VorbisStream, source:BitByteArray):Floor1 {
+
+ var i:int;
+ var j:int;
+ var offset:int;
+
+ if (!source.readBit()) {
+ return null;
+ }
+
+ var clone:Floor1 = clone();
+
+ clone.yList = new Vector.<int>(xList.length);
+
+ var range:int = RANGES[multiplier - 1];
+
+ clone.yList[0] = source.readUnsignedBitwiseInt(Util.ilog(range - 1));
+ clone.yList[1] = source.readUnsignedBitwiseInt(Util.ilog(range - 1));
+
+ offset = 2;
+
+ for (i = 0; i < partitionClassList.length; i++) {
+ var cls:int = partitionClassList[i];
+ var cdim:int = classDimensions[cls];
+ var cbits:int = classSubclasses[cls];
+ var csub:int = (1 << cbits) - 1;
+ var cval:int = 0;
+ if (cbits > 0) {
+ cval = source.readUnsignedHuffmanInt(vorbis.setupHeader.codeBooks[classMasterbooks[cls]].huffmanRoot);
+ }
+
+ for (j = 0; j < cdim; j++) {
+ var book:int = subclassBooks[cls][cval & csub];
+ cval >>>= cbits;
+ if (book >= 0) {
+ clone.yList[j + offset] = source.readUnsignedHuffmanInt(vorbis.setupHeader.codeBooks[book].huffmanRoot);
+ } else {
+ clone.yList[j + offset] = 0;
+ }
+ }
+ offset += cdim;
+ }
+
+ return clone;
+ }
+
+ public override function computeFloor(vector:Vector.<Number>):void {
+
+ var i:int;
+ var j:int;
+
+ var n:int = vector.length;
+ var values:int = xList.length;
+ //var step2Flags:Vector.<Boolean> = new Vector.<Boolean>(values);
+
+ var range:int = RANGES[multiplier - 1];
+
+ for (i = 2; i < values; i++) {
+
+ var lowNeighbourOffset:int = lowNeighbours[i];
+ var highNeighbourOffset:int = highNeighbours[i];
+
+ var predicted:int = Util.renderPoint(
+ xList[lowNeighbourOffset], xList[highNeighbourOffset],
+ yList[lowNeighbourOffset], yList[highNeighbourOffset], xList[i]);
+
+ var val:int = yList[i];
+ var highRoom:int = range - predicted;
+ var lowRoom:int = predicted;
+ var room:int = highRoom < lowRoom ? highRoom * 2 : lowRoom * 2;
+
+ if (val != 0) {
+ step2Flags[lowNeighbourOffset] = true;
+ step2Flags[highNeighbourOffset] = true;
+ step2Flags[i] = true;
+ if (val >= room) {
+ yList[i] = highRoom > lowRoom ? val - lowRoom + predicted
+ : -val + highRoom + predicted - 1;
+ } else {
+ yList[i] = (val & 1) == 1 ? predicted - ((val + 1) >> 1)
+ : predicted + (val >> 1);
+ }
+ } else {
+ step2Flags[i] = false;
+ yList[i] = predicted;
+ }
+ }
+
+ for(i=0; i<xList.length; i++) {
+ xList2[i] = xList[i];
+ }
+
+ sort(xList2, yList, step2Flags);
+
+ var hx:int = 0;
+ var hy:int = 0;
+ var lx:int = 0;
+ var ly:int = yList[0] * multiplier;
+
+ for (i = 1; i < values; i++) {
+ if (step2Flags[i]) {
+ hy = yList[i] * multiplier;
+ hx = xList2[i];
+ Util.renderLine(lx, ly, hx, hy, vector);
+ lx = hx;
+ ly = hy;
+ }
+ }
+
+ var r:Number = DB_STATIC_TABLE[hy];
+
+ while(hx < n/2) {
+ vector[hx++] = r;
+ }
+
+ }
+
+ public function clone():Floor1 {
+ var clone:Floor1 = new Floor1();
+ clone.classDimensions = classDimensions;
+ clone.classMasterbooks = classMasterbooks;
+ clone.classSubclasses = classSubclasses;
+ clone.maximumClass = maximumClass;
+ clone.multiplier = multiplier;
+ clone.partitionClassList = partitionClassList;
+ clone.rangeBits = rangeBits;
+ clone.subclassBooks = subclassBooks;
+ clone.xList = xList;
+ clone.yList = yList;
+ clone.lowNeighbours = lowNeighbours;
+ clone.highNeighbours = highNeighbours;
+ clone.xList2 = xList2;
+ clone.step2Flags = step2Flags;
+ return clone;
+ }
+
+ private function sort(x:Vector.<int>, y:Vector.<int>, b:Vector.<Boolean>):void {
+ var off:int = 0;
+ var len:int = x.length;
+ var lim:int = len + off;
+ var itmp:int;
+ var btmp:Boolean;
+ var i:int;
+ var j:int;
+ // Insertion sort on smallest arrays
+ for (i = off; i < lim; i++) {
+ for (j = i; j > off && x[j - 1] > x[j]; j--) {
+ itmp = x[j];
+ x[j] = x[j - 1];
+ x[j - 1] = itmp;
+ itmp = y[j];
+ y[j] = y[j - 1];
+ y[j - 1] = itmp;
+ btmp = b[j];
+ b[j] = b[j - 1];
+ b[j - 1] = btmp;
+ }
+ }
+ }
+
+ }
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.vorbis {\r
-\r
- import flash.utils.ByteArray;\r
- \r
- public class IdentificationHeader {\r
- \r
- private var _version:uint;\r
- private var _channels:uint;\r
- private var _sampleRate:uint;\r
- private var _bitrateMaximum:int;\r
- private var _bitrateMinimum:int;\r
- private var _bitrateNominal:int;\r
- private var _blockSize0:uint;\r
- private var _blockSize1:uint;\r
- \r
- private var _mdct:Vector.<Mdct>;\r
-\r
- public function IdentificationHeader(source:ByteArray) {\r
-\r
- source.readByte();\r
- source.readByte();\r
- source.readByte();\r
- source.readByte();\r
- source.readByte();\r
- source.readByte();\r
- \r
- _version = source.readUnsignedInt();\r
- _channels = source.readUnsignedByte();\r
- _sampleRate = source.readUnsignedInt();\r
- _bitrateMaximum = source.readUnsignedInt();\r
- _bitrateNominal = source.readUnsignedInt();\r
- _bitrateMinimum = source.readUnsignedInt();\r
- var bs:int = source.readUnsignedByte();\r
- _blockSize0 = 1<<(bs&0xf);\r
- _blockSize1 = 1<<(bs>>4);\r
- \r
- _mdct = new Vector.<Mdct>(2, false);\r
- _mdct[0] = new Mdct(_blockSize0);\r
- _mdct[1] = new Mdct(_blockSize1);\r
- }\r
- \r
- public function get channels():uint {\r
- return _channels;\r
- }\r
- \r
- public function get sampleRate():uint {\r
- return _sampleRate;\r
- }\r
- \r
- public function get blockSize0():uint {\r
- return _blockSize0;\r
- }\r
- \r
- public function get blockSize1():uint {\r
- return _blockSize1;\r
- }\r
- \r
- public function get mdct0():Mdct {\r
- return _mdct[0];\r
- }\r
- \r
- public function get mdct1():Mdct {\r
- return _mdct[1];\r
- }\r
-\r
- }\r
-\r
-\r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+ import flash.utils.ByteArray;
+
+ public class IdentificationHeader {
+
+ private var _version:uint;
+ private var _channels:uint;
+ private var _sampleRate:uint;
+ private var _bitrateMaximum:int;
+ private var _bitrateMinimum:int;
+ private var _bitrateNominal:int;
+ private var _blockSize0:uint;
+ private var _blockSize1:uint;
+
+ private var _mdct:Vector.<Mdct>;
+
+ public function IdentificationHeader(source:ByteArray) {
+
+ source.readByte();
+ source.readByte();
+ source.readByte();
+ source.readByte();
+ source.readByte();
+ source.readByte();
+
+ _version = source.readUnsignedInt();
+ _channels = source.readUnsignedByte();
+ _sampleRate = source.readUnsignedInt();
+ _bitrateMaximum = source.readUnsignedInt();
+ _bitrateNominal = source.readUnsignedInt();
+ _bitrateMinimum = source.readUnsignedInt();
+ var bs:int = source.readUnsignedByte();
+ _blockSize0 = 1<<(bs&0xf);
+ _blockSize1 = 1<<(bs>>4);
+
+ _mdct = new Vector.<Mdct>(2, false);
+ _mdct[0] = new Mdct(_blockSize0);
+ _mdct[1] = new Mdct(_blockSize1);
+ }
+
+ public function get channels():uint {
+ return _channels;
+ }
+
+ public function get sampleRate():uint {
+ return _sampleRate;
+ }
+
+ public function get blockSize0():uint {
+ return _blockSize0;
+ }
+
+ public function get blockSize1():uint {
+ return _blockSize1;
+ }
+
+ public function get mdct0():Mdct {
+ return _mdct[0];
+ }
+
+ public function get mdct1():Mdct {
+ return _mdct[1];
+ }
+
+ }
+
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.vorbis {\r
-\r
- import org.omtk.util.BitByteArray;\r
- \r
- public class Look {\r
- \r
- private var _map:int;\r
- private var _parts:int;\r
- private var _stages:int;\r
- private var _fullbooks:Vector.<CodeBook>;\r
- private var _phrasebook:CodeBook;\r
- private var _partbooks:Vector.<Vector.<int>>;\r
- private var _partvals:int;\r
- private var _decodemap:Vector.<Vector.<int>>;\r
- private var _postbits:int;\r
- private var _phrasebits:int;\r
- private var _frames:int;\r
-\r
- public function Look(source:VorbisStream, residue:Residue, mode:Mode) {\r
- \r
- var i:int;\r
- var j:int;\r
- var k:int;\r
- \r
- var dim:int = 0;\r
- var acc:int = 0;\r
- var maxstage:int = 0;\r
-\r
- _map = mode.mapping;\r
- \r
- _parts = residue.classifications;\r
- _fullbooks = source.setupHeader.codeBooks;\r
- _phrasebook = _fullbooks[residue.classBook];\r
- dim = _phrasebook.dimensions;\r
-\r
- _partbooks = new Vector.<Vector.<int>>(_parts);\r
-\r
- for (j = 0; j < _parts; j++) {\r
- var s:int = Util.ilog(residue.cascade[j]);\r
- if (s != 0) {\r
- if (s > maxstage) {\r
- maxstage = s;\r
- }\r
- _partbooks[j] = new Vector.<int>(s);\r
- for (k = 0; k < s; k++) {\r
- if ((residue.cascade[j] & (1 << k)) != 0) {\r
- _partbooks[j][k] = residue.books[j][k];\r
- }\r
- }\r
- }\r
- }\r
-\r
- _partvals = Math.round(Math.pow(_parts, dim));\r
- _stages = maxstage;\r
-\r
- _decodemap = new Vector.<Vector.<int>>(_partvals, true);\r
-\r
- for (j = 0; j < _partvals; j++) {\r
- var val:int = j;\r
- var mult:int = _partvals / _parts;\r
- _decodemap[j] = new Vector.<int>(dim);\r
-\r
- for (k = 0; k < dim; k++) {\r
- var deco:int = val / mult;\r
- val -= deco * mult;\r
- mult /= _parts;\r
- _decodemap[j][k] = deco;\r
- }\r
- }\r
- }\r
-\r
- public function get map():int {\r
- return _map;\r
- }\r
- \r
- public function get parts():int {\r
- return _parts;\r
- }\r
- \r
- public function get stages():int {\r
- return _stages;\r
- }\r
- \r
- public function get fullbooks():Vector.<CodeBook> {\r
- return _fullbooks;\r
- }\r
- \r
- public function get phrasebook():CodeBook {\r
- return _phrasebook;\r
- }\r
- \r
- public function get partbooks():Vector.<Vector.<int>> {\r
- return _partbooks;\r
- }\r
- \r
- public function get partvals():int {\r
- return _partvals;\r
- }\r
- \r
- public function get decodemap():Vector.<Vector.<int>> {\r
- return _decodemap;\r
- }\r
- \r
- public function get postbits():int {\r
- return _postbits;\r
- }\r
- \r
- public function get phrasebits():int {\r
- return _phrasebits;\r
- }\r
- \r
- public function get frames():int {\r
- return _frames;\r
- }\r
- \r
- }\r
- \r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+ import org.omtk.util.BitByteArray;
+
+ public class Look {
+
+ private var _map:int;
+ private var _parts:int;
+ private var _stages:int;
+ private var _fullbooks:Vector.<CodeBook>;
+ private var _phrasebook:CodeBook;
+ private var _partbooks:Vector.<Vector.<int>>;
+ private var _partvals:int;
+ private var _decodemap:Vector.<Vector.<int>>;
+ private var _postbits:int;
+ private var _phrasebits:int;
+ private var _frames:int;
+
+ public function Look(source:VorbisStream, residue:Residue, mode:Mode) {
+
+ var i:int;
+ var j:int;
+ var k:int;
+
+ var dim:int = 0;
+ var acc:int = 0;
+ var maxstage:int = 0;
+
+ _map = mode.mapping;
+
+ _parts = residue.classifications;
+ _fullbooks = source.setupHeader.codeBooks;
+ _phrasebook = _fullbooks[residue.classBook];
+ dim = _phrasebook.dimensions;
+
+ _partbooks = new Vector.<Vector.<int>>(_parts);
+
+ for (j = 0; j < _parts; j++) {
+ var s:int = Util.ilog(residue.cascade[j]);
+ if (s != 0) {
+ if (s > maxstage) {
+ maxstage = s;
+ }
+ _partbooks[j] = new Vector.<int>(s);
+ for (k = 0; k < s; k++) {
+ if ((residue.cascade[j] & (1 << k)) != 0) {
+ _partbooks[j][k] = residue.books[j][k];
+ }
+ }
+ }
+ }
+
+ _partvals = Math.round(Math.pow(_parts, dim));
+ _stages = maxstage;
+
+ _decodemap = new Vector.<Vector.<int>>(_partvals, true);
+
+ for (j = 0; j < _partvals; j++) {
+ var val:int = j;
+ var mult:int = _partvals / _parts;
+ _decodemap[j] = new Vector.<int>(dim);
+
+ for (k = 0; k < dim; k++) {
+ var deco:int = val / mult;
+ val -= deco * mult;
+ mult /= _parts;
+ _decodemap[j][k] = deco;
+ }
+ }
+ }
+
+ public function get map():int {
+ return _map;
+ }
+
+ public function get parts():int {
+ return _parts;
+ }
+
+ public function get stages():int {
+ return _stages;
+ }
+
+ public function get fullbooks():Vector.<CodeBook> {
+ return _fullbooks;
+ }
+
+ public function get phrasebook():CodeBook {
+ return _phrasebook;
+ }
+
+ public function get partbooks():Vector.<Vector.<int>> {
+ return _partbooks;
+ }
+
+ public function get partvals():int {
+ return _partvals;
+ }
+
+ public function get decodemap():Vector.<Vector.<int>> {
+ return _decodemap;
+ }
+
+ public function get postbits():int {
+ return _postbits;
+ }
+
+ public function get phrasebits():int {
+ return _phrasebits;
+ }
+
+ public function get frames():int {
+ return _frames;
+ }
+
+ }
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.vorbis {\r
-\r
- import flash.errors.IllegalOperationError;\r
- import org.omtk.util.BitByteArray;\r
-\r
- public class Mapping {\r
- \r
- public static function createInstance(stream:VorbisStream, source:BitByteArray, header:SetupHeader):Mapping {\r
- \r
- var type:int = source.readUnsignedBitwiseInt(16);\r
- switch (type) {\r
- case 0:\r
- return new Mapping0(stream, source, header);\r
- default:\r
- throw new Error("Mapping type " + type + " is not supported.");\r
- }\r
- \r
- }\r
- \r
- public function get type():int {\r
- throw new IllegalOperationError("not implemented");\r
- }\r
- \r
- public function get couplingSteps():int {\r
- throw new IllegalOperationError("not implemented");\r
- }\r
-\r
- public function get submaps():int {\r
- throw new IllegalOperationError("not implemented");\r
- }\r
-\r
- public function get angles():Vector.<int> {\r
- throw new IllegalOperationError("not implemented");\r
- }\r
-\r
- public function get magnitudes():Vector.<int> {\r
- throw new IllegalOperationError("not implemented");\r
- }\r
-\r
- public function get mux():Vector.<int> {\r
- throw new IllegalOperationError("not implemented");\r
- }\r
-\r
- public function get submapFloors():Vector.<int> {\r
- throw new IllegalOperationError("not implemented");\r
- }\r
-\r
- public function get submapResidues():Vector.<int> {\r
- throw new IllegalOperationError("not implemented");\r
- }\r
-\r
- \r
- }\r
-\r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+ import flash.errors.IllegalOperationError;
+ import org.omtk.util.BitByteArray;
+
+ public class Mapping {
+
+ public static function createInstance(stream:VorbisStream, source:BitByteArray, header:SetupHeader):Mapping {
+
+ var type:int = source.readUnsignedBitwiseInt(16);
+ switch (type) {
+ case 0:
+ return new Mapping0(stream, source, header);
+ default:
+ throw new Error("Mapping type " + type + " is not supported.");
+ }
+
+ }
+
+ public function get type():int {
+ throw new IllegalOperationError("not implemented");
+ }
+
+ public function get couplingSteps():int {
+ throw new IllegalOperationError("not implemented");
+ }
+
+ public function get submaps():int {
+ throw new IllegalOperationError("not implemented");
+ }
+
+ public function get angles():Vector.<int> {
+ throw new IllegalOperationError("not implemented");
+ }
+
+ public function get magnitudes():Vector.<int> {
+ throw new IllegalOperationError("not implemented");
+ }
+
+ public function get mux():Vector.<int> {
+ throw new IllegalOperationError("not implemented");
+ }
+
+ public function get submapFloors():Vector.<int> {
+ throw new IllegalOperationError("not implemented");
+ }
+
+ public function get submapResidues():Vector.<int> {
+ throw new IllegalOperationError("not implemented");
+ }
+
+
+ }
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.vorbis {\r
-\r
- import flash.errors.IllegalOperationError;\r
- import org.omtk.util.BitByteArray;\r
-\r
- public class Mapping0 extends Mapping {\r
- \r
- private var _magnitudes:Vector.<int>;\r
- private var _angles:Vector.<int>;\r
- private var _mux:Vector.<int>;\r
- private var _submapFloors:Vector.<int>;\r
- private var _submapResidues:Vector.<int>;\r
- \r
- public function Mapping0(stream:VorbisStream, source:BitByteArray, header:SetupHeader) {\r
-\r
- var i:int;\r
- var j:int;\r
- \r
- var submaps:int = 1;\r
- \r
- if (source.readBit()) {\r
- submaps = source.readUnsignedBitwiseInt(4) + 1;\r
- }\r
- \r
- var channels:int = stream.identificationHeader.channels;\r
- var ilogChannels:int = Util.ilog(channels - 1);\r
- \r
- if (source.readBit()) {\r
- var couplingSteps:int = source.readUnsignedBitwiseInt(8) + 1;\r
- _magnitudes = new Vector.<int>(couplingSteps);\r
- _angles = new Vector.<int>(couplingSteps);\r
- \r
- for (i = 0; i < couplingSteps; i++) {\r
- magnitudes[i] = source.readUnsignedBitwiseInt(ilogChannels);\r
- angles[i] = source.readUnsignedBitwiseInt(ilogChannels);\r
- if (magnitudes[i] == angles[i] || magnitudes[i] >= channels\r
- || angles[i] >= channels) {\r
- throw new Error("The channel magnitude and/or angle mismatch.");\r
- }\r
- }\r
- } else {\r
- _magnitudes = Vector.<int>([]);\r
- _angles = Vector.<int>([]);\r
- }\r
- \r
- if (source.readUnsignedBitwiseInt(2) != 0) {\r
- throw new Error("A reserved mapping field has an invalid value.");\r
- }\r
- \r
- _mux = new Vector.<int>(channels);\r
- if (submaps > 1) {\r
- for (i = 0; i < channels; i++) {\r
- _mux[i] = source.readUnsignedBitwiseInt(4);\r
- if (_mux[i] > submaps) {\r
- throw new Error("A mapping mux value is higher than the number of submaps");\r
- }\r
- }\r
- } else {\r
- for (i = 0; i < channels; i++) {\r
- _mux[i] = 0;\r
- }\r
- }\r
- \r
- _submapFloors = new Vector.<int>(submaps);\r
- _submapResidues = new Vector.<int>(submaps);\r
- \r
- var floorCount:int = header.floors.length;\r
- var residueCount:int = header.residues.length;\r
- \r
- for (i = 0; i < submaps; i++) {\r
- source.readUnsignedBitwiseInt(8); // discard time placeholder\r
- _submapFloors[i] = source.readUnsignedBitwiseInt(8);\r
- _submapResidues[i] = source.readUnsignedBitwiseInt(8);\r
- \r
- if (_submapFloors[i] > floorCount) {\r
- throw new Error("A mapping floor value is higher than the number of floors.");\r
- }\r
- \r
- if (_submapResidues[i] > residueCount) {\r
- throw new Error("A mapping residue value is higher than the number of residues.");\r
- }\r
- }\r
- }\r
- \r
- public override function get type():int {\r
- return 0;\r
- }\r
- \r
- public override function get couplingSteps():int {\r
- return _angles.length;\r
- }\r
-\r
- public override function get submaps():int {\r
- return _submapFloors.length;\r
- }\r
-\r
- public override function get angles():Vector.<int> {\r
- return _angles;\r
- }\r
-\r
- public override function get magnitudes():Vector.<int> {\r
- return _magnitudes;\r
- }\r
-\r
- public override function get mux():Vector.<int> {\r
- return _mux;\r
- }\r
-\r
- public override function get submapFloors():Vector.<int> {\r
- return _submapFloors;\r
- }\r
-\r
- public override function get submapResidues():Vector.<int> {\r
- return _submapResidues;\r
- } \r
- }\r
-\r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+ import flash.errors.IllegalOperationError;
+ import org.omtk.util.BitByteArray;
+
+ public class Mapping0 extends Mapping {
+
+ private var _magnitudes:Vector.<int>;
+ private var _angles:Vector.<int>;
+ private var _mux:Vector.<int>;
+ private var _submapFloors:Vector.<int>;
+ private var _submapResidues:Vector.<int>;
+
+ public function Mapping0(stream:VorbisStream, source:BitByteArray, header:SetupHeader) {
+
+ var i:int;
+ var j:int;
+
+ var submaps:int = 1;
+
+ if (source.readBit()) {
+ submaps = source.readUnsignedBitwiseInt(4) + 1;
+ }
+
+ var channels:int = stream.identificationHeader.channels;
+ var ilogChannels:int = Util.ilog(channels - 1);
+
+ if (source.readBit()) {
+ var couplingSteps:int = source.readUnsignedBitwiseInt(8) + 1;
+ _magnitudes = new Vector.<int>(couplingSteps);
+ _angles = new Vector.<int>(couplingSteps);
+
+ for (i = 0; i < couplingSteps; i++) {
+ magnitudes[i] = source.readUnsignedBitwiseInt(ilogChannels);
+ angles[i] = source.readUnsignedBitwiseInt(ilogChannels);
+ if (magnitudes[i] == angles[i] || magnitudes[i] >= channels
+ || angles[i] >= channels) {
+ throw new Error("The channel magnitude and/or angle mismatch.");
+ }
+ }
+ } else {
+ _magnitudes = Vector.<int>([]);
+ _angles = Vector.<int>([]);
+ }
+
+ if (source.readUnsignedBitwiseInt(2) != 0) {
+ throw new Error("A reserved mapping field has an invalid value.");
+ }
+
+ _mux = new Vector.<int>(channels);
+ if (submaps > 1) {
+ for (i = 0; i < channels; i++) {
+ _mux[i] = source.readUnsignedBitwiseInt(4);
+ if (_mux[i] > submaps) {
+ throw new Error("A mapping mux value is higher than the number of submaps");
+ }
+ }
+ } else {
+ for (i = 0; i < channels; i++) {
+ _mux[i] = 0;
+ }
+ }
+
+ _submapFloors = new Vector.<int>(submaps);
+ _submapResidues = new Vector.<int>(submaps);
+
+ var floorCount:int = header.floors.length;
+ var residueCount:int = header.residues.length;
+
+ for (i = 0; i < submaps; i++) {
+ source.readUnsignedBitwiseInt(8); // discard time placeholder
+ _submapFloors[i] = source.readUnsignedBitwiseInt(8);
+ _submapResidues[i] = source.readUnsignedBitwiseInt(8);
+
+ if (_submapFloors[i] > floorCount) {
+ throw new Error("A mapping floor value is higher than the number of floors.");
+ }
+
+ if (_submapResidues[i] > residueCount) {
+ throw new Error("A mapping residue value is higher than the number of residues.");
+ }
+ }
+ }
+
+ public override function get type():int {
+ return 0;
+ }
+
+ public override function get couplingSteps():int {
+ return _angles.length;
+ }
+
+ public override function get submaps():int {
+ return _submapFloors.length;
+ }
+
+ public override function get angles():Vector.<int> {
+ return _angles;
+ }
+
+ public override function get magnitudes():Vector.<int> {
+ return _magnitudes;
+ }
+
+ public override function get mux():Vector.<int> {
+ return _mux;
+ }
+
+ public override function get submapFloors():Vector.<int> {
+ return _submapFloors;
+ }
+
+ public override function get submapResidues():Vector.<int> {
+ return _submapResidues;
+ }
+ }
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.vorbis {\r
-\r
- import flash.events.*;\r
- import flash.system.*;\r
- import flash.display.*;\r
- import flash.net.*;\r
- import flash.utils.getTimer;\r
- \r
- /*\r
- * Wrapper for the haXe compiled class org.omtk.vorbis.MdctHX\r
- */\r
- public class Mdct {\r
- \r
- public static var initialized : Boolean = false;\r
- private static var hxClass : Class;\r
- \r
- public static function initialize() : void {\r
- var ldr:Loader = new Loader();\r
- var swfUrl:String = "hxmdct.swf";\r
- var req:URLRequest = new URLRequest(swfUrl);\r
- var ldrContext:LoaderContext = \r
- new LoaderContext(false, ApplicationDomain.currentDomain);\r
- ldr.load(req, ldrContext);\r
- ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, swfLoaded);\r
- \r
- function swfLoaded(e:Event):void {\r
- hxClass = ApplicationDomain.currentDomain.getDefinition("org.omtk.vorbis.MdctHX") as Class;\r
- initialized = true;\r
- } \r
- }\r
-\r
- private var delegate : Object;\r
- \r
- public function Mdct(n:int) { \r
- delegate = new hxClass(n);\r
- }\r
- \r
- public function imdct(frq:Vector.<Number>, window:Vector.<Number>, pcm:Vector.<Number>):void {\r
- delegate.imdct(frq, window, pcm);\r
- }\r
-\r
- }\r
- \r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+ import flash.events.*;
+ import flash.system.*;
+ import flash.display.*;
+ import flash.net.*;
+ import flash.utils.getTimer;
+
+ /*
+ * Wrapper for the haXe compiled class org.omtk.vorbis.MdctHX
+ */
+ public class Mdct {
+
+ public static var initialized : Boolean = false;
+ private static var hxClass : Class;
+
+ public static function initialize() : void {
+ var ldr:Loader = new Loader();
+ var swfUrl:String = "hxmdct.swf";
+ var req:URLRequest = new URLRequest(swfUrl);
+ var ldrContext:LoaderContext =
+ new LoaderContext(false, ApplicationDomain.currentDomain);
+ ldr.load(req, ldrContext);
+ ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, swfLoaded);
+
+ function swfLoaded(e:Event):void {
+ hxClass = ApplicationDomain.currentDomain.getDefinition("org.omtk.vorbis.MdctHX") as Class;
+ initialized = true;
+ }
+ }
+
+ private var delegate : Object;
+
+ public function Mdct(n:int) {
+ delegate = new hxClass(n);
+ }
+
+ public function imdct(frq:Vector.<Number>, window:Vector.<Number>, pcm:Vector.<Number>):void {
+ delegate.imdct(frq, window, pcm);
+ }
+
+ }
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.vorbis {\r
-\r
- import flash.errors.IllegalOperationError;\r
- import flash.utils.Dictionary;\r
- import org.omtk.util.BitByteArray;\r
- \r
- public class Mode\r
- {\r
- private var _blockFlag:Boolean;\r
- private var _windowType:uint;\r
- private var _transformType:uint;\r
- private var _mapping:uint;\r
- \r
- public function Mode(source:BitByteArray, header:SetupHeader) {\r
-\r
- _blockFlag=source.readBit();\r
- _windowType=source.readUnsignedBitwiseInt(16);\r
- _transformType=source.readUnsignedBitwiseInt(16);\r
- _mapping=source.readUnsignedBitwiseInt(8);\r
- \r
- if(_windowType!=0) {\r
- throw new Error("Window type = "+windowType+", != 0");\r
- }\r
- \r
- if(_transformType!=0) {\r
- throw new Error("Transform type = "+transformType+", != 0");\r
- }\r
- \r
- if(_mapping > header.mappings.length) {\r
- throw new Error("Mode mapping number is higher than total number of mappings.");\r
- }\r
- }\r
- \r
- public function get blockFlag():Boolean {\r
- return _blockFlag;\r
- }\r
- \r
- public function get windowType():uint {\r
- return _windowType;\r
- }\r
- \r
- public function get transformType():uint {\r
- return _transformType;\r
- }\r
- \r
- public function get mapping():uint {\r
- return _mapping;\r
- }\r
- \r
- }\r
- \r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+ import flash.errors.IllegalOperationError;
+ import flash.utils.Dictionary;
+ import org.omtk.util.BitByteArray;
+
+ public class Mode
+ {
+ private var _blockFlag:Boolean;
+ private var _windowType:uint;
+ private var _transformType:uint;
+ private var _mapping:uint;
+
+ public function Mode(source:BitByteArray, header:SetupHeader) {
+
+ _blockFlag=source.readBit();
+ _windowType=source.readUnsignedBitwiseInt(16);
+ _transformType=source.readUnsignedBitwiseInt(16);
+ _mapping=source.readUnsignedBitwiseInt(8);
+
+ if(_windowType!=0) {
+ throw new Error("Window type = "+windowType+", != 0");
+ }
+
+ if(_transformType!=0) {
+ throw new Error("Transform type = "+transformType+", != 0");
+ }
+
+ if(_mapping > header.mappings.length) {
+ throw new Error("Mode mapping number is higher than total number of mappings.");
+ }
+ }
+
+ public function get blockFlag():Boolean {
+ return _blockFlag;
+ }
+
+ public function get windowType():uint {
+ return _windowType;
+ }
+
+ public function get transformType():uint {
+ return _transformType;
+ }
+
+ public function get mapping():uint {
+ return _mapping;
+ }
+
+ }
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.vorbis {\r
-\r
- import flash.errors.IllegalOperationError;\r
- import flash.utils.Dictionary;\r
- import org.omtk.util.BitByteArray;\r
- \r
- public class Residue {\r
-\r
- private var _begin:int;\r
- private var _end:int;\r
- private var _partitionSize:int;\r
- private var _classifications:int;\r
- private var _classBook:int;\r
- private var _cascade:Vector.<int>;\r
- private var _books:Vector.<Vector.<int>>;\r
- \r
- private var _looks:Dictionary;\r
-\r
- \r
- public function Residue(source:BitByteArray, header:SetupHeader) {\r
-\r
- _begin = source.readUnsignedBitwiseInt(24);\r
- _end = source.readUnsignedBitwiseInt(24);\r
- _partitionSize = source.readUnsignedBitwiseInt(24) + 1;\r
- _classifications = source.readUnsignedBitwiseInt(6) + 1;\r
- _classBook = source.readUnsignedBitwiseInt(8);\r
- \r
- _cascade = new Vector.<int>(classifications);\r
- \r
- var acc:int = 0;\r
- var i:int;\r
- var j:int;\r
- \r
- for (i = 0; i < classifications; i++) {\r
- var highBits:int = 0;\r
- var lowBits:int = 0;\r
- \r
- lowBits = source.readUnsignedBitwiseInt(3);\r
- if (source.readBit()) {\r
- highBits = source.readUnsignedBitwiseInt(5);\r
- }\r
- _cascade[i] = (highBits << 3) | lowBits;\r
- acc += Util.icount(cascade[i]);\r
- }\r
- \r
- _books = new Vector.<Vector.<int>>(classifications);\r
- \r
- for (i = 0; i < classifications; i++) {\r
- books[i] = new Vector.<int>(8);\r
- for (j = 0; j < 8; j++) {\r
- if ((cascade[i] & (1 << j)) != 0) {\r
- books[i][j] = source.readUnsignedBitwiseInt(8);\r
- if (books[i][j] > header.codeBooks.length) {\r
- throw new Error(\r
- "Reference to invalid codebook entry in residue header.");\r
- }\r
- }\r
- }\r
- }\r
- \r
- _looks = new Dictionary();\r
- }\r
- \r
- public static function createInstance(source:BitByteArray, header:SetupHeader):Residue {\r
- \r
- var type:int = source.readUnsignedBitwiseInt(16);\r
- switch (type) {\r
- case 2:\r
- return new Residue2(source, header);\r
- default:\r
- throw new Error("Residue type " + type + " is not supported.");\r
- }\r
- }\r
- \r
- public function decodeResidue(\r
- vorbis:VorbisStream, source:BitByteArray, \r
- mode:Mode, ch:int,\r
- doNotDecodeFlags:Vector.<Boolean>, vectors0:Vector.<Number>, vectors1:Vector.<Number>):void {\r
- \r
- throw new IllegalOperationError("not implemented");\r
- }\r
- \r
- \r
- public function getLook(stream:VorbisStream, key:Mode):Look {\r
- var look:Look = _looks[key];\r
- if (look == null) {\r
- look = new Look(stream, this, key);\r
- _looks[key] = look;\r
- }\r
- return new Look(stream, this, key);//look;\r
- }\r
- \r
- \r
- public function get begin():int {\r
- return _begin;\r
- }\r
- \r
- public function get end():int {\r
- return _end;\r
- }\r
- \r
- public function get partitionSize():int {\r
- return _partitionSize;\r
- }\r
- \r
- public function get classifications():int {\r
- return _classifications;\r
- }\r
- \r
- public function get classBook():int {\r
- return _classBook;\r
- }\r
- \r
- public function get cascade():Vector.<int> {\r
- return _cascade;\r
- }\r
- \r
- public function get books():Vector.<Vector.<int>> {\r
- return _books;\r
- }\r
- \r
- }\r
- \r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+ import flash.errors.IllegalOperationError;
+ import flash.utils.Dictionary;
+ import org.omtk.util.BitByteArray;
+
+ public class Residue {
+
+ private var _begin:int;
+ private var _end:int;
+ private var _partitionSize:int;
+ private var _classifications:int;
+ private var _classBook:int;
+ private var _cascade:Vector.<int>;
+ private var _books:Vector.<Vector.<int>>;
+
+ private var _looks:Dictionary;
+
+
+ public function Residue(source:BitByteArray, header:SetupHeader) {
+
+ _begin = source.readUnsignedBitwiseInt(24);
+ _end = source.readUnsignedBitwiseInt(24);
+ _partitionSize = source.readUnsignedBitwiseInt(24) + 1;
+ _classifications = source.readUnsignedBitwiseInt(6) + 1;
+ _classBook = source.readUnsignedBitwiseInt(8);
+
+ _cascade = new Vector.<int>(classifications);
+
+ var acc:int = 0;
+ var i:int;
+ var j:int;
+
+ for (i = 0; i < classifications; i++) {
+ var highBits:int = 0;
+ var lowBits:int = 0;
+
+ lowBits = source.readUnsignedBitwiseInt(3);
+ if (source.readBit()) {
+ highBits = source.readUnsignedBitwiseInt(5);
+ }
+ _cascade[i] = (highBits << 3) | lowBits;
+ acc += Util.icount(cascade[i]);
+ }
+
+ _books = new Vector.<Vector.<int>>(classifications);
+
+ for (i = 0; i < classifications; i++) {
+ books[i] = new Vector.<int>(8);
+ for (j = 0; j < 8; j++) {
+ if ((cascade[i] & (1 << j)) != 0) {
+ books[i][j] = source.readUnsignedBitwiseInt(8);
+ if (books[i][j] > header.codeBooks.length) {
+ throw new Error(
+ "Reference to invalid codebook entry in residue header.");
+ }
+ }
+ }
+ }
+
+ _looks = new Dictionary();
+ }
+
+ public static function createInstance(source:BitByteArray, header:SetupHeader):Residue {
+
+ var type:int = source.readUnsignedBitwiseInt(16);
+ switch (type) {
+ case 2:
+ return new Residue2(source, header);
+ default:
+ throw new Error("Residue type " + type + " is not supported.");
+ }
+ }
+
+ public function decodeResidue(
+ vorbis:VorbisStream, source:BitByteArray,
+ mode:Mode, ch:int,
+ doNotDecodeFlags:Vector.<Boolean>, vectors0:Vector.<Number>, vectors1:Vector.<Number>):void {
+
+ throw new IllegalOperationError("not implemented");
+ }
+
+
+ public function getLook(stream:VorbisStream, key:Mode):Look {
+ var look:Look = _looks[key];
+ if (look == null) {
+ look = new Look(stream, this, key);
+ _looks[key] = look;
+ }
+ return new Look(stream, this, key);//look;
+ }
+
+
+ public function get begin():int {
+ return _begin;
+ }
+
+ public function get end():int {
+ return _end;
+ }
+
+ public function get partitionSize():int {
+ return _partitionSize;
+ }
+
+ public function get classifications():int {
+ return _classifications;
+ }
+
+ public function get classBook():int {
+ return _classBook;
+ }
+
+ public function get cascade():Vector.<int> {
+ return _cascade;
+ }
+
+ public function get books():Vector.<Vector.<int>> {
+ return _books;
+ }
+
+ }
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.vorbis {\r
-\r
- import flash.errors.IllegalOperationError;\r
- import flash.utils.Dictionary;\r
- import org.omtk.util.BitByteArray;\r
-\r
- public class Residue2 extends Residue {\r
- \r
- public function Residue2(source:BitByteArray, header:SetupHeader) {\r
- super(source, header);\r
- }\r
-\r
- public override function decodeResidue(\r
- vorbis:VorbisStream, source:BitByteArray, \r
- mode:Mode, ch:int,\r
- doNotDecodeFlags:Vector.<Boolean>, vectors0:Vector.<Number>, vectors1:Vector.<Number>):void {\r
-\r
- var i:int;\r
- var j:int;\r
- var k:int;\r
- var l:int;\r
- var s:int;\r
- var slim:int;\r
-\r
- var look:Look = getLook(vorbis, mode);\r
- \r
- var codeBook:CodeBook = vorbis.setupHeader.codeBooks[classBook];\r
- \r
- var classvalsPerCodeword:int = codeBook.dimensions;\r
- var nToRead:int = end - begin;\r
- var partitionsToRead:int = nToRead / partitionSize; // partvals\r
- \r
- var samplesPerPartition:int = partitionSize;\r
- var partitionsPerWord:int = look.phrasebook.dimensions;\r
- \r
- var partWords:int = (partitionsToRead + partitionsPerWord - 1) / partitionsPerWord;\r
- \r
- var offset:int;\r
- \r
- var left:Boolean = false;\r
- var right:Boolean = false;\r
- \r
- for (i = 0; i < doNotDecodeFlags.length; i++) {\r
- if (!doNotDecodeFlags[i]) {\r
- if(i==0) {\r
- left = true;\r
- }\r
- else if (i==1) {\r
- right = true;\r
- }\r
- }\r
- }\r
- \r
- var partword:Array = new Array(partWords);\r
- \r
- var pb:int = source.position;\r
- \r
- slim = look.stages;\r
- for (s = 0; s < slim; s++) {\r
- \r
- for (i = 0, l = 0; i < partitionsToRead; l++) {\r
- \r
- if (s == 0) {\r
- var temp:int = source.readUnsignedHuffmanInt(look.phrasebook.huffmanRoot);\r
- if (temp == -1) {\r
- throw new Error("Foo??");\r
- }\r
- partword[l] = look.decodemap[temp];\r
- if (partword[l] == null) {\r
- throw new Error("Foo??");\r
- }\r
- }\r
- \r
- for (k = 0; k < partitionsPerWord && i < partitionsToRead; k++, i++) {\r
- offset = begin + i * samplesPerPartition;\r
-\r
- if ((cascade[partword[l][k]] & (1 << s)) != 0) {\r
- var stagebook:CodeBook = \r
- vorbis.setupHeader.codeBooks[look.partbooks[partword[l][k]][s]];\r
- if (stagebook != null) {\r
- stagebook.readVvAdd(vectors0, vectors1, left, right, source, offset, samplesPerPartition);\r
- }\r
- }\r
- }\r
- }\r
- }\r
- \r
- }\r
- \r
- }\r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+ import flash.errors.IllegalOperationError;
+ import flash.utils.Dictionary;
+ import org.omtk.util.BitByteArray;
+
+ public class Residue2 extends Residue {
+
+ public function Residue2(source:BitByteArray, header:SetupHeader) {
+ super(source, header);
+ }
+
+ public override function decodeResidue(
+ vorbis:VorbisStream, source:BitByteArray,
+ mode:Mode, ch:int,
+ doNotDecodeFlags:Vector.<Boolean>, vectors0:Vector.<Number>, vectors1:Vector.<Number>):void {
+
+ var i:int;
+ var j:int;
+ var k:int;
+ var l:int;
+ var s:int;
+ var slim:int;
+
+ var look:Look = getLook(vorbis, mode);
+
+ var codeBook:CodeBook = vorbis.setupHeader.codeBooks[classBook];
+
+ var classvalsPerCodeword:int = codeBook.dimensions;
+ var nToRead:int = end - begin;
+ var partitionsToRead:int = nToRead / partitionSize; // partvals
+
+ var samplesPerPartition:int = partitionSize;
+ var partitionsPerWord:int = look.phrasebook.dimensions;
+
+ var partWords:int = (partitionsToRead + partitionsPerWord - 1) / partitionsPerWord;
+
+ var offset:int;
+
+ var left:Boolean = false;
+ var right:Boolean = false;
+
+ for (i = 0; i < doNotDecodeFlags.length; i++) {
+ if (!doNotDecodeFlags[i]) {
+ if(i==0) {
+ left = true;
+ }
+ else if (i==1) {
+ right = true;
+ }
+ }
+ }
+
+ var partword:Array = new Array(partWords);
+
+ var pb:int = source.position;
+
+ slim = look.stages;
+ for (s = 0; s < slim; s++) {
+
+ for (i = 0, l = 0; i < partitionsToRead; l++) {
+
+ if (s == 0) {
+ var temp:int = source.readUnsignedHuffmanInt(look.phrasebook.huffmanRoot);
+ if (temp == -1) {
+ throw new Error("Foo??");
+ }
+ partword[l] = look.decodemap[temp];
+ if (partword[l] == null) {
+ throw new Error("Foo??");
+ }
+ }
+
+ for (k = 0; k < partitionsPerWord && i < partitionsToRead; k++, i++) {
+ offset = begin + i * samplesPerPartition;
+
+ if ((cascade[partword[l][k]] & (1 << s)) != 0) {
+ var stagebook:CodeBook =
+ vorbis.setupHeader.codeBooks[look.partbooks[partword[l][k]][s]];
+ if (stagebook != null) {
+ stagebook.readVvAdd(vectors0, vectors1, left, right, source, offset, samplesPerPartition);
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+ }
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.vorbis {\r
-\r
- import org.omtk.util.BitByteArray;\r
-\r
- public class SetupHeader {\r
- \r
- private var _codeBooks:Vector.<CodeBook>;\r
- private var _floors:Vector.<Floor>;\r
- private var _residues:Vector.<Residue>;\r
- private var _mappings:Vector.<Mapping>;\r
- private var _modes:Vector.<Mode>;\r
- \r
- public function SetupHeader(stream:VorbisStream, source:BitByteArray) {\r
-\r
- var i:int;\r
- \r
- source.readByte();\r
- source.readByte();\r
- source.readByte();\r
- source.readByte();\r
- source.readByte();\r
- source.readByte();\r
- \r
- var codeBookCount:uint = source.readUnsignedBitwiseInt(8)+1;\r
- _codeBooks = new Vector.<CodeBook>(codeBookCount);\r
- \r
- for(i = 0; i < codeBookCount; i++) {\r
- _codeBooks[i] = new CodeBook(source);\r
- }\r
- \r
- // read the time domain transformations,\r
- // these should all be 0\r
- \r
- var timeCount:int = source.readUnsignedBitwiseInt(6) + 1;\r
- for (i = 0; i < timeCount; i++) {\r
- if (source.readUnsignedBitwiseInt(16) != 0) {\r
- throw new Error(\r
- "Time domain transformation != 0");\r
- }\r
- }\r
- \r
- // read floor entries\r
- \r
- var floorCount:int = source.readUnsignedBitwiseInt(6) + 1;\r
- _floors = new Vector.<Floor>(floorCount);\r
- \r
- for (i = 0; i < floorCount; i++) {\r
- _floors[i] = Floor.createInstance(source, this);\r
- }\r
-\r
- var residueCount:int = source.readUnsignedBitwiseInt(6) + 1;\r
- _residues = new Vector.<Residue>(residueCount);\r
-\r
- for (i = 0; i < residueCount; i++) {\r
- _residues[i] = Residue.createInstance(source, this);\r
- }\r
- \r
- var mappingCount:int = source.readUnsignedBitwiseInt(6) + 1;\r
- _mappings = new Vector.<Mapping>(mappingCount);\r
- \r
- for (i = 0; i < mappingCount; i++) {\r
- _mappings[i] = Mapping.createInstance(stream, source, this);\r
- }\r
- \r
- var modeCount:int = source.readUnsignedBitwiseInt(6) + 1;\r
- _modes = new Vector.<Mode>(modeCount);\r
- \r
- for (i = 0; i < modeCount; i++) {\r
- _modes[i] = new Mode(source, this);\r
- }\r
- \r
- if (!source.readBit()) {\r
- throw new Error("The setup header framing bit is incorrect.");\r
- }\r
- }\r
- \r
- public function get codeBooks():Vector.<CodeBook> {\r
- return _codeBooks;\r
- }\r
- \r
- public function get floors():Vector.<Floor> {\r
- return _floors;\r
- }\r
-\r
- public function get mappings():Vector.<Mapping> {\r
- return _mappings;\r
- }\r
- \r
- public function get residues():Vector.<Residue> {\r
- return _residues;\r
- }\r
-\r
- public function get modes():Vector.<Mode> {\r
- return _modes;\r
- }\r
- \r
- }\r
-\r
-\r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+ import org.omtk.util.BitByteArray;
+
+ public class SetupHeader {
+
+ private var _codeBooks:Vector.<CodeBook>;
+ private var _floors:Vector.<Floor>;
+ private var _residues:Vector.<Residue>;
+ private var _mappings:Vector.<Mapping>;
+ private var _modes:Vector.<Mode>;
+
+ public function SetupHeader(stream:VorbisStream, source:BitByteArray) {
+
+ var i:int;
+
+ source.readByte();
+ source.readByte();
+ source.readByte();
+ source.readByte();
+ source.readByte();
+ source.readByte();
+
+ var codeBookCount:uint = source.readUnsignedBitwiseInt(8)+1;
+ _codeBooks = new Vector.<CodeBook>(codeBookCount);
+
+ for(i = 0; i < codeBookCount; i++) {
+ _codeBooks[i] = new CodeBook(source);
+ }
+
+ // read the time domain transformations,
+ // these should all be 0
+
+ var timeCount:int = source.readUnsignedBitwiseInt(6) + 1;
+ for (i = 0; i < timeCount; i++) {
+ if (source.readUnsignedBitwiseInt(16) != 0) {
+ throw new Error(
+ "Time domain transformation != 0");
+ }
+ }
+
+ // read floor entries
+
+ var floorCount:int = source.readUnsignedBitwiseInt(6) + 1;
+ _floors = new Vector.<Floor>(floorCount);
+
+ for (i = 0; i < floorCount; i++) {
+ _floors[i] = Floor.createInstance(source, this);
+ }
+
+ var residueCount:int = source.readUnsignedBitwiseInt(6) + 1;
+ _residues = new Vector.<Residue>(residueCount);
+
+ for (i = 0; i < residueCount; i++) {
+ _residues[i] = Residue.createInstance(source, this);
+ }
+
+ var mappingCount:int = source.readUnsignedBitwiseInt(6) + 1;
+ _mappings = new Vector.<Mapping>(mappingCount);
+
+ for (i = 0; i < mappingCount; i++) {
+ _mappings[i] = Mapping.createInstance(stream, source, this);
+ }
+
+ var modeCount:int = source.readUnsignedBitwiseInt(6) + 1;
+ _modes = new Vector.<Mode>(modeCount);
+
+ for (i = 0; i < modeCount; i++) {
+ _modes[i] = new Mode(source, this);
+ }
+
+ if (!source.readBit()) {
+ throw new Error("The setup header framing bit is incorrect.");
+ }
+ }
+
+ public function get codeBooks():Vector.<CodeBook> {
+ return _codeBooks;
+ }
+
+ public function get floors():Vector.<Floor> {
+ return _floors;
+ }
+
+ public function get mappings():Vector.<Mapping> {
+ return _mappings;
+ }
+
+ public function get residues():Vector.<Residue> {
+ return _residues;
+ }
+
+ public function get modes():Vector.<Mode> {
+ return _modes;
+ }
+
+ }
+
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.vorbis {\r
-\r
- public class Util {\r
-\r
- public static function ilog(x:uint):uint {\r
- var res:int = 0;\r
- for(; x>0; x>>=1, res++);\r
- return res;\r
- } \r
- \r
- public static function float32unpack(x:uint):Number {\r
- var mantissa:Number = x&0x1fffff;\r
- var e:Number = (x&0x7fe00000)>>21;\r
- if((x&0x80000000)!=0) {\r
- mantissa=-mantissa;\r
- }\r
- return mantissa*Math.pow(2.0, e-788.0);\r
- }\r
-\r
- public static function lookup1Values(a:int, b:int):uint {\r
- var res:uint = Math.pow(Math.E, Math.log(a)/b);\r
- return intPow(res+1, b)<=a?res+1:res;\r
- }\r
-\r
- public static function intPow(base:uint, e:uint):uint {\r
- var res:uint = 1;\r
- for(; e>0; e--, res*=base);\r
- return res;\r
- }\r
-\r
- public static function isBitSet(value:uint, bit:uint):Boolean {\r
- return (value&(1<<bit))!=0;\r
- }\r
- \r
- public static function icount(value:uint):uint {\r
- var res:uint = 0;\r
- while (value > 0) {\r
- res += value & 1;\r
- value >>= 1;\r
- }\r
- return res;\r
- }\r
-\r
- public static function lowNeighbour(v:Vector.<int>, x:int):int {\r
-\r
- var max:int = -1;\r
- var n:int = 0;\r
- var i:int;\r
- \r
- for (i = 0; i < v.length && i < x; i++) {\r
- if (v[i] > max && v[i] < v[x]) {\r
- max = v[i];\r
- n = i;\r
- }\r
- }\r
- return n;\r
- }\r
-\r
- public static function highNeighbour(v:Vector.<int>, x:int):int {\r
- \r
- var min:int = int.MAX_VALUE;\r
- var n:int = 0;\r
- var i:int;\r
- \r
- for (i = 0; i < v.length && i < x; i++) {\r
- if (v[i] < min && v[i] > v[x]) {\r
- min = v[i];\r
- n = i;\r
- }\r
- }\r
- return n;\r
- }\r
-\r
- public static function renderPoint(x0:int, x1:int, y0:int, y1:int, x:int):int {\r
- return y0 + int(((y1-y0) * (x - x0)) / (x1 - x0));\r
- }\r
-\r
- public static function renderLine(x0:int, y0:int, x1:int, y1:int, v:Vector.<Number>):void {\r
- \r
- var dy:int = y1 - y0;\r
- var adx:int = x1 - x0;\r
- var b:int = dy / adx;\r
- var sy:int = dy < 0 ? b - 1 : b + 1;\r
- var x:int = x0;\r
- var y:int = y0;\r
- var err:int = 0;\r
- var ady:int = (dy < 0 ? -dy : dy) - (b > 0 ? b * adx : -b * adx);\r
- \r
- v[x] *= Floor.DB_STATIC_TABLE[y];\r
- for (x = x0 + 1; x < x1; x++) {\r
- err += ady;\r
- if (err >= adx) {\r
- err -= adx;\r
- v[x] *= Floor.DB_STATIC_TABLE[y += sy];\r
- } else {\r
- v[x] *= Floor.DB_STATIC_TABLE[y += b];\r
- }\r
- }\r
-\r
- }\r
-\r
- }\r
- \r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+ public class Util {
+
+ public static function ilog(x:uint):uint {
+ var res:int = 0;
+ for(; x>0; x>>=1, res++);
+ return res;
+ }
+
+ public static function float32unpack(x:uint):Number {
+ var mantissa:Number = x&0x1fffff;
+ var e:Number = (x&0x7fe00000)>>21;
+ if((x&0x80000000)!=0) {
+ mantissa=-mantissa;
+ }
+ return mantissa*Math.pow(2.0, e-788.0);
+ }
+
+ public static function lookup1Values(a:int, b:int):uint {
+ var res:uint = Math.pow(Math.E, Math.log(a)/b);
+ return intPow(res+1, b)<=a?res+1:res;
+ }
+
+ public static function intPow(base:uint, e:uint):uint {
+ var res:uint = 1;
+ for(; e>0; e--, res*=base);
+ return res;
+ }
+
+ public static function isBitSet(value:uint, bit:uint):Boolean {
+ return (value&(1<<bit))!=0;
+ }
+
+ public static function icount(value:uint):uint {
+ var res:uint = 0;
+ while (value > 0) {
+ res += value & 1;
+ value >>= 1;
+ }
+ return res;
+ }
+
+ public static function lowNeighbour(v:Vector.<int>, x:int):int {
+
+ var max:int = -1;
+ var n:int = 0;
+ var i:int;
+
+ for (i = 0; i < v.length && i < x; i++) {
+ if (v[i] > max && v[i] < v[x]) {
+ max = v[i];
+ n = i;
+ }
+ }
+ return n;
+ }
+
+ public static function highNeighbour(v:Vector.<int>, x:int):int {
+
+ var min:int = int.MAX_VALUE;
+ var n:int = 0;
+ var i:int;
+
+ for (i = 0; i < v.length && i < x; i++) {
+ if (v[i] < min && v[i] > v[x]) {
+ min = v[i];
+ n = i;
+ }
+ }
+ return n;
+ }
+
+ public static function renderPoint(x0:int, x1:int, y0:int, y1:int, x:int):int {
+ return y0 + int(((y1-y0) * (x - x0)) / (x1 - x0));
+ }
+
+ public static function renderLine(x0:int, y0:int, x1:int, y1:int, v:Vector.<Number>):void {
+
+ var dy:int = y1 - y0;
+ var adx:int = x1 - x0;
+ var b:int = dy / adx;
+ var sy:int = dy < 0 ? b - 1 : b + 1;
+ var x:int = x0;
+ var y:int = y0;
+ var err:int = 0;
+ var ady:int = (dy < 0 ? -dy : dy) - (b > 0 ? b * adx : -b * adx);
+
+ v[x] *= Floor.DB_STATIC_TABLE[y];
+ for (x = x0 + 1; x < x1; x++) {
+ err += ady;
+ if (err >= adx) {
+ err -= adx;
+ v[x] *= Floor.DB_STATIC_TABLE[y += sy];
+ } else {
+ v[x] *= Floor.DB_STATIC_TABLE[y += b];
+ }
+ }
+
+ }
+
+ }
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.vorbis {\r
-\r
- import flash.net.URLRequest;\r
- import flash.net.URLStream;\r
- import flash.utils.ByteArray;\r
- import flash.utils.Endian;\r
- import flash.events.Event;\r
- import flash.events.ProgressEvent;\r
- import flash.events.SampleDataEvent;\r
- \r
- import flash.external.ExternalInterface;\r
-\r
- import flash.media.Sound;\r
- \r
- import org.omtk.ogg.UncachedUrlStream;\r
- import org.omtk.ogg.EndOfOggStreamError;\r
- import flash.utils.setTimeout;\r
- \r
- public class VorbisSound extends Sound {\r
- \r
- public static var METADATA_UPDATE: String = "metadata_update";\r
- \r
- private var urlStream: URLStream;\r
- \r
- private var oggStream:UncachedUrlStream;\r
- private var vorbisStream:VorbisStream;\r
-\r
- private var bytesAvailable:int;\r
-\r
- private var initialized:Boolean = false;\r
- private var playing:Boolean = false;\r
- \r
- private var fill1:Boolean = true;\r
- private var fill2:Boolean = true;\r
- \r
- private var stopped: Boolean = false;\r
- private var completeEventDispatched: Boolean = false;\r
- \r
- public function VorbisSound(url: URLRequest ) {\r
- urlStream = new URLStream();\r
- urlStream.endian = Endian.LITTLE_ENDIAN;\r
- urlStream.load(url);\r
-\r
- Mdct.initialize();\r
-\r
- oggStream = new UncachedUrlStream(urlStream);\r
- oggStream.addEventListener('progress', progress);\r
- bytesAvailable = oggStream.bytesAvailable;\r
- addEventListener("sampleData", sampleGenerator);\r
- }\r
- \r
- private function initialize():void {\r
- vorbisStream = new VorbisStream(oggStream.getLogicalOggStream());\r
- setTimeout(dispatchEvent, 100, new Event(METADATA_UPDATE));\r
- initialized = true;\r
- }\r
- \r
- private var samplesPlayed: int = 0;\r
- \r
- private function sampleGenerator(event:SampleDataEvent):void {\r
- \r
- if(stopped) {\r
- return;\r
- }\r
- \r
- if(Mdct.initialized && !initialized && bytesAvailable > 64*1024) {\r
- initialize();\r
- }\r
- \r
- if(initialized && bytesAvailable > 16*1024 && !vorbisStream.finished) {\r
- var cnt: int;\r
- cnt = vorbisStream.readPcm(event.data);\r
- samplesPlayed += cnt;\r
- if(cnt < 2048 && oggStream.bytesAvailable > 0) {\r
- vorbisStream = new VorbisStream(oggStream.getLogicalOggStream());\r
- setTimeout(dispatchEvent, 100, new Event(METADATA_UPDATE));\r
- samplesPlayed += vorbisStream.readPcm(event.data);\r
- }\r
- }\r
- else if(vorbisStream == null || !vorbisStream.finished) {\r
- for(var c:int=0; c<2048; c++) {\r
- event.data.writeFloat(0);\r
- event.data.writeFloat(0);\r
- }\r
- }\r
- \r
- if(initialized && vorbisStream.finished && oggStream.bytesAvailable == 0 && !completeEventDispatched) {\r
- dispatchEvent(new Event(Event.COMPLETE));\r
- completeEventDispatched = true;\r
- }\r
- \r
- //trace("samples played: " + samplesPlayed + "/" + oggStream.bytesAvailable);\r
- \r
- }\r
-\r
- public function stop(): void {\r
- stopped = true;\r
- }\r
-\r
- public function progress(event:ProgressEvent):void {\r
- bytesAvailable = oggStream.bytesAvailable;\r
- }\r
-\r
- public function get position(): int {\r
- return samplesPlayed * 1000 / 44100;\r
- }\r
-\r
- public function getMetaData(key: String):String {\r
- if(vorbisStream != null) {\r
- return vorbisStream.commentHeader.comments[key];\r
- }\r
- else {\r
- return null;\r
- }\r
- }\r
- }\r
- \r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+ import flash.net.URLRequest;
+ import flash.net.URLStream;
+ import flash.utils.ByteArray;
+ import flash.utils.Endian;
+ import flash.events.Event;
+ import flash.events.ProgressEvent;
+ import flash.events.SampleDataEvent;
+
+ import flash.external.ExternalInterface;
+
+ import flash.media.Sound;
+
+ import org.omtk.ogg.UncachedUrlStream;
+ import org.omtk.ogg.EndOfOggStreamError;
+ import flash.utils.setTimeout;
+
+ public class VorbisSound extends Sound {
+
+ public static var METADATA_UPDATE: String = "metadata_update";
+
+ private var urlStream: URLStream;
+
+ private var oggStream:UncachedUrlStream;
+ private var vorbisStream:VorbisStream;
+
+ private var bytesAvailable:int;
+
+ private var initialized:Boolean = false;
+ private var playing:Boolean = false;
+
+ private var fill1:Boolean = true;
+ private var fill2:Boolean = true;
+
+ private var stopped: Boolean = false;
+ private var completeEventDispatched: Boolean = false;
+
+ public function VorbisSound(url: URLRequest ) {
+ urlStream = new URLStream();
+ urlStream.endian = Endian.LITTLE_ENDIAN;
+ urlStream.load(url);
+
+ Mdct.initialize();
+
+ oggStream = new UncachedUrlStream(urlStream);
+ oggStream.addEventListener('progress', progress);
+ bytesAvailable = oggStream.bytesAvailable;
+ addEventListener("sampleData", sampleGenerator);
+ }
+
+ private function initialize():void {
+ vorbisStream = new VorbisStream(oggStream.getLogicalOggStream());
+ setTimeout(dispatchEvent, 100, new Event(METADATA_UPDATE));
+ initialized = true;
+ }
+
+ private var samplesPlayed: int = 0;
+
+ private function sampleGenerator(event:SampleDataEvent):void {
+
+ if(stopped) {
+ return;
+ }
+
+ if(Mdct.initialized && !initialized && bytesAvailable > 64*1024) {
+ initialize();
+ }
+
+ if(initialized && bytesAvailable > 16*1024 && !vorbisStream.finished) {
+ var cnt: int;
+ cnt = vorbisStream.readPcm(event.data);
+ samplesPlayed += cnt;
+ if(cnt < 2048 && oggStream.bytesAvailable > 0) {
+ vorbisStream = new VorbisStream(oggStream.getLogicalOggStream());
+ setTimeout(dispatchEvent, 100, new Event(METADATA_UPDATE));
+ samplesPlayed += vorbisStream.readPcm(event.data);
+ }
+ }
+ else if(vorbisStream == null || !vorbisStream.finished) {
+ for(var c:int=0; c<2048; c++) {
+ event.data.writeFloat(0);
+ event.data.writeFloat(0);
+ }
+ }
+
+ if(initialized && vorbisStream.finished && oggStream.bytesAvailable == 0 && !completeEventDispatched) {
+ dispatchEvent(new Event(Event.COMPLETE));
+ completeEventDispatched = true;
+ }
+
+ //trace("samples played: " + samplesPlayed + "/" + oggStream.bytesAvailable);
+
+ }
+
+ public function stop(): void {
+ stopped = true;
+ }
+
+ public function progress(event:ProgressEvent):void {
+ bytesAvailable = oggStream.bytesAvailable;
+ }
+
+ public function get position(): int {
+ return samplesPlayed * 1000 / 44100;
+ }
+
+ public function getMetaData(key: String):String {
+ if(vorbisStream != null) {
+ return vorbisStream.commentHeader.comments[key];
+ }
+ else {
+ return null;
+ }
+ }
+ }
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.vorbis {\r
-\r
- import flash.events.SampleDataEvent;\r
- import flash.utils.ByteArray;\r
- import flash.utils.Endian;\r
- import org.omtk.util.*;\r
- import org.omtk.ogg.*;\r
- \r
- public class VorbisStream {\r
- \r
- private const IDENTIFICATION_HEADER:int = 1;\r
- private const COMMENT_HEADER:int = 3;\r
- private const SETUP_HEADER:int = 5;\r
- \r
- private var source:LogicalOggStream;\r
- \r
- private var _identificationHeader:IdentificationHeader;\r
- private var _commentHeader:CommentHeader;\r
- private var _setupHeader:SetupHeader;\r
- \r
- private var _lastAudioPacket:AudioPacket;\r
- \r
- private var _currentGranulePosition:int=0;\r
- private var packetCounter:int;\r
- \r
- private var _finished: Boolean = false;\r
- \r
- public var windows:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>(8);\r
-\r
- public function VorbisStream(source:LogicalOggStream) {\r
-\r
- this.source = source;\r
-\r
- for (var i:int = 0; i < 3; i++) {\r
-\r
- var data:BitByteArray = source.getNextOggPacket().data;\r
- var headerType:int = data.readUnsignedByte();\r
-\r
- switch(headerType) {\r
- case IDENTIFICATION_HEADER:\r
- _identificationHeader = new IdentificationHeader(data);\r
- break;\r
- case COMMENT_HEADER:\r
- _commentHeader = new CommentHeader(data);\r
- break;\r
- case SETUP_HEADER:\r
- _setupHeader = new SetupHeader(this, data);\r
- break;\r
- }\r
- }\r
- \r
- }\r
- \r
- public function get identificationHeader():IdentificationHeader {\r
- return _identificationHeader;\r
- }\r
- \r
- public function get commentHeader():CommentHeader {\r
- return _commentHeader;\r
- }\r
- \r
- public function get setupHeader():SetupHeader {\r
- return _setupHeader;\r
- }\r
- \r
- public function readPcm(data:ByteArray): int {\r
- \r
- var total:int;\r
- var i:int;\r
- \r
- if(_lastAudioPacket == null) {\r
- _lastAudioPacket = getNextAudioPacket();\r
- }\r
-\r
- total = 0;\r
- \r
- while(total < 2048 && !_finished) {\r
- try {\r
- var ap:AudioPacket = getNextAudioPacket();\r
- total += ap.readPcm(_lastAudioPacket, data);\r
- _lastAudioPacket = ap;\r
- }\r
- catch(e: EndOfOggStreamError) {\r
- // ok, stream finished\r
- _finished = true;\r
- }\r
- }\r
- \r
- return total;\r
- }\r
-\r
- private function getNextAudioPacket():AudioPacket {\r
- packetCounter++;\r
- var packet:OggPacket = source.getNextOggPacket();\r
- var res:AudioPacket = new AudioPacket(this, packet, _currentGranulePosition);\r
- if(_lastAudioPacket != null) {\r
- // don't count the first packet, since it doesn't contain any "real" samples\r
- _currentGranulePosition += res.numberOfSamples;\r
- }\r
- return res;\r
- } \r
- \r
- public function get finished() : Boolean {\r
- return _finished;\r
- }\r
- \r
- public function get currentGranulePosition(): int {\r
- return _currentGranulePosition;\r
- }\r
- }\r
- \r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.vorbis {
+
+ import flash.events.SampleDataEvent;
+ import flash.utils.ByteArray;
+ import flash.utils.Endian;
+ import org.omtk.util.*;
+ import org.omtk.ogg.*;
+
+ public class VorbisStream {
+
+ private const IDENTIFICATION_HEADER:int = 1;
+ private const COMMENT_HEADER:int = 3;
+ private const SETUP_HEADER:int = 5;
+
+ private var source:LogicalOggStream;
+
+ private var _identificationHeader:IdentificationHeader;
+ private var _commentHeader:CommentHeader;
+ private var _setupHeader:SetupHeader;
+
+ private var _lastAudioPacket:AudioPacket;
+
+ private var _currentGranulePosition:int=0;
+ private var packetCounter:int;
+
+ private var _finished: Boolean = false;
+
+ public var windows:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>(8);
+
+ public function VorbisStream(source:LogicalOggStream) {
+
+ this.source = source;
+
+ for (var i:int = 0; i < 3; i++) {
+
+ var data:BitByteArray = source.getNextOggPacket().data;
+ var headerType:int = data.readUnsignedByte();
+
+ switch(headerType) {
+ case IDENTIFICATION_HEADER:
+ _identificationHeader = new IdentificationHeader(data);
+ break;
+ case COMMENT_HEADER:
+ _commentHeader = new CommentHeader(data);
+ break;
+ case SETUP_HEADER:
+ _setupHeader = new SetupHeader(this, data);
+ break;
+ }
+ }
+
+ }
+
+ public function get identificationHeader():IdentificationHeader {
+ return _identificationHeader;
+ }
+
+ public function get commentHeader():CommentHeader {
+ return _commentHeader;
+ }
+
+ public function get setupHeader():SetupHeader {
+ return _setupHeader;
+ }
+
+ public function readPcm(data:ByteArray): int {
+
+ var total:int;
+ var i:int;
+
+ if(_lastAudioPacket == null) {
+ _lastAudioPacket = getNextAudioPacket();
+ }
+
+ total = 0;
+
+ while(total < 2048 && !_finished) {
+ try {
+ var ap:AudioPacket = getNextAudioPacket();
+ total += ap.readPcm(_lastAudioPacket, data);
+ _lastAudioPacket = ap;
+ }
+ catch(e: EndOfOggStreamError) {
+ // ok, stream finished
+ _finished = true;
+ }
+ }
+
+ return total;
+ }
+
+ private function getNextAudioPacket():AudioPacket {
+ packetCounter++;
+ var packet:OggPacket = source.getNextOggPacket();
+ var res:AudioPacket = new AudioPacket(this, packet, _currentGranulePosition);
+ if(_lastAudioPacket != null) {
+ // don't count the first packet, since it doesn't contain any "real" samples
+ _currentGranulePosition += res.numberOfSamples;
+ }
+ return res;
+ }
+
+ public function get finished() : Boolean {
+ return _finished;
+ }
+
+ public function get currentGranulePosition(): int {
+ return _currentGranulePosition;
+ }
+ }
+
}
\ No newline at end of file
-/*\r
-\r
-Copyright 2008 Tor-Einar Jarnbjo\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
-\r
-*/\r
-\r
-package org.omtk.vorbis;\r
-\r
-import flash.Vector;\r
-\r
-class MdctHX {\r
-\r
- private static var cPI1_8:Float = 0.92387953251128675613;\r
- private static var cPI2_8:Float = 0.70710678118654752441;\r
- private static var cPI3_8:Float = 0.38268343236508977175;\r
- \r
- private var n:Int;\r
- private var log2n:Int;\r
- private var trig:Vector<Float>;\r
- private var bitrev:Vector<Int>;\r
- \r
- private var dtmp1:Float;\r
- private var dtmp2:Float;\r
- private var dtmp3:Float;\r
- private var dtmp4:Float;\r
-\r
- private var x:Vector<Float>;\r
- private var w:Vector<Float>;\r
-\r
- public function new(n:Int) { \r
- this.n = n;\r
- \r
- var i:Int;\r
- var j:Int;\r
- \r
- bitrev = new Vector<Int>();\r
- trig = new Vector<Float>(Std.int(n+n/4), true);\r
-\r
- for(i in 0...Std.int(n+n/4)) {\r
- trig[i] = 0;\r
- }\r
-\r
- x = new Vector<Float>(Std.int(n/2), true);\r
- w = new Vector<Float>(Std.int(n/2), true);\r
-\r
- for(i in 0...Std.int(n/2)) {\r
- x[i] = 0;\r
- w[i] = 0;\r
- }\r
- \r
- var n2:Int = n >>> 1;\r
- log2n = Math.round(Math.log(n) / Math.log(2));\r
-\r
- var AE:Int = 0;\r
- var AO:Int = 1;\r
- var BE:Int = Std.int(AE + n / 2);\r
- var BO:Int = BE + 1;\r
- var CE:Int = Std.int(BE + n / 2);\r
- var CO:Int = CE + 1;\r
- \r
- for (i in 0...Std.int(n/4)) {\r
- trig[AE + i * 2] = Math.cos((Math.PI / n) * (4 * i));\r
- trig[AO + i * 2] = -Math.sin((Math.PI / n) * (4 * i));\r
- trig[BE + i * 2] = Math.cos((Math.PI / (2 * n)) * (2 * i + 1));\r
- trig[BO + i * 2] = Math.sin((Math.PI / (2 * n)) * (2 * i + 1));\r
- }\r
-\r
- for (i in 0...Std.int(n/8)) {\r
- trig[CE + i * 2] = Math.cos((Math.PI / n) * (4 * i + 2));\r
- trig[CO + i * 2] = -Math.sin((Math.PI / n) * (4 * i + 2));\r
- }\r
- \r
- var mask:Int = (1 << (log2n - 1)) - 1;\r
- var msb:Int = 1 << (log2n - 2);\r
- \r
- for (i in 0...Std.int(n/8)) {\r
- var acc:Int = 0;\r
- j = 0;\r
- while(msb>>>j!=0) {\r
- if (((msb >>> j) & i) != 0) {\r
- acc |= 1 << j;\r
- }\r
- j++;\r
- }\r
- bitrev[i * 2] = ((~acc) & mask);\r
- bitrev[i * 2 + 1] = acc;\r
- }\r
- \r
- } \r
-\r
- public function imdct(frq:Vector<Float>, window:Vector<Float>, pcm:Vector<Float>):Void {\r
- \r
- var i:Int;\r
-\r
- var n2:Int;\r
- var n4:Int;\r
- var n8:Int;\r
-\r
- var inO:Int;\r
- var xO:Int;\r
- var A:Int;\r
-\r
- var temp1:Float;\r
- var temp2:Float;\r
-\r
- var B:Int;\r
- var o1:Int;\r
- var o2:Int;\r
- var o3:Int;\r
- var o4:Int;\r
-\r
- var xx:Int;\r
- var xxx:Vector<Float>;\r
- \r
- n2 = n >> 1;\r
- n4 = n >> 2;\r
- n8 = n >> 3;\r
-\r
- inO = -1;\r
- xO = 0;\r
- A = n2;\r
- \r
- temp1 = 0.0;\r
- temp2 = 0.0;\r
- \r
- for (i in 0...n8) {\r
- dtmp1 = frq[inO += 2];\r
- dtmp2 = frq[inO += 2];\r
- dtmp3 = trig[--A];\r
- dtmp4 = trig[--A];\r
- x[xO++] = -dtmp2 * dtmp3 - dtmp1 * dtmp4;\r
- x[xO++] = dtmp1 * dtmp3 - dtmp2 * dtmp4;\r
- }\r
-\r
- inO = n2;\r
-\r
- for(i in 0...n8) {\r
- dtmp1 = frq[inO -= 2];\r
- dtmp2 = frq[inO -= 2];\r
- dtmp3 = trig[--A];\r
- dtmp4 = trig[--A];\r
- x[xO++] = dtmp2 * dtmp3 + dtmp1 * dtmp4;\r
- x[xO++] = dtmp2 * dtmp4 - dtmp1 * dtmp3;\r
- }\r
-\r
- xxx = kernel(x, w, n, n2, n4, n8);\r
- xx = 0;\r
- \r
- B = n2;\r
- o1 = n4;\r
- o2 = o1 - 1;\r
- o3 = n4 + n2;\r
- o4 = o3 - 1;\r
-\r
- for (i in 0...n4) {\r
- dtmp1 = xxx[xx++];\r
- dtmp2 = xxx[xx++];\r
- dtmp3 = trig[B++];\r
- dtmp4 = trig[B++];\r
-\r
- temp1 = (dtmp1 * dtmp4 - dtmp2 * dtmp3);\r
- temp2 = -(dtmp1 * dtmp3 + dtmp2 * dtmp4);\r
-\r
- pcm[o1] = -temp1 * window[o1];\r
- pcm[o2] = temp1 * window[o2];\r
- pcm[o3] = temp2 * window[o3];\r
- pcm[o4] = temp2 * window[o4];\r
-\r
- o1++;\r
- o2--;\r
- o3++;\r
- o4--;\r
- }\r
- \r
- }\r
-\r
- private inline function kernel(x:Vector<Float>, w:Vector<Float>, n:Int, n2:Int, n4:Int, n8:Int):Vector<Float> {\r
-\r
- var i:Int;\r
- var r:Int;\r
- var s:Int;\r
- var rlim:Int;\r
- var slim:Int;\r
- \r
- var xA:Int = n4;\r
- var xB:Int = 0;\r
- var w1:Int = 0;\r
- var w2:Int = n4;\r
- var A:Int = n2;\r
-\r
- var x0:Float;\r
- var x1:Float;\r
- var wA:Float;\r
- var wB:Float;\r
- var wC:Float;\r
- var wD:Float;\r
- var k0:Int;\r
- var k1:Int;\r
- var t1:Int;\r
- var t2:Int;\r
- \r
- var wbase:Int;\r
- var temp:Vector<Float>;\r
- \r
- var wACE:Float;\r
- var wBCE:Float;\r
- var wACO:Float;\r
- var wBCO:Float;\r
- \r
- var AEv:Float;\r
- var AOv:Float;\r
- \r
- i=0;\r
- while(i < n4) {\r
- x0 = x[xA] - x[xB];\r
- \r
- w[w2 + i] = x[xA++] + x[xB++];\r
-\r
- x1 = x[xA] - x[xB];\r
- A -= 4;\r
-\r
- w[i++] = x0 * trig[A] + x1 * trig[A + 1];\r
- w[i] = x1 * trig[A] - x0 * trig[A + 1];\r
-\r
- w[w2 + i] = x[xA++] + x[xB++];\r
- i++;\r
- }\r
-\r
- for (i in 0...log2n-3) {\r
- k0 = n >>> (i + 2);\r
- k1 = 1 << (i + 3);\r
- wbase = n2 - 2;\r
-\r
- A = 0;\r
-\r
- rlim = k0 >>> 2;\r
- for (r in 0...rlim) {\r
- \r
- w1 = wbase;\r
- w2 = w1 - (k0 >> 1);\r
- AEv = trig[A];\r
- AOv = trig[A + 1];\r
- wbase -= 2;\r
-\r
- k0++;\r
- \r
- slim = 2 << i;\r
- for (s in 0...slim) {\r
- dtmp1 = w[w1];\r
- dtmp2 = w[w2];\r
- wB = dtmp1 - dtmp2;\r
- x[w1] = dtmp1 + dtmp2;\r
- dtmp1 = w[++w1];\r
- dtmp2 = w[++w2];\r
- wA = dtmp1 - dtmp2;\r
- x[w1] = dtmp1 + dtmp2;\r
- x[w2] = wA * AEv - wB * AOv;\r
- x[w2-1] = wB * AEv + wA * AOv;\r
- w1 -= k0;\r
- w2 -= k0;\r
- }\r
- k0--;\r
- A += k1;\r
- }\r
-\r
- temp = w;\r
- w = x;\r
- x = temp;\r
- }\r
- \r
-\r
- var C:Int = n;\r
- var bit:Int = 0;\r
- var xx1:Int = 0;\r
- var xx2:Int = n2 - 1;\r
- \r
- var wt1: Float;\r
- var wt2: Float;\r
- var wt12: Float;\r
- var wt21: Float;\r
- var trigV: Float;\r
-\r
- for (i in 0...n8) {\r
- t1 = bitrev[bit++];\r
- t2 = bitrev[bit++];\r
- \r
- wt1 = w[t1];\r
- wt2 = w[t2];\r
- wt12 = w[t1-1];\r
- wt21 = w[t2+1];\r
-\r
- wA = wt1 - wt21;\r
- wB = wt12 + wt2;\r
- wC = wt1 + wt21;\r
- wD = wt12 - wt2;\r
- \r
- trigV = trig[C];\r
-\r
- wACE = wA * trigV;\r
- wBCE = wB * trigV;\r
- \r
- trigV = trig[++C];\r
- \r
- wACO = wA * trigV;\r
- wBCO = wB * trigV;\r
- \r
- ++C;\r
-\r
- x[xx1++] = (wC + wACO + wBCE);\r
- x[xx2--] = (-wD + wBCO - wACE);\r
- x[xx1++] = (wD + wBCO - wACE);\r
- x[xx2--] = (wC - wACO - wBCE);\r
- }\r
-\r
- return x;\r
- } \r
-\r
- /*\r
- * Dummy function required for the haXe compiler to build this to\r
- * a .SWF file.\r
- */\r
- public static function main() : Void { \r
- }\r
- \r
-}\r
+/*
+
+Copyright 2008 Tor-Einar Jarnbjo
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.omtk.vorbis;
+
+import flash.Vector;
+
+class MdctHX {
+
+ private static var cPI1_8:Float = 0.92387953251128675613;
+ private static var cPI2_8:Float = 0.70710678118654752441;
+ private static var cPI3_8:Float = 0.38268343236508977175;
+
+ private var n:Int;
+ private var log2n:Int;
+ private var trig:Vector<Float>;
+ private var bitrev:Vector<Int>;
+
+ private var dtmp1:Float;
+ private var dtmp2:Float;
+ private var dtmp3:Float;
+ private var dtmp4:Float;
+
+ private var x:Vector<Float>;
+ private var w:Vector<Float>;
+
+ public function new(n:Int) {
+ this.n = n;
+
+ var i:Int;
+ var j:Int;
+
+ bitrev = new Vector<Int>();
+ trig = new Vector<Float>(Std.int(n+n/4), true);
+
+ for(i in 0...Std.int(n+n/4)) {
+ trig[i] = 0;
+ }
+
+ x = new Vector<Float>(Std.int(n/2), true);
+ w = new Vector<Float>(Std.int(n/2), true);
+
+ for(i in 0...Std.int(n/2)) {
+ x[i] = 0;
+ w[i] = 0;
+ }
+
+ var n2:Int = n >>> 1;
+ log2n = Math.round(Math.log(n) / Math.log(2));
+
+ var AE:Int = 0;
+ var AO:Int = 1;
+ var BE:Int = Std.int(AE + n / 2);
+ var BO:Int = BE + 1;
+ var CE:Int = Std.int(BE + n / 2);
+ var CO:Int = CE + 1;
+
+ for (i in 0...Std.int(n/4)) {
+ trig[AE + i * 2] = Math.cos((Math.PI / n) * (4 * i));
+ trig[AO + i * 2] = -Math.sin((Math.PI / n) * (4 * i));
+ trig[BE + i * 2] = Math.cos((Math.PI / (2 * n)) * (2 * i + 1));
+ trig[BO + i * 2] = Math.sin((Math.PI / (2 * n)) * (2 * i + 1));
+ }
+
+ for (i in 0...Std.int(n/8)) {
+ trig[CE + i * 2] = Math.cos((Math.PI / n) * (4 * i + 2));
+ trig[CO + i * 2] = -Math.sin((Math.PI / n) * (4 * i + 2));
+ }
+
+ var mask:Int = (1 << (log2n - 1)) - 1;
+ var msb:Int = 1 << (log2n - 2);
+
+ for (i in 0...Std.int(n/8)) {
+ var acc:Int = 0;
+ j = 0;
+ while(msb>>>j!=0) {
+ if (((msb >>> j) & i) != 0) {
+ acc |= 1 << j;
+ }
+ j++;
+ }
+ bitrev[i * 2] = ((~acc) & mask);
+ bitrev[i * 2 + 1] = acc;
+ }
+
+ }
+
+ public function imdct(frq:Vector<Float>, window:Vector<Float>, pcm:Vector<Float>):Void {
+
+ var i:Int;
+
+ var n2:Int;
+ var n4:Int;
+ var n8:Int;
+
+ var inO:Int;
+ var xO:Int;
+ var A:Int;
+
+ var temp1:Float;
+ var temp2:Float;
+
+ var B:Int;
+ var o1:Int;
+ var o2:Int;
+ var o3:Int;
+ var o4:Int;
+
+ var xx:Int;
+ var xxx:Vector<Float>;
+
+ n2 = n >> 1;
+ n4 = n >> 2;
+ n8 = n >> 3;
+
+ inO = -1;
+ xO = 0;
+ A = n2;
+
+ temp1 = 0.0;
+ temp2 = 0.0;
+
+ for (i in 0...n8) {
+ dtmp1 = frq[inO += 2];
+ dtmp2 = frq[inO += 2];
+ dtmp3 = trig[--A];
+ dtmp4 = trig[--A];
+ x[xO++] = -dtmp2 * dtmp3 - dtmp1 * dtmp4;
+ x[xO++] = dtmp1 * dtmp3 - dtmp2 * dtmp4;
+ }
+
+ inO = n2;
+
+ for(i in 0...n8) {
+ dtmp1 = frq[inO -= 2];
+ dtmp2 = frq[inO -= 2];
+ dtmp3 = trig[--A];
+ dtmp4 = trig[--A];
+ x[xO++] = dtmp2 * dtmp3 + dtmp1 * dtmp4;
+ x[xO++] = dtmp2 * dtmp4 - dtmp1 * dtmp3;
+ }
+
+ xxx = kernel(x, w, n, n2, n4, n8);
+ xx = 0;
+
+ B = n2;
+ o1 = n4;
+ o2 = o1 - 1;
+ o3 = n4 + n2;
+ o4 = o3 - 1;
+
+ for (i in 0...n4) {
+ dtmp1 = xxx[xx++];
+ dtmp2 = xxx[xx++];
+ dtmp3 = trig[B++];
+ dtmp4 = trig[B++];
+
+ temp1 = (dtmp1 * dtmp4 - dtmp2 * dtmp3);
+ temp2 = -(dtmp1 * dtmp3 + dtmp2 * dtmp4);
+
+ pcm[o1] = -temp1 * window[o1];
+ pcm[o2] = temp1 * window[o2];
+ pcm[o3] = temp2 * window[o3];
+ pcm[o4] = temp2 * window[o4];
+
+ o1++;
+ o2--;
+ o3++;
+ o4--;
+ }
+
+ }
+
+ private inline function kernel(x:Vector<Float>, w:Vector<Float>, n:Int, n2:Int, n4:Int, n8:Int):Vector<Float> {
+
+ var i:Int;
+ var r:Int;
+ var s:Int;
+ var rlim:Int;
+ var slim:Int;
+
+ var xA:Int = n4;
+ var xB:Int = 0;
+ var w1:Int = 0;
+ var w2:Int = n4;
+ var A:Int = n2;
+
+ var x0:Float;
+ var x1:Float;
+ var wA:Float;
+ var wB:Float;
+ var wC:Float;
+ var wD:Float;
+ var k0:Int;
+ var k1:Int;
+ var t1:Int;
+ var t2:Int;
+
+ var wbase:Int;
+ var temp:Vector<Float>;
+
+ var wACE:Float;
+ var wBCE:Float;
+ var wACO:Float;
+ var wBCO:Float;
+
+ var AEv:Float;
+ var AOv:Float;
+
+ i=0;
+ while(i < n4) {
+ x0 = x[xA] - x[xB];
+
+ w[w2 + i] = x[xA++] + x[xB++];
+
+ x1 = x[xA] - x[xB];
+ A -= 4;
+
+ w[i++] = x0 * trig[A] + x1 * trig[A + 1];
+ w[i] = x1 * trig[A] - x0 * trig[A + 1];
+
+ w[w2 + i] = x[xA++] + x[xB++];
+ i++;
+ }
+
+ for (i in 0...log2n-3) {
+ k0 = n >>> (i + 2);
+ k1 = 1 << (i + 3);
+ wbase = n2 - 2;
+
+ A = 0;
+
+ rlim = k0 >>> 2;
+ for (r in 0...rlim) {
+
+ w1 = wbase;
+ w2 = w1 - (k0 >> 1);
+ AEv = trig[A];
+ AOv = trig[A + 1];
+ wbase -= 2;
+
+ k0++;
+
+ slim = 2 << i;
+ for (s in 0...slim) {
+ dtmp1 = w[w1];
+ dtmp2 = w[w2];
+ wB = dtmp1 - dtmp2;
+ x[w1] = dtmp1 + dtmp2;
+ dtmp1 = w[++w1];
+ dtmp2 = w[++w2];
+ wA = dtmp1 - dtmp2;
+ x[w1] = dtmp1 + dtmp2;
+ x[w2] = wA * AEv - wB * AOv;
+ x[w2-1] = wB * AEv + wA * AOv;
+ w1 -= k0;
+ w2 -= k0;
+ }
+ k0--;
+ A += k1;
+ }
+
+ temp = w;
+ w = x;
+ x = temp;
+ }
+
+
+ var C:Int = n;
+ var bit:Int = 0;
+ var xx1:Int = 0;
+ var xx2:Int = n2 - 1;
+
+ var wt1: Float;
+ var wt2: Float;
+ var wt12: Float;
+ var wt21: Float;
+ var trigV: Float;
+
+ for (i in 0...n8) {
+ t1 = bitrev[bit++];
+ t2 = bitrev[bit++];
+
+ wt1 = w[t1];
+ wt2 = w[t2];
+ wt12 = w[t1-1];
+ wt21 = w[t2+1];
+
+ wA = wt1 - wt21;
+ wB = wt12 + wt2;
+ wC = wt1 + wt21;
+ wD = wt12 - wt2;
+
+ trigV = trig[C];
+
+ wACE = wA * trigV;
+ wBCE = wB * trigV;
+
+ trigV = trig[++C];
+
+ wACO = wA * trigV;
+ wBCO = wB * trigV;
+
+ ++C;
+
+ x[xx1++] = (wC + wACO + wBCE);
+ x[xx2--] = (-wD + wBCO - wACE);
+ x[xx1++] = (wD + wBCO - wACE);
+ x[xx2--] = (wC - wACO - wBCE);
+ }
+
+ return x;
+ }
+
+ /*
+ * Dummy function required for the haXe compiler to build this to
+ * a .SWF file.
+ */
+ public static function main() : Void {
+ }
+
+}
-1\r
-00:00:01,080 --> 00:00:09,078\r
-片名:鐵扇公主\r
-\r
-2\r
-00:02:03,119 --> 00:02:09,280\r
-西遊記,本為一部絕妙之童話\r
-\r
-3\r
-00:02:09,280 --> 00:02:15,280\r
-特以世多誤解,致被目為神怪小說\r
-\r
-4\r
-00:02:15,280 --> 00:02:19,240\r
-本片取材於是\r
-\r
-5\r
-00:02:19,240 --> 00:02:24,240\r
-實為培育兒童心理而作\r
-\r
-6\r
-00:02:24,240 --> 00:02:29,280\r
-故內容刪蕪存精,不涉神怪\r
-\r
-7\r
-00:02:29,280 --> 00:02:32,560\r
-僅以唐僧等四人路阻火焰山\r
-\r
-8\r
-00:02:32,560 --> 00:02:41,040\r
-以示人生途徑中之磨難\r
-\r
-9\r
-00:02:41,040 --> 00:02:46,440\r
-欲求經此磨難,則必須堅持信念\r
-大眾一心\r
-\r
-10\r
-00:02:46,440 --> 00:02:52,436\r
-始能獲得此撲滅凶焰之芭蕉扇\r
-\r
-11\r
-00:03:34,480 --> 00:03:37,790\r
-現在已經秋天了,怎麼還這麼熱\r
-\r
-12\r
-00:03:37,840 --> 00:03:42,356\r
-呆子,不要說廢話,趕路要緊\r
-\r
-13\r
-00:04:06,920 --> 00:04:09,354\r
-悟空,這是到了什麼地方\r
-\r
-14\r
-00:04:09,400 --> 00:04:13,678\r
-反正是我們上西天必定要經過的地方\r
-\r
-15\r
-00:04:13,720 --> 00:04:18,111\r
-我們沒有走錯路線吧\r
-\r
-16\r
-00:04:18,159 --> 00:04:22,311\r
-為什麼這個地方這麼樣的熱呢\r
-\r
-17\r
-00:04:30,039 --> 00:04:31,711\r
-師傅,你看\r
-\r
-18\r
-00:04:31,759 --> 00:04:33,795\r
-前面那兒,不是有一座房子了嗎\r
-\r
-19\r
-00:04:33,839 --> 00:04:38,117\r
-我們大家進去歇息一會兒好吧\r
-\r
-20\r
-00:04:59,399 --> 00:05:02,914\r
-這個地方名叫火焰山\r
-\r
-21\r
-00:05:02,959 --> 00:05:06,031\r
-周圍有幾百里的火焰\r
-\r
-22\r
-00:05:06,079 --> 00:05:08,752\r
-一根草都不生\r
-\r
-23\r
-00:05:08,799 --> 00:05:11,632\r
-一年四季都是熱的\r
-\r
-24\r
-00:05:11,680 --> 00:05:19,633\r
-就是銅頭鐵臂要經過那個山\r
-也得融化成水\r
-\r
-25\r
-00:05:19,679 --> 00:05:23,592\r
-哪有這種事,師傅,你請放心\r
-\r
-26\r
-00:05:23,639 --> 00:05:27,154\r
-我們三個人都有法子可以過去\r
-\r
-27\r
-00:05:27,199 --> 00:05:30,714\r
-師傅,我去看看好吧\r
-\r
-28\r
-00:08:06,319 --> 00:08:09,595\r
-悟空,你去看了怎麼樣\r
-\r
-29\r
-00:08:09,639 --> 00:08:11,834\r
-厲害,厲害,真厲言\r
-\r
-30\r
-00:08:11,880 --> 00:08:15,919\r
-要不是我跑得快,尾巴都燒光了\r
-\r
-31\r
-00:08:42,720 --> 00:08:47,600\r
-老施主,這裡的火這樣大\r
-\r
-32\r
-00:08:47,600 --> 00:08:49,670\r
-這五穀從哪兒來的\r
-\r
-33\r
-00:08:49,719 --> 00:08:53,997\r
-你看這兒有一千多里的路\r
-有一位鐵扇公主\r
-\r
-34\r
-00:08:54,040 --> 00:08:56,508\r
-她有一把芭蕉扇\r
-\r
-35\r
-00:08:56,560 --> 00:08:59,074\r
-一扇呢,火就熄了\r
-\r
-36\r
-00:08:59,120 --> 00:09:01,634\r
-兩扇呢,風就來了\r
-\r
-37\r
-00:09:01,680 --> 00:09:03,989\r
-三扇呢,就下雨了\r
-\r
-38\r
-00:09:04,040 --> 00:09:07,510\r
-我們就從這個時候播種收割\r
-\r
-39\r
-00:09:07,560 --> 00:09:11,348\r
-不過,要請那位公主來\r
-\r
-40\r
-00:09:11,400 --> 00:09:14,870\r
-可不是一件容易的事\r
-\r
-41\r
-00:09:14,919 --> 00:09:16,830\r
-她住在什麼地方\r
-\r
-42\r
-00:09:16,880 --> 00:09:20,190\r
-她住在翠雲山芭蕉洞\r
-\r
-43\r
-00:09:20,240 --> 00:09:23,676\r
-是她一個人住在那兒嗎\r
-\r
-44\r
-00:09:23,720 --> 00:09:25,756\r
-她有沒有丈夫啊\r
-\r
-45\r
-00:09:25,800 --> 00:09:29,588\r
-她的丈夫是牛魔王\r
-\r
-46\r
-00:09:29,640 --> 00:09:32,200\r
-原來是老牛\r
-\r
-47\r
-00:09:32,240 --> 00:09:36,791\r
-呆子,你竟然認識他嗎?\r
-跟我一塊兒借扇子去\r
-\r
-48\r
-00:09:36,840 --> 00:09:41,755\r
-我…我知道老牛不住在那兒的\r
-\r
-49\r
-00:09:41,800 --> 00:09:46,351\r
-在他男人不在家的時候\r
-我們去找他的女人\r
-\r
-50\r
-00:09:46,400 --> 00:09:51,520\r
-這…這有點不大方便吧\r
-\r
-51\r
-00:09:51,560 --> 00:09:58,318\r
-你們…兩個人…去吧\r
-\r
-52\r
-00:09:58,360 --> 00:10:05,198\r
-我…我在…這兒…伺候師父\r
-\r
-53\r
-00:10:05,240 --> 00:10:11,270\r
-悟淨,你也跟你兩個師兄一同去吧\r
-\r
-54\r
-00:10:47,200 --> 00:10:51,557\r
-呆子,每次都是我去打頭陣的\r
-\r
-55\r
-00:10:51,600 --> 00:10:54,353\r
-這次該你去了\r
-\r
-56\r
-00:10:58,520 --> 00:11:04,914\r
-三弟,每次都是我去打頭陣\r
-這次該你去了\r
-\r
-57\r
-00:11:04,960 --> 00:11:06,837\r
-大師兄\r
-\r
-58\r
-00:11:06,880 --> 00:11:10,998\r
-我叫你去給師父出一點力\r
-你都不肯嗎\r
-\r
-59\r
-00:11:11,040 --> 00:11:14,316\r
-快去…\r
-\r
-60\r
-00:11:39,640 --> 00:11:43,040\r
-你是哪兒跑來的野和尚\r
-\r
-61\r
-00:11:43,040 --> 00:11:49,878\r
-大唐…聖僧…要你家…大公主…\r
-\r
-62\r
-00:11:49,920 --> 00:11:52,480\r
-胡說\r
-\r
-63\r
-00:12:47,559 --> 00:12:52,075\r
-大…大師兄,還是你去吧\r
-\r
-64\r
-00:12:52,120 --> 00:12:56,955\r
-呆子,你去\r
-\r
-65\r
-00:12:57,000 --> 00:13:00,709\r
-大師兄,還是你去吧\r
-\r
-66\r
-00:13:04,039 --> 00:13:07,475\r
-偷懶的東西\r
-\r
-67\r
-00:13:54,280 --> 00:13:57,909\r
-好雷公菩薩,你饒了我放了我吧\r
-\r
-68\r
-00:13:57,960 --> 00:13:59,951\r
-你跟你們公主說\r
-\r
-69\r
-00:14:00,000 --> 00:14:03,280\r
-我孫悟空要來借芭蕉扇\r
-\r
-70\r
-00:14:03,280 --> 00:14:08,400\r
-好,好,你放了我,我就去\r
-\r
-71\r
-00:14:29,560 --> 00:14:37,069\r
-奶奶,外面有一個孫悟空\r
-要來借芭蕉扇\r
-\r
-72\r
-00:14:41,520 --> 00:14:44,159\r
-快拿我的劍來\r
-\r
-73\r
-00:15:01,640 --> 00:15:04,154\r
-孫悟空,害我兒子的仇人\r
-\r
-74\r
-00:15:04,200 --> 00:15:08,557\r
-你今天也敢自己來送死嗎\r
-\r
-75\r
-00:15:08,600 --> 00:15:12,040\r
-我是從來沒見過你,怎麼會害你的兒子\r
-\r
-76\r
-00:15:12,040 --> 00:15:15,794\r
-我的孩子紅孩兒不是你害死的嗎\r
-\r
-77\r
-00:15:15,840 --> 00:15:20,391\r
-令郎已成正果,怎麼說老孫害他呢\r
-\r
-78\r
-00:15:20,440 --> 00:15:23,750\r
-少說廢話,伸過頭來讓我砍幾劍\r
-\r
-79\r
-00:15:23,800 --> 00:15:26,155\r
-受得住我就把芭蕉扇借給你\r
-\r
-80\r
-00:15:26,200 --> 00:15:28,555\r
-真的嗎\r
-\r
-81\r
-00:15:56,800 --> 00:16:00,634\r
-慢著,快把扇子借給我\r
-\r
-82\r
-00:17:53,639 --> 00:18:00,112\r
-大聖不保唐僧到西天去\r
-來到這兒做什麼\r
-\r
-83\r
-00:18:11,159 --> 00:18:17,155\r
-我被鐵扇公主一扇扇到這兒來的\r
-\r
-84\r
-00:18:17,199 --> 00:18:23,877\r
-大聖你來得巧極了\r
-我有一樣東西送給你\r
-\r
-85\r
-00:18:28,519 --> 00:18:33,468\r
-這裡是一粒定風珠,大聖你有了這珠子\r
-\r
-86\r
-00:18:33,519 --> 00:18:36,158\r
-可以使你的心堅定了\r
-\r
-87\r
-00:18:36,199 --> 00:18:39,191\r
-保那鐵扇公主扇不動你了\r
-\r
-88\r
-00:18:39,239 --> 00:18:42,868\r
-大聖你來看\r
-\r
-89\r
-00:19:00,439 --> 00:19:02,555\r
-謝謝\r
-\r
-90\r
-00:19:06,079 --> 00:19:12,314\r
-大…大師兄…不知給…\r
-\r
-91\r
-00:19:12,359 --> 00:19:18,707\r
-吹到什麼…地方去了\r
-\r
-92\r
-00:19:18,759 --> 00:19:26,109\r
-管他呢,讓猴子也吃點舌頭,我們走\r
-\r
-93\r
-00:19:35,199 --> 00:19:37,269\r
-大…大…師兄\r
-\r
-94\r
-00:19:37,319 --> 00:19:43,479\r
-你…被…被…那…\r
-\r
-95\r
-00:19:43,479 --> 00:19:50,237\r
-大師兄,你被那個婆娘扇到\r
-什麼地方去了\r
-\r
-96\r
-00:19:50,279 --> 00:19:57,196\r
-呆子,現在總該你去了\r
-\r
-97\r
-00:19:57,239 --> 00:20:00,948\r
-我不去,我要是被她一扇\r
-\r
-98\r
-00:20:00,999 --> 00:20:03,467\r
-簡直就認不得回來了\r
-\r
-99\r
-00:20:03,519 --> 00:20:09,719\r
-還是…你再去一趟吧\r
-\r
-100\r
-00:20:09,719 --> 00:20:12,233\r
-不去,不去\r
-\r
-101\r
-00:20:17,799 --> 00:20:22,793\r
-下次輪到你,可不准再偷懶了\r
-\r
-102\r
-00:20:56,159 --> 00:21:00,152\r
-這次你儘管扇,扇得我動一動\r
-\r
-103\r
-00:21:00,199 --> 00:21:05,227\r
-我不算男子漢大丈夫\r
-\r
-104\r
-00:21:33,679 --> 00:21:38,594\r
-大師兄,怎麼這回\r
-她的扇子沒有用啊\r
-\r
-105\r
-00:21:46,839 --> 00:21:50,115\r
-我們來打進去\r
-\r
-106\r
-00:23:59,639 --> 00:24:04,190\r
-快把芭蕉拿出來,給我孫悟空用一用\r
-\r
-107\r
-00:24:14,879 --> 00:24:16,915\r
-孫悟空,你在什麼地方\r
-\r
-108\r
-00:24:16,959 --> 00:24:19,996\r
-我在你肚子裡呢\r
-\r
-109\r
-00:24:45,759 --> 00:24:48,557\r
-孫悟空,你饒了我的命吧\r
-\r
-110\r
-00:24:48,599 --> 00:24:51,193\r
-你把扇子拿出來就是了\r
-\r
-111\r
-00:24:51,239 --> 00:24:56,552\r
-我答應你就是了,請你快點出來吧\r
-\r
-112\r
-00:25:00,239 --> 00:25:02,833\r
-快把扇子拿來\r
-\r
-113\r
-00:25:07,439 --> 00:25:09,236\r
-扇子已經來了\r
-\r
-114\r
-00:25:09,280 --> 00:25:12,078\r
-孫悟空你怎麼還不出來呢\r
-\r
-115\r
-00:25:12,119 --> 00:25:16,635\r
-你把嘴張開來,我就出來了\r
-\r
-116\r
-00:25:25,359 --> 00:25:29,432\r
-孫祖宗,你怎麼還不出來呢\r
-\r
-117\r
-00:25:50,359 --> 00:25:55,592\r
-我在這兒呢,借給我用用就還你的\r
-\r
-118\r
-00:26:32,559 --> 00:26:36,598\r
-師父等了好久了,我們快去吧\r
-\r
-119\r
-00:27:01,879 --> 00:27:04,916\r
-經,經是什麼\r
-\r
-120\r
-00:27:04,959 --> 00:27:10,039\r
-經是天地之間不能辨易的道理\r
-\r
-121\r
-00:27:10,039 --> 00:27:14,191\r
-這個道理也就是做人的道理\r
-\r
-122\r
-00:27:14,239 --> 00:27:18,710\r
-任何一個人有了這個道理\r
-\r
-123\r
-00:27:18,759 --> 00:27:25,358\r
-才可以免去諸般痛苦\r
-好好的安居樂業\r
-\r
-124\r
-00:27:25,399 --> 00:27:29,950\r
-實實在在的過日子\r
-\r
-125\r
-00:27:34,680 --> 00:27:36,352\r
-反過來說\r
-\r
-126\r
-00:27:36,399 --> 00:27:40,108\r
-要是做人不曉得這個道理\r
-\r
-127\r
-00:27:40,159 --> 00:27:46,394\r
-就跟沉陷在苦海裡頭一樣\r
-一生一世\r
-\r
-128\r
-00:27:46,439 --> 00:27:52,628\r
-甚至於子孫孫,都得不到幸福\r
-\r
-129\r
-00:27:52,679 --> 00:27:55,671\r
-我為什麼要去取經\r
-\r
-130\r
-00:27:55,719 --> 00:28:01,316\r
-就是因為現在的人都陷在苦海裡了\r
-\r
-131\r
-00:28:01,359 --> 00:28:04,192\r
-要想成就這此些人\r
-\r
-132\r
-00:28:04,239 --> 00:28:12,510\r
-所以在大唐皇帝面前討下這\r
-重大繁難的差事\r
-\r
-133\r
-00:28:15,679 --> 00:28:17,829\r
-芭蕉扇借到了沒有\r
-\r
-134\r
-00:28:17,879 --> 00:28:19,517\r
-借來了\r
-\r
-135\r
-00:28:19,559 --> 00:28:22,790\r
-是不是這個\r
-\r
-136\r
-00:28:22,839 --> 00:28:27,993\r
-諸位施主,現在扇子既然借到了\r
-\r
-137\r
-00:28:28,039 --> 00:28:32,157\r
-貧僧師徒就要告辭了\r
-\r
-138\r
-00:28:32,199 --> 00:28:34,040\r
-慢一點\r
-\r
-139\r
-00:28:34,040 --> 00:28:39,797\r
-諸位,我想留聖僧在這兒多住幾天\r
-\r
-140\r
-00:28:39,839 --> 00:28:41,352\r
-好不好啊\r
-\r
-141\r
-00:28:41,399 --> 00:28:43,469\r
-好的,好的\r
-\r
-142\r
-00:28:43,519 --> 00:28:45,908\r
-謝謝諸位的好意\r
-\r
-143\r
-00:28:45,959 --> 00:28:51,795\r
-我早走一步就是早一步完成\r
-我們的任務\r
-\r
-144\r
-00:28:51,839 --> 00:28:56,196\r
-那麼就請令高徒先到火焰山\r
-\r
-145\r
-00:28:56,239 --> 00:29:02,155\r
-扇滅了火之後,再陪聖僧同行\r
-\r
-146\r
-00:29:02,199 --> 00:29:05,475\r
-好,你就去吧\r
-\r
-147\r
-00:30:24,479 --> 00:30:30,039\r
-鐵扇公主真可惡,拿假的芭蕉扇\r
-來騙我\r
-\r
-148\r
-00:30:30,039 --> 00:30:32,792\r
-我非殺了她不可\r
-\r
-149\r
-00:30:32,839 --> 00:30:36,309\r
-不,殺了她也是枉然\r
-\r
-150\r
-00:30:36,359 --> 00:30:39,590\r
-我素來不願意你多殺人\r
-\r
-151\r
-00:30:39,639 --> 00:30:42,995\r
-我們再想辦法\r
-\r
-152\r
-00:30:52,159 --> 00:30:56,232\r
-師兄,怎麼你也會上她的當\r
-\r
-153\r
-00:30:56,279 --> 00:30:58,554\r
-費了這麼許多的力氣\r
-\r
-154\r
-00:30:58,599 --> 00:31:02,114\r
-卻弄了一把假的扇子來\r
-\r
-155\r
-00:31:02,159 --> 00:31:06,516\r
-笑話,笑話\r
-\r
-156\r
-00:31:08,919 --> 00:31:10,432\r
-那麼你去\r
-\r
-157\r
-00:31:10,479 --> 00:31:14,392\r
-好好,我去我去,我就去\r
-\r
-158\r
-00:31:14,439 --> 00:31:17,033\r
-我去找牛魔王\r
-\r
-159\r
-00:31:17,119 --> 00:31:19,952\r
-這倒是一個好辦法\r
-\r
-160\r
-00:31:21,399 --> 00:31:24,550\r
-師兄,你看好不好\r
-\r
-161\r
-00:31:24,599 --> 00:31:27,397\r
-好,看你的了\r
-\r
-162\r
-00:33:07,199 --> 00:33:11,159\r
-你看我今天化妝得好嗎\r
-\r
-163\r
-00:33:11,159 --> 00:33:13,798\r
-好極了,我的小寶貝\r
-\r
-164\r
-00:33:13,839 --> 00:33:17,070\r
-你陪我到洞外頭去走走,好不好\r
-\r
-165\r
-00:33:17,119 --> 00:33:21,556\r
-我的寶貝,還是你一個人去吧\r
-\r
-166\r
-00:33:21,599 --> 00:33:24,830\r
-本來嘛,我們這種草婆子\r
-\r
-167\r
-00:33:24,879 --> 00:33:28,030\r
-跟你出去了會使你丟臉的\r
-\r
-168\r
-00:33:28,079 --> 00:33:32,039\r
-小寶貝,這是什麼話呢\r
-\r
-169\r
-00:33:32,039 --> 00:33:37,511\r
-你先去,我隨後就來好不好\r
-\r
-170\r
-00:35:28,039 --> 00:35:35,673\r
-女菩薩,你真是天仙下凡\r
-\r
-171\r
-00:35:35,719 --> 00:35:37,914\r
-你…你是什麼人\r
-\r
-172\r
-00:35:37,959 --> 00:35:41,474\r
-我是從芭蕉洞來找牛魔王的\r
-\r
-173\r
-00:35:41,520 --> 00:35:43,988\r
-快放手\r
-\r
-174\r
-00:35:49,559 --> 00:35:52,949\r
-女菩薩,你慢點走\r
-\r
-175\r
-00:36:44,239 --> 00:36:49,233\r
-小寶貝,誰來欺負你\r
-\r
-176\r
-00:36:49,279 --> 00:36:50,837\r
-是你\r
-\r
-177\r
-00:36:50,879 --> 00:36:54,349\r
-我哪裡捨得欺負你呢\r
-\r
-178\r
-00:36:56,919 --> 00:36:59,274\r
-你還是回芭蕉洞去吧\r
-\r
-179\r
-00:36:59,320 --> 00:37:01,709\r
-省得那個不要臉的東西\r
-\r
-180\r
-00:37:01,759 --> 00:37:07,675\r
-時常派人來請你,欺負我\r
-\r
-181\r
-00:37:07,719 --> 00:37:11,075\r
-你說有人來找我\r
-\r
-182\r
-00:37:11,119 --> 00:37:15,078\r
-外邊有一個豬臉的和尚來請你\r
-\r
-183\r
-00:37:15,120 --> 00:37:18,510\r
-差一點把我嚇死了\r
-\r
-184\r
-00:37:18,559 --> 00:37:22,757\r
-真有這回事嗎?待我出去看一看\r
-\r
-185\r
-00:37:50,679 --> 00:37:53,796\r
-牛大哥\r
-\r
-186\r
-00:37:53,839 --> 00:37:58,151\r
-這裡頭有個頂漂亮的小娘們\r
-\r
-187\r
-00:37:58,200 --> 00:38:03,991\r
-呸,那是我的女人,你為什麼要欺負她\r
-\r
-188\r
-00:38:04,039 --> 00:38:08,559\r
-大哥,我不知那就是二嫂,請原瓊\r
-\r
-189\r
-00:38:08,559 --> 00:38:11,949\r
-不知道不見罪,好啊,你走啊\r
-\r
-190\r
-00:38:11,999 --> 00:38:16,117\r
-不不不,我還有事情請大哥幫忙\r
-\r
-191\r
-00:38:18,479 --> 00:38:24,719\r
-小弟保唐僧取經,路過火焰山\r
-\r
-192\r
-00:38:24,719 --> 00:38:27,313\r
-請大哥跟嫂子說一聲\r
-\r
-193\r
-00:38:27,359 --> 00:38:30,829\r
-把這個芭蕉扇借來用一用\r
-\r
-194\r
-00:38:30,880 --> 00:38:33,519\r
-不成,那唐僧和孫悟空\r
-\r
-195\r
-00:38:33,519 --> 00:38:35,191\r
-是我孩子的仇人\r
-\r
-196\r
-00:38:35,239 --> 00:38:38,754\r
-我正要抓他們報仇\r
-\r
-197\r
-00:38:38,799 --> 00:38:44,988\r
-令郎已成正果,請大哥不必再計較吧\r
-\r
-198\r
-00:38:45,039 --> 00:38:48,952\r
-好,看在我們從前的交情\r
-我不跟你計較\r
-\r
-199\r
-00:38:49,000 --> 00:38:51,719\r
-那麼去吧\r
-\r
-200\r
-00:39:38,399 --> 00:39:44,190\r
-寶貝,那個豬臉和尚\r
-是我從前一個朋友\r
-\r
-201\r
-00:39:44,239 --> 00:39:46,514\r
-並不是芭蕉洞派來的\r
-\r
-202\r
-00:39:46,559 --> 00:39:47,753\r
-我不相信\r
-\r
-203\r
-00:39:47,799 --> 00:39:50,950\r
-我不騙你\r
-\r
-204\r
-00:39:50,999 --> 00:39:54,036\r
-現在那個和尚到哪兒去了呢\r
-\r
-205\r
-00:39:54,119 --> 00:39:57,794\r
-已經被我打走了\r
-\r
-206\r
-00:43:58,639 --> 00:44:01,358\r
-大王回來了\r
-\r
-207\r
-00:44:01,399 --> 00:44:02,388\r
-奶奶呢\r
-\r
-208\r
-00:44:02,439 --> 00:44:04,794\r
-在裡邊\r
-\r
-209\r
-00:44:42,999 --> 00:44:48,232\r
-今天是什麼風會把大王吹到這兒來的\r
-\r
-210\r
-00:44:48,279 --> 00:44:52,272\r
-聽到孫悟空保唐僧快到這兒\r
-\r
-211\r
-00:44:52,320 --> 00:44:56,916\r
-恐怕他要來借芭蕉扇過火焰山\r
-\r
-212\r
-00:44:56,959 --> 00:45:00,872\r
-那猴子是害我們兒子的仇人\r
-\r
-213\r
-00:45:00,919 --> 00:45:08,507\r
-早晚來了抓著他,讓我們夫妻出出恨\r
-\r
-214\r
-00:45:08,559 --> 00:45:12,711\r
-夫人,你為什麼哭\r
-\r
-215\r
-00:45:12,759 --> 00:45:15,717\r
-那猴子已經來過了\r
-\r
-216\r
-00:45:15,759 --> 00:45:18,876\r
-是我不肯把扇子借給他\r
-\r
-217\r
-00:45:18,919 --> 00:45:22,275\r
-不知道怎麼會跑到我的肚子裡來\r
-\r
-218\r
-00:45:22,319 --> 00:45:25,516\r
-弄得我肚子痛得要命\r
-\r
-219\r
-00:45:25,559 --> 00:45:31,399\r
-後來我沒有法子,只好把扇子借給他\r
-\r
-220\r
-00:45:31,399 --> 00:45:38,271\r
-可惜可惜,你怎麼把扇子借給他\r
-\r
-221\r
-00:45:38,320 --> 00:45:40,470\r
-拿去的是假的\r
-\r
-222\r
-00:45:40,519 --> 00:45:43,033\r
-假的\r
-\r
-223\r
-00:46:14,199 --> 00:46:19,876\r
-開筵慶祝大王歸\r
-\r
-224\r
-00:46:19,919 --> 00:46:25,630\r
-好酒殷勤勸幾杯\r
-\r
-225\r
-00:46:25,679 --> 00:46:34,189\r
-雞又香,鴨又美,豬又肥\r
-\r
-226\r
-00:46:34,240 --> 00:46:45,674\r
-我盡量的歌,我盡量的舞\r
-\r
-227\r
-00:46:45,719 --> 00:46:54,514\r
-你也要盡量的醉\r
-\r
-228\r
-00:47:03,599 --> 00:47:16,399\r
-大王啊,你把舊人丟\r
-\r
-229\r
-00:47:16,439 --> 00:47:22,628\r
-你愛新人媚\r
-\r
-230\r
-00:47:22,679 --> 00:47:36,673\r
-為你淌了多少相思淚\r
-\r
-231\r
-00:47:46,719 --> 00:47:55,718\r
-等一會燈兒吹帳兒垂\r
-\r
-232\r
-00:47:55,759 --> 00:48:00,879\r
-你獨自兒睡\r
-\r
-233\r
-00:48:00,879 --> 00:48:05,519\r
-也嘗嘗這個淒涼味\r
-\r
-234\r
-00:48:05,519 --> 00:48:13,437\r
-恕我不奉陪\r
-\r
-235\r
-00:48:18,559 --> 00:48:24,634\r
-就是同床\r
-\r
-236\r
-00:48:24,679 --> 00:48:34,350\r
-我們各人蓋著各人的被\r
-\r
-237\r
-00:48:38,399 --> 00:48:42,392\r
-大王,我醉了\r
-\r
-238\r
-00:48:55,079 --> 00:48:58,151\r
-夫人,那真扇子你放在什麼地方\r
-\r
-239\r
-00:48:58,199 --> 00:49:05,469\r
-那猴子花樣很多,而且那豬八戒\r
-本事更大\r
-\r
-240\r
-00:49:05,519 --> 00:49:09,797\r
-當心給他們騙了去\r
-\r
-241\r
-00:49:18,360 --> 00:49:21,989\r
-寶貝不是在這兒嗎\r
-\r
-242\r
-00:49:31,439 --> 00:49:39,319\r
-大王,你出神想什麼呢?\r
-還是收了吧\r
-\r
-243\r
-00:49:39,319 --> 00:49:43,551\r
-小寶貝\r
-\r
-244\r
-00:49:43,599 --> 00:49:49,037\r
-寶貝,你多喝一杯,你喝啊\r
-\r
-245\r
-00:49:53,919 --> 00:49:59,519\r
-今兒晚上,金龍大王\r
-還要請我去喝酒呢\r
-\r
-246\r
-00:49:59,519 --> 00:50:01,430\r
-那你就該去了\r
-\r
-247\r
-00:50:01,479 --> 00:50:02,878\r
-是的\r
-\r
-248\r
-00:50:02,919 --> 00:50:06,628\r
-你去替爺爺把金睛獸牽出去預備好\r
-\r
-249\r
-00:50:06,679 --> 00:50:08,271\r
-是\r
-\r
-250\r
-00:50:08,320 --> 00:50:12,598\r
-可是,你今兒個晚上去要少喝一點兒\r
-\r
-251\r
-00:50:12,639 --> 00:50:15,756\r
-免得回來睡著叫不醒你\r
-\r
-252\r
-00:50:15,800 --> 00:50:19,110\r
-不好了,爺爺那個金隋獸不見了\r
-\r
-253\r
-00:50:19,159 --> 00:50:20,911\r
-你們全都是死人嗎\r
-\r
-254\r
-00:50:20,959 --> 00:50:24,039\r
-家裡頭的東西怎麼會不見了呢\r
-\r
-255\r
-00:50:24,039 --> 00:50:27,918\r
-寶貝,不要管他們吧\r
-\r
-256\r
-00:50:27,960 --> 00:50:31,714\r
-恐怕是那豬八戒偷了去了\r
-\r
-257\r
-00:50:31,759 --> 00:50:35,274\r
-說不定我要到芭蕉洞去一趟\r
-\r
-258\r
-00:50:35,320 --> 00:50:39,313\r
-原來是你們做好了的圈套\r
-\r
-259\r
-00:50:42,280 --> 00:50:48,150\r
-你還是要到那個不要臉的女人那兒去\r
-\r
-260\r
-00:50:48,199 --> 00:50:50,713\r
-好寶貝,你不要哭了\r
-\r
-261\r
-00:50:50,759 --> 00:50:54,069\r
-我去去就來的\r
-\r
-262\r
-00:51:02,679 --> 00:51:07,309\r
-來來,喝喝\r
-\r
-263\r
-00:51:10,359 --> 00:51:12,475\r
-我現在放心了\r
-\r
-264\r
-00:51:12,519 --> 00:51:16,717\r
-不怕他們偷我們的寶貝\r
-\r
-265\r
-00:51:16,759 --> 00:51:21,310\r
-他們就是偷了去\r
-不知道把那絲線一拉\r
-\r
-266\r
-00:51:21,360 --> 00:51:26,275\r
-單是一顆珠子也沒有用處啊\r
-\r
-267\r
-00:51:26,319 --> 00:51:31,791\r
-是不是那麼一拉就變成扇子\r
-\r
-268\r
-00:51:35,120 --> 00:51:38,078\r
-大王,你今天喝醉了\r
-\r
-269\r
-00:51:38,119 --> 00:51:44,035\r
-自己的寶貝都忘了,還來問我\r
-\r
-270\r
-00:51:49,999 --> 00:51:53,708\r
-娘子,你看看我是誰\r
-\r
-271\r
-00:52:00,320 --> 00:52:03,756\r
-你是什麼人\r
-\r
-272\r
-00:52:03,799 --> 00:52:09,908\r
-我是唐僧的二徒弟,豬八戒\r
-\r
-273\r
-00:52:09,959 --> 00:52:14,794\r
-對不住,謝謝你,打擾了\r
-\r
-274\r
-00:52:19,080 --> 00:52:21,719\r
-再見\r
-\r
-275\r
-00:53:06,839 --> 00:53:10,718\r
-牛大嫂太風騷\r
-\r
-276\r
-00:53:10,760 --> 00:53:14,719\r
-眾小妖都俊俏\r
-\r
-277\r
-00:53:14,759 --> 00:53:24,828\r
-老豬真有點受不了\r
-\r
-278\r
-00:53:24,879 --> 00:53:28,872\r
-心機巧,手段妙\r
-\r
-279\r
-00:53:28,919 --> 00:53:32,832\r
-居然騙得了無價寶\r
-\r
-280\r
-00:53:32,880 --> 00:53:36,793\r
-這一番勞苦功高\r
-\r
-281\r
-00:53:36,839 --> 00:53:38,318\r
-沙僧該拜倒\r
-\r
-282\r
-00:53:38,359 --> 00:53:40,748\r
-猴兒該領教\r
-\r
-283\r
-00:53:40,799 --> 00:53:45,236\r
-師父也要嚇一跳\r
-\r
-284\r
-00:53:45,280 --> 00:53:49,193\r
-我老豬也有今朝\r
-\r
-285\r
-00:53:49,239 --> 00:53:54,359\r
-我老豬也有今朝\r
-\r
-286\r
-00:54:36,720 --> 00:54:40,474\r
-呆子,事情辦得怎麼樣了\r
-\r
-287\r
-00:54:40,519 --> 00:54:42,828\r
-不僅扇子到手\r
-\r
-288\r
-00:54:42,880 --> 00:54:48,796\r
-鐵扇公主並且還做了我\r
-半天的老婆\r
-\r
-289\r
-00:54:48,839 --> 00:54:51,717\r
-這倒便宜了你了\r
-\r
-290\r
-00:54:58,159 --> 00:55:01,595\r
-扇子拿來給我看看\r
-\r
-291\r
-00:55:16,039 --> 00:55:20,237\r
-你怎麼會把它縮小了的呀\r
-\r
-292\r
-00:55:40,559 --> 00:55:45,349\r
-老豬,你可認識我嗎\r
-\r
-293\r
-00:55:45,399 --> 00:55:49,187\r
-你不要跟我開玩笑了\r
-\r
-294\r
-00:55:49,239 --> 00:55:52,151\r
-誰跟你開玩笑\r
-\r
-295\r
-00:56:42,879 --> 00:56:45,393\r
-呆子,你去了怎麼樣\r
-\r
-296\r
-00:56:45,439 --> 00:56:47,111\r
-白跑了一趟\r
-\r
-297\r
-00:56:47,159 --> 00:56:49,992\r
-悟能,扇子借來沒有\r
-\r
-298\r
-00:56:50,039 --> 00:56:53,349\r
-我去找牛魔王,他不肯借\r
-\r
-299\r
-00:56:53,400 --> 00:56:59,191\r
-後來,我又變成老牛的樣子\r
-\r
-300\r
-00:56:59,239 --> 00:57:03,551\r
-在鐵扇公主那兒把扇子已經騙過來了\r
-\r
-301\r
-00:57:03,599 --> 00:57:10,599\r
-誰知道他又變成你的樣子又給他騙回去了\r
-\r
-302\r
-00:57:10,599 --> 00:57:12,749\r
-老牛的本領大\r
-\r
-303\r
-00:57:12,800 --> 00:57:16,156\r
-我還被他揍了一頓呢\r
-\r
-304\r
-00:57:16,199 --> 00:57:21,398\r
-呆子,你能辦這樣大的事那\r
-還算是呆子嗎\r
-\r
-305\r
-00:57:21,439 --> 00:57:25,671\r
-事情不都環在你頭上\r
-\r
-306\r
-00:57:30,759 --> 00:57:34,388\r
-你們不要吵了,趕緊再想辦法\r
-\r
-307\r
-00:57:34,439 --> 00:57:40,275\r
-哪一方…沒…沒有火啊\r
-\r
-308\r
-00:57:40,320 --> 00:57:47,078\r
-東南西北,只有西方有火\r
-\r
-309\r
-00:57:47,120 --> 00:57:50,749\r
-那我們不是要走回去了嗎\r
-\r
-310\r
-00:57:50,799 --> 00:57:52,949\r
-這路不通,不回去怎麼樣呢\r
-\r
-311\r
-00:57:52,999 --> 00:57:55,229\r
-八戒,你不要這樣說\r
-\r
-312\r
-00:57:55,279 --> 00:57:59,158\r
-要成功一件事情總是有阻礙的\r
-\r
-313\r
-00:57:59,199 --> 00:58:04,557\r
-我們要做這樣神聖的事情\r
-就要堅定我們的信念\r
-\r
-314\r
-00:58:04,599 --> 00:58:09,229\r
-不能因為有一點兒困難\r
-就中適改變我們的宗旨\r
-\r
-315\r
-00:58:09,280 --> 00:58:14,593\r
-你們這次失敗的原因是由於\r
-既不同心又不合力\r
-\r
-316\r
-00:58:14,639 --> 00:58:17,153\r
-假使你們三個人一條心\r
-\r
-317\r
-00:58:17,199 --> 00:58:20,509\r
-合起力量,共同跟牛魔王決鬥\r
-\r
-318\r
-00:58:20,559 --> 00:58:22,868\r
-事情一定可以成功的\r
-\r
-319\r
-00:58:22,919 --> 00:58:26,039\r
-我們謹遵師父的命令\r
-\r
-320\r
-00:58:26,039 --> 00:58:30,157\r
-去跟牛魔王爭一個誰勝誰敗\r
-\r
-321\r
-00:58:30,199 --> 00:58:34,272\r
-誰…誰…誰勝誰敗\r
-\r
-322\r
-00:58:34,320 --> 00:58:37,710\r
-那就好極了\r
-\r
-323\r
-00:58:37,759 --> 00:58:40,990\r
-各位受他的害處也不小了\r
-\r
-324\r
-00:58:41,040 --> 00:58:43,879\r
-希望各位也出此些力量\r
-\r
-325\r
-00:58:43,879 --> 00:58:49,590\r
-跟小徒們共同征服牛魔王,消滅火焰山\r
-\r
-326\r
-00:58:49,639 --> 00:58:53,837\r
-免除永遠的禍害\r
-\r
-327\r
-00:58:53,879 --> 00:58:57,508\r
-我們聽從師父的命令,為大家謀幸福\r
-\r
-328\r
-00:58:57,559 --> 00:58:58,878\r
-大家一起出力去\r
-\r
-329\r
-00:58:58,919 --> 00:59:01,035\r
-好\r
-\r
-330\r
-01:08:23,239 --> 01:08:25,628\r
-奶奶,不好了\r
-\r
-331\r
-01:08:25,679 --> 01:08:30,799\r
-爺爺給人家抓住了,你快點去看看吧\r
-\r
-332\r
-01:08:54,479 --> 01:08:56,709\r
-還不過來打,過來打\r
-\r
-333\r
-01:08:56,760 --> 01:08:59,718\r
-慢一點,慢一點\r
-\r
-334\r
-01:08:59,760 --> 01:09:05,790\r
-孽畜,只要你把扇子交出來,饒你不死\r
-\r
-335\r
-01:09:05,840 --> 01:09:12,757\r
-老牛,扇子在什麼地方?快拿出來啊\r
-\r
-336\r
-01:09:12,799 --> 01:09:19,352\r
-在我老…老婆那兒\r
-\r
-337\r
-01:09:25,240 --> 01:09:27,993\r
-夫人,夫人,夫人\r
-\r
-338\r
-01:09:28,039 --> 01:09:32,271\r
-你快點來救救我\r
-\r
-339\r
-01:09:32,320 --> 01:09:35,118\r
-把扇子拿出來吧\r
-\r
-340\r
-01:09:35,159 --> 01:09:39,630\r
-大王,好,好的\r
-\r
-341\r
-01:09:43,400 --> 01:09:47,234\r
-悟空,你再去一趟吧\r
-\r
+1
+00:00:01,080 --> 00:00:09,078
+片名:鐵扇公主
+
+2
+00:02:03,119 --> 00:02:09,280
+西遊記,本為一部絕妙之童話
+
+3
+00:02:09,280 --> 00:02:15,280
+特以世多誤解,致被目為神怪小說
+
+4
+00:02:15,280 --> 00:02:19,240
+本片取材於是
+
+5
+00:02:19,240 --> 00:02:24,240
+實為培育兒童心理而作
+
+6
+00:02:24,240 --> 00:02:29,280
+故內容刪蕪存精,不涉神怪
+
+7
+00:02:29,280 --> 00:02:32,560
+僅以唐僧等四人路阻火焰山
+
+8
+00:02:32,560 --> 00:02:41,040
+以示人生途徑中之磨難
+
+9
+00:02:41,040 --> 00:02:46,440
+欲求經此磨難,則必須堅持信念
+大眾一心
+
+10
+00:02:46,440 --> 00:02:52,436
+始能獲得此撲滅凶焰之芭蕉扇
+
+11
+00:03:34,480 --> 00:03:37,790
+現在已經秋天了,怎麼還這麼熱
+
+12
+00:03:37,840 --> 00:03:42,356
+呆子,不要說廢話,趕路要緊
+
+13
+00:04:06,920 --> 00:04:09,354
+悟空,這是到了什麼地方
+
+14
+00:04:09,400 --> 00:04:13,678
+反正是我們上西天必定要經過的地方
+
+15
+00:04:13,720 --> 00:04:18,111
+我們沒有走錯路線吧
+
+16
+00:04:18,159 --> 00:04:22,311
+為什麼這個地方這麼樣的熱呢
+
+17
+00:04:30,039 --> 00:04:31,711
+師傅,你看
+
+18
+00:04:31,759 --> 00:04:33,795
+前面那兒,不是有一座房子了嗎
+
+19
+00:04:33,839 --> 00:04:38,117
+我們大家進去歇息一會兒好吧
+
+20
+00:04:59,399 --> 00:05:02,914
+這個地方名叫火焰山
+
+21
+00:05:02,959 --> 00:05:06,031
+周圍有幾百里的火焰
+
+22
+00:05:06,079 --> 00:05:08,752
+一根草都不生
+
+23
+00:05:08,799 --> 00:05:11,632
+一年四季都是熱的
+
+24
+00:05:11,680 --> 00:05:19,633
+就是銅頭鐵臂要經過那個山
+也得融化成水
+
+25
+00:05:19,679 --> 00:05:23,592
+哪有這種事,師傅,你請放心
+
+26
+00:05:23,639 --> 00:05:27,154
+我們三個人都有法子可以過去
+
+27
+00:05:27,199 --> 00:05:30,714
+師傅,我去看看好吧
+
+28
+00:08:06,319 --> 00:08:09,595
+悟空,你去看了怎麼樣
+
+29
+00:08:09,639 --> 00:08:11,834
+厲害,厲害,真厲言
+
+30
+00:08:11,880 --> 00:08:15,919
+要不是我跑得快,尾巴都燒光了
+
+31
+00:08:42,720 --> 00:08:47,600
+老施主,這裡的火這樣大
+
+32
+00:08:47,600 --> 00:08:49,670
+這五穀從哪兒來的
+
+33
+00:08:49,719 --> 00:08:53,997
+你看這兒有一千多里的路
+有一位鐵扇公主
+
+34
+00:08:54,040 --> 00:08:56,508
+她有一把芭蕉扇
+
+35
+00:08:56,560 --> 00:08:59,074
+一扇呢,火就熄了
+
+36
+00:08:59,120 --> 00:09:01,634
+兩扇呢,風就來了
+
+37
+00:09:01,680 --> 00:09:03,989
+三扇呢,就下雨了
+
+38
+00:09:04,040 --> 00:09:07,510
+我們就從這個時候播種收割
+
+39
+00:09:07,560 --> 00:09:11,348
+不過,要請那位公主來
+
+40
+00:09:11,400 --> 00:09:14,870
+可不是一件容易的事
+
+41
+00:09:14,919 --> 00:09:16,830
+她住在什麼地方
+
+42
+00:09:16,880 --> 00:09:20,190
+她住在翠雲山芭蕉洞
+
+43
+00:09:20,240 --> 00:09:23,676
+是她一個人住在那兒嗎
+
+44
+00:09:23,720 --> 00:09:25,756
+她有沒有丈夫啊
+
+45
+00:09:25,800 --> 00:09:29,588
+她的丈夫是牛魔王
+
+46
+00:09:29,640 --> 00:09:32,200
+原來是老牛
+
+47
+00:09:32,240 --> 00:09:36,791
+呆子,你竟然認識他嗎?
+跟我一塊兒借扇子去
+
+48
+00:09:36,840 --> 00:09:41,755
+我…我知道老牛不住在那兒的
+
+49
+00:09:41,800 --> 00:09:46,351
+在他男人不在家的時候
+我們去找他的女人
+
+50
+00:09:46,400 --> 00:09:51,520
+這…這有點不大方便吧
+
+51
+00:09:51,560 --> 00:09:58,318
+你們…兩個人…去吧
+
+52
+00:09:58,360 --> 00:10:05,198
+我…我在…這兒…伺候師父
+
+53
+00:10:05,240 --> 00:10:11,270
+悟淨,你也跟你兩個師兄一同去吧
+
+54
+00:10:47,200 --> 00:10:51,557
+呆子,每次都是我去打頭陣的
+
+55
+00:10:51,600 --> 00:10:54,353
+這次該你去了
+
+56
+00:10:58,520 --> 00:11:04,914
+三弟,每次都是我去打頭陣
+這次該你去了
+
+57
+00:11:04,960 --> 00:11:06,837
+大師兄
+
+58
+00:11:06,880 --> 00:11:10,998
+我叫你去給師父出一點力
+你都不肯嗎
+
+59
+00:11:11,040 --> 00:11:14,316
+快去…
+
+60
+00:11:39,640 --> 00:11:43,040
+你是哪兒跑來的野和尚
+
+61
+00:11:43,040 --> 00:11:49,878
+大唐…聖僧…要你家…大公主…
+
+62
+00:11:49,920 --> 00:11:52,480
+胡說
+
+63
+00:12:47,559 --> 00:12:52,075
+大…大師兄,還是你去吧
+
+64
+00:12:52,120 --> 00:12:56,955
+呆子,你去
+
+65
+00:12:57,000 --> 00:13:00,709
+大師兄,還是你去吧
+
+66
+00:13:04,039 --> 00:13:07,475
+偷懶的東西
+
+67
+00:13:54,280 --> 00:13:57,909
+好雷公菩薩,你饒了我放了我吧
+
+68
+00:13:57,960 --> 00:13:59,951
+你跟你們公主說
+
+69
+00:14:00,000 --> 00:14:03,280
+我孫悟空要來借芭蕉扇
+
+70
+00:14:03,280 --> 00:14:08,400
+好,好,你放了我,我就去
+
+71
+00:14:29,560 --> 00:14:37,069
+奶奶,外面有一個孫悟空
+要來借芭蕉扇
+
+72
+00:14:41,520 --> 00:14:44,159
+快拿我的劍來
+
+73
+00:15:01,640 --> 00:15:04,154
+孫悟空,害我兒子的仇人
+
+74
+00:15:04,200 --> 00:15:08,557
+你今天也敢自己來送死嗎
+
+75
+00:15:08,600 --> 00:15:12,040
+我是從來沒見過你,怎麼會害你的兒子
+
+76
+00:15:12,040 --> 00:15:15,794
+我的孩子紅孩兒不是你害死的嗎
+
+77
+00:15:15,840 --> 00:15:20,391
+令郎已成正果,怎麼說老孫害他呢
+
+78
+00:15:20,440 --> 00:15:23,750
+少說廢話,伸過頭來讓我砍幾劍
+
+79
+00:15:23,800 --> 00:15:26,155
+受得住我就把芭蕉扇借給你
+
+80
+00:15:26,200 --> 00:15:28,555
+真的嗎
+
+81
+00:15:56,800 --> 00:16:00,634
+慢著,快把扇子借給我
+
+82
+00:17:53,639 --> 00:18:00,112
+大聖不保唐僧到西天去
+來到這兒做什麼
+
+83
+00:18:11,159 --> 00:18:17,155
+我被鐵扇公主一扇扇到這兒來的
+
+84
+00:18:17,199 --> 00:18:23,877
+大聖你來得巧極了
+我有一樣東西送給你
+
+85
+00:18:28,519 --> 00:18:33,468
+這裡是一粒定風珠,大聖你有了這珠子
+
+86
+00:18:33,519 --> 00:18:36,158
+可以使你的心堅定了
+
+87
+00:18:36,199 --> 00:18:39,191
+保那鐵扇公主扇不動你了
+
+88
+00:18:39,239 --> 00:18:42,868
+大聖你來看
+
+89
+00:19:00,439 --> 00:19:02,555
+謝謝
+
+90
+00:19:06,079 --> 00:19:12,314
+大…大師兄…不知給…
+
+91
+00:19:12,359 --> 00:19:18,707
+吹到什麼…地方去了
+
+92
+00:19:18,759 --> 00:19:26,109
+管他呢,讓猴子也吃點舌頭,我們走
+
+93
+00:19:35,199 --> 00:19:37,269
+大…大…師兄
+
+94
+00:19:37,319 --> 00:19:43,479
+你…被…被…那…
+
+95
+00:19:43,479 --> 00:19:50,237
+大師兄,你被那個婆娘扇到
+什麼地方去了
+
+96
+00:19:50,279 --> 00:19:57,196
+呆子,現在總該你去了
+
+97
+00:19:57,239 --> 00:20:00,948
+我不去,我要是被她一扇
+
+98
+00:20:00,999 --> 00:20:03,467
+簡直就認不得回來了
+
+99
+00:20:03,519 --> 00:20:09,719
+還是…你再去一趟吧
+
+100
+00:20:09,719 --> 00:20:12,233
+不去,不去
+
+101
+00:20:17,799 --> 00:20:22,793
+下次輪到你,可不准再偷懶了
+
+102
+00:20:56,159 --> 00:21:00,152
+這次你儘管扇,扇得我動一動
+
+103
+00:21:00,199 --> 00:21:05,227
+我不算男子漢大丈夫
+
+104
+00:21:33,679 --> 00:21:38,594
+大師兄,怎麼這回
+她的扇子沒有用啊
+
+105
+00:21:46,839 --> 00:21:50,115
+我們來打進去
+
+106
+00:23:59,639 --> 00:24:04,190
+快把芭蕉拿出來,給我孫悟空用一用
+
+107
+00:24:14,879 --> 00:24:16,915
+孫悟空,你在什麼地方
+
+108
+00:24:16,959 --> 00:24:19,996
+我在你肚子裡呢
+
+109
+00:24:45,759 --> 00:24:48,557
+孫悟空,你饒了我的命吧
+
+110
+00:24:48,599 --> 00:24:51,193
+你把扇子拿出來就是了
+
+111
+00:24:51,239 --> 00:24:56,552
+我答應你就是了,請你快點出來吧
+
+112
+00:25:00,239 --> 00:25:02,833
+快把扇子拿來
+
+113
+00:25:07,439 --> 00:25:09,236
+扇子已經來了
+
+114
+00:25:09,280 --> 00:25:12,078
+孫悟空你怎麼還不出來呢
+
+115
+00:25:12,119 --> 00:25:16,635
+你把嘴張開來,我就出來了
+
+116
+00:25:25,359 --> 00:25:29,432
+孫祖宗,你怎麼還不出來呢
+
+117
+00:25:50,359 --> 00:25:55,592
+我在這兒呢,借給我用用就還你的
+
+118
+00:26:32,559 --> 00:26:36,598
+師父等了好久了,我們快去吧
+
+119
+00:27:01,879 --> 00:27:04,916
+經,經是什麼
+
+120
+00:27:04,959 --> 00:27:10,039
+經是天地之間不能辨易的道理
+
+121
+00:27:10,039 --> 00:27:14,191
+這個道理也就是做人的道理
+
+122
+00:27:14,239 --> 00:27:18,710
+任何一個人有了這個道理
+
+123
+00:27:18,759 --> 00:27:25,358
+才可以免去諸般痛苦
+好好的安居樂業
+
+124
+00:27:25,399 --> 00:27:29,950
+實實在在的過日子
+
+125
+00:27:34,680 --> 00:27:36,352
+反過來說
+
+126
+00:27:36,399 --> 00:27:40,108
+要是做人不曉得這個道理
+
+127
+00:27:40,159 --> 00:27:46,394
+就跟沉陷在苦海裡頭一樣
+一生一世
+
+128
+00:27:46,439 --> 00:27:52,628
+甚至於子孫孫,都得不到幸福
+
+129
+00:27:52,679 --> 00:27:55,671
+我為什麼要去取經
+
+130
+00:27:55,719 --> 00:28:01,316
+就是因為現在的人都陷在苦海裡了
+
+131
+00:28:01,359 --> 00:28:04,192
+要想成就這此些人
+
+132
+00:28:04,239 --> 00:28:12,510
+所以在大唐皇帝面前討下這
+重大繁難的差事
+
+133
+00:28:15,679 --> 00:28:17,829
+芭蕉扇借到了沒有
+
+134
+00:28:17,879 --> 00:28:19,517
+借來了
+
+135
+00:28:19,559 --> 00:28:22,790
+是不是這個
+
+136
+00:28:22,839 --> 00:28:27,993
+諸位施主,現在扇子既然借到了
+
+137
+00:28:28,039 --> 00:28:32,157
+貧僧師徒就要告辭了
+
+138
+00:28:32,199 --> 00:28:34,040
+慢一點
+
+139
+00:28:34,040 --> 00:28:39,797
+諸位,我想留聖僧在這兒多住幾天
+
+140
+00:28:39,839 --> 00:28:41,352
+好不好啊
+
+141
+00:28:41,399 --> 00:28:43,469
+好的,好的
+
+142
+00:28:43,519 --> 00:28:45,908
+謝謝諸位的好意
+
+143
+00:28:45,959 --> 00:28:51,795
+我早走一步就是早一步完成
+我們的任務
+
+144
+00:28:51,839 --> 00:28:56,196
+那麼就請令高徒先到火焰山
+
+145
+00:28:56,239 --> 00:29:02,155
+扇滅了火之後,再陪聖僧同行
+
+146
+00:29:02,199 --> 00:29:05,475
+好,你就去吧
+
+147
+00:30:24,479 --> 00:30:30,039
+鐵扇公主真可惡,拿假的芭蕉扇
+來騙我
+
+148
+00:30:30,039 --> 00:30:32,792
+我非殺了她不可
+
+149
+00:30:32,839 --> 00:30:36,309
+不,殺了她也是枉然
+
+150
+00:30:36,359 --> 00:30:39,590
+我素來不願意你多殺人
+
+151
+00:30:39,639 --> 00:30:42,995
+我們再想辦法
+
+152
+00:30:52,159 --> 00:30:56,232
+師兄,怎麼你也會上她的當
+
+153
+00:30:56,279 --> 00:30:58,554
+費了這麼許多的力氣
+
+154
+00:30:58,599 --> 00:31:02,114
+卻弄了一把假的扇子來
+
+155
+00:31:02,159 --> 00:31:06,516
+笑話,笑話
+
+156
+00:31:08,919 --> 00:31:10,432
+那麼你去
+
+157
+00:31:10,479 --> 00:31:14,392
+好好,我去我去,我就去
+
+158
+00:31:14,439 --> 00:31:17,033
+我去找牛魔王
+
+159
+00:31:17,119 --> 00:31:19,952
+這倒是一個好辦法
+
+160
+00:31:21,399 --> 00:31:24,550
+師兄,你看好不好
+
+161
+00:31:24,599 --> 00:31:27,397
+好,看你的了
+
+162
+00:33:07,199 --> 00:33:11,159
+你看我今天化妝得好嗎
+
+163
+00:33:11,159 --> 00:33:13,798
+好極了,我的小寶貝
+
+164
+00:33:13,839 --> 00:33:17,070
+你陪我到洞外頭去走走,好不好
+
+165
+00:33:17,119 --> 00:33:21,556
+我的寶貝,還是你一個人去吧
+
+166
+00:33:21,599 --> 00:33:24,830
+本來嘛,我們這種草婆子
+
+167
+00:33:24,879 --> 00:33:28,030
+跟你出去了會使你丟臉的
+
+168
+00:33:28,079 --> 00:33:32,039
+小寶貝,這是什麼話呢
+
+169
+00:33:32,039 --> 00:33:37,511
+你先去,我隨後就來好不好
+
+170
+00:35:28,039 --> 00:35:35,673
+女菩薩,你真是天仙下凡
+
+171
+00:35:35,719 --> 00:35:37,914
+你…你是什麼人
+
+172
+00:35:37,959 --> 00:35:41,474
+我是從芭蕉洞來找牛魔王的
+
+173
+00:35:41,520 --> 00:35:43,988
+快放手
+
+174
+00:35:49,559 --> 00:35:52,949
+女菩薩,你慢點走
+
+175
+00:36:44,239 --> 00:36:49,233
+小寶貝,誰來欺負你
+
+176
+00:36:49,279 --> 00:36:50,837
+是你
+
+177
+00:36:50,879 --> 00:36:54,349
+我哪裡捨得欺負你呢
+
+178
+00:36:56,919 --> 00:36:59,274
+你還是回芭蕉洞去吧
+
+179
+00:36:59,320 --> 00:37:01,709
+省得那個不要臉的東西
+
+180
+00:37:01,759 --> 00:37:07,675
+時常派人來請你,欺負我
+
+181
+00:37:07,719 --> 00:37:11,075
+你說有人來找我
+
+182
+00:37:11,119 --> 00:37:15,078
+外邊有一個豬臉的和尚來請你
+
+183
+00:37:15,120 --> 00:37:18,510
+差一點把我嚇死了
+
+184
+00:37:18,559 --> 00:37:22,757
+真有這回事嗎?待我出去看一看
+
+185
+00:37:50,679 --> 00:37:53,796
+牛大哥
+
+186
+00:37:53,839 --> 00:37:58,151
+這裡頭有個頂漂亮的小娘們
+
+187
+00:37:58,200 --> 00:38:03,991
+呸,那是我的女人,你為什麼要欺負她
+
+188
+00:38:04,039 --> 00:38:08,559
+大哥,我不知那就是二嫂,請原瓊
+
+189
+00:38:08,559 --> 00:38:11,949
+不知道不見罪,好啊,你走啊
+
+190
+00:38:11,999 --> 00:38:16,117
+不不不,我還有事情請大哥幫忙
+
+191
+00:38:18,479 --> 00:38:24,719
+小弟保唐僧取經,路過火焰山
+
+192
+00:38:24,719 --> 00:38:27,313
+請大哥跟嫂子說一聲
+
+193
+00:38:27,359 --> 00:38:30,829
+把這個芭蕉扇借來用一用
+
+194
+00:38:30,880 --> 00:38:33,519
+不成,那唐僧和孫悟空
+
+195
+00:38:33,519 --> 00:38:35,191
+是我孩子的仇人
+
+196
+00:38:35,239 --> 00:38:38,754
+我正要抓他們報仇
+
+197
+00:38:38,799 --> 00:38:44,988
+令郎已成正果,請大哥不必再計較吧
+
+198
+00:38:45,039 --> 00:38:48,952
+好,看在我們從前的交情
+我不跟你計較
+
+199
+00:38:49,000 --> 00:38:51,719
+那麼去吧
+
+200
+00:39:38,399 --> 00:39:44,190
+寶貝,那個豬臉和尚
+是我從前一個朋友
+
+201
+00:39:44,239 --> 00:39:46,514
+並不是芭蕉洞派來的
+
+202
+00:39:46,559 --> 00:39:47,753
+我不相信
+
+203
+00:39:47,799 --> 00:39:50,950
+我不騙你
+
+204
+00:39:50,999 --> 00:39:54,036
+現在那個和尚到哪兒去了呢
+
+205
+00:39:54,119 --> 00:39:57,794
+已經被我打走了
+
+206
+00:43:58,639 --> 00:44:01,358
+大王回來了
+
+207
+00:44:01,399 --> 00:44:02,388
+奶奶呢
+
+208
+00:44:02,439 --> 00:44:04,794
+在裡邊
+
+209
+00:44:42,999 --> 00:44:48,232
+今天是什麼風會把大王吹到這兒來的
+
+210
+00:44:48,279 --> 00:44:52,272
+聽到孫悟空保唐僧快到這兒
+
+211
+00:44:52,320 --> 00:44:56,916
+恐怕他要來借芭蕉扇過火焰山
+
+212
+00:44:56,959 --> 00:45:00,872
+那猴子是害我們兒子的仇人
+
+213
+00:45:00,919 --> 00:45:08,507
+早晚來了抓著他,讓我們夫妻出出恨
+
+214
+00:45:08,559 --> 00:45:12,711
+夫人,你為什麼哭
+
+215
+00:45:12,759 --> 00:45:15,717
+那猴子已經來過了
+
+216
+00:45:15,759 --> 00:45:18,876
+是我不肯把扇子借給他
+
+217
+00:45:18,919 --> 00:45:22,275
+不知道怎麼會跑到我的肚子裡來
+
+218
+00:45:22,319 --> 00:45:25,516
+弄得我肚子痛得要命
+
+219
+00:45:25,559 --> 00:45:31,399
+後來我沒有法子,只好把扇子借給他
+
+220
+00:45:31,399 --> 00:45:38,271
+可惜可惜,你怎麼把扇子借給他
+
+221
+00:45:38,320 --> 00:45:40,470
+拿去的是假的
+
+222
+00:45:40,519 --> 00:45:43,033
+假的
+
+223
+00:46:14,199 --> 00:46:19,876
+開筵慶祝大王歸
+
+224
+00:46:19,919 --> 00:46:25,630
+好酒殷勤勸幾杯
+
+225
+00:46:25,679 --> 00:46:34,189
+雞又香,鴨又美,豬又肥
+
+226
+00:46:34,240 --> 00:46:45,674
+我盡量的歌,我盡量的舞
+
+227
+00:46:45,719 --> 00:46:54,514
+你也要盡量的醉
+
+228
+00:47:03,599 --> 00:47:16,399
+大王啊,你把舊人丟
+
+229
+00:47:16,439 --> 00:47:22,628
+你愛新人媚
+
+230
+00:47:22,679 --> 00:47:36,673
+為你淌了多少相思淚
+
+231
+00:47:46,719 --> 00:47:55,718
+等一會燈兒吹帳兒垂
+
+232
+00:47:55,759 --> 00:48:00,879
+你獨自兒睡
+
+233
+00:48:00,879 --> 00:48:05,519
+也嘗嘗這個淒涼味
+
+234
+00:48:05,519 --> 00:48:13,437
+恕我不奉陪
+
+235
+00:48:18,559 --> 00:48:24,634
+就是同床
+
+236
+00:48:24,679 --> 00:48:34,350
+我們各人蓋著各人的被
+
+237
+00:48:38,399 --> 00:48:42,392
+大王,我醉了
+
+238
+00:48:55,079 --> 00:48:58,151
+夫人,那真扇子你放在什麼地方
+
+239
+00:48:58,199 --> 00:49:05,469
+那猴子花樣很多,而且那豬八戒
+本事更大
+
+240
+00:49:05,519 --> 00:49:09,797
+當心給他們騙了去
+
+241
+00:49:18,360 --> 00:49:21,989
+寶貝不是在這兒嗎
+
+242
+00:49:31,439 --> 00:49:39,319
+大王,你出神想什麼呢?
+還是收了吧
+
+243
+00:49:39,319 --> 00:49:43,551
+小寶貝
+
+244
+00:49:43,599 --> 00:49:49,037
+寶貝,你多喝一杯,你喝啊
+
+245
+00:49:53,919 --> 00:49:59,519
+今兒晚上,金龍大王
+還要請我去喝酒呢
+
+246
+00:49:59,519 --> 00:50:01,430
+那你就該去了
+
+247
+00:50:01,479 --> 00:50:02,878
+是的
+
+248
+00:50:02,919 --> 00:50:06,628
+你去替爺爺把金睛獸牽出去預備好
+
+249
+00:50:06,679 --> 00:50:08,271
+是
+
+250
+00:50:08,320 --> 00:50:12,598
+可是,你今兒個晚上去要少喝一點兒
+
+251
+00:50:12,639 --> 00:50:15,756
+免得回來睡著叫不醒你
+
+252
+00:50:15,800 --> 00:50:19,110
+不好了,爺爺那個金隋獸不見了
+
+253
+00:50:19,159 --> 00:50:20,911
+你們全都是死人嗎
+
+254
+00:50:20,959 --> 00:50:24,039
+家裡頭的東西怎麼會不見了呢
+
+255
+00:50:24,039 --> 00:50:27,918
+寶貝,不要管他們吧
+
+256
+00:50:27,960 --> 00:50:31,714
+恐怕是那豬八戒偷了去了
+
+257
+00:50:31,759 --> 00:50:35,274
+說不定我要到芭蕉洞去一趟
+
+258
+00:50:35,320 --> 00:50:39,313
+原來是你們做好了的圈套
+
+259
+00:50:42,280 --> 00:50:48,150
+你還是要到那個不要臉的女人那兒去
+
+260
+00:50:48,199 --> 00:50:50,713
+好寶貝,你不要哭了
+
+261
+00:50:50,759 --> 00:50:54,069
+我去去就來的
+
+262
+00:51:02,679 --> 00:51:07,309
+來來,喝喝
+
+263
+00:51:10,359 --> 00:51:12,475
+我現在放心了
+
+264
+00:51:12,519 --> 00:51:16,717
+不怕他們偷我們的寶貝
+
+265
+00:51:16,759 --> 00:51:21,310
+他們就是偷了去
+不知道把那絲線一拉
+
+266
+00:51:21,360 --> 00:51:26,275
+單是一顆珠子也沒有用處啊
+
+267
+00:51:26,319 --> 00:51:31,791
+是不是那麼一拉就變成扇子
+
+268
+00:51:35,120 --> 00:51:38,078
+大王,你今天喝醉了
+
+269
+00:51:38,119 --> 00:51:44,035
+自己的寶貝都忘了,還來問我
+
+270
+00:51:49,999 --> 00:51:53,708
+娘子,你看看我是誰
+
+271
+00:52:00,320 --> 00:52:03,756
+你是什麼人
+
+272
+00:52:03,799 --> 00:52:09,908
+我是唐僧的二徒弟,豬八戒
+
+273
+00:52:09,959 --> 00:52:14,794
+對不住,謝謝你,打擾了
+
+274
+00:52:19,080 --> 00:52:21,719
+再見
+
+275
+00:53:06,839 --> 00:53:10,718
+牛大嫂太風騷
+
+276
+00:53:10,760 --> 00:53:14,719
+眾小妖都俊俏
+
+277
+00:53:14,759 --> 00:53:24,828
+老豬真有點受不了
+
+278
+00:53:24,879 --> 00:53:28,872
+心機巧,手段妙
+
+279
+00:53:28,919 --> 00:53:32,832
+居然騙得了無價寶
+
+280
+00:53:32,880 --> 00:53:36,793
+這一番勞苦功高
+
+281
+00:53:36,839 --> 00:53:38,318
+沙僧該拜倒
+
+282
+00:53:38,359 --> 00:53:40,748
+猴兒該領教
+
+283
+00:53:40,799 --> 00:53:45,236
+師父也要嚇一跳
+
+284
+00:53:45,280 --> 00:53:49,193
+我老豬也有今朝
+
+285
+00:53:49,239 --> 00:53:54,359
+我老豬也有今朝
+
+286
+00:54:36,720 --> 00:54:40,474
+呆子,事情辦得怎麼樣了
+
+287
+00:54:40,519 --> 00:54:42,828
+不僅扇子到手
+
+288
+00:54:42,880 --> 00:54:48,796
+鐵扇公主並且還做了我
+半天的老婆
+
+289
+00:54:48,839 --> 00:54:51,717
+這倒便宜了你了
+
+290
+00:54:58,159 --> 00:55:01,595
+扇子拿來給我看看
+
+291
+00:55:16,039 --> 00:55:20,237
+你怎麼會把它縮小了的呀
+
+292
+00:55:40,559 --> 00:55:45,349
+老豬,你可認識我嗎
+
+293
+00:55:45,399 --> 00:55:49,187
+你不要跟我開玩笑了
+
+294
+00:55:49,239 --> 00:55:52,151
+誰跟你開玩笑
+
+295
+00:56:42,879 --> 00:56:45,393
+呆子,你去了怎麼樣
+
+296
+00:56:45,439 --> 00:56:47,111
+白跑了一趟
+
+297
+00:56:47,159 --> 00:56:49,992
+悟能,扇子借來沒有
+
+298
+00:56:50,039 --> 00:56:53,349
+我去找牛魔王,他不肯借
+
+299
+00:56:53,400 --> 00:56:59,191
+後來,我又變成老牛的樣子
+
+300
+00:56:59,239 --> 00:57:03,551
+在鐵扇公主那兒把扇子已經騙過來了
+
+301
+00:57:03,599 --> 00:57:10,599
+誰知道他又變成你的樣子又給他騙回去了
+
+302
+00:57:10,599 --> 00:57:12,749
+老牛的本領大
+
+303
+00:57:12,800 --> 00:57:16,156
+我還被他揍了一頓呢
+
+304
+00:57:16,199 --> 00:57:21,398
+呆子,你能辦這樣大的事那
+還算是呆子嗎
+
+305
+00:57:21,439 --> 00:57:25,671
+事情不都環在你頭上
+
+306
+00:57:30,759 --> 00:57:34,388
+你們不要吵了,趕緊再想辦法
+
+307
+00:57:34,439 --> 00:57:40,275
+哪一方…沒…沒有火啊
+
+308
+00:57:40,320 --> 00:57:47,078
+東南西北,只有西方有火
+
+309
+00:57:47,120 --> 00:57:50,749
+那我們不是要走回去了嗎
+
+310
+00:57:50,799 --> 00:57:52,949
+這路不通,不回去怎麼樣呢
+
+311
+00:57:52,999 --> 00:57:55,229
+八戒,你不要這樣說
+
+312
+00:57:55,279 --> 00:57:59,158
+要成功一件事情總是有阻礙的
+
+313
+00:57:59,199 --> 00:58:04,557
+我們要做這樣神聖的事情
+就要堅定我們的信念
+
+314
+00:58:04,599 --> 00:58:09,229
+不能因為有一點兒困難
+就中適改變我們的宗旨
+
+315
+00:58:09,280 --> 00:58:14,593
+你們這次失敗的原因是由於
+既不同心又不合力
+
+316
+00:58:14,639 --> 00:58:17,153
+假使你們三個人一條心
+
+317
+00:58:17,199 --> 00:58:20,509
+合起力量,共同跟牛魔王決鬥
+
+318
+00:58:20,559 --> 00:58:22,868
+事情一定可以成功的
+
+319
+00:58:22,919 --> 00:58:26,039
+我們謹遵師父的命令
+
+320
+00:58:26,039 --> 00:58:30,157
+去跟牛魔王爭一個誰勝誰敗
+
+321
+00:58:30,199 --> 00:58:34,272
+誰…誰…誰勝誰敗
+
+322
+00:58:34,320 --> 00:58:37,710
+那就好極了
+
+323
+00:58:37,759 --> 00:58:40,990
+各位受他的害處也不小了
+
+324
+00:58:41,040 --> 00:58:43,879
+希望各位也出此些力量
+
+325
+00:58:43,879 --> 00:58:49,590
+跟小徒們共同征服牛魔王,消滅火焰山
+
+326
+00:58:49,639 --> 00:58:53,837
+免除永遠的禍害
+
+327
+00:58:53,879 --> 00:58:57,508
+我們聽從師父的命令,為大家謀幸福
+
+328
+00:58:57,559 --> 00:58:58,878
+大家一起出力去
+
+329
+00:58:58,919 --> 00:59:01,035
+好
+
+330
+01:08:23,239 --> 01:08:25,628
+奶奶,不好了
+
+331
+01:08:25,679 --> 01:08:30,799
+爺爺給人家抓住了,你快點去看看吧
+
+332
+01:08:54,479 --> 01:08:56,709
+還不過來打,過來打
+
+333
+01:08:56,760 --> 01:08:59,718
+慢一點,慢一點
+
+334
+01:08:59,760 --> 01:09:05,790
+孽畜,只要你把扇子交出來,饒你不死
+
+335
+01:09:05,840 --> 01:09:12,757
+老牛,扇子在什麼地方?快拿出來啊
+
+336
+01:09:12,799 --> 01:09:19,352
+在我老…老婆那兒
+
+337
+01:09:25,240 --> 01:09:27,993
+夫人,夫人,夫人
+
+338
+01:09:28,039 --> 01:09:32,271
+你快點來救救我
+
+339
+01:09:32,320 --> 01:09:35,118
+把扇子拿出來吧
+
+340
+01:09:35,159 --> 01:09:39,630
+大王,好,好的
+
+341
+01:09:43,400 --> 01:09:47,234
+悟空,你再去一趟吧
+
-1\r
-00:00:01,080 --> 00:00:09,070\r
-Princess Iron Fan\r
-\r
-2\r
-00:02:03,109 --> 00:02:09,280\r
-Journey to the West is a wonderful children's story,\r
-\r
-3\r
-00:02:09,280 --> 00:02:15,280\r
-but the world often misunderstands it as a fantasy novel.\r
-\r
-4\r
-00:02:15,280 --> 00:02:19,240\r
-This film was made for the purpose of\r
-\r
-5\r
-00:02:19,240 --> 00:02:24,240\r
-training the hearts and minds of children.\r
-\r
-6\r
-00:02:24,240 --> 00:02:29,280\r
-The story is pure, untainted by fantasy.\r
-\r
-7\r
-00:02:29,280 --> 00:02:32,560\r
-Fiery Mountain blocking the path of Tang Seng's company\r
-\r
-8\r
-00:02:32,560 --> 00:02:41,039\r
-is a metaphor for the difficulties in life.\r
-\r
-9\r
-00:02:41,039 --> 00:02:46,439\r
-In order to overcome them, one must keep faith.\r
-Everybody must work together\r
-\r
-10\r
-00:02:46,439 --> 00:02:52,430\r
-in order to obtain the palm leaf fan and put out the flames.\r
-\r
-11\r
-00:02:52,839 --> 00:02:58,178\r
-Tripikata True Sutra\r
-\r
-12\r
-00:03:34,479 --> 00:03:37,789\r
-It's already autumn, how can it still be so warm?\r
-\r
-13\r
-00:03:37,840 --> 00:03:42,349\r
-Fool, don't talk rubbish. We should hurry and get on our way.\r
-\r
-14\r
-00:04:06,919 --> 00:04:09,349\r
-Wukong, where is this place?\r
-\r
-15\r
-00:04:09,400 --> 00:04:13,669\r
-We must pass through here to continue westwards, that much is certain.\r
-\r
-16\r
-00:04:13,719 --> 00:04:18,110\r
-Might we have taken the wrong path?\r
-\r
-17\r
-00:04:18,149 --> 00:04:21,700\r
-Why is it so hot here?\r
-\r
-18\r
-00:04:30,029 --> 00:04:31,649\r
-Master, look!\r
-\r
-19\r
-00:04:31,650 --> 00:04:33,779\r
-Isn't that a house up ahead?\r
-\r
-20\r
-00:04:33,829 --> 00:04:38,100\r
-Let's go in and rest for a while, OK?\r
-\r
-21\r
-00:04:59,389 --> 00:05:02,899\r
-This place is called Fiery Mountain.\r
-\r
-22\r
-00:05:02,949 --> 00:05:06,019\r
-The fire stretches for hundreds of miles.\r
-\r
-23\r
-00:05:06,069 --> 00:05:08,740\r
-Not single straw of grass can grow here.\r
-\r
-24\r
-00:05:08,790 --> 00:05:11,620\r
-The four seasons of the year are all warm.\r
-\r
-25\r
-00:05:11,680 --> 00:05:19,629\r
-You couldn't pass through the mountain even with a head of copper and arms of iron.\r
-\r
-26\r
-00:05:19,670 --> 00:05:23,579\r
-What kind of place is this? Master, don't worry!\r
-\r
-27\r
-00:05:23,629 --> 00:05:27,139\r
-The three of us are all strong enough to pass!\r
-\r
-28\r
-00:05:27,189 --> 00:05:30,699\r
-Master, I'll go and have a look!\r
-\r
-29\r
-00:08:06,310 --> 00:08:09,579\r
-Wukong, what was it like?\r
-\r
-30\r
-00:08:09,629 --> 00:08:11,819\r
-Bad, bad, very bad.\r
-\r
-31\r
-00:08:11,879 --> 00:08:15,910\r
-If I were any slower the fur on my tail would have been burned off.\r
-\r
-32\r
-00:08:42,720 --> 00:08:47,600\r
-Noble host, the fires here are so big.\r
-\r
-33\r
-00:08:47,600 --> 00:08:49,669\r
-How can you grow any crops?\r
-\r
-34\r
-00:08:49,710 --> 00:08:53,980\r
-A thousand miles from here lives Princess Iron Fan.\r
-\r
-35\r
-00:08:54,039 --> 00:08:56,500\r
-She has a palm leaf fan.\r
-\r
-36\r
-00:08:56,559 --> 00:08:59,070\r
-Wave the fan once and the fire goes out.\r
-\r
-37\r
-00:08:59,120 --> 00:09:01,629\r
-Twice and the wind starts blowing.\r
-\r
-38\r
-00:09:01,679 --> 00:09:03,980\r
-Three times and the rain starts coming down.\r
-\r
-39\r
-00:09:04,039 --> 00:09:07,509\r
-In the following period we plant and harvest.\r
-\r
-40\r
-00:09:07,559 --> 00:09:11,340\r
-However, asking that princess to come\r
-\r
-41\r
-00:09:11,399 --> 00:09:14,870\r
-is certainly no simple matter.\r
-\r
-42\r
-00:09:14,909 --> 00:09:16,820\r
-Where does she live?\r
-\r
-43\r
-00:09:16,879 --> 00:09:20,190\r
-She lives in Palm Leaf Cave at Emerald Cloud Mountain.\r
-\r
-44\r
-00:09:20,240 --> 00:09:23,669\r
-Does she live there alone?\r
-\r
-45\r
-00:09:23,720 --> 00:09:25,750\r
-Doesn't she have a husband?\r
-\r
-46\r
-00:09:25,799 --> 00:09:29,580\r
-Her husband is Bull Demon King.\r
-\r
-47\r
-00:09:29,639 --> 00:09:32,200\r
-What, her husband is Old Bull?\r
-\r
-48\r
-00:09:32,240 --> 00:09:36,789\r
-Fool, you know him? Come with me to borrow the fan!\r
-\r
-49\r
-00:09:36,840 --> 00:09:41,750\r
-Actually... Old Bull doesn't live there.\r
-\r
-50\r
-00:09:41,799 --> 00:09:46,350\r
-Looking for his woman when he isn't home\r
-\r
-51\r
-00:09:46,399 --> 00:09:51,519\r
-isn't very... appropriate.\r
-\r
-52\r
-00:09:51,559 --> 00:09:58,309\r
-You... you... the two of you go.\r
-\r
-53\r
-00:09:58,360 --> 00:10:04,290\r
-I... I'll stay here and serve Master.\r
-\r
-54\r
-00:10:04,440 --> 00:10:11,269\r
-Sha Wujing, go with your two fellow apprentices.\r
-\r
-55\r
-00:10:38,571 --> 00:10:44,978\r
-Palm Leaf Cave\r
-\r
-56\r
-00:10:47,200 --> 00:10:51,549\r
-Fool, I always go first.\r
-\r
-57\r
-00:10:51,600 --> 00:10:54,350\r
-This time it's your turn!\r
-\r
-58\r
-00:10:58,519 --> 00:11:04,909\r
-Junior! I always go first, this time it's your turn!\r
-\r
-59\r
-00:11:04,960 --> 00:11:06,830\r
-Senior...\r
-\r
-60\r
-00:11:06,879 --> 00:11:10,990\r
-I'm asking you to make a small effort for Master. Can't you do that?\r
-\r
-61\r
-00:11:11,039 --> 00:11:14,309\r
-Hurry up!\r
-\r
-62\r
-00:11:39,639 --> 00:11:43,039\r
-Simple monk, where did you come from?\r
-\r
-63\r
-00:11:43,039 --> 00:11:49,870\r
-The Great Sage... Tang Seng... wants your princess...\r
-\r
-64\r
-00:11:49,919 --> 00:11:52,480\r
-Nonsense!\r
-\r
-65\r
-00:12:47,549 --> 00:12:52,059\r
-Senior... why don't you go instead?\r
-\r
-66\r
-00:12:52,120 --> 00:12:56,950\r
-Fool, you go!\r
-\r
-67\r
-00:12:57,000 --> 00:13:00,700\r
-Senior, why don't you go?\r
-\r
-68\r
-00:13:04,029 --> 00:13:07,460\r
-Lazy fool!\r
-\r
-69\r
-00:13:54,279 --> 00:13:57,899\r
-Great God of Thunder! Don't kill me, let me go!\r
-\r
-70\r
-00:13:57,960 --> 00:13:59,950\r
-Go tell your princess\r
-\r
-71\r
-00:14:00,000 --> 00:14:03,279\r
-that Sun Wukong has come to borrow the fan.\r
-\r
-72\r
-00:14:03,279 --> 00:14:08,399\r
-Yes, yes! Let me loose, I'll go at once.\r
-\r
-73\r
-00:14:29,559 --> 00:14:37,059\r
-Grandma, there's a Sun Wukong outside asking to borrow the fan.\r
-\r
-74\r
-00:14:41,519 --> 00:14:44,149\r
-Quickly fetch my sword.\r
-\r
-75\r
-00:15:01,639 --> 00:15:04,149\r
-Sun Wukong, you hurt my son!\r
-\r
-76\r
-00:15:04,200 --> 00:15:08,549\r
-You dare come here to meet your death?\r
-\r
-77\r
-00:15:08,600 --> 00:15:12,039\r
-I've never met you before, how could I have harmed your son?\r
-\r
-78\r
-00:15:12,039 --> 00:15:15,789\r
-My son Red Child's life was ruined, wasn't that your doing?\r
-\r
-79\r
-00:15:15,840 --> 00:15:20,389\r
-Your son is with the Goddess of Mercy now, how can you say that I hurt him?\r
-\r
-80\r
-00:15:20,440 --> 00:15:23,750\r
-Enough rubbish! Come here and let me chop you with my sword.\r
-\r
-81\r
-00:15:23,799 --> 00:15:26,149\r
-If you can take it I'll lend you the fan.\r
-\r
-82\r
-00:15:26,200 --> 00:15:28,549\r
-Really?\r
-\r
-83\r
-00:15:56,799 --> 00:16:00,629\r
-Stop! Quickly give me the fan!\r
-\r
-84\r
-00:17:53,630 --> 00:18:00,099\r
-Great Sage, weren't you going west? Why have you come back here?\r
-\r
-85\r
-00:18:11,150 --> 00:18:17,140\r
-Princess Iron Fan blew me here with a single wave of her fan.\r
-\r
-86\r
-00:18:17,190 --> 00:18:23,859\r
-That's truly amazing, Great Sage. I have something for you.\r
-\r
-87\r
-00:18:28,509 --> 00:18:33,450\r
-This is a wind pearl. When you use it,\r
-\r
-88\r
-00:18:33,509 --> 00:18:36,140\r
-your heart will become steady as a rock.\r
-\r
-89\r
-00:18:36,190 --> 00:18:39,180\r
-Princess Iron Fan won't be able to move you.\r
-\r
-90\r
-00:18:39,230 --> 00:18:42,849\r
-Great Sage, come and have a look.\r
-\r
-91\r
-00:19:00,430 --> 00:19:02,539\r
-Thank you.\r
-\r
-92\r
-00:19:06,069 --> 00:19:12,299\r
-Senior... where...\r
-\r
-93\r
-00:19:12,349 --> 00:19:18,690\r
-where has he... been blown to?\r
-\r
-94\r
-00:19:18,750 --> 00:19:26,099\r
-Who cares about him? Let the monkey handle himself. Let's go.\r
-\r
-95\r
-00:19:35,190 --> 00:19:37,259\r
-Senior... senior...\r
-\r
-96\r
-00:19:37,309 --> 00:19:43,470\r
-You... you...\r
-\r
-97\r
-00:19:43,470 --> 00:19:50,220\r
-Where were you blown to by that old lady?\r
-\r
-98\r
-00:19:50,269 --> 00:19:57,180\r
-Fool, now it's definitely your turn to go.\r
-\r
-99\r
-00:19:57,230 --> 00:20:00,930\r
-I'm not going, a single wave of her fan\r
-\r
-100\r
-00:20:00,990 --> 00:20:03,450\r
-could blow me to some faraway land.\r
-\r
-101\r
-00:20:03,509 --> 00:20:09,710\r
-Maybe it's better if you go again.\r
-\r
-102\r
-00:20:09,710 --> 00:20:12,220\r
-I won't go.\r
-\r
-103\r
-00:20:17,789 --> 00:20:22,779\r
-Next time I won't let you off!\r
-\r
-104\r
-00:20:56,150 --> 00:21:00,140\r
-This time I won't move no matter how much you wave,\r
-\r
-105\r
-00:21:00,190 --> 00:21:05,210\r
-as sure as I call myself am a man!\r
-\r
-106\r
-00:21:33,670 --> 00:21:38,579\r
-Senior, how come this time her fan couldn't move you?\r
-\r
-107\r
-00:21:46,829 --> 00:21:50,099\r
-Let's break our way in.\r
-\r
-108\r
-00:23:59,630 --> 00:24:04,180\r
-Quickly bring out the fan for Sun Wukong!\r
-\r
-109\r
-00:24:14,869 --> 00:24:16,900\r
-Sun Wukong, where are you?\r
-\r
-110\r
-00:24:16,950 --> 00:24:19,980\r
-I'm in your stomach!\r
-\r
-111\r
-00:24:45,750 --> 00:24:48,539\r
-Sun Wukong, spare me!\r
-\r
-112\r
-00:24:48,589 --> 00:24:51,180\r
-Only if you give me the fan!\r
-\r
-113\r
-00:24:51,230 --> 00:24:56,539\r
-I promise, I'll give it to you. Please come out!\r
-\r
-114\r
-00:25:00,230 --> 00:25:02,819\r
-Hurry up and bring the fan.\r
-\r
-115\r
-00:25:07,430 --> 00:25:09,220\r
-We've brought out the fan.\r
-\r
-116\r
-00:25:09,279 --> 00:25:12,069\r
-Why haven't you come out?\r
-\r
-117\r
-00:25:12,109 --> 00:25:16,619\r
-Open your mouth and I'll come out.\r
-\r
-118\r
-00:25:25,349 --> 00:25:29,420\r
-Sun Wukong, why haven't you come out?\r
-\r
-119\r
-00:25:50,349 --> 00:25:55,579\r
-Here I am. Lend me the fan for a while, I'll return it.\r
-\r
-120\r
-00:26:32,549 --> 00:26:36,579\r
-Master has been waiting long enough, let's get going!\r
-\r
-121\r
-00:27:01,869 --> 00:27:04,900\r
-Scripture, what is scripture?\r
-\r
-122\r
-00:27:04,950 --> 00:27:10,029\r
-Scriptures are the principles that link heaven and earth.\r
-\r
-123\r
-00:27:10,029 --> 00:27:14,180\r
-They are the principles of man.\r
-\r
-124\r
-00:27:14,230 --> 00:27:18,700\r
-Only he who holds these principles\r
-\r
-125\r
-00:27:18,750 --> 00:27:25,339\r
-can rid himself of pain and live a good life,\r
-\r
-126\r
-00:27:25,390 --> 00:27:29,940\r
-live a true and honest life.\r
-\r
-127\r
-00:27:34,680 --> 00:27:36,349\r
-Conversely,\r
-\r
-128\r
-00:27:36,390 --> 00:27:40,089\r
-he who does not know these principles,\r
-\r
-129\r
-00:27:40,150 --> 00:27:46,380\r
-will live a life full of misery.\r
-\r
-130\r
-00:27:46,430 --> 00:27:52,609\r
-Even his son or grandson will not achieve happiness.\r
-\r
-131\r
-00:27:52,670 --> 00:27:55,660\r
-Why am I going to get the scripture?\r
-\r
-132\r
-00:27:55,710 --> 00:28:01,299\r
-Because men nowadays are trapped in misery.\r
-\r
-133\r
-00:28:01,349 --> 00:28:04,180\r
-In order to achieve this goal, we are going to\r
-\r
-134\r
-00:28:04,230 --> 00:28:12,500\r
-appear before the Tang emperor and discuss this very complicated matter.\r
-\r
-135\r
-00:28:15,670 --> 00:28:17,819\r
-Did you get the palm leaf fan?\r
-\r
-136\r
-00:28:17,869 --> 00:28:19,400\r
-We have it.\r
-\r
-137\r
-00:28:19,401 --> 00:28:20,779\r
-Is this it?\r
-\r
-138\r
-00:28:22,829 --> 00:28:27,980\r
-Noble hosts, now that we have the fan,\r
-\r
-139\r
-00:28:28,029 --> 00:28:32,140\r
-we will take our leave.\r
-\r
-140\r
-00:28:32,190 --> 00:28:34,039\r
-Hold on.\r
-\r
-141\r
-00:28:34,039 --> 00:28:39,789\r
-Everyone, I would like to ask Sage Seng to stay here for a few more days.\r
-\r
-142\r
-00:28:39,829 --> 00:28:41,339\r
-Do you agree?\r
-\r
-143\r
-00:28:41,390 --> 00:28:43,460\r
-Agreed!\r
-\r
-144\r
-00:28:43,509 --> 00:28:45,890\r
-Thank you for your kindness.\r
-\r
-145\r
-00:28:45,950 --> 00:28:51,779\r
-But the sooner I leave the sooner we can complete our task.\r
-\r
-146\r
-00:28:51,829 --> 00:28:56,180\r
-Very well, will the honorable apprentice first go to Fiery Mountain.\r
-\r
-147\r
-00:28:56,230 --> 00:29:02,140\r
-After extinguishing the flames, continue to follow Sage Seng.\r
-\r
-148\r
-00:29:02,190 --> 00:29:05,460\r
-All right, go ahead!\r
-\r
-149\r
-00:30:24,470 --> 00:30:30,029\r
-Princess Iron Fan is really despicable, she gave us a fake fan!\r
-\r
-150\r
-00:30:30,029 --> 00:30:32,779\r
-I'll kill her for sure!\r
-\r
-151\r
-00:30:32,829 --> 00:30:36,299\r
-No, killing her is the wrong thing to do.\r
-\r
-152\r
-00:30:36,349 --> 00:30:39,579\r
-I won't let you kill anyone.\r
-\r
-153\r
-00:30:39,630 --> 00:30:42,980\r
-Let's think of something else.\r
-\r
-154\r
-00:30:52,150 --> 00:30:56,220\r
-Senior, how could you be fooled by her?\r
-\r
-155\r
-00:30:56,269 --> 00:30:58,539\r
-After making such an effort\r
-\r
-156\r
-00:30:58,589 --> 00:31:02,099\r
-all we got was a fake fan.\r
-\r
-157\r
-00:31:02,150 --> 00:31:06,500\r
-Ridiculous, ridiculous.\r
-\r
-158\r
-00:31:08,910 --> 00:31:10,420\r
-Then you go!\r
-\r
-159\r
-00:31:10,470 --> 00:31:14,380\r
-OK, I'll go, I'll go, I'm going!\r
-\r
-160\r
-00:31:14,430 --> 00:31:16,908\r
-I'll go find Bull Demon King.\r
-\r
-161\r
-00:31:16,909 --> 00:31:19,940\r
-This is a good solution.\r
-\r
-162\r
-00:31:21,390 --> 00:31:24,439\r
-Partner, what do you think?\r
-\r
-163\r
-00:31:24,440 --> 00:31:27,380\r
-We'll see how you do.\r
-\r
-164\r
-00:33:07,190 --> 00:33:11,150\r
-What do you think, am I pretty today?\r
-\r
-165\r
-00:33:11,150 --> 00:33:13,779\r
-Beautiful, my baby.\r
-\r
-166\r
-00:33:13,829 --> 00:33:17,059\r
-Accompany me for a walk outside the cave, all right?\r
-\r
-167\r
-00:33:17,109 --> 00:33:21,539\r
-My baby, why don't you go by yourself.\r
-\r
-168\r
-00:33:21,589 --> 00:33:24,819\r
-Why of course, I'm just a plain country girl.\r
-\r
-169\r
-00:33:24,869 --> 00:33:28,019\r
-Taking me outside might cause you to lose face.\r
-\r
-170\r
-00:33:28,069 --> 00:33:32,029\r
-Baby, what are you saying?\r
-\r
-171\r
-00:33:32,029 --> 00:33:37,500\r
-You go ahead, I'll come out in a while, all right?\r
-\r
-172\r
-00:33:39,852 --> 00:33:44,557\r
-Emerald Cloud Cave\r
-\r
-173\r
-00:35:28,030 --> 00:35:35,659\r
-Goddess, you're truly an angel come down from heaven.\r
-\r
-174\r
-00:35:35,710 --> 00:35:37,900\r
-Who... who are you?\r
-\r
-175\r
-00:35:37,949 --> 00:35:41,460\r
-I've come from Palm Leaf Cave to look for Bull Demon King.\r
-\r
-176\r
-00:35:41,519 --> 00:35:43,980\r
-Let go of me!\r
-\r
-177\r
-00:35:49,550 --> 00:35:52,940\r
-Goddess, slow down!\r
-\r
-178\r
-00:36:38,768 --> 00:36:40,133\r
-Emerald Cloud Cave\r
-\r
-179\r
-00:36:44,230 --> 00:36:49,219\r
-Baby, who has bullied you?\r
-\r
-180\r
-00:36:49,269 --> 00:36:50,820\r
-You!\r
-\r
-181\r
-00:36:50,869 --> 00:36:54,340\r
-How could I bully you?\r
-\r
-182\r
-00:36:56,909 --> 00:36:59,260\r
-Why don't you go back to Palm Leaf Cave?\r
-\r
-183\r
-00:36:59,320 --> 00:37:01,699\r
-It would spare you some embarrassment.\r
-\r
-184\r
-00:37:01,750 --> 00:37:07,659\r
-They often send people to look for you, and bully me.\r
-\r
-185\r
-00:37:07,710 --> 00:37:11,059\r
-Has there been someone here to look for me?\r
-\r
-186\r
-00:37:11,110 --> 00:37:15,059\r
-There's a pig monk outside looking for you.\r
-\r
-187\r
-00:37:15,119 --> 00:37:18,510\r
-He almost scared me to death.\r
-\r
-188\r
-00:37:18,550 --> 00:37:22,739\r
-How can this be? Wait while I go out to have a look.\r
-\r
-189\r
-00:37:50,670 --> 00:37:53,780\r
-Bull, old friend!\r
-\r
-190\r
-00:37:53,829 --> 00:37:58,139\r
-There's a very beautiful young lady in here.\r
-\r
-191\r
-00:37:58,199 --> 00:38:03,889\r
-Hey, that's my woman! Why have you come to bother her?\r
-\r
-192\r
-00:38:03,930 --> 00:38:08,550\r
-Oh, I didn't know, please forgive me!\r
-\r
-193\r
-00:38:08,550 --> 00:38:11,940\r
-You didn't know, so I can't blame you. Off you go!\r
-\r
-194\r
-00:38:11,989 --> 00:38:16,099\r
-No, no. I still have something I need you to help me with.\r
-\r
-195\r
-00:38:18,469 --> 00:38:24,710\r
-We were on our way to retrieve the scriptures when we arrived at Fiery Mountain.\r
-\r
-196\r
-00:38:24,710 --> 00:38:27,300\r
-Please ask your wife\r
-\r
-197\r
-00:38:27,349 --> 00:38:30,820\r
-to lend us the palm leaf fan for a while.\r
-\r
-198\r
-00:38:30,880 --> 00:38:33,510\r
-Absolutely not! Tang Seng and Sun Wukong\r
-\r
-199\r
-00:38:33,510 --> 00:38:35,179\r
-are my son's enemies.\r
-\r
-200\r
-00:38:35,230 --> 00:38:38,739\r
-I'd love to take my revenge on them.\r
-\r
-201\r
-00:38:38,789 --> 00:38:44,969\r
-Your son is with the Goddess of Mercy now, please don't fight.\r
-\r
-202\r
-00:38:45,030 --> 00:38:48,940\r
-All right, since we are old friends, I won't fight you.\r
-\r
-203\r
-00:38:49,000 --> 00:38:51,710\r
-Now go away!\r
-\r
-204\r
-00:39:38,389 --> 00:39:44,179\r
-Baby, that pig monk is a friend of mine.\r
-\r
-205\r
-00:39:44,230 --> 00:39:46,500\r
-He wasn't sent from Palm Leaf Cave at all.\r
-\r
-206\r
-00:39:46,550 --> 00:39:47,739\r
-I don't believe you.\r
-\r
-207\r
-00:39:47,789 --> 00:39:50,940\r
-I'm not lying to you!\r
-\r
-208\r
-00:39:50,989 --> 00:39:54,019\r
-Where is that monk now?\r
-\r
-209\r
-00:39:54,110 --> 00:39:57,780\r
-I've already scared him away.\r
-\r
-210\r
-00:43:34,814 --> 00:43:40,987\r
-Palm Leaf Cave\r
-\r
-211\r
-00:43:58,630 --> 00:44:01,340\r
-The king has returned!\r
-\r
-212\r
-00:44:01,389 --> 00:44:02,369\r
-Where's grandma?\r
-\r
-213\r
-00:44:02,429 --> 00:44:04,780\r
-She's inside.\r
-\r
-214\r
-00:44:42,989 --> 00:44:48,219\r
-By what honor has the king come to visit today?\r
-\r
-215\r
-00:44:48,269 --> 00:44:52,260\r
-I heard that Sun Wukong and Tang Seng are coming here.\r
-\r
-216\r
-00:44:52,320 --> 00:44:56,909\r
-I'm afraid they want to use the palm leaf fan to pass Fiery Mountain.\r
-\r
-217\r
-00:44:56,949 --> 00:45:00,860\r
-That monkey is the one who harmed our son.\r
-\r
-218\r
-00:45:00,909 --> 00:45:08,489\r
-I'll get him sooner or later, we will have our revenge.\r
-\r
-219\r
-00:45:08,550 --> 00:45:12,699\r
-Darling, why are you crying?\r
-\r
-220\r
-00:45:12,750 --> 00:45:15,699\r
-That monkey has already been here.\r
-\r
-221\r
-00:45:15,750 --> 00:45:18,860\r
-I refused to give him the fan.\r
-\r
-222\r
-00:45:18,909 --> 00:45:22,260\r
-I don't know how, but he got inside my stomach.\r
-\r
-223\r
-00:45:22,309 --> 00:45:25,500\r
-It hurt so bad I thought I would die.\r
-\r
-224\r
-00:45:25,550 --> 00:45:30,589\r
-At last I had no choice but to give him the fan.\r
-\r
-225\r
-00:45:30,789 --> 00:45:35,260\r
-That's terrible, how could you give him the fan?\r
-\r
-226\r
-00:45:38,320 --> 00:45:40,469\r
-I gave him a false one.\r
-\r
-227\r
-00:45:40,720 --> 00:45:43,019\r
-A false one?\r
-\r
-228\r
-00:46:14,190 --> 00:46:19,860\r
-A banquet to celebrate the king's return\r
-\r
-229\r
-00:46:19,909 --> 00:46:25,619\r
-Please drink the fine wine.\r
-\r
-230\r
-00:46:25,670 --> 00:46:34,179\r
-The chicken is fragrant, the duck is beautiful, and the pig is fat.\r
-\r
-231\r
-00:46:34,239 --> 00:46:45,670\r
-I try my best to sing, I try my best to dance.\r
-\r
-232\r
-00:46:45,710 --> 00:46:54,500\r
-You must also try your best to drink.\r
-\r
-233\r
-00:47:03,590 --> 00:47:16,389\r
-My king! You dumped the old one.\r
-\r
-234\r
-00:47:16,429 --> 00:47:22,610\r
-You love another woman.\r
-\r
-235\r
-00:47:22,670 --> 00:47:34,659\r
-Countless tears were spilled for you.\r
-\r
-236\r
-00:47:46,710 --> 00:47:55,699\r
-When the light is out and the curtain is dropped,\r
-\r
-237\r
-00:47:55,750 --> 00:48:00,869\r
-you will sleep alone.\r
-\r
-238\r
-00:48:00,869 --> 00:48:05,510\r
-You too will taste loneliness.\r
-\r
-239\r
-00:48:05,510 --> 00:48:13,420\r
-Pardon me for not making you company.\r
-\r
-240\r
-00:48:18,550 --> 00:48:24,619\r
-Even if we are on the same bed,\r
-\r
-241\r
-00:48:24,670 --> 00:48:34,340\r
-we will sleep under separate sheets.\r
-\r
-242\r
-00:48:38,389 --> 00:48:42,380\r
-King, I'm drunk.\r
-\r
-243\r
-00:48:55,070 --> 00:48:58,139\r
-Darling, where did you put the real fan?\r
-\r
-244\r
-00:48:58,190 --> 00:49:05,460\r
-That monkey is very deceitful, and the pig has even greater skill.\r
-\r
-245\r
-00:49:05,510 --> 00:49:09,780\r
-If you're not careful they might trick you.\r
-\r
-246\r
-00:49:18,360 --> 00:49:21,980\r
-Our treasure is right here.\r
-\r
-247\r
-00:49:31,429 --> 00:49:39,309\r
-King, what are you thinking about? Why don't you take it?\r
-\r
-248\r
-00:49:39,309 --> 00:49:40,847\r
-My treasure.\r
-\r
-249\r
-00:49:41,514 --> 00:49:44,150\r
-Emerald Cloud Cave\r
-\r
-250\r
-00:49:44,250 --> 00:49:49,019\r
-Baby, have another cup. Drink.\r
-\r
-251\r
-00:49:53,909 --> 00:49:59,510\r
-Gold Dragon King has asked me to drink with him tonight\r
-\r
-252\r
-00:49:59,510 --> 00:50:01,420\r
-Then you should go.\r
-\r
-253\r
-00:50:01,469 --> 00:50:02,860\r
-That's right.\r
-\r
-254\r
-00:50:02,909 --> 00:50:06,610\r
-You should prepare the golden eyed beast for grandpa.\r
-\r
-255\r
-00:50:06,670 --> 00:50:08,260\r
-I will.\r
-\r
-256\r
-00:50:08,320 --> 00:50:12,590\r
-You should drink a little less tonight.\r
-\r
-257\r
-00:50:12,630 --> 00:50:15,739\r
-Otherwise I won't be able to wake you up.\r
-\r
-258\r
-00:50:15,800 --> 00:50:19,110\r
-It's terrible, grandpa's golden eyed beast has disappeared!\r
-\r
-259\r
-00:50:19,150 --> 00:50:20,900\r
-Are you all deaf and blind?\r
-\r
-260\r
-00:50:20,949 --> 00:50:24,030\r
-How could it just disappear?\r
-\r
-261\r
-00:50:24,030 --> 00:50:27,900\r
-Baby, don't mind them.\r
-\r
-262\r
-00:50:27,960 --> 00:50:31,710\r
-I'm afraid Zhu Bajie might have stolen it.\r
-\r
-263\r
-00:50:31,750 --> 00:50:35,260\r
-Maybe I should go over to Palm Leaf Cave.\r
-\r
-264\r
-00:50:35,320 --> 00:50:39,309\r
-What? You've had this planned all along.\r
-\r
-265\r
-00:50:42,280 --> 00:50:48,150\r
-You still want to go over to that shameless woman?\r
-\r
-266\r
-00:50:48,190 --> 00:50:50,699\r
-Please baby, don't cry.\r
-\r
-267\r
-00:50:50,750 --> 00:50:54,059\r
-I'll be back soon.\r
-\r
-268\r
-00:50:57,624 --> 00:51:01,194\r
-Palm Leaf Cave\r
-\r
-269\r
-00:51:02,670 --> 00:51:07,300\r
-Come over here, drink a little!\r
-\r
-270\r
-00:51:10,349 --> 00:51:12,460\r
-Now I can relax.\r
-\r
-271\r
-00:51:12,510 --> 00:51:16,699\r
-We don't have to worry about our treasure being stolen.\r
-\r
-272\r
-00:51:16,750 --> 00:51:21,300\r
-Even if they stole it, they wouldn't know to pull the silk thread.\r
-\r
-273\r
-00:51:21,360 --> 00:51:26,269\r
-Having just a pearl won't be of any use.\r
-\r
-274\r
-00:51:26,309 --> 00:51:31,780\r
-Pulling the thread will turn it into a fan, right?\r
-\r
-275\r
-00:51:35,119 --> 00:51:38,070\r
-King, you're drunk.\r
-\r
-276\r
-00:51:38,110 --> 00:51:44,019\r
-You forgot about your own treasure, and are asking me.\r
-\r
-277\r
-00:51:49,989 --> 00:51:53,690\r
-Lady, look at who I am.\r
-\r
-278\r
-00:52:00,320 --> 00:52:03,750\r
-Who are you?\r
-\r
-279\r
-00:52:03,789 --> 00:52:09,889\r
-I am Tang Seng's second apprentice, Zhu Bajie.\r
-\r
-280\r
-00:52:09,949 --> 00:52:14,780\r
-Sorry about bothering you, and thanks!\r
-\r
-281\r
-00:52:19,079 --> 00:52:21,710\r
-Bye!\r
-\r
-282\r
-00:53:06,829 --> 00:53:10,699\r
-Bull's wife is too flirtatious.\r
-\r
-283\r
-00:53:10,760 --> 00:53:14,710\r
-All her underlings are handsome.\r
-\r
-284\r
-00:53:14,750 --> 00:53:24,809\r
-Old Pig almost couldn't take it.\r
-\r
-285\r
-00:53:24,869 --> 00:53:28,860\r
-Using clever tricks and tactics,\r
-\r
-286\r
-00:53:28,909 --> 00:53:32,820\r
-I stole their treasure away.\r
-\r
-287\r
-00:53:32,880 --> 00:53:36,789\r
-This is a great accomplishment.\r
-\r
-288\r
-00:53:36,829 --> 00:53:38,300\r
-Sandy should be on his knees.\r
-\r
-289\r
-00:53:38,349 --> 00:53:40,730\r
-Monkey should learn from me.\r
-\r
-290\r
-00:53:40,789 --> 00:53:45,219\r
-Even Master will be astonished.\r
-\r
-291\r
-00:53:45,280 --> 00:53:49,190\r
-Old Pig is truly masterful.\r
-\r
-292\r
-00:53:49,230 --> 00:53:54,349\r
-Old Pig is truly masterful.\r
-\r
-293\r
-00:54:36,719 --> 00:54:40,469\r
-Fool, how are things going?\r
-\r
-294\r
-00:54:40,510 --> 00:54:42,809\r
-Not only did I get the fan,\r
-\r
-295\r
-00:54:42,880 --> 00:54:48,789\r
-Princess Iron Fan was my wife for half a day, too.\r
-\r
-296\r
-00:54:48,829 --> 00:54:51,699\r
-You got a good deal.\r
-\r
-297\r
-00:54:58,150 --> 00:55:01,579\r
-Hey, let me see the fan.\r
-\r
-298\r
-00:55:16,030 --> 00:55:20,219\r
-Why did you shrink it?\r
-\r
-299\r
-00:55:40,550 --> 00:55:45,340\r
-Old Pig, you do recognize me, right?\r
-\r
-300\r
-00:55:45,389 --> 00:55:49,170\r
-Stop joking around with me.\r
-\r
-301\r
-00:55:49,230 --> 00:55:52,139\r
-Who's joking around with you?\r
-\r
-302\r
-00:56:42,869 --> 00:56:45,380\r
-Fool, how did it go?\r
-\r
-303\r
-00:56:45,429 --> 00:56:47,099\r
-It was all for nothing.\r
-\r
-304\r
-00:56:47,150 --> 00:56:49,980\r
-Wuneng, did you borrow the fan?\r
-\r
-305\r
-00:56:50,030 --> 00:56:53,340\r
-I found Bull Demon King, but he refused.\r
-\r
-306\r
-00:56:53,400 --> 00:56:59,190\r
-Then, I turned into his look-alike.\r
-\r
-307\r
-00:56:59,230 --> 00:57:03,539\r
-I tricked Princess Iron Fan into giving me the fan.\r
-\r
-308\r
-00:57:03,590 --> 00:57:10,590\r
-But then Old Bull turned into your look-alike and tricked me into giving it back.\r
-\r
-309\r
-00:57:10,590 --> 00:57:12,739\r
-Old Bull's skills are great.\r
-\r
-310\r
-00:57:12,800 --> 00:57:16,150\r
-I got beaten up by him, too.\r
-\r
-311\r
-00:57:16,190 --> 00:57:21,380\r
-How could you get the fan and still be such a fool?\r
-\r
-312\r
-00:57:21,429 --> 00:57:25,659\r
-Not everything revolves around you!\r
-\r
-313\r
-00:57:30,750 --> 00:57:34,369\r
-Don't fight, we should quickly think of a solution.\r
-\r
-314\r
-00:57:34,429 --> 00:57:40,260\r
-In which... which direction is there no fire?\r
-\r
-315\r
-00:57:40,320 --> 00:57:47,070\r
-Of east, south, west, north, there's fire only to the west.\r
-\r
-316\r
-00:57:47,119 --> 00:57:50,739\r
-So we have no option but to go back.\r
-\r
-317\r
-00:57:50,789 --> 00:57:52,940\r
-This path is blocked, what other options do we have?\r
-\r
-318\r
-00:57:52,989 --> 00:57:55,219\r
-Bajie, don't talk like that.\r
-\r
-319\r
-00:57:55,269 --> 00:57:59,139\r
-There will always be obstacles in our path.\r
-\r
-320\r
-00:57:59,190 --> 00:58:04,539\r
-To complete our sacred task we must be strong in our faith.\r
-\r
-321\r
-00:58:04,590 --> 00:58:09,219\r
-We can't change our goal half way just because we encounter some obstacles.\r
-\r
-322\r
-00:58:09,280 --> 00:58:14,590\r
-The reason that we've been defeated is that we haven't worked together.\r
-\r
-323\r
-00:58:14,630 --> 00:58:17,139\r
-If the three of you work as one,\r
-\r
-324\r
-00:58:17,190 --> 00:58:20,500\r
-put your strength together to fight Bull Demon King,\r
-\r
-325\r
-00:58:20,550 --> 00:58:22,849\r
-then you will certainly be victorious.\r
-\r
-326\r
-00:58:22,909 --> 00:58:26,030\r
-We have heard the order of Master\r
-\r
-327\r
-00:58:26,030 --> 00:58:30,139\r
-and will fight Bull Demon King to the end.\r
-\r
-328\r
-00:58:30,190 --> 00:58:34,260\r
-to... to the end.\r
-\r
-329\r
-00:58:34,320 --> 00:58:37,710\r
-That's excellent!\r
-\r
-330\r
-00:58:37,750 --> 00:58:40,980\r
-We have all been through hardships.\r
-\r
-331\r
-00:58:41,039 --> 00:58:43,869\r
-I hope everyone will make an effort\r
-\r
-332\r
-00:58:43,869 --> 00:58:49,579\r
-together with my disciples to defeat Bull Demon King and put out the flames of Fiery Mountain.\r
-\r
-333\r
-00:58:49,630 --> 00:58:52,820\r
-Otherwise this misery will never end.\r
-\r
-334\r
-00:58:53,869 --> 00:58:57,489\r
-We have heard the order of Master, to seek happiness for all.\r
-\r
-335\r
-00:58:57,550 --> 00:58:58,860\r
-Everyone work together!\r
-\r
-336\r
-00:58:58,909 --> 00:59:00,519\r
-All right!\r
-\r
-337\r
-01:08:23,229 --> 01:08:25,609\r
-Grandma, it's terrible!\r
-\r
-338\r
-01:08:25,670 --> 01:08:30,789\r
-Grandpa has been trapped, come quickly and look!\r
-\r
-339\r
-01:08:54,470 --> 01:08:56,699\r
-The fight's not over yet, not over.\r
-\r
-340\r
-01:08:56,760 --> 01:08:58,710\r
-Careful, careful.\r
-\r
-341\r
-01:08:59,760 --> 01:09:05,789\r
-Beast, all you have to is give us the fan and we'll spare your life.\r
-\r
-342\r
-01:09:05,840 --> 01:09:12,750\r
-Old Bull, where is the fan? Hand it over!\r
-\r
-343\r
-01:09:12,789 --> 01:09:19,340\r
-My... my wife... has it.\r
-\r
-344\r
-01:09:25,239 --> 01:09:27,989\r
-Darling, darling!\r
-\r
-345\r
-01:09:28,029 --> 01:09:32,260\r
-Save me, hurry!\r
-\r
-346\r
-01:09:32,319 --> 01:09:35,109\r
-Give them the fan.\r
-\r
-347\r
-01:09:35,149 --> 01:09:39,619\r
-King! All right, all right!\r
-\r
-348\r
-01:09:43,399 --> 01:09:47,229\r
-Wukong, you go one more time!\r
-\r
-349\r
-01:12:30,850 --> 01:12:46,599\r
-The End\r
+1
+00:00:01,080 --> 00:00:09,070
+Princess Iron Fan
+
+2
+00:02:03,109 --> 00:02:09,280
+Journey to the West is a wonderful children's story,
+
+3
+00:02:09,280 --> 00:02:15,280
+but the world often misunderstands it as a fantasy novel.
+
+4
+00:02:15,280 --> 00:02:19,240
+This film was made for the purpose of
+
+5
+00:02:19,240 --> 00:02:24,240
+training the hearts and minds of children.
+
+6
+00:02:24,240 --> 00:02:29,280
+The story is pure, untainted by fantasy.
+
+7
+00:02:29,280 --> 00:02:32,560
+Fiery Mountain blocking the path of Tang Seng's company
+
+8
+00:02:32,560 --> 00:02:41,039
+is a metaphor for the difficulties in life.
+
+9
+00:02:41,039 --> 00:02:46,439
+In order to overcome them, one must keep faith.
+Everybody must work together
+
+10
+00:02:46,439 --> 00:02:52,430
+in order to obtain the palm leaf fan and put out the flames.
+
+11
+00:02:52,839 --> 00:02:58,178
+Tripikata True Sutra
+
+12
+00:03:34,479 --> 00:03:37,789
+It's already autumn, how can it still be so warm?
+
+13
+00:03:37,840 --> 00:03:42,349
+Fool, don't talk rubbish. We should hurry and get on our way.
+
+14
+00:04:06,919 --> 00:04:09,349
+Wukong, where is this place?
+
+15
+00:04:09,400 --> 00:04:13,669
+We must pass through here to continue westwards, that much is certain.
+
+16
+00:04:13,719 --> 00:04:18,110
+Might we have taken the wrong path?
+
+17
+00:04:18,149 --> 00:04:21,700
+Why is it so hot here?
+
+18
+00:04:30,029 --> 00:04:31,649
+Master, look!
+
+19
+00:04:31,650 --> 00:04:33,779
+Isn't that a house up ahead?
+
+20
+00:04:33,829 --> 00:04:38,100
+Let's go in and rest for a while, OK?
+
+21
+00:04:59,389 --> 00:05:02,899
+This place is called Fiery Mountain.
+
+22
+00:05:02,949 --> 00:05:06,019
+The fire stretches for hundreds of miles.
+
+23
+00:05:06,069 --> 00:05:08,740
+Not single straw of grass can grow here.
+
+24
+00:05:08,790 --> 00:05:11,620
+The four seasons of the year are all warm.
+
+25
+00:05:11,680 --> 00:05:19,629
+You couldn't pass through the mountain even with a head of copper and arms of iron.
+
+26
+00:05:19,670 --> 00:05:23,579
+What kind of place is this? Master, don't worry!
+
+27
+00:05:23,629 --> 00:05:27,139
+The three of us are all strong enough to pass!
+
+28
+00:05:27,189 --> 00:05:30,699
+Master, I'll go and have a look!
+
+29
+00:08:06,310 --> 00:08:09,579
+Wukong, what was it like?
+
+30
+00:08:09,629 --> 00:08:11,819
+Bad, bad, very bad.
+
+31
+00:08:11,879 --> 00:08:15,910
+If I were any slower the fur on my tail would have been burned off.
+
+32
+00:08:42,720 --> 00:08:47,600
+Noble host, the fires here are so big.
+
+33
+00:08:47,600 --> 00:08:49,669
+How can you grow any crops?
+
+34
+00:08:49,710 --> 00:08:53,980
+A thousand miles from here lives Princess Iron Fan.
+
+35
+00:08:54,039 --> 00:08:56,500
+She has a palm leaf fan.
+
+36
+00:08:56,559 --> 00:08:59,070
+Wave the fan once and the fire goes out.
+
+37
+00:08:59,120 --> 00:09:01,629
+Twice and the wind starts blowing.
+
+38
+00:09:01,679 --> 00:09:03,980
+Three times and the rain starts coming down.
+
+39
+00:09:04,039 --> 00:09:07,509
+In the following period we plant and harvest.
+
+40
+00:09:07,559 --> 00:09:11,340
+However, asking that princess to come
+
+41
+00:09:11,399 --> 00:09:14,870
+is certainly no simple matter.
+
+42
+00:09:14,909 --> 00:09:16,820
+Where does she live?
+
+43
+00:09:16,879 --> 00:09:20,190
+She lives in Palm Leaf Cave at Emerald Cloud Mountain.
+
+44
+00:09:20,240 --> 00:09:23,669
+Does she live there alone?
+
+45
+00:09:23,720 --> 00:09:25,750
+Doesn't she have a husband?
+
+46
+00:09:25,799 --> 00:09:29,580
+Her husband is Bull Demon King.
+
+47
+00:09:29,639 --> 00:09:32,200
+What, her husband is Old Bull?
+
+48
+00:09:32,240 --> 00:09:36,789
+Fool, you know him? Come with me to borrow the fan!
+
+49
+00:09:36,840 --> 00:09:41,750
+Actually... Old Bull doesn't live there.
+
+50
+00:09:41,799 --> 00:09:46,350
+Looking for his woman when he isn't home
+
+51
+00:09:46,399 --> 00:09:51,519
+isn't very... appropriate.
+
+52
+00:09:51,559 --> 00:09:58,309
+You... you... the two of you go.
+
+53
+00:09:58,360 --> 00:10:04,290
+I... I'll stay here and serve Master.
+
+54
+00:10:04,440 --> 00:10:11,269
+Sha Wujing, go with your two fellow apprentices.
+
+55
+00:10:38,571 --> 00:10:44,978
+Palm Leaf Cave
+
+56
+00:10:47,200 --> 00:10:51,549
+Fool, I always go first.
+
+57
+00:10:51,600 --> 00:10:54,350
+This time it's your turn!
+
+58
+00:10:58,519 --> 00:11:04,909
+Junior! I always go first, this time it's your turn!
+
+59
+00:11:04,960 --> 00:11:06,830
+Senior...
+
+60
+00:11:06,879 --> 00:11:10,990
+I'm asking you to make a small effort for Master. Can't you do that?
+
+61
+00:11:11,039 --> 00:11:14,309
+Hurry up!
+
+62
+00:11:39,639 --> 00:11:43,039
+Simple monk, where did you come from?
+
+63
+00:11:43,039 --> 00:11:49,870
+The Great Sage... Tang Seng... wants your princess...
+
+64
+00:11:49,919 --> 00:11:52,480
+Nonsense!
+
+65
+00:12:47,549 --> 00:12:52,059
+Senior... why don't you go instead?
+
+66
+00:12:52,120 --> 00:12:56,950
+Fool, you go!
+
+67
+00:12:57,000 --> 00:13:00,700
+Senior, why don't you go?
+
+68
+00:13:04,029 --> 00:13:07,460
+Lazy fool!
+
+69
+00:13:54,279 --> 00:13:57,899
+Great God of Thunder! Don't kill me, let me go!
+
+70
+00:13:57,960 --> 00:13:59,950
+Go tell your princess
+
+71
+00:14:00,000 --> 00:14:03,279
+that Sun Wukong has come to borrow the fan.
+
+72
+00:14:03,279 --> 00:14:08,399
+Yes, yes! Let me loose, I'll go at once.
+
+73
+00:14:29,559 --> 00:14:37,059
+Grandma, there's a Sun Wukong outside asking to borrow the fan.
+
+74
+00:14:41,519 --> 00:14:44,149
+Quickly fetch my sword.
+
+75
+00:15:01,639 --> 00:15:04,149
+Sun Wukong, you hurt my son!
+
+76
+00:15:04,200 --> 00:15:08,549
+You dare come here to meet your death?
+
+77
+00:15:08,600 --> 00:15:12,039
+I've never met you before, how could I have harmed your son?
+
+78
+00:15:12,039 --> 00:15:15,789
+My son Red Child's life was ruined, wasn't that your doing?
+
+79
+00:15:15,840 --> 00:15:20,389
+Your son is with the Goddess of Mercy now, how can you say that I hurt him?
+
+80
+00:15:20,440 --> 00:15:23,750
+Enough rubbish! Come here and let me chop you with my sword.
+
+81
+00:15:23,799 --> 00:15:26,149
+If you can take it I'll lend you the fan.
+
+82
+00:15:26,200 --> 00:15:28,549
+Really?
+
+83
+00:15:56,799 --> 00:16:00,629
+Stop! Quickly give me the fan!
+
+84
+00:17:53,630 --> 00:18:00,099
+Great Sage, weren't you going west? Why have you come back here?
+
+85
+00:18:11,150 --> 00:18:17,140
+Princess Iron Fan blew me here with a single wave of her fan.
+
+86
+00:18:17,190 --> 00:18:23,859
+That's truly amazing, Great Sage. I have something for you.
+
+87
+00:18:28,509 --> 00:18:33,450
+This is a wind pearl. When you use it,
+
+88
+00:18:33,509 --> 00:18:36,140
+your heart will become steady as a rock.
+
+89
+00:18:36,190 --> 00:18:39,180
+Princess Iron Fan won't be able to move you.
+
+90
+00:18:39,230 --> 00:18:42,849
+Great Sage, come and have a look.
+
+91
+00:19:00,430 --> 00:19:02,539
+Thank you.
+
+92
+00:19:06,069 --> 00:19:12,299
+Senior... where...
+
+93
+00:19:12,349 --> 00:19:18,690
+where has he... been blown to?
+
+94
+00:19:18,750 --> 00:19:26,099
+Who cares about him? Let the monkey handle himself. Let's go.
+
+95
+00:19:35,190 --> 00:19:37,259
+Senior... senior...
+
+96
+00:19:37,309 --> 00:19:43,470
+You... you...
+
+97
+00:19:43,470 --> 00:19:50,220
+Where were you blown to by that old lady?
+
+98
+00:19:50,269 --> 00:19:57,180
+Fool, now it's definitely your turn to go.
+
+99
+00:19:57,230 --> 00:20:00,930
+I'm not going, a single wave of her fan
+
+100
+00:20:00,990 --> 00:20:03,450
+could blow me to some faraway land.
+
+101
+00:20:03,509 --> 00:20:09,710
+Maybe it's better if you go again.
+
+102
+00:20:09,710 --> 00:20:12,220
+I won't go.
+
+103
+00:20:17,789 --> 00:20:22,779
+Next time I won't let you off!
+
+104
+00:20:56,150 --> 00:21:00,140
+This time I won't move no matter how much you wave,
+
+105
+00:21:00,190 --> 00:21:05,210
+as sure as I call myself am a man!
+
+106
+00:21:33,670 --> 00:21:38,579
+Senior, how come this time her fan couldn't move you?
+
+107
+00:21:46,829 --> 00:21:50,099
+Let's break our way in.
+
+108
+00:23:59,630 --> 00:24:04,180
+Quickly bring out the fan for Sun Wukong!
+
+109
+00:24:14,869 --> 00:24:16,900
+Sun Wukong, where are you?
+
+110
+00:24:16,950 --> 00:24:19,980
+I'm in your stomach!
+
+111
+00:24:45,750 --> 00:24:48,539
+Sun Wukong, spare me!
+
+112
+00:24:48,589 --> 00:24:51,180
+Only if you give me the fan!
+
+113
+00:24:51,230 --> 00:24:56,539
+I promise, I'll give it to you. Please come out!
+
+114
+00:25:00,230 --> 00:25:02,819
+Hurry up and bring the fan.
+
+115
+00:25:07,430 --> 00:25:09,220
+We've brought out the fan.
+
+116
+00:25:09,279 --> 00:25:12,069
+Why haven't you come out?
+
+117
+00:25:12,109 --> 00:25:16,619
+Open your mouth and I'll come out.
+
+118
+00:25:25,349 --> 00:25:29,420
+Sun Wukong, why haven't you come out?
+
+119
+00:25:50,349 --> 00:25:55,579
+Here I am. Lend me the fan for a while, I'll return it.
+
+120
+00:26:32,549 --> 00:26:36,579
+Master has been waiting long enough, let's get going!
+
+121
+00:27:01,869 --> 00:27:04,900
+Scripture, what is scripture?
+
+122
+00:27:04,950 --> 00:27:10,029
+Scriptures are the principles that link heaven and earth.
+
+123
+00:27:10,029 --> 00:27:14,180
+They are the principles of man.
+
+124
+00:27:14,230 --> 00:27:18,700
+Only he who holds these principles
+
+125
+00:27:18,750 --> 00:27:25,339
+can rid himself of pain and live a good life,
+
+126
+00:27:25,390 --> 00:27:29,940
+live a true and honest life.
+
+127
+00:27:34,680 --> 00:27:36,349
+Conversely,
+
+128
+00:27:36,390 --> 00:27:40,089
+he who does not know these principles,
+
+129
+00:27:40,150 --> 00:27:46,380
+will live a life full of misery.
+
+130
+00:27:46,430 --> 00:27:52,609
+Even his son or grandson will not achieve happiness.
+
+131
+00:27:52,670 --> 00:27:55,660
+Why am I going to get the scripture?
+
+132
+00:27:55,710 --> 00:28:01,299
+Because men nowadays are trapped in misery.
+
+133
+00:28:01,349 --> 00:28:04,180
+In order to achieve this goal, we are going to
+
+134
+00:28:04,230 --> 00:28:12,500
+appear before the Tang emperor and discuss this very complicated matter.
+
+135
+00:28:15,670 --> 00:28:17,819
+Did you get the palm leaf fan?
+
+136
+00:28:17,869 --> 00:28:19,400
+We have it.
+
+137
+00:28:19,401 --> 00:28:20,779
+Is this it?
+
+138
+00:28:22,829 --> 00:28:27,980
+Noble hosts, now that we have the fan,
+
+139
+00:28:28,029 --> 00:28:32,140
+we will take our leave.
+
+140
+00:28:32,190 --> 00:28:34,039
+Hold on.
+
+141
+00:28:34,039 --> 00:28:39,789
+Everyone, I would like to ask Sage Seng to stay here for a few more days.
+
+142
+00:28:39,829 --> 00:28:41,339
+Do you agree?
+
+143
+00:28:41,390 --> 00:28:43,460
+Agreed!
+
+144
+00:28:43,509 --> 00:28:45,890
+Thank you for your kindness.
+
+145
+00:28:45,950 --> 00:28:51,779
+But the sooner I leave the sooner we can complete our task.
+
+146
+00:28:51,829 --> 00:28:56,180
+Very well, will the honorable apprentice first go to Fiery Mountain.
+
+147
+00:28:56,230 --> 00:29:02,140
+After extinguishing the flames, continue to follow Sage Seng.
+
+148
+00:29:02,190 --> 00:29:05,460
+All right, go ahead!
+
+149
+00:30:24,470 --> 00:30:30,029
+Princess Iron Fan is really despicable, she gave us a fake fan!
+
+150
+00:30:30,029 --> 00:30:32,779
+I'll kill her for sure!
+
+151
+00:30:32,829 --> 00:30:36,299
+No, killing her is the wrong thing to do.
+
+152
+00:30:36,349 --> 00:30:39,579
+I won't let you kill anyone.
+
+153
+00:30:39,630 --> 00:30:42,980
+Let's think of something else.
+
+154
+00:30:52,150 --> 00:30:56,220
+Senior, how could you be fooled by her?
+
+155
+00:30:56,269 --> 00:30:58,539
+After making such an effort
+
+156
+00:30:58,589 --> 00:31:02,099
+all we got was a fake fan.
+
+157
+00:31:02,150 --> 00:31:06,500
+Ridiculous, ridiculous.
+
+158
+00:31:08,910 --> 00:31:10,420
+Then you go!
+
+159
+00:31:10,470 --> 00:31:14,380
+OK, I'll go, I'll go, I'm going!
+
+160
+00:31:14,430 --> 00:31:16,908
+I'll go find Bull Demon King.
+
+161
+00:31:16,909 --> 00:31:19,940
+This is a good solution.
+
+162
+00:31:21,390 --> 00:31:24,439
+Partner, what do you think?
+
+163
+00:31:24,440 --> 00:31:27,380
+We'll see how you do.
+
+164
+00:33:07,190 --> 00:33:11,150
+What do you think, am I pretty today?
+
+165
+00:33:11,150 --> 00:33:13,779
+Beautiful, my baby.
+
+166
+00:33:13,829 --> 00:33:17,059
+Accompany me for a walk outside the cave, all right?
+
+167
+00:33:17,109 --> 00:33:21,539
+My baby, why don't you go by yourself.
+
+168
+00:33:21,589 --> 00:33:24,819
+Why of course, I'm just a plain country girl.
+
+169
+00:33:24,869 --> 00:33:28,019
+Taking me outside might cause you to lose face.
+
+170
+00:33:28,069 --> 00:33:32,029
+Baby, what are you saying?
+
+171
+00:33:32,029 --> 00:33:37,500
+You go ahead, I'll come out in a while, all right?
+
+172
+00:33:39,852 --> 00:33:44,557
+Emerald Cloud Cave
+
+173
+00:35:28,030 --> 00:35:35,659
+Goddess, you're truly an angel come down from heaven.
+
+174
+00:35:35,710 --> 00:35:37,900
+Who... who are you?
+
+175
+00:35:37,949 --> 00:35:41,460
+I've come from Palm Leaf Cave to look for Bull Demon King.
+
+176
+00:35:41,519 --> 00:35:43,980
+Let go of me!
+
+177
+00:35:49,550 --> 00:35:52,940
+Goddess, slow down!
+
+178
+00:36:38,768 --> 00:36:40,133
+Emerald Cloud Cave
+
+179
+00:36:44,230 --> 00:36:49,219
+Baby, who has bullied you?
+
+180
+00:36:49,269 --> 00:36:50,820
+You!
+
+181
+00:36:50,869 --> 00:36:54,340
+How could I bully you?
+
+182
+00:36:56,909 --> 00:36:59,260
+Why don't you go back to Palm Leaf Cave?
+
+183
+00:36:59,320 --> 00:37:01,699
+It would spare you some embarrassment.
+
+184
+00:37:01,750 --> 00:37:07,659
+They often send people to look for you, and bully me.
+
+185
+00:37:07,710 --> 00:37:11,059
+Has there been someone here to look for me?
+
+186
+00:37:11,110 --> 00:37:15,059
+There's a pig monk outside looking for you.
+
+187
+00:37:15,119 --> 00:37:18,510
+He almost scared me to death.
+
+188
+00:37:18,550 --> 00:37:22,739
+How can this be? Wait while I go out to have a look.
+
+189
+00:37:50,670 --> 00:37:53,780
+Bull, old friend!
+
+190
+00:37:53,829 --> 00:37:58,139
+There's a very beautiful young lady in here.
+
+191
+00:37:58,199 --> 00:38:03,889
+Hey, that's my woman! Why have you come to bother her?
+
+192
+00:38:03,930 --> 00:38:08,550
+Oh, I didn't know, please forgive me!
+
+193
+00:38:08,550 --> 00:38:11,940
+You didn't know, so I can't blame you. Off you go!
+
+194
+00:38:11,989 --> 00:38:16,099
+No, no. I still have something I need you to help me with.
+
+195
+00:38:18,469 --> 00:38:24,710
+We were on our way to retrieve the scriptures when we arrived at Fiery Mountain.
+
+196
+00:38:24,710 --> 00:38:27,300
+Please ask your wife
+
+197
+00:38:27,349 --> 00:38:30,820
+to lend us the palm leaf fan for a while.
+
+198
+00:38:30,880 --> 00:38:33,510
+Absolutely not! Tang Seng and Sun Wukong
+
+199
+00:38:33,510 --> 00:38:35,179
+are my son's enemies.
+
+200
+00:38:35,230 --> 00:38:38,739
+I'd love to take my revenge on them.
+
+201
+00:38:38,789 --> 00:38:44,969
+Your son is with the Goddess of Mercy now, please don't fight.
+
+202
+00:38:45,030 --> 00:38:48,940
+All right, since we are old friends, I won't fight you.
+
+203
+00:38:49,000 --> 00:38:51,710
+Now go away!
+
+204
+00:39:38,389 --> 00:39:44,179
+Baby, that pig monk is a friend of mine.
+
+205
+00:39:44,230 --> 00:39:46,500
+He wasn't sent from Palm Leaf Cave at all.
+
+206
+00:39:46,550 --> 00:39:47,739
+I don't believe you.
+
+207
+00:39:47,789 --> 00:39:50,940
+I'm not lying to you!
+
+208
+00:39:50,989 --> 00:39:54,019
+Where is that monk now?
+
+209
+00:39:54,110 --> 00:39:57,780
+I've already scared him away.
+
+210
+00:43:34,814 --> 00:43:40,987
+Palm Leaf Cave
+
+211
+00:43:58,630 --> 00:44:01,340
+The king has returned!
+
+212
+00:44:01,389 --> 00:44:02,369
+Where's grandma?
+
+213
+00:44:02,429 --> 00:44:04,780
+She's inside.
+
+214
+00:44:42,989 --> 00:44:48,219
+By what honor has the king come to visit today?
+
+215
+00:44:48,269 --> 00:44:52,260
+I heard that Sun Wukong and Tang Seng are coming here.
+
+216
+00:44:52,320 --> 00:44:56,909
+I'm afraid they want to use the palm leaf fan to pass Fiery Mountain.
+
+217
+00:44:56,949 --> 00:45:00,860
+That monkey is the one who harmed our son.
+
+218
+00:45:00,909 --> 00:45:08,489
+I'll get him sooner or later, we will have our revenge.
+
+219
+00:45:08,550 --> 00:45:12,699
+Darling, why are you crying?
+
+220
+00:45:12,750 --> 00:45:15,699
+That monkey has already been here.
+
+221
+00:45:15,750 --> 00:45:18,860
+I refused to give him the fan.
+
+222
+00:45:18,909 --> 00:45:22,260
+I don't know how, but he got inside my stomach.
+
+223
+00:45:22,309 --> 00:45:25,500
+It hurt so bad I thought I would die.
+
+224
+00:45:25,550 --> 00:45:30,589
+At last I had no choice but to give him the fan.
+
+225
+00:45:30,789 --> 00:45:35,260
+That's terrible, how could you give him the fan?
+
+226
+00:45:38,320 --> 00:45:40,469
+I gave him a false one.
+
+227
+00:45:40,720 --> 00:45:43,019
+A false one?
+
+228
+00:46:14,190 --> 00:46:19,860
+A banquet to celebrate the king's return
+
+229
+00:46:19,909 --> 00:46:25,619
+Please drink the fine wine.
+
+230
+00:46:25,670 --> 00:46:34,179
+The chicken is fragrant, the duck is beautiful, and the pig is fat.
+
+231
+00:46:34,239 --> 00:46:45,670
+I try my best to sing, I try my best to dance.
+
+232
+00:46:45,710 --> 00:46:54,500
+You must also try your best to drink.
+
+233
+00:47:03,590 --> 00:47:16,389
+My king! You dumped the old one.
+
+234
+00:47:16,429 --> 00:47:22,610
+You love another woman.
+
+235
+00:47:22,670 --> 00:47:34,659
+Countless tears were spilled for you.
+
+236
+00:47:46,710 --> 00:47:55,699
+When the light is out and the curtain is dropped,
+
+237
+00:47:55,750 --> 00:48:00,869
+you will sleep alone.
+
+238
+00:48:00,869 --> 00:48:05,510
+You too will taste loneliness.
+
+239
+00:48:05,510 --> 00:48:13,420
+Pardon me for not making you company.
+
+240
+00:48:18,550 --> 00:48:24,619
+Even if we are on the same bed,
+
+241
+00:48:24,670 --> 00:48:34,340
+we will sleep under separate sheets.
+
+242
+00:48:38,389 --> 00:48:42,380
+King, I'm drunk.
+
+243
+00:48:55,070 --> 00:48:58,139
+Darling, where did you put the real fan?
+
+244
+00:48:58,190 --> 00:49:05,460
+That monkey is very deceitful, and the pig has even greater skill.
+
+245
+00:49:05,510 --> 00:49:09,780
+If you're not careful they might trick you.
+
+246
+00:49:18,360 --> 00:49:21,980
+Our treasure is right here.
+
+247
+00:49:31,429 --> 00:49:39,309
+King, what are you thinking about? Why don't you take it?
+
+248
+00:49:39,309 --> 00:49:40,847
+My treasure.
+
+249
+00:49:41,514 --> 00:49:44,150
+Emerald Cloud Cave
+
+250
+00:49:44,250 --> 00:49:49,019
+Baby, have another cup. Drink.
+
+251
+00:49:53,909 --> 00:49:59,510
+Gold Dragon King has asked me to drink with him tonight
+
+252
+00:49:59,510 --> 00:50:01,420
+Then you should go.
+
+253
+00:50:01,469 --> 00:50:02,860
+That's right.
+
+254
+00:50:02,909 --> 00:50:06,610
+You should prepare the golden eyed beast for grandpa.
+
+255
+00:50:06,670 --> 00:50:08,260
+I will.
+
+256
+00:50:08,320 --> 00:50:12,590
+You should drink a little less tonight.
+
+257
+00:50:12,630 --> 00:50:15,739
+Otherwise I won't be able to wake you up.
+
+258
+00:50:15,800 --> 00:50:19,110
+It's terrible, grandpa's golden eyed beast has disappeared!
+
+259
+00:50:19,150 --> 00:50:20,900
+Are you all deaf and blind?
+
+260
+00:50:20,949 --> 00:50:24,030
+How could it just disappear?
+
+261
+00:50:24,030 --> 00:50:27,900
+Baby, don't mind them.
+
+262
+00:50:27,960 --> 00:50:31,710
+I'm afraid Zhu Bajie might have stolen it.
+
+263
+00:50:31,750 --> 00:50:35,260
+Maybe I should go over to Palm Leaf Cave.
+
+264
+00:50:35,320 --> 00:50:39,309
+What? You've had this planned all along.
+
+265
+00:50:42,280 --> 00:50:48,150
+You still want to go over to that shameless woman?
+
+266
+00:50:48,190 --> 00:50:50,699
+Please baby, don't cry.
+
+267
+00:50:50,750 --> 00:50:54,059
+I'll be back soon.
+
+268
+00:50:57,624 --> 00:51:01,194
+Palm Leaf Cave
+
+269
+00:51:02,670 --> 00:51:07,300
+Come over here, drink a little!
+
+270
+00:51:10,349 --> 00:51:12,460
+Now I can relax.
+
+271
+00:51:12,510 --> 00:51:16,699
+We don't have to worry about our treasure being stolen.
+
+272
+00:51:16,750 --> 00:51:21,300
+Even if they stole it, they wouldn't know to pull the silk thread.
+
+273
+00:51:21,360 --> 00:51:26,269
+Having just a pearl won't be of any use.
+
+274
+00:51:26,309 --> 00:51:31,780
+Pulling the thread will turn it into a fan, right?
+
+275
+00:51:35,119 --> 00:51:38,070
+King, you're drunk.
+
+276
+00:51:38,110 --> 00:51:44,019
+You forgot about your own treasure, and are asking me.
+
+277
+00:51:49,989 --> 00:51:53,690
+Lady, look at who I am.
+
+278
+00:52:00,320 --> 00:52:03,750
+Who are you?
+
+279
+00:52:03,789 --> 00:52:09,889
+I am Tang Seng's second apprentice, Zhu Bajie.
+
+280
+00:52:09,949 --> 00:52:14,780
+Sorry about bothering you, and thanks!
+
+281
+00:52:19,079 --> 00:52:21,710
+Bye!
+
+282
+00:53:06,829 --> 00:53:10,699
+Bull's wife is too flirtatious.
+
+283
+00:53:10,760 --> 00:53:14,710
+All her underlings are handsome.
+
+284
+00:53:14,750 --> 00:53:24,809
+Old Pig almost couldn't take it.
+
+285
+00:53:24,869 --> 00:53:28,860
+Using clever tricks and tactics,
+
+286
+00:53:28,909 --> 00:53:32,820
+I stole their treasure away.
+
+287
+00:53:32,880 --> 00:53:36,789
+This is a great accomplishment.
+
+288
+00:53:36,829 --> 00:53:38,300
+Sandy should be on his knees.
+
+289
+00:53:38,349 --> 00:53:40,730
+Monkey should learn from me.
+
+290
+00:53:40,789 --> 00:53:45,219
+Even Master will be astonished.
+
+291
+00:53:45,280 --> 00:53:49,190
+Old Pig is truly masterful.
+
+292
+00:53:49,230 --> 00:53:54,349
+Old Pig is truly masterful.
+
+293
+00:54:36,719 --> 00:54:40,469
+Fool, how are things going?
+
+294
+00:54:40,510 --> 00:54:42,809
+Not only did I get the fan,
+
+295
+00:54:42,880 --> 00:54:48,789
+Princess Iron Fan was my wife for half a day, too.
+
+296
+00:54:48,829 --> 00:54:51,699
+You got a good deal.
+
+297
+00:54:58,150 --> 00:55:01,579
+Hey, let me see the fan.
+
+298
+00:55:16,030 --> 00:55:20,219
+Why did you shrink it?
+
+299
+00:55:40,550 --> 00:55:45,340
+Old Pig, you do recognize me, right?
+
+300
+00:55:45,389 --> 00:55:49,170
+Stop joking around with me.
+
+301
+00:55:49,230 --> 00:55:52,139
+Who's joking around with you?
+
+302
+00:56:42,869 --> 00:56:45,380
+Fool, how did it go?
+
+303
+00:56:45,429 --> 00:56:47,099
+It was all for nothing.
+
+304
+00:56:47,150 --> 00:56:49,980
+Wuneng, did you borrow the fan?
+
+305
+00:56:50,030 --> 00:56:53,340
+I found Bull Demon King, but he refused.
+
+306
+00:56:53,400 --> 00:56:59,190
+Then, I turned into his look-alike.
+
+307
+00:56:59,230 --> 00:57:03,539
+I tricked Princess Iron Fan into giving me the fan.
+
+308
+00:57:03,590 --> 00:57:10,590
+But then Old Bull turned into your look-alike and tricked me into giving it back.
+
+309
+00:57:10,590 --> 00:57:12,739
+Old Bull's skills are great.
+
+310
+00:57:12,800 --> 00:57:16,150
+I got beaten up by him, too.
+
+311
+00:57:16,190 --> 00:57:21,380
+How could you get the fan and still be such a fool?
+
+312
+00:57:21,429 --> 00:57:25,659
+Not everything revolves around you!
+
+313
+00:57:30,750 --> 00:57:34,369
+Don't fight, we should quickly think of a solution.
+
+314
+00:57:34,429 --> 00:57:40,260
+In which... which direction is there no fire?
+
+315
+00:57:40,320 --> 00:57:47,070
+Of east, south, west, north, there's fire only to the west.
+
+316
+00:57:47,119 --> 00:57:50,739
+So we have no option but to go back.
+
+317
+00:57:50,789 --> 00:57:52,940
+This path is blocked, what other options do we have?
+
+318
+00:57:52,989 --> 00:57:55,219
+Bajie, don't talk like that.
+
+319
+00:57:55,269 --> 00:57:59,139
+There will always be obstacles in our path.
+
+320
+00:57:59,190 --> 00:58:04,539
+To complete our sacred task we must be strong in our faith.
+
+321
+00:58:04,590 --> 00:58:09,219
+We can't change our goal half way just because we encounter some obstacles.
+
+322
+00:58:09,280 --> 00:58:14,590
+The reason that we've been defeated is that we haven't worked together.
+
+323
+00:58:14,630 --> 00:58:17,139
+If the three of you work as one,
+
+324
+00:58:17,190 --> 00:58:20,500
+put your strength together to fight Bull Demon King,
+
+325
+00:58:20,550 --> 00:58:22,849
+then you will certainly be victorious.
+
+326
+00:58:22,909 --> 00:58:26,030
+We have heard the order of Master
+
+327
+00:58:26,030 --> 00:58:30,139
+and will fight Bull Demon King to the end.
+
+328
+00:58:30,190 --> 00:58:34,260
+to... to the end.
+
+329
+00:58:34,320 --> 00:58:37,710
+That's excellent!
+
+330
+00:58:37,750 --> 00:58:40,980
+We have all been through hardships.
+
+331
+00:58:41,039 --> 00:58:43,869
+I hope everyone will make an effort
+
+332
+00:58:43,869 --> 00:58:49,579
+together with my disciples to defeat Bull Demon King and put out the flames of Fiery Mountain.
+
+333
+00:58:49,630 --> 00:58:52,820
+Otherwise this misery will never end.
+
+334
+00:58:53,869 --> 00:58:57,489
+We have heard the order of Master, to seek happiness for all.
+
+335
+00:58:57,550 --> 00:58:58,860
+Everyone work together!
+
+336
+00:58:58,909 --> 00:59:00,519
+All right!
+
+337
+01:08:23,229 --> 01:08:25,609
+Grandma, it's terrible!
+
+338
+01:08:25,670 --> 01:08:30,789
+Grandpa has been trapped, come quickly and look!
+
+339
+01:08:54,470 --> 01:08:56,699
+The fight's not over yet, not over.
+
+340
+01:08:56,760 --> 01:08:58,710
+Careful, careful.
+
+341
+01:08:59,760 --> 01:09:05,789
+Beast, all you have to is give us the fan and we'll spare your life.
+
+342
+01:09:05,840 --> 01:09:12,750
+Old Bull, where is the fan? Hand it over!
+
+343
+01:09:12,789 --> 01:09:19,340
+My... my wife... has it.
+
+344
+01:09:25,239 --> 01:09:27,989
+Darling, darling!
+
+345
+01:09:28,029 --> 01:09:32,260
+Save me, hurry!
+
+346
+01:09:32,319 --> 01:09:35,109
+Give them the fan.
+
+347
+01:09:35,149 --> 01:09:39,619
+King! All right, all right!
+
+348
+01:09:43,399 --> 01:09:47,229
+Wukong, you go one more time!
+
+349
+01:12:30,850 --> 01:12:46,599
+The End
-/**\r
- * --------------------------------------------------------------------\r
- * jQuery-Plugin "pngFix"\r
- * Version: 1.2, 09.03.2009\r
- * by Andreas Eberhard, andreas.eberhard@gmail.com\r
- * http://jquery.andreaseberhard.de/\r
- *\r
- * Copyright (c) 2007 Andreas Eberhard\r
- * Licensed under GPL (http://www.opensource.org/licenses/gpl-license.php)\r
- *\r
- * Changelog:\r
- * 09.03.2009 Version 1.2\r
- * - Update for jQuery 1.3.x, removed @ from selectors\r
- * 11.09.2007 Version 1.1\r
- * - removed noConflict\r
- * - added png-support for input type=image\r
- * - 01.08.2007 CSS background-image support extension added by Scott Jehl, scott@filamentgroup.com, http://www.filamentgroup.com\r
- * 31.05.2007 initial Version 1.0\r
- * --------------------------------------------------------------------\r
- * @example $(function(){$(document).pngFix();});\r
- * @desc Fixes all PNG's in the document on document.ready\r
- *\r
- * jQuery(function(){jQuery(document).pngFix();});\r
- * @desc Fixes all PNG's in the document on document.ready when using noConflict\r
- *\r
- * @example $(function(){$('div.examples').pngFix();});\r
- * @desc Fixes all PNG's within div with class examples\r
- *\r
- * @example $(function(){$('div.examples').pngFix( { blankgif:'ext.gif' } );});\r
- * @desc Fixes all PNG's within div with class examples, provides blank gif for input with png\r
- * --------------------------------------------------------------------\r
- */\r
-\r
-(function($) {\r
-\r
-jQuery.fn.pngFix = function(settings) {\r
-\r
- // Settings\r
- settings = jQuery.extend({\r
- blankgif: 'blank.gif'\r
- }, settings);\r
-\r
- var ie55 = (navigator.appName == "Microsoft Internet Explorer" && parseInt(navigator.appVersion) == 4 && navigator.appVersion.indexOf("MSIE 5.5") != -1);\r
- var ie6 = (navigator.appName == "Microsoft Internet Explorer" && parseInt(navigator.appVersion) == 4 && navigator.appVersion.indexOf("MSIE 6.0") != -1);\r
-\r
- if (jQuery.browser.msie && (ie55 || ie6)) {\r
-\r
- //fix images with png-source\r
- jQuery(this).find("img[src$=.png]").each(function() {\r
-\r
- jQuery(this).attr('width',jQuery(this).width());\r
- jQuery(this).attr('height',jQuery(this).height());\r
-\r
- var prevStyle = '';\r
- var strNewHTML = '';\r
- var imgId = (jQuery(this).attr('id')) ? 'id="' + jQuery(this).attr('id') + '" ' : '';\r
- var imgClass = (jQuery(this).attr('class')) ? 'class="' + jQuery(this).attr('class') + '" ' : '';\r
- var imgTitle = (jQuery(this).attr('title')) ? 'title="' + jQuery(this).attr('title') + '" ' : '';\r
- var imgAlt = (jQuery(this).attr('alt')) ? 'alt="' + jQuery(this).attr('alt') + '" ' : '';\r
- var imgAlign = (jQuery(this).attr('align')) ? 'float:' + jQuery(this).attr('align') + ';' : '';\r
- var imgHand = (jQuery(this).parent().attr('href')) ? 'cursor:hand;' : '';\r
- if (this.style.border) {\r
- prevStyle += 'border:'+this.style.border+';';\r
- this.style.border = '';\r
- }\r
- if (this.style.padding) {\r
- prevStyle += 'padding:'+this.style.padding+';';\r
- this.style.padding = '';\r
- }\r
- if (this.style.margin) {\r
- prevStyle += 'margin:'+this.style.margin+';';\r
- this.style.margin = '';\r
- }\r
- var imgStyle = (this.style.cssText);\r
-\r
- strNewHTML += '<span '+imgId+imgClass+imgTitle+imgAlt;\r
- strNewHTML += 'style="position:relative;white-space:pre-line;display:inline-block;background:transparent;'+imgAlign+imgHand;\r
- strNewHTML += 'width:' + jQuery(this).width() + 'px;' + 'height:' + jQuery(this).height() + 'px;';\r
- strNewHTML += 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader' + '(src=\'' + jQuery(this).attr('src') + '\', sizingMethod=\'scale\');';\r
- strNewHTML += imgStyle+'"></span>';\r
- if (prevStyle != ''){\r
- strNewHTML = '<span style="position:relative;display:inline-block;'+prevStyle+imgHand+'width:' + jQuery(this).width() + 'px;' + 'height:' + jQuery(this).height() + 'px;'+'">' + strNewHTML + '</span>';\r
- }\r
-\r
- jQuery(this).hide();\r
- jQuery(this).after(strNewHTML);\r
-\r
- });\r
-\r
- // fix css background pngs\r
- jQuery(this).find("*").each(function(){\r
- var bgIMG = jQuery(this).css('background-image');\r
- if(bgIMG.indexOf(".png")!=-1){\r
- var iebg = bgIMG.split('url("')[1].split('")')[0];\r
- jQuery(this).css('background-image', 'none');\r
- jQuery(this).get(0).runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + iebg + "',sizingMethod='scale')";\r
- }\r
- });\r
- \r
- //fix input with png-source\r
- jQuery(this).find("input[src$=.png]").each(function() {\r
- var bgIMG = jQuery(this).attr('src');\r
- jQuery(this).get(0).runtimeStyle.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader' + '(src=\'' + bgIMG + '\', sizingMethod=\'scale\');';\r
- jQuery(this).attr('src', settings.blankgif)\r
- });\r
- \r
- }\r
- \r
- return jQuery;\r
-\r
-};\r
-\r
-})(jQuery);\r
+/**
+ * --------------------------------------------------------------------
+ * jQuery-Plugin "pngFix"
+ * Version: 1.2, 09.03.2009
+ * by Andreas Eberhard, andreas.eberhard@gmail.com
+ * http://jquery.andreaseberhard.de/
+ *
+ * Copyright (c) 2007 Andreas Eberhard
+ * Licensed under GPL (http://www.opensource.org/licenses/gpl-license.php)
+ *
+ * Changelog:
+ * 09.03.2009 Version 1.2
+ * - Update for jQuery 1.3.x, removed @ from selectors
+ * 11.09.2007 Version 1.1
+ * - removed noConflict
+ * - added png-support for input type=image
+ * - 01.08.2007 CSS background-image support extension added by Scott Jehl, scott@filamentgroup.com, http://www.filamentgroup.com
+ * 31.05.2007 initial Version 1.0
+ * --------------------------------------------------------------------
+ * @example $(function(){$(document).pngFix();});
+ * @desc Fixes all PNG's in the document on document.ready
+ *
+ * jQuery(function(){jQuery(document).pngFix();});
+ * @desc Fixes all PNG's in the document on document.ready when using noConflict
+ *
+ * @example $(function(){$('div.examples').pngFix();});
+ * @desc Fixes all PNG's within div with class examples
+ *
+ * @example $(function(){$('div.examples').pngFix( { blankgif:'ext.gif' } );});
+ * @desc Fixes all PNG's within div with class examples, provides blank gif for input with png
+ * --------------------------------------------------------------------
+ */
+
+(function($) {
+
+jQuery.fn.pngFix = function(settings) {
+
+ // Settings
+ settings = jQuery.extend({
+ blankgif: 'blank.gif'
+ }, settings);
+
+ var ie55 = (navigator.appName == "Microsoft Internet Explorer" && parseInt(navigator.appVersion) == 4 && navigator.appVersion.indexOf("MSIE 5.5") != -1);
+ var ie6 = (navigator.appName == "Microsoft Internet Explorer" && parseInt(navigator.appVersion) == 4 && navigator.appVersion.indexOf("MSIE 6.0") != -1);
+
+ if (jQuery.browser.msie && (ie55 || ie6)) {
+
+ //fix images with png-source
+ jQuery(this).find("img[src$=.png]").each(function() {
+
+ jQuery(this).attr('width',jQuery(this).width());
+ jQuery(this).attr('height',jQuery(this).height());
+
+ var prevStyle = '';
+ var strNewHTML = '';
+ var imgId = (jQuery(this).attr('id')) ? 'id="' + jQuery(this).attr('id') + '" ' : '';
+ var imgClass = (jQuery(this).attr('class')) ? 'class="' + jQuery(this).attr('class') + '" ' : '';
+ var imgTitle = (jQuery(this).attr('title')) ? 'title="' + jQuery(this).attr('title') + '" ' : '';
+ var imgAlt = (jQuery(this).attr('alt')) ? 'alt="' + jQuery(this).attr('alt') + '" ' : '';
+ var imgAlign = (jQuery(this).attr('align')) ? 'float:' + jQuery(this).attr('align') + ';' : '';
+ var imgHand = (jQuery(this).parent().attr('href')) ? 'cursor:hand;' : '';
+ if (this.style.border) {
+ prevStyle += 'border:'+this.style.border+';';
+ this.style.border = '';
+ }
+ if (this.style.padding) {
+ prevStyle += 'padding:'+this.style.padding+';';
+ this.style.padding = '';
+ }
+ if (this.style.margin) {
+ prevStyle += 'margin:'+this.style.margin+';';
+ this.style.margin = '';
+ }
+ var imgStyle = (this.style.cssText);
+
+ strNewHTML += '<span '+imgId+imgClass+imgTitle+imgAlt;
+ strNewHTML += 'style="position:relative;white-space:pre-line;display:inline-block;background:transparent;'+imgAlign+imgHand;
+ strNewHTML += 'width:' + jQuery(this).width() + 'px;' + 'height:' + jQuery(this).height() + 'px;';
+ strNewHTML += 'filter:progid:DXImageTransform.Microsoft.AlphaImageLoader' + '(src=\'' + jQuery(this).attr('src') + '\', sizingMethod=\'scale\');';
+ strNewHTML += imgStyle+'"></span>';
+ if (prevStyle != ''){
+ strNewHTML = '<span style="position:relative;display:inline-block;'+prevStyle+imgHand+'width:' + jQuery(this).width() + 'px;' + 'height:' + jQuery(this).height() + 'px;'+'">' + strNewHTML + '</span>';
+ }
+
+ jQuery(this).hide();
+ jQuery(this).after(strNewHTML);
+
+ });
+
+ // fix css background pngs
+ jQuery(this).find("*").each(function(){
+ var bgIMG = jQuery(this).css('background-image');
+ if(bgIMG.indexOf(".png")!=-1){
+ var iebg = bgIMG.split('url("')[1].split('")')[0];
+ jQuery(this).css('background-image', 'none');
+ jQuery(this).get(0).runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + iebg + "',sizingMethod='scale')";
+ }
+ });
+
+ //fix input with png-source
+ jQuery(this).find("input[src$=.png]").each(function() {
+ var bgIMG = jQuery(this).attr('src');
+ jQuery(this).get(0).runtimeStyle.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader' + '(src=\'' + bgIMG + '\', sizingMethod=\'scale\');';
+ jQuery(this).attr('src', settings.blankgif)
+ });
+
+ }
+
+ return jQuery;
+
+};
+
+})(jQuery);
-body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td { \r
- margin:0;\r
- padding:0;\r
-}\r
-table {\r
- border-collapse:collapse;\r
- border-spacing:0;\r
-}\r
-fieldset,img { \r
- border:0;\r
-}\r
-address,caption,cite,code,dfn,em,strong,th,var {\r
- font-style:normal;\r
- font-weight:normal;\r
-}\r
-ol,ul {\r
- list-style:none;\r
-}\r
-caption,th {\r
- text-align:left;\r
-}\r
-h1,h2,h3,h4,h5,h6 {\r
- font-size:100%;\r
- font-weight:normal;\r
-}\r
-q:before,q:after {\r
- content:'';\r
-}\r
-abbr,acronym { border:0;\r
-}\r
-html, body {\r
- background-color: #fff;\r
- font-family: Arial, Helvetica, sans-serif;\r
- font-size: 12px;\r
- line-height: 18px;\r
- color: #52697E;\r
-}\r
-body {\r
- text-align: center;\r
- overflow: auto;\r
-}\r
-.wrapper {\r
- width: 700px;\r
- margin: 0 auto;\r
- text-align: left;\r
-}\r
-h1 {\r
- font-size: 21px;\r
- height: 47px;\r
- line-height: 47px;\r
- text-transform: uppercase;\r
-}\r
-.navigationTabs {\r
- height: 23px;\r
- line-height: 23px;\r
- border-bottom: 1px solid #ccc;\r
-}\r
-.navigationTabs li {\r
- float: left;\r
- height: 23px;\r
- line-height: 23px;\r
- padding-right: 3px;\r
-}\r
-.navigationTabs li a{\r
- float: left;\r
- dispaly: block;\r
- height: 23px;\r
- line-height: 23px;\r
- padding: 0 10px;\r
- overflow: hidden;\r
- color: #52697E;\r
- background-color: #eee;\r
- position: relative;\r
- text-decoration: none;\r
-}\r
-.navigationTabs li a:hover {\r
- background-color: #f0f0f0;\r
-}\r
-.navigationTabs li a.active {\r
- background-color: #fff;\r
- border: 1px solid #ccc;\r
- border-bottom: 0px solid;\r
-}\r
-.tabsContent {\r
- border: 1px solid #ccc;\r
- border-top: 0px solid;\r
- width: 698px;\r
- overflow: hidden;\r
-}\r
-.tab {\r
- padding: 16px;\r
- display: none;\r
-}\r
-.tab h2 {\r
- font-weight: bold;\r
- font-size: 16px;\r
-}\r
-.tab h3 {\r
- font-weight: bold;\r
- font-size: 14px;\r
- margin-top: 20px;\r
-}\r
-.tab p {\r
- margin-top: 16px;\r
- clear: both;\r
-}\r
-.tab ul {\r
- margin-top: 16px;\r
- list-style: disc;\r
-}\r
-.tab li {\r
- margin: 10px 0 0 35px;\r
-}\r
-.tab a {\r
- color: #8FB0CF;\r
-}\r
-.tab strong {\r
- font-weight: bold;\r
-}\r
-.tab pre {\r
- font-size: 11px;\r
- margin-top: 20px;\r
- width: 668px;\r
- overflow: auto;\r
- clear: both;\r
-}\r
-.tab table {\r
- width: 100%;\r
-}\r
-.tab table td {\r
- padding: 6px 10px 6px 0;\r
- vertical-align: top;\r
-}\r
-.tab dt {\r
- margin-top: 16px;\r
-}\r
-\r
-#colorSelector {\r
- position: relative;\r
- width: 36px;\r
- height: 36px;\r
- background: url(../images/select.png);\r
-}\r
-#colorSelector div {\r
- position: absolute;\r
- top: 3px;\r
- left: 3px;\r
- width: 30px;\r
- height: 30px;\r
- background: url(../images/select.png) center;\r
-}\r
-#colorSelector2 {\r
- position: absolute;\r
- top: 0;\r
- left: 0;\r
- width: 36px;\r
- height: 36px;\r
- background: url(../images/select2.png);\r
-}\r
-#colorSelector2 div {\r
- position: absolute;\r
- top: 4px;\r
- left: 4px;\r
- width: 28px;\r
- height: 28px;\r
- background: url(../images/select2.png) center;\r
-}\r
-#colorpickerHolder2 {\r
- top: 32px;\r
- left: 0;\r
- width: 356px;\r
- height: 0;\r
- overflow: hidden;\r
- position: absolute;\r
-}\r
-#colorpickerHolder2 .colorpicker {\r
- background-image: url(../images/custom_background.png);\r
- position: absolute;\r
- bottom: 0;\r
- left: 0;\r
-}\r
-#colorpickerHolder2 .colorpicker_hue div {\r
- background-image: url(../images/custom_indic.gif);\r
-}\r
-#colorpickerHolder2 .colorpicker_hex {\r
- background-image: url(../images/custom_hex.png);\r
-}\r
-#colorpickerHolder2 .colorpicker_rgb_r {\r
- background-image: url(../images/custom_rgb_r.png);\r
-}\r
-#colorpickerHolder2 .colorpicker_rgb_g {\r
- background-image: url(../images/custom_rgb_g.png);\r
-}\r
-#colorpickerHolder2 .colorpicker_rgb_b {\r
- background-image: url(../images/custom_rgb_b.png);\r
-}\r
-#colorpickerHolder2 .colorpicker_hsb_s {\r
- background-image: url(../images/custom_hsb_s.png);\r
- display: none;\r
-}\r
-#colorpickerHolder2 .colorpicker_hsb_h {\r
- background-image: url(../images/custom_hsb_h.png);\r
- display: none;\r
-}\r
-#colorpickerHolder2 .colorpicker_hsb_b {\r
- background-image: url(../images/custom_hsb_b.png);\r
- display: none;\r
-}\r
-#colorpickerHolder2 .colorpicker_submit {\r
- background-image: url(../images/custom_submit.png);\r
-}\r
-#colorpickerHolder2 .colorpicker input {\r
- color: #778398;\r
-}\r
-#customWidget {\r
- position: relative;\r
- height: 36px;\r
-}\r
+body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td {
+ margin:0;
+ padding:0;
+}
+table {
+ border-collapse:collapse;
+ border-spacing:0;
+}
+fieldset,img {
+ border:0;
+}
+address,caption,cite,code,dfn,em,strong,th,var {
+ font-style:normal;
+ font-weight:normal;
+}
+ol,ul {
+ list-style:none;
+}
+caption,th {
+ text-align:left;
+}
+h1,h2,h3,h4,h5,h6 {
+ font-size:100%;
+ font-weight:normal;
+}
+q:before,q:after {
+ content:'';
+}
+abbr,acronym { border:0;
+}
+html, body {
+ background-color: #fff;
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 12px;
+ line-height: 18px;
+ color: #52697E;
+}
+body {
+ text-align: center;
+ overflow: auto;
+}
+.wrapper {
+ width: 700px;
+ margin: 0 auto;
+ text-align: left;
+}
+h1 {
+ font-size: 21px;
+ height: 47px;
+ line-height: 47px;
+ text-transform: uppercase;
+}
+.navigationTabs {
+ height: 23px;
+ line-height: 23px;
+ border-bottom: 1px solid #ccc;
+}
+.navigationTabs li {
+ float: left;
+ height: 23px;
+ line-height: 23px;
+ padding-right: 3px;
+}
+.navigationTabs li a{
+ float: left;
+ dispaly: block;
+ height: 23px;
+ line-height: 23px;
+ padding: 0 10px;
+ overflow: hidden;
+ color: #52697E;
+ background-color: #eee;
+ position: relative;
+ text-decoration: none;
+}
+.navigationTabs li a:hover {
+ background-color: #f0f0f0;
+}
+.navigationTabs li a.active {
+ background-color: #fff;
+ border: 1px solid #ccc;
+ border-bottom: 0px solid;
+}
+.tabsContent {
+ border: 1px solid #ccc;
+ border-top: 0px solid;
+ width: 698px;
+ overflow: hidden;
+}
+.tab {
+ padding: 16px;
+ display: none;
+}
+.tab h2 {
+ font-weight: bold;
+ font-size: 16px;
+}
+.tab h3 {
+ font-weight: bold;
+ font-size: 14px;
+ margin-top: 20px;
+}
+.tab p {
+ margin-top: 16px;
+ clear: both;
+}
+.tab ul {
+ margin-top: 16px;
+ list-style: disc;
+}
+.tab li {
+ margin: 10px 0 0 35px;
+}
+.tab a {
+ color: #8FB0CF;
+}
+.tab strong {
+ font-weight: bold;
+}
+.tab pre {
+ font-size: 11px;
+ margin-top: 20px;
+ width: 668px;
+ overflow: auto;
+ clear: both;
+}
+.tab table {
+ width: 100%;
+}
+.tab table td {
+ padding: 6px 10px 6px 0;
+ vertical-align: top;
+}
+.tab dt {
+ margin-top: 16px;
+}
+
+#colorSelector {
+ position: relative;
+ width: 36px;
+ height: 36px;
+ background: url(../images/select.png);
+}
+#colorSelector div {
+ position: absolute;
+ top: 3px;
+ left: 3px;
+ width: 30px;
+ height: 30px;
+ background: url(../images/select.png) center;
+}
+#colorSelector2 {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 36px;
+ height: 36px;
+ background: url(../images/select2.png);
+}
+#colorSelector2 div {
+ position: absolute;
+ top: 4px;
+ left: 4px;
+ width: 28px;
+ height: 28px;
+ background: url(../images/select2.png) center;
+}
+#colorpickerHolder2 {
+ top: 32px;
+ left: 0;
+ width: 356px;
+ height: 0;
+ overflow: hidden;
+ position: absolute;
+}
+#colorpickerHolder2 .colorpicker {
+ background-image: url(../images/custom_background.png);
+ position: absolute;
+ bottom: 0;
+ left: 0;
+}
+#colorpickerHolder2 .colorpicker_hue div {
+ background-image: url(../images/custom_indic.gif);
+}
+#colorpickerHolder2 .colorpicker_hex {
+ background-image: url(../images/custom_hex.png);
+}
+#colorpickerHolder2 .colorpicker_rgb_r {
+ background-image: url(../images/custom_rgb_r.png);
+}
+#colorpickerHolder2 .colorpicker_rgb_g {
+ background-image: url(../images/custom_rgb_g.png);
+}
+#colorpickerHolder2 .colorpicker_rgb_b {
+ background-image: url(../images/custom_rgb_b.png);
+}
+#colorpickerHolder2 .colorpicker_hsb_s {
+ background-image: url(../images/custom_hsb_s.png);
+ display: none;
+}
+#colorpickerHolder2 .colorpicker_hsb_h {
+ background-image: url(../images/custom_hsb_h.png);
+ display: none;
+}
+#colorpickerHolder2 .colorpicker_hsb_b {
+ background-image: url(../images/custom_hsb_b.png);
+ display: none;
+}
+#colorpickerHolder2 .colorpicker_submit {
+ background-image: url(../images/custom_submit.png);
+}
+#colorpickerHolder2 .colorpicker input {
+ color: #778398;
+}
+#customWidget {
+ position: relative;
+ height: 36px;
+}
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\r
-<head>\r
- <link rel="stylesheet" href="css/colorpicker.css" type="text/css" />\r
- <link rel="stylesheet" media="screen" type="text/css" href="css/layout.css" />\r
- <title>ColorPicker - jQuery plugin</title>\r
- <script type="text/javascript" src="js/jquery.js"></script>\r
- <script type="text/javascript" src="js/colorpicker.js"></script>\r
- <script type="text/javascript" src="js/eye.js"></script>\r
- <script type="text/javascript" src="js/utils.js"></script>\r
- <script type="text/javascript" src="js/layout.js?ver=1.0.2"></script>\r
-</head>\r
-<body>\r
- <div class="wrapper">\r
- <h1>Color Picker - jQuery plugin</h1>\r
- <ul class="navigationTabs">\r
- <li><a href="#about" rel="about">About</a></li>\r
- <li><a href="#download" rel="download">Download</a></li>\r
- <li><a href="#implement" rel="implement">Implement</a></li>\r
- </ul>\r
- <div class="tabsContent">\r
- <div class="tab">\r
- <h2>About</h2>\r
- <p>A simple component to select color in the same way you select color in Adobe Photoshop</p>\r
- <h3>Last update</h3>\r
- <p>23.05.2009 - Check Download tab</p>\r
- <h3>Features</h3>\r
- <ul>\r
- <li>Flat mode - as element in page</li>\r
- <li>Powerful controls for color selection</li>\r
- <li>Easy to customize the look by changing some images</li>\r
- <li>Fits into the viewport</li>\r
- </ul>\r
- <h3>License</h3>\r
- <p>Dual licensed under the MIT and GPL licenses.</p>\r
- <h3>Examples</h3>\r
- <p>Flat mode.</p>\r
- <p id="colorpickerHolder">\r
- </p>\r
- <pre>\r
-$('#colorpickerHolder').ColorPicker({flat: true});\r
- </pre>\r
- <p>Custom skin and using flat mode to display the color picker in a custom widget.</p>\r
- <div id="customWidget">\r
- <div id="colorSelector2"><div style="background-color: #00ff00"></div></div>\r
- <div id="colorpickerHolder2">\r
- </div>\r
- </div>\r
-\r
- <p>Attached to an text field and using callback functions to update the color with field's value and set the value back in the field by submiting the color.</p>\r
- <p><input type="text" maxlength="6" size="6" id="colorpickerField1" value="00ff00" /></p>\r
- <p><input type="text" maxlength="6" size="6" id="colorpickerField3" value="0000ff" /></p>\r
- <p><input type="text" maxlength="6" size="6" id="colorpickerField2" value="ff0000" /></p>\r
- <pre>$('#colorpickerField1, #colorpickerField2, #colorpickerField3').ColorPicker({\r
- onSubmit: function(hsb, hex, rgb, el) {\r
- $(el).val(hex);\r
- $(el).ColorPickerHide();\r
- },\r
- onBeforeShow: function () {\r
- $(this).ColorPickerSetColor(this.value);\r
- }\r
-})\r
-.bind('keyup', function(){\r
- $(this).ColorPickerSetColor(this.value);\r
-});\r
-</pre>\r
- <p>Attached to DOMElement and using callbacks to live preview the color and adding animation.</p>\r
- <p>\r
- <div id="colorSelector"><div style="background-color: #0000ff"></div></div>\r
- </p>\r
- <pre>\r
-$('#colorSelector').ColorPicker({\r
- color: '#0000ff',\r
- onShow: function (colpkr) {\r
- $(colpkr).fadeIn(500);\r
- return false;\r
- },\r
- onHide: function (colpkr) {\r
- $(colpkr).fadeOut(500);\r
- return false;\r
- },\r
- onChange: function (hsb, hex, rgb) {\r
- $('#colorSelector div').css('backgroundColor', '#' + hex);\r
- }\r
-});\r
-</pre>\r
- </div>\r
- <div class="tab">\r
- <h2>Download</h2>\r
- <p><a href="colorpicker.zip">colorpicker.zip (73 kb)</a>: jQuery, Javscript files, CSS files, images, examples and instructions.</p>\r
- <h3>Changelog</h3>\r
- <dl>\r
- <dt>23.05.2009</dt>\r
- <dd>Added: close on color selection example</dd>\r
- <dd>Added: restore original color option</dd>\r
- <dd>Changed: color update on key up event</dd>\r
- <dd>Fixed: colorpicker hide and show methods</dd>\r
- <dd>Fixed: reference to options. Multiple fields with colorpickers is possible now.</dd>\r
- <dd>Fixed: RGB to HSB convertion</dd>\r
- <dt>22.08.2008</dt>\r
- <dd>Fixed bug: where some events were not canceled right on Safari</dd>\r
- <dd>Fixed bug: where teh view port was not detected right on Safari</dd>\r
- <dt>16-07-2008</dt>\r
- <dd>Fixed bug where the letter 'F' could not be typed in the Hex field</dd>\r
- <dd>Fixed bug where the changes on Hex field where not parsed</dd>\r
- <dd>Added new option 'livePreview'</dd>\r
- <dt>08-07-2008</dt>\r
- <dd>Fixed typo in the code, both JavaScript and CSS</dd>\r
- <dd>Changed the cursor for some elements</dd>\r
- <dd>Added new demo explaining how to implement custom skin</dd>\r
- <dt>07.07.2008</dt>\r
- <dd>The first release.</dd>\r
- </dl>\r
- </div>\r
- <div class="tab">\r
- <h2>Implement</h2>\r
- <p>Attach the Javascript and CSS files to your document. Edit CSS file and fix the paths to images and change colors to fit your site theme.</p>\r
- <pre>\r
-<link rel="stylesheet" media="screen" type="text/css" href="css/colorpicker.css" />\r
-<script type="text/javascript" src="js/colorpicker.js"></script>\r
- </pre>\r
- <h3>Invocation code</h3>\r
- <p>All you have to do is to select the elements in a jQuery way and call the plugin.</p>\r
- <pre>\r
- $('input').ColorPicker(options);\r
- </pre>\r
- <h3>Options</h3>\r
- <p>A hash of parameters. All parameters are optional.</p>\r
- <table>\r
- <tr>\r
- <td><strong>eventName</strong></td>\r
- <td>string</td>\r
- <td>The desired event to trigger the colorpicker. Default: 'click'</td>\r
- </tr>\r
- <tr>\r
- <td><strong>color</strong></td>\r
- <td>string or hash</td>\r
- <td>The default color. String for hex color or hash for RGB and HSB ({r:255, r:0, b:0}) . Default: 'ff0000'</td>\r
- </tr>\r
- <tr>\r
- <td><strong>flat</strong></td>\r
- <td>boolean</td>\r
- <td>Whatever if the color picker is appended to the element or triggered by an event. Default false</td>\r
- </tr>\r
- <tr>\r
- <td><strong>livePreview</strong></td>\r
- <td>boolean</td>\r
- <td>Whatever if the color values are filled in the fields while changing values on selector or a field. If false it may improve speed. Default true</td>\r
- </tr>\r
- <tr>\r
- <td><strong>onShow</strong></td>\r
- <td>function</td>\r
- <td>Callback function triggered when the color picker is shown</td>\r
- </tr>\r
- <tr>\r
- <td><strong>onBeforeShow</strong></td>\r
- <td>function</td>\r
- <td>Callback function triggered before the color picker is shown</td>\r
- </tr>\r
- <tr>\r
- <td><strong>onHide</strong></td>\r
- <td>function</td>\r
- <td>Callback function triggered when the color picker is hidden</td>\r
- </tr>\r
- <tr>\r
- <td><strong>onChange</strong></td>\r
- <td>function</td>\r
- <td>Callback function triggered when the color is changed</td>\r
- </tr>\r
- <tr>\r
- <td><strong>onSubmit</strong></td>\r
- <td>function</td>\r
- <td>Callback function triggered when the color it is chosen</td>\r
- </tr>\r
- </table>\r
- <h3>Set color</h3>\r
- <p>If you want to set a new color.</p>\r
- <pre>$('input').ColorPickerSetColor(color);</pre>\r
- <p>The 'color' argument is the same format as the option color, string for hex color or hash for RGB and HSB ({r:255, r:0, b:0}).</p>\r
- </div>\r
- </div>\r
- </div>\r
-</body>\r
-</html>\r
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <link rel="stylesheet" href="css/colorpicker.css" type="text/css" />
+ <link rel="stylesheet" media="screen" type="text/css" href="css/layout.css" />
+ <title>ColorPicker - jQuery plugin</title>
+ <script type="text/javascript" src="js/jquery.js"></script>
+ <script type="text/javascript" src="js/colorpicker.js"></script>
+ <script type="text/javascript" src="js/eye.js"></script>
+ <script type="text/javascript" src="js/utils.js"></script>
+ <script type="text/javascript" src="js/layout.js?ver=1.0.2"></script>
+</head>
+<body>
+ <div class="wrapper">
+ <h1>Color Picker - jQuery plugin</h1>
+ <ul class="navigationTabs">
+ <li><a href="#about" rel="about">About</a></li>
+ <li><a href="#download" rel="download">Download</a></li>
+ <li><a href="#implement" rel="implement">Implement</a></li>
+ </ul>
+ <div class="tabsContent">
+ <div class="tab">
+ <h2>About</h2>
+ <p>A simple component to select color in the same way you select color in Adobe Photoshop</p>
+ <h3>Last update</h3>
+ <p>23.05.2009 - Check Download tab</p>
+ <h3>Features</h3>
+ <ul>
+ <li>Flat mode - as element in page</li>
+ <li>Powerful controls for color selection</li>
+ <li>Easy to customize the look by changing some images</li>
+ <li>Fits into the viewport</li>
+ </ul>
+ <h3>License</h3>
+ <p>Dual licensed under the MIT and GPL licenses.</p>
+ <h3>Examples</h3>
+ <p>Flat mode.</p>
+ <p id="colorpickerHolder">
+ </p>
+ <pre>
+$('#colorpickerHolder').ColorPicker({flat: true});
+ </pre>
+ <p>Custom skin and using flat mode to display the color picker in a custom widget.</p>
+ <div id="customWidget">
+ <div id="colorSelector2"><div style="background-color: #00ff00"></div></div>
+ <div id="colorpickerHolder2">
+ </div>
+ </div>
+
+ <p>Attached to an text field and using callback functions to update the color with field's value and set the value back in the field by submiting the color.</p>
+ <p><input type="text" maxlength="6" size="6" id="colorpickerField1" value="00ff00" /></p>
+ <p><input type="text" maxlength="6" size="6" id="colorpickerField3" value="0000ff" /></p>
+ <p><input type="text" maxlength="6" size="6" id="colorpickerField2" value="ff0000" /></p>
+ <pre>$('#colorpickerField1, #colorpickerField2, #colorpickerField3').ColorPicker({
+ onSubmit: function(hsb, hex, rgb, el) {
+ $(el).val(hex);
+ $(el).ColorPickerHide();
+ },
+ onBeforeShow: function () {
+ $(this).ColorPickerSetColor(this.value);
+ }
+})
+.bind('keyup', function(){
+ $(this).ColorPickerSetColor(this.value);
+});
+</pre>
+ <p>Attached to DOMElement and using callbacks to live preview the color and adding animation.</p>
+ <p>
+ <div id="colorSelector"><div style="background-color: #0000ff"></div></div>
+ </p>
+ <pre>
+$('#colorSelector').ColorPicker({
+ color: '#0000ff',
+ onShow: function (colpkr) {
+ $(colpkr).fadeIn(500);
+ return false;
+ },
+ onHide: function (colpkr) {
+ $(colpkr).fadeOut(500);
+ return false;
+ },
+ onChange: function (hsb, hex, rgb) {
+ $('#colorSelector div').css('backgroundColor', '#' + hex);
+ }
+});
+</pre>
+ </div>
+ <div class="tab">
+ <h2>Download</h2>
+ <p><a href="colorpicker.zip">colorpicker.zip (73 kb)</a>: jQuery, Javscript files, CSS files, images, examples and instructions.</p>
+ <h3>Changelog</h3>
+ <dl>
+ <dt>23.05.2009</dt>
+ <dd>Added: close on color selection example</dd>
+ <dd>Added: restore original color option</dd>
+ <dd>Changed: color update on key up event</dd>
+ <dd>Fixed: colorpicker hide and show methods</dd>
+ <dd>Fixed: reference to options. Multiple fields with colorpickers is possible now.</dd>
+ <dd>Fixed: RGB to HSB convertion</dd>
+ <dt>22.08.2008</dt>
+ <dd>Fixed bug: where some events were not canceled right on Safari</dd>
+ <dd>Fixed bug: where teh view port was not detected right on Safari</dd>
+ <dt>16-07-2008</dt>
+ <dd>Fixed bug where the letter 'F' could not be typed in the Hex field</dd>
+ <dd>Fixed bug where the changes on Hex field where not parsed</dd>
+ <dd>Added new option 'livePreview'</dd>
+ <dt>08-07-2008</dt>
+ <dd>Fixed typo in the code, both JavaScript and CSS</dd>
+ <dd>Changed the cursor for some elements</dd>
+ <dd>Added new demo explaining how to implement custom skin</dd>
+ <dt>07.07.2008</dt>
+ <dd>The first release.</dd>
+ </dl>
+ </div>
+ <div class="tab">
+ <h2>Implement</h2>
+ <p>Attach the Javascript and CSS files to your document. Edit CSS file and fix the paths to images and change colors to fit your site theme.</p>
+ <pre>
+<link rel="stylesheet" media="screen" type="text/css" href="css/colorpicker.css" />
+<script type="text/javascript" src="js/colorpicker.js"></script>
+ </pre>
+ <h3>Invocation code</h3>
+ <p>All you have to do is to select the elements in a jQuery way and call the plugin.</p>
+ <pre>
+ $('input').ColorPicker(options);
+ </pre>
+ <h3>Options</h3>
+ <p>A hash of parameters. All parameters are optional.</p>
+ <table>
+ <tr>
+ <td><strong>eventName</strong></td>
+ <td>string</td>
+ <td>The desired event to trigger the colorpicker. Default: 'click'</td>
+ </tr>
+ <tr>
+ <td><strong>color</strong></td>
+ <td>string or hash</td>
+ <td>The default color. String for hex color or hash for RGB and HSB ({r:255, r:0, b:0}) . Default: 'ff0000'</td>
+ </tr>
+ <tr>
+ <td><strong>flat</strong></td>
+ <td>boolean</td>
+ <td>Whatever if the color picker is appended to the element or triggered by an event. Default false</td>
+ </tr>
+ <tr>
+ <td><strong>livePreview</strong></td>
+ <td>boolean</td>
+ <td>Whatever if the color values are filled in the fields while changing values on selector or a field. If false it may improve speed. Default true</td>
+ </tr>
+ <tr>
+ <td><strong>onShow</strong></td>
+ <td>function</td>
+ <td>Callback function triggered when the color picker is shown</td>
+ </tr>
+ <tr>
+ <td><strong>onBeforeShow</strong></td>
+ <td>function</td>
+ <td>Callback function triggered before the color picker is shown</td>
+ </tr>
+ <tr>
+ <td><strong>onHide</strong></td>
+ <td>function</td>
+ <td>Callback function triggered when the color picker is hidden</td>
+ </tr>
+ <tr>
+ <td><strong>onChange</strong></td>
+ <td>function</td>
+ <td>Callback function triggered when the color is changed</td>
+ </tr>
+ <tr>
+ <td><strong>onSubmit</strong></td>
+ <td>function</td>
+ <td>Callback function triggered when the color it is chosen</td>
+ </tr>
+ </table>
+ <h3>Set color</h3>
+ <p>If you want to set a new color.</p>
+ <pre>$('input').ColorPickerSetColor(color);</pre>
+ <p>The 'color' argument is the same format as the option color, string for hex color or hash for RGB and HSB ({r:255, r:0, b:0}).</p>
+ </div>
+ </div>
+ </div>
+</body>
+</html>
-/**\r
- *\r
- * Color picker\r
- * Author: Stefan Petre www.eyecon.ro\r
- * \r
- * Dual licensed under the MIT and GPL licenses\r
- * \r
- */\r
-(function ($) {\r
- var ColorPicker = function () {\r
- var\r
- ids = {},\r
- inAction,\r
- charMin = 65,\r
- visible,\r
- tpl = '<div class="colorpicker"><div class="colorpicker_color"><div><div></div></div></div><div class="colorpicker_hue"><div></div></div><div class="colorpicker_new_color"></div><div class="colorpicker_current_color"></div><div class="colorpicker_hex"><input type="text" maxlength="6" size="6" /></div><div class="colorpicker_rgb_r colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_rgb_g colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_rgb_b colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_h colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_s colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_b colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_submit"></div></div>',\r
- defaults = {\r
- eventName: 'click',\r
- onShow: function () {},\r
- onBeforeShow: function(){},\r
- onHide: function () {},\r
- onChange: function () {},\r
- onSubmit: function () {},\r
- color: 'ff0000',\r
- livePreview: true,\r
- flat: false\r
- },\r
- fillRGBFields = function (hsb, cal) {\r
- var rgb = HSBToRGB(hsb);\r
- $(cal).data('colorpicker').fields\r
- .eq(1).val(rgb.r).end()\r
- .eq(2).val(rgb.g).end()\r
- .eq(3).val(rgb.b).end();\r
- },\r
- fillHSBFields = function (hsb, cal) {\r
- $(cal).data('colorpicker').fields\r
- .eq(4).val(hsb.h).end()\r
- .eq(5).val(hsb.s).end()\r
- .eq(6).val(hsb.b).end();\r
- },\r
- fillHexFields = function (hsb, cal) {\r
- $(cal).data('colorpicker').fields\r
- .eq(0).val(HSBToHex(hsb)).end();\r
- },\r
- setSelector = function (hsb, cal) {\r
- $(cal).data('colorpicker').selector.css('backgroundColor', '#' + HSBToHex({h: hsb.h, s: 100, b: 100}));\r
- $(cal).data('colorpicker').selectorIndic.css({\r
- left: parseInt(150 * hsb.s/100, 10),\r
- top: parseInt(150 * (100-hsb.b)/100, 10)\r
- });\r
- },\r
- setHue = function (hsb, cal) {\r
- $(cal).data('colorpicker').hue.css('top', parseInt(150 - 150 * hsb.h/360, 10));\r
- },\r
- setCurrentColor = function (hsb, cal) {\r
- $(cal).data('colorpicker').currentColor.css('backgroundColor', '#' + HSBToHex(hsb));\r
- },\r
- setNewColor = function (hsb, cal) {\r
- $(cal).data('colorpicker').newColor.css('backgroundColor', '#' + HSBToHex(hsb));\r
- },\r
- keyDown = function (ev) {\r
- var pressedKey = ev.charCode || ev.keyCode || -1;\r
- if ((pressedKey > charMin && pressedKey <= 90) || pressedKey == 32) {\r
- return false;\r
- }\r
- var cal = $(this).parent().parent();\r
- if (cal.data('colorpicker').livePreview === true) {\r
- change.apply(this);\r
- }\r
- },\r
- change = function (ev) {\r
- var cal = $(this).parent().parent(), col;\r
- if (this.parentNode.className.indexOf('_hex') > 0) {\r
- cal.data('colorpicker').color = col = HexToHSB(fixHex(this.value));\r
- } else if (this.parentNode.className.indexOf('_hsb') > 0) {\r
- cal.data('colorpicker').color = col = fixHSB({\r
- h: parseInt(cal.data('colorpicker').fields.eq(4).val(), 10),\r
- s: parseInt(cal.data('colorpicker').fields.eq(5).val(), 10),\r
- b: parseInt(cal.data('colorpicker').fields.eq(6).val(), 10)\r
- });\r
- } else {\r
- cal.data('colorpicker').color = col = RGBToHSB(fixRGB({\r
- r: parseInt(cal.data('colorpicker').fields.eq(1).val(), 10),\r
- g: parseInt(cal.data('colorpicker').fields.eq(2).val(), 10),\r
- b: parseInt(cal.data('colorpicker').fields.eq(3).val(), 10)\r
- }));\r
- }\r
- if (ev) {\r
- fillRGBFields(col, cal.get(0));\r
- fillHexFields(col, cal.get(0));\r
- fillHSBFields(col, cal.get(0));\r
- }\r
- setSelector(col, cal.get(0));\r
- setHue(col, cal.get(0));\r
- setNewColor(col, cal.get(0));\r
- cal.data('colorpicker').onChange.apply(cal, [col, HSBToHex(col), HSBToRGB(col)]);\r
- },\r
- blur = function (ev) {\r
- var cal = $(this).parent().parent();\r
- cal.data('colorpicker').fields.parent().removeClass('colorpicker_focus');\r
- },\r
- focus = function () {\r
- charMin = this.parentNode.className.indexOf('_hex') > 0 ? 70 : 65;\r
- $(this).parent().parent().data('colorpicker').fields.parent().removeClass('colorpicker_focus');\r
- $(this).parent().addClass('colorpicker_focus');\r
- },\r
- downIncrement = function (ev) {\r
- var field = $(this).parent().find('input').focus();\r
- var current = {\r
- el: $(this).parent().addClass('colorpicker_slider'),\r
- max: this.parentNode.className.indexOf('_hsb_h') > 0 ? 360 : (this.parentNode.className.indexOf('_hsb') > 0 ? 100 : 255),\r
- y: ev.pageY,\r
- field: field,\r
- val: parseInt(field.val(), 10),\r
- preview: $(this).parent().parent().data('colorpicker').livePreview \r
- };\r
- $(document).bind('mouseup', current, upIncrement);\r
- $(document).bind('mousemove', current, moveIncrement);\r
- },\r
- moveIncrement = function (ev) {\r
- ev.data.field.val(Math.max(0, Math.min(ev.data.max, parseInt(ev.data.val + ev.pageY - ev.data.y, 10))));\r
- if (ev.data.preview) {\r
- change.apply(ev.data.field.get(0), [true]);\r
- }\r
- return false;\r
- },\r
- upIncrement = function (ev) {\r
- change.apply(ev.data.field.get(0), [true]);\r
- ev.data.el.removeClass('colorpicker_slider').find('input').focus();\r
- $(document).unbind('mouseup', upIncrement);\r
- $(document).unbind('mousemove', moveIncrement);\r
- return false;\r
- },\r
- downHue = function (ev) {\r
- var current = {\r
- cal: $(this).parent(),\r
- y: $(this).offset().top\r
- };\r
- current.preview = current.cal.data('colorpicker').livePreview;\r
- $(document).bind('mouseup', current, upHue);\r
- $(document).bind('mousemove', current, moveHue);\r
- },\r
- moveHue = function (ev) {\r
- change.apply(\r
- ev.data.cal.data('colorpicker')\r
- .fields\r
- .eq(4)\r
- .val(parseInt(360*(150 - Math.max(0,Math.min(150,(ev.pageY - ev.data.y))))/150, 10))\r
- .get(0),\r
- [ev.data.preview]\r
- );\r
- return false;\r
- },\r
- upHue = function (ev) {\r
- fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));\r
- fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));\r
- $(document).unbind('mouseup', upHue);\r
- $(document).unbind('mousemove', moveHue);\r
- return false;\r
- },\r
- downSelector = function (ev) {\r
- var current = {\r
- cal: $(this).parent(),\r
- pos: $(this).offset()\r
- };\r
- current.preview = current.cal.data('colorpicker').livePreview;\r
- $(document).bind('mouseup', current, upSelector);\r
- $(document).bind('mousemove', current, moveSelector);\r
- },\r
- moveSelector = function (ev) {\r
- change.apply(\r
- ev.data.cal.data('colorpicker')\r
- .fields\r
- .eq(6)\r
- .val(parseInt(100*(150 - Math.max(0,Math.min(150,(ev.pageY - ev.data.pos.top))))/150, 10))\r
- .end()\r
- .eq(5)\r
- .val(parseInt(100*(Math.max(0,Math.min(150,(ev.pageX - ev.data.pos.left))))/150, 10))\r
- .get(0),\r
- [ev.data.preview]\r
- );\r
- return false;\r
- },\r
- upSelector = function (ev) {\r
- fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));\r
- fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));\r
- $(document).unbind('mouseup', upSelector);\r
- $(document).unbind('mousemove', moveSelector);\r
- return false;\r
- },\r
- enterSubmit = function (ev) {\r
- $(this).addClass('colorpicker_focus');\r
- },\r
- leaveSubmit = function (ev) {\r
- $(this).removeClass('colorpicker_focus');\r
- },\r
- clickSubmit = function (ev) {\r
- var cal = $(this).parent();\r
- var col = cal.data('colorpicker').color;\r
- cal.data('colorpicker').origColor = col;\r
- setCurrentColor(col, cal.get(0));\r
- cal.data('colorpicker').onSubmit(col, HSBToHex(col), HSBToRGB(col), cal.data('colorpicker').el);\r
- },\r
- show = function (ev) {\r
- var cal = $('#' + $(this).data('colorpickerId'));\r
- cal.data('colorpicker').onBeforeShow.apply(this, [cal.get(0)]);\r
- var pos = $(this).offset();\r
- var viewPort = getViewport();\r
- var top = pos.top + this.offsetHeight;\r
- var left = pos.left;\r
- if (top + 176 > viewPort.t + viewPort.h) {\r
- top -= this.offsetHeight + 176;\r
- }\r
- if (left + 356 > viewPort.l + viewPort.w) {\r
- left -= 356;\r
- }\r
- cal.css({left: left + 'px', top: top + 'px'});\r
- if (cal.data('colorpicker').onShow.apply(this, [cal.get(0)]) != false) {\r
- cal.show();\r
- }\r
- $(document).bind('mousedown', {cal: cal}, hide);\r
- return false;\r
- },\r
- hide = function (ev) {\r
- if (!isChildOf(ev.data.cal.get(0), ev.target, ev.data.cal.get(0))) {\r
- if (ev.data.cal.data('colorpicker').onHide.apply(this, [ev.data.cal.get(0)]) != false) {\r
- ev.data.cal.hide();\r
- }\r
- $(document).unbind('mousedown', hide);\r
- }\r
- },\r
- isChildOf = function(parentEl, el, container) {\r
- if (parentEl == el) {\r
- return true;\r
- }\r
- if (parentEl.contains) {\r
- return parentEl.contains(el);\r
- }\r
- if ( parentEl.compareDocumentPosition ) {\r
- return !!(parentEl.compareDocumentPosition(el) & 16);\r
- }\r
- var prEl = el.parentNode;\r
- while(prEl && prEl != container) {\r
- if (prEl == parentEl)\r
- return true;\r
- prEl = prEl.parentNode;\r
- }\r
- return false;\r
- },\r
- getViewport = function () {\r
- var m = document.compatMode == 'CSS1Compat';\r
- return {\r
- l : window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft),\r
- t : window.pageYOffset || (m ? document.documentElement.scrollTop : document.body.scrollTop),\r
- w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth),\r
- h : window.innerHeight || (m ? document.documentElement.clientHeight : document.body.clientHeight)\r
- };\r
- },\r
- fixHSB = function (hsb) {\r
- return {\r
- h: Math.min(360, Math.max(0, hsb.h)),\r
- s: Math.min(100, Math.max(0, hsb.s)),\r
- b: Math.min(100, Math.max(0, hsb.b))\r
- };\r
- }, \r
- fixRGB = function (rgb) {\r
- return {\r
- r: Math.min(255, Math.max(0, rgb.r)),\r
- g: Math.min(255, Math.max(0, rgb.g)),\r
- b: Math.min(255, Math.max(0, rgb.b))\r
- };\r
- },\r
- fixHex = function (hex) {\r
- var len = 6 - hex.length;\r
- if (len > 0) {\r
- var o = [];\r
- for (var i=0; i<len; i++) {\r
- o.push('0');\r
- }\r
- o.push(hex);\r
- hex = o.join('');\r
- }\r
- return hex;\r
- }, \r
- HexToRGB = function (hex) {\r
- var hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);\r
- return {r: hex >> 16, g: (hex & 0x00FF00) >> 8, b: (hex & 0x0000FF)};\r
- },\r
- HexToHSB = function (hex) {\r
- return RGBToHSB(HexToRGB(hex));\r
- },\r
- RGBToHSB = function (rgb) {\r
- var hsb = {\r
- h: 0,\r
- s: 0,\r
- b: 0\r
- };\r
- var min = Math.min(rgb.r, rgb.g, rgb.b);\r
- var max = Math.max(rgb.r, rgb.g, rgb.b);\r
- var delta = max - min;\r
- hsb.b = max;\r
- if (max != 0) {\r
- \r
- }\r
- hsb.s = max != 0 ? 255 * delta / max : 0;\r
- if (hsb.s != 0) {\r
- if (rgb.r == max) {\r
- hsb.h = (rgb.g - rgb.b) / delta;\r
- } else if (rgb.g == max) {\r
- hsb.h = 2 + (rgb.b - rgb.r) / delta;\r
- } else {\r
- hsb.h = 4 + (rgb.r - rgb.g) / delta;\r
- }\r
- } else {\r
- hsb.h = -1;\r
- }\r
- hsb.h *= 60;\r
- if (hsb.h < 0) {\r
- hsb.h += 360;\r
- }\r
- hsb.s *= 100/255;\r
- hsb.b *= 100/255;\r
- return hsb;\r
- },\r
- HSBToRGB = function (hsb) {\r
- var rgb = {};\r
- var h = Math.round(hsb.h);\r
- var s = Math.round(hsb.s*255/100);\r
- var v = Math.round(hsb.b*255/100);\r
- if(s == 0) {\r
- rgb.r = rgb.g = rgb.b = v;\r
- } else {\r
- var t1 = v;\r
- var t2 = (255-s)*v/255;\r
- var t3 = (t1-t2)*(h%60)/60;\r
- if(h==360) h = 0;\r
- if(h<60) {rgb.r=t1; rgb.b=t2; rgb.g=t2+t3}\r
- else if(h<120) {rgb.g=t1; rgb.b=t2; rgb.r=t1-t3}\r
- else if(h<180) {rgb.g=t1; rgb.r=t2; rgb.b=t2+t3}\r
- else if(h<240) {rgb.b=t1; rgb.r=t2; rgb.g=t1-t3}\r
- else if(h<300) {rgb.b=t1; rgb.g=t2; rgb.r=t2+t3}\r
- else if(h<360) {rgb.r=t1; rgb.g=t2; rgb.b=t1-t3}\r
- else {rgb.r=0; rgb.g=0; rgb.b=0}\r
- }\r
- return {r:Math.round(rgb.r), g:Math.round(rgb.g), b:Math.round(rgb.b)};\r
- },\r
- RGBToHex = function (rgb) {\r
- var hex = [\r
- rgb.r.toString(16),\r
- rgb.g.toString(16),\r
- rgb.b.toString(16)\r
- ];\r
- $.each(hex, function (nr, val) {\r
- if (val.length == 1) {\r
- hex[nr] = '0' + val;\r
- }\r
- });\r
- return hex.join('');\r
- },\r
- HSBToHex = function (hsb) {\r
- return RGBToHex(HSBToRGB(hsb));\r
- },\r
- restoreOriginal = function () {\r
- var cal = $(this).parent();\r
- var col = cal.data('colorpicker').origColor;\r
- cal.data('colorpicker').color = col;\r
- fillRGBFields(col, cal.get(0));\r
- fillHexFields(col, cal.get(0));\r
- fillHSBFields(col, cal.get(0));\r
- setSelector(col, cal.get(0));\r
- setHue(col, cal.get(0));\r
- setNewColor(col, cal.get(0));\r
- };\r
- return {\r
- init: function (opt) {\r
- opt = $.extend({}, defaults, opt||{});\r
- if (typeof opt.color == 'string') {\r
- opt.color = HexToHSB(opt.color);\r
- } else if (opt.color.r != undefined && opt.color.g != undefined && opt.color.b != undefined) {\r
- opt.color = RGBToHSB(opt.color);\r
- } else if (opt.color.h != undefined && opt.color.s != undefined && opt.color.b != undefined) {\r
- opt.color = fixHSB(opt.color);\r
- } else {\r
- return this;\r
- }\r
- return this.each(function () {\r
- if (!$(this).data('colorpickerId')) {\r
- var options = $.extend({}, opt);\r
- options.origColor = opt.color;\r
- var id = 'collorpicker_' + parseInt(Math.random() * 1000);\r
- $(this).data('colorpickerId', id);\r
- var cal = $(tpl).attr('id', id);\r
- if (options.flat) {\r
- cal.appendTo(this).show();\r
- } else {\r
- cal.appendTo(document.body);\r
- }\r
- options.fields = cal\r
- .find('input')\r
- .bind('keyup', keyDown)\r
- .bind('change', change)\r
- .bind('blur', blur)\r
- .bind('focus', focus);\r
- cal\r
- .find('span').bind('mousedown', downIncrement).end()\r
- .find('>div.colorpicker_current_color').bind('click', restoreOriginal);\r
- options.selector = cal.find('div.colorpicker_color').bind('mousedown', downSelector);\r
- options.selectorIndic = options.selector.find('div div');\r
- options.el = this;\r
- options.hue = cal.find('div.colorpicker_hue div');\r
- cal.find('div.colorpicker_hue').bind('mousedown', downHue);\r
- options.newColor = cal.find('div.colorpicker_new_color');\r
- options.currentColor = cal.find('div.colorpicker_current_color');\r
- cal.data('colorpicker', options);\r
- cal.find('div.colorpicker_submit')\r
- .bind('mouseenter', enterSubmit)\r
- .bind('mouseleave', leaveSubmit)\r
- .bind('click', clickSubmit);\r
- fillRGBFields(options.color, cal.get(0));\r
- fillHSBFields(options.color, cal.get(0));\r
- fillHexFields(options.color, cal.get(0));\r
- setHue(options.color, cal.get(0));\r
- setSelector(options.color, cal.get(0));\r
- setCurrentColor(options.color, cal.get(0));\r
- setNewColor(options.color, cal.get(0));\r
- if (options.flat) {\r
- cal.css({\r
- position: 'relative',\r
- display: 'block'\r
- });\r
- } else {\r
- $(this).bind(options.eventName, show);\r
- }\r
- }\r
- });\r
- },\r
- showPicker: function() {\r
- return this.each( function () {\r
- if ($(this).data('colorpickerId')) {\r
- show.apply(this);\r
- }\r
- });\r
- },\r
- hidePicker: function() {\r
- return this.each( function () {\r
- if ($(this).data('colorpickerId')) {\r
- $('#' + $(this).data('colorpickerId')).hide();\r
- }\r
- });\r
- },\r
- setColor: function(col) {\r
- if (typeof col == 'string') {\r
- col = HexToHSB(col);\r
- } else if (col.r != undefined && col.g != undefined && col.b != undefined) {\r
- col = RGBToHSB(col);\r
- } else if (col.h != undefined && col.s != undefined && col.b != undefined) {\r
- col = fixHSB(col);\r
- } else {\r
- return this;\r
- }\r
- return this.each(function(){\r
- if ($(this).data('colorpickerId')) {\r
- var cal = $('#' + $(this).data('colorpickerId'));\r
- cal.data('colorpicker').color = col;\r
- cal.data('colorpicker').origColor = col;\r
- fillRGBFields(col, cal.get(0));\r
- fillHSBFields(col, cal.get(0));\r
- fillHexFields(col, cal.get(0));\r
- setHue(col, cal.get(0));\r
- setSelector(col, cal.get(0));\r
- setCurrentColor(col, cal.get(0));\r
- setNewColor(col, cal.get(0));\r
- }\r
- });\r
- }\r
- };\r
- }();\r
- $.fn.extend({\r
- ColorPicker: ColorPicker.init,\r
- ColorPickerHide: ColorPicker.hidePicker,\r
- ColorPickerShow: ColorPicker.showPicker,\r
- ColorPickerSetColor: ColorPicker.setColor\r
- });\r
+/**
+ *
+ * Color picker
+ * Author: Stefan Petre www.eyecon.ro
+ *
+ * Dual licensed under the MIT and GPL licenses
+ *
+ */
+(function ($) {
+ var ColorPicker = function () {
+ var
+ ids = {},
+ inAction,
+ charMin = 65,
+ visible,
+ tpl = '<div class="colorpicker"><div class="colorpicker_color"><div><div></div></div></div><div class="colorpicker_hue"><div></div></div><div class="colorpicker_new_color"></div><div class="colorpicker_current_color"></div><div class="colorpicker_hex"><input type="text" maxlength="6" size="6" /></div><div class="colorpicker_rgb_r colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_rgb_g colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_rgb_b colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_h colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_s colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_hsb_b colorpicker_field"><input type="text" maxlength="3" size="3" /><span></span></div><div class="colorpicker_submit"></div></div>',
+ defaults = {
+ eventName: 'click',
+ onShow: function () {},
+ onBeforeShow: function(){},
+ onHide: function () {},
+ onChange: function () {},
+ onSubmit: function () {},
+ color: 'ff0000',
+ livePreview: true,
+ flat: false
+ },
+ fillRGBFields = function (hsb, cal) {
+ var rgb = HSBToRGB(hsb);
+ $(cal).data('colorpicker').fields
+ .eq(1).val(rgb.r).end()
+ .eq(2).val(rgb.g).end()
+ .eq(3).val(rgb.b).end();
+ },
+ fillHSBFields = function (hsb, cal) {
+ $(cal).data('colorpicker').fields
+ .eq(4).val(hsb.h).end()
+ .eq(5).val(hsb.s).end()
+ .eq(6).val(hsb.b).end();
+ },
+ fillHexFields = function (hsb, cal) {
+ $(cal).data('colorpicker').fields
+ .eq(0).val(HSBToHex(hsb)).end();
+ },
+ setSelector = function (hsb, cal) {
+ $(cal).data('colorpicker').selector.css('backgroundColor', '#' + HSBToHex({h: hsb.h, s: 100, b: 100}));
+ $(cal).data('colorpicker').selectorIndic.css({
+ left: parseInt(150 * hsb.s/100, 10),
+ top: parseInt(150 * (100-hsb.b)/100, 10)
+ });
+ },
+ setHue = function (hsb, cal) {
+ $(cal).data('colorpicker').hue.css('top', parseInt(150 - 150 * hsb.h/360, 10));
+ },
+ setCurrentColor = function (hsb, cal) {
+ $(cal).data('colorpicker').currentColor.css('backgroundColor', '#' + HSBToHex(hsb));
+ },
+ setNewColor = function (hsb, cal) {
+ $(cal).data('colorpicker').newColor.css('backgroundColor', '#' + HSBToHex(hsb));
+ },
+ keyDown = function (ev) {
+ var pressedKey = ev.charCode || ev.keyCode || -1;
+ if ((pressedKey > charMin && pressedKey <= 90) || pressedKey == 32) {
+ return false;
+ }
+ var cal = $(this).parent().parent();
+ if (cal.data('colorpicker').livePreview === true) {
+ change.apply(this);
+ }
+ },
+ change = function (ev) {
+ var cal = $(this).parent().parent(), col;
+ if (this.parentNode.className.indexOf('_hex') > 0) {
+ cal.data('colorpicker').color = col = HexToHSB(fixHex(this.value));
+ } else if (this.parentNode.className.indexOf('_hsb') > 0) {
+ cal.data('colorpicker').color = col = fixHSB({
+ h: parseInt(cal.data('colorpicker').fields.eq(4).val(), 10),
+ s: parseInt(cal.data('colorpicker').fields.eq(5).val(), 10),
+ b: parseInt(cal.data('colorpicker').fields.eq(6).val(), 10)
+ });
+ } else {
+ cal.data('colorpicker').color = col = RGBToHSB(fixRGB({
+ r: parseInt(cal.data('colorpicker').fields.eq(1).val(), 10),
+ g: parseInt(cal.data('colorpicker').fields.eq(2).val(), 10),
+ b: parseInt(cal.data('colorpicker').fields.eq(3).val(), 10)
+ }));
+ }
+ if (ev) {
+ fillRGBFields(col, cal.get(0));
+ fillHexFields(col, cal.get(0));
+ fillHSBFields(col, cal.get(0));
+ }
+ setSelector(col, cal.get(0));
+ setHue(col, cal.get(0));
+ setNewColor(col, cal.get(0));
+ cal.data('colorpicker').onChange.apply(cal, [col, HSBToHex(col), HSBToRGB(col)]);
+ },
+ blur = function (ev) {
+ var cal = $(this).parent().parent();
+ cal.data('colorpicker').fields.parent().removeClass('colorpicker_focus');
+ },
+ focus = function () {
+ charMin = this.parentNode.className.indexOf('_hex') > 0 ? 70 : 65;
+ $(this).parent().parent().data('colorpicker').fields.parent().removeClass('colorpicker_focus');
+ $(this).parent().addClass('colorpicker_focus');
+ },
+ downIncrement = function (ev) {
+ var field = $(this).parent().find('input').focus();
+ var current = {
+ el: $(this).parent().addClass('colorpicker_slider'),
+ max: this.parentNode.className.indexOf('_hsb_h') > 0 ? 360 : (this.parentNode.className.indexOf('_hsb') > 0 ? 100 : 255),
+ y: ev.pageY,
+ field: field,
+ val: parseInt(field.val(), 10),
+ preview: $(this).parent().parent().data('colorpicker').livePreview
+ };
+ $(document).bind('mouseup', current, upIncrement);
+ $(document).bind('mousemove', current, moveIncrement);
+ },
+ moveIncrement = function (ev) {
+ ev.data.field.val(Math.max(0, Math.min(ev.data.max, parseInt(ev.data.val + ev.pageY - ev.data.y, 10))));
+ if (ev.data.preview) {
+ change.apply(ev.data.field.get(0), [true]);
+ }
+ return false;
+ },
+ upIncrement = function (ev) {
+ change.apply(ev.data.field.get(0), [true]);
+ ev.data.el.removeClass('colorpicker_slider').find('input').focus();
+ $(document).unbind('mouseup', upIncrement);
+ $(document).unbind('mousemove', moveIncrement);
+ return false;
+ },
+ downHue = function (ev) {
+ var current = {
+ cal: $(this).parent(),
+ y: $(this).offset().top
+ };
+ current.preview = current.cal.data('colorpicker').livePreview;
+ $(document).bind('mouseup', current, upHue);
+ $(document).bind('mousemove', current, moveHue);
+ },
+ moveHue = function (ev) {
+ change.apply(
+ ev.data.cal.data('colorpicker')
+ .fields
+ .eq(4)
+ .val(parseInt(360*(150 - Math.max(0,Math.min(150,(ev.pageY - ev.data.y))))/150, 10))
+ .get(0),
+ [ev.data.preview]
+ );
+ return false;
+ },
+ upHue = function (ev) {
+ fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
+ fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
+ $(document).unbind('mouseup', upHue);
+ $(document).unbind('mousemove', moveHue);
+ return false;
+ },
+ downSelector = function (ev) {
+ var current = {
+ cal: $(this).parent(),
+ pos: $(this).offset()
+ };
+ current.preview = current.cal.data('colorpicker').livePreview;
+ $(document).bind('mouseup', current, upSelector);
+ $(document).bind('mousemove', current, moveSelector);
+ },
+ moveSelector = function (ev) {
+ change.apply(
+ ev.data.cal.data('colorpicker')
+ .fields
+ .eq(6)
+ .val(parseInt(100*(150 - Math.max(0,Math.min(150,(ev.pageY - ev.data.pos.top))))/150, 10))
+ .end()
+ .eq(5)
+ .val(parseInt(100*(Math.max(0,Math.min(150,(ev.pageX - ev.data.pos.left))))/150, 10))
+ .get(0),
+ [ev.data.preview]
+ );
+ return false;
+ },
+ upSelector = function (ev) {
+ fillRGBFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
+ fillHexFields(ev.data.cal.data('colorpicker').color, ev.data.cal.get(0));
+ $(document).unbind('mouseup', upSelector);
+ $(document).unbind('mousemove', moveSelector);
+ return false;
+ },
+ enterSubmit = function (ev) {
+ $(this).addClass('colorpicker_focus');
+ },
+ leaveSubmit = function (ev) {
+ $(this).removeClass('colorpicker_focus');
+ },
+ clickSubmit = function (ev) {
+ var cal = $(this).parent();
+ var col = cal.data('colorpicker').color;
+ cal.data('colorpicker').origColor = col;
+ setCurrentColor(col, cal.get(0));
+ cal.data('colorpicker').onSubmit(col, HSBToHex(col), HSBToRGB(col), cal.data('colorpicker').el);
+ },
+ show = function (ev) {
+ var cal = $('#' + $(this).data('colorpickerId'));
+ cal.data('colorpicker').onBeforeShow.apply(this, [cal.get(0)]);
+ var pos = $(this).offset();
+ var viewPort = getViewport();
+ var top = pos.top + this.offsetHeight;
+ var left = pos.left;
+ if (top + 176 > viewPort.t + viewPort.h) {
+ top -= this.offsetHeight + 176;
+ }
+ if (left + 356 > viewPort.l + viewPort.w) {
+ left -= 356;
+ }
+ cal.css({left: left + 'px', top: top + 'px'});
+ if (cal.data('colorpicker').onShow.apply(this, [cal.get(0)]) != false) {
+ cal.show();
+ }
+ $(document).bind('mousedown', {cal: cal}, hide);
+ return false;
+ },
+ hide = function (ev) {
+ if (!isChildOf(ev.data.cal.get(0), ev.target, ev.data.cal.get(0))) {
+ if (ev.data.cal.data('colorpicker').onHide.apply(this, [ev.data.cal.get(0)]) != false) {
+ ev.data.cal.hide();
+ }
+ $(document).unbind('mousedown', hide);
+ }
+ },
+ isChildOf = function(parentEl, el, container) {
+ if (parentEl == el) {
+ return true;
+ }
+ if (parentEl.contains) {
+ return parentEl.contains(el);
+ }
+ if ( parentEl.compareDocumentPosition ) {
+ return !!(parentEl.compareDocumentPosition(el) & 16);
+ }
+ var prEl = el.parentNode;
+ while(prEl && prEl != container) {
+ if (prEl == parentEl)
+ return true;
+ prEl = prEl.parentNode;
+ }
+ return false;
+ },
+ getViewport = function () {
+ var m = document.compatMode == 'CSS1Compat';
+ return {
+ l : window.pageXOffset || (m ? document.documentElement.scrollLeft : document.body.scrollLeft),
+ t : window.pageYOffset || (m ? document.documentElement.scrollTop : document.body.scrollTop),
+ w : window.innerWidth || (m ? document.documentElement.clientWidth : document.body.clientWidth),
+ h : window.innerHeight || (m ? document.documentElement.clientHeight : document.body.clientHeight)
+ };
+ },
+ fixHSB = function (hsb) {
+ return {
+ h: Math.min(360, Math.max(0, hsb.h)),
+ s: Math.min(100, Math.max(0, hsb.s)),
+ b: Math.min(100, Math.max(0, hsb.b))
+ };
+ },
+ fixRGB = function (rgb) {
+ return {
+ r: Math.min(255, Math.max(0, rgb.r)),
+ g: Math.min(255, Math.max(0, rgb.g)),
+ b: Math.min(255, Math.max(0, rgb.b))
+ };
+ },
+ fixHex = function (hex) {
+ var len = 6 - hex.length;
+ if (len > 0) {
+ var o = [];
+ for (var i=0; i<len; i++) {
+ o.push('0');
+ }
+ o.push(hex);
+ hex = o.join('');
+ }
+ return hex;
+ },
+ HexToRGB = function (hex) {
+ var hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);
+ return {r: hex >> 16, g: (hex & 0x00FF00) >> 8, b: (hex & 0x0000FF)};
+ },
+ HexToHSB = function (hex) {
+ return RGBToHSB(HexToRGB(hex));
+ },
+ RGBToHSB = function (rgb) {
+ var hsb = {
+ h: 0,
+ s: 0,
+ b: 0
+ };
+ var min = Math.min(rgb.r, rgb.g, rgb.b);
+ var max = Math.max(rgb.r, rgb.g, rgb.b);
+ var delta = max - min;
+ hsb.b = max;
+ if (max != 0) {
+
+ }
+ hsb.s = max != 0 ? 255 * delta / max : 0;
+ if (hsb.s != 0) {
+ if (rgb.r == max) {
+ hsb.h = (rgb.g - rgb.b) / delta;
+ } else if (rgb.g == max) {
+ hsb.h = 2 + (rgb.b - rgb.r) / delta;
+ } else {
+ hsb.h = 4 + (rgb.r - rgb.g) / delta;
+ }
+ } else {
+ hsb.h = -1;
+ }
+ hsb.h *= 60;
+ if (hsb.h < 0) {
+ hsb.h += 360;
+ }
+ hsb.s *= 100/255;
+ hsb.b *= 100/255;
+ return hsb;
+ },
+ HSBToRGB = function (hsb) {
+ var rgb = {};
+ var h = Math.round(hsb.h);
+ var s = Math.round(hsb.s*255/100);
+ var v = Math.round(hsb.b*255/100);
+ if(s == 0) {
+ rgb.r = rgb.g = rgb.b = v;
+ } else {
+ var t1 = v;
+ var t2 = (255-s)*v/255;
+ var t3 = (t1-t2)*(h%60)/60;
+ if(h==360) h = 0;
+ if(h<60) {rgb.r=t1; rgb.b=t2; rgb.g=t2+t3}
+ else if(h<120) {rgb.g=t1; rgb.b=t2; rgb.r=t1-t3}
+ else if(h<180) {rgb.g=t1; rgb.r=t2; rgb.b=t2+t3}
+ else if(h<240) {rgb.b=t1; rgb.r=t2; rgb.g=t1-t3}
+ else if(h<300) {rgb.b=t1; rgb.g=t2; rgb.r=t2+t3}
+ else if(h<360) {rgb.r=t1; rgb.g=t2; rgb.b=t1-t3}
+ else {rgb.r=0; rgb.g=0; rgb.b=0}
+ }
+ return {r:Math.round(rgb.r), g:Math.round(rgb.g), b:Math.round(rgb.b)};
+ },
+ RGBToHex = function (rgb) {
+ var hex = [
+ rgb.r.toString(16),
+ rgb.g.toString(16),
+ rgb.b.toString(16)
+ ];
+ $.each(hex, function (nr, val) {
+ if (val.length == 1) {
+ hex[nr] = '0' + val;
+ }
+ });
+ return hex.join('');
+ },
+ HSBToHex = function (hsb) {
+ return RGBToHex(HSBToRGB(hsb));
+ },
+ restoreOriginal = function () {
+ var cal = $(this).parent();
+ var col = cal.data('colorpicker').origColor;
+ cal.data('colorpicker').color = col;
+ fillRGBFields(col, cal.get(0));
+ fillHexFields(col, cal.get(0));
+ fillHSBFields(col, cal.get(0));
+ setSelector(col, cal.get(0));
+ setHue(col, cal.get(0));
+ setNewColor(col, cal.get(0));
+ };
+ return {
+ init: function (opt) {
+ opt = $.extend({}, defaults, opt||{});
+ if (typeof opt.color == 'string') {
+ opt.color = HexToHSB(opt.color);
+ } else if (opt.color.r != undefined && opt.color.g != undefined && opt.color.b != undefined) {
+ opt.color = RGBToHSB(opt.color);
+ } else if (opt.color.h != undefined && opt.color.s != undefined && opt.color.b != undefined) {
+ opt.color = fixHSB(opt.color);
+ } else {
+ return this;
+ }
+ return this.each(function () {
+ if (!$(this).data('colorpickerId')) {
+ var options = $.extend({}, opt);
+ options.origColor = opt.color;
+ var id = 'collorpicker_' + parseInt(Math.random() * 1000);
+ $(this).data('colorpickerId', id);
+ var cal = $(tpl).attr('id', id);
+ if (options.flat) {
+ cal.appendTo(this).show();
+ } else {
+ cal.appendTo(document.body);
+ }
+ options.fields = cal
+ .find('input')
+ .bind('keyup', keyDown)
+ .bind('change', change)
+ .bind('blur', blur)
+ .bind('focus', focus);
+ cal
+ .find('span').bind('mousedown', downIncrement).end()
+ .find('>div.colorpicker_current_color').bind('click', restoreOriginal);
+ options.selector = cal.find('div.colorpicker_color').bind('mousedown', downSelector);
+ options.selectorIndic = options.selector.find('div div');
+ options.el = this;
+ options.hue = cal.find('div.colorpicker_hue div');
+ cal.find('div.colorpicker_hue').bind('mousedown', downHue);
+ options.newColor = cal.find('div.colorpicker_new_color');
+ options.currentColor = cal.find('div.colorpicker_current_color');
+ cal.data('colorpicker', options);
+ cal.find('div.colorpicker_submit')
+ .bind('mouseenter', enterSubmit)
+ .bind('mouseleave', leaveSubmit)
+ .bind('click', clickSubmit);
+ fillRGBFields(options.color, cal.get(0));
+ fillHSBFields(options.color, cal.get(0));
+ fillHexFields(options.color, cal.get(0));
+ setHue(options.color, cal.get(0));
+ setSelector(options.color, cal.get(0));
+ setCurrentColor(options.color, cal.get(0));
+ setNewColor(options.color, cal.get(0));
+ if (options.flat) {
+ cal.css({
+ position: 'relative',
+ display: 'block'
+ });
+ } else {
+ $(this).bind(options.eventName, show);
+ }
+ }
+ });
+ },
+ showPicker: function() {
+ return this.each( function () {
+ if ($(this).data('colorpickerId')) {
+ show.apply(this);
+ }
+ });
+ },
+ hidePicker: function() {
+ return this.each( function () {
+ if ($(this).data('colorpickerId')) {
+ $('#' + $(this).data('colorpickerId')).hide();
+ }
+ });
+ },
+ setColor: function(col) {
+ if (typeof col == 'string') {
+ col = HexToHSB(col);
+ } else if (col.r != undefined && col.g != undefined && col.b != undefined) {
+ col = RGBToHSB(col);
+ } else if (col.h != undefined && col.s != undefined && col.b != undefined) {
+ col = fixHSB(col);
+ } else {
+ return this;
+ }
+ return this.each(function(){
+ if ($(this).data('colorpickerId')) {
+ var cal = $('#' + $(this).data('colorpickerId'));
+ cal.data('colorpicker').color = col;
+ cal.data('colorpicker').origColor = col;
+ fillRGBFields(col, cal.get(0));
+ fillHSBFields(col, cal.get(0));
+ fillHexFields(col, cal.get(0));
+ setHue(col, cal.get(0));
+ setSelector(col, cal.get(0));
+ setCurrentColor(col, cal.get(0));
+ setNewColor(col, cal.get(0));
+ }
+ });
+ }
+ };
+ }();
+ $.fn.extend({
+ ColorPicker: ColorPicker.init,
+ ColorPickerHide: ColorPicker.hidePicker,
+ ColorPickerShow: ColorPicker.showPicker,
+ ColorPickerSetColor: ColorPicker.setColor
+ });
})(jQuery)
\ No newline at end of file
-/**\r
- *\r
- * Zoomimage\r
- * Author: Stefan Petre www.eyecon.ro\r
- * \r
- */\r
-(function($){\r
- var EYE = window.EYE = function() {\r
- var _registered = {\r
- init: []\r
- };\r
- return {\r
- init: function() {\r
- $.each(_registered.init, function(nr, fn){\r
- fn.call();\r
- });\r
- },\r
- extend: function(prop) {\r
- for (var i in prop) {\r
- if (prop[i] != undefined) {\r
- this[i] = prop[i];\r
- }\r
- }\r
- },\r
- register: function(fn, type) {\r
- if (!_registered[type]) {\r
- _registered[type] = [];\r
- }\r
- _registered[type].push(fn);\r
- }\r
- };\r
- }();\r
- $(EYE.init);\r
-})(jQuery);\r
+/**
+ *
+ * Zoomimage
+ * Author: Stefan Petre www.eyecon.ro
+ *
+ */
+(function($){
+ var EYE = window.EYE = function() {
+ var _registered = {
+ init: []
+ };
+ return {
+ init: function() {
+ $.each(_registered.init, function(nr, fn){
+ fn.call();
+ });
+ },
+ extend: function(prop) {
+ for (var i in prop) {
+ if (prop[i] != undefined) {
+ this[i] = prop[i];
+ }
+ }
+ },
+ register: function(fn, type) {
+ if (!_registered[type]) {
+ _registered[type] = [];
+ }
+ _registered[type].push(fn);
+ }
+ };
+ }();
+ $(EYE.init);
+})(jQuery);
-(function($){\r
- var initLayout = function() {\r
- var hash = window.location.hash.replace('#', '');\r
- var currentTab = $('ul.navigationTabs a')\r
- .bind('click', showTab)\r
- .filter('a[rel=' + hash + ']');\r
- if (currentTab.size() == 0) {\r
- currentTab = $('ul.navigationTabs a:first');\r
- }\r
- showTab.apply(currentTab.get(0));\r
- $('#colorpickerHolder').ColorPicker({flat: true});\r
- $('#colorpickerHolder2').ColorPicker({\r
- flat: true,\r
- color: '#00ff00',\r
- onSubmit: function(hsb, hex, rgb) {\r
- $('#colorSelector2 div').css('backgroundColor', '#' + hex);\r
- }\r
- });\r
- $('#colorpickerHolder2>div').css('position', 'absolute');\r
- var widt = false;\r
- $('#colorSelector2').bind('click', function() {\r
- $('#colorpickerHolder2').stop().animate({height: widt ? 0 : 173}, 500);\r
- widt = !widt;\r
- });\r
- $('#colorpickerField1, #colorpickerField2, #colorpickerField3').ColorPicker({\r
- onSubmit: function(hsb, hex, rgb, el) {\r
- $(el).val(hex);\r
- $(el).ColorPickerHide();\r
- },\r
- onBeforeShow: function () {\r
- $(this).ColorPickerSetColor(this.value);\r
- }\r
- })\r
- .bind('keyup', function(){\r
- $(this).ColorPickerSetColor(this.value);\r
- });\r
- $('#colorSelector').ColorPicker({\r
- color: '#0000ff',\r
- onShow: function (colpkr) {\r
- $(colpkr).fadeIn(500);\r
- return false;\r
- },\r
- onHide: function (colpkr) {\r
- $(colpkr).fadeOut(500);\r
- return false;\r
- },\r
- onChange: function (hsb, hex, rgb) {\r
- $('#colorSelector div').css('backgroundColor', '#' + hex);\r
- }\r
- });\r
- };\r
- \r
- var showTab = function(e) {\r
- var tabIndex = $('ul.navigationTabs a')\r
- .removeClass('active')\r
- .index(this);\r
- $(this)\r
- .addClass('active')\r
- .blur();\r
- $('div.tab')\r
- .hide()\r
- .eq(tabIndex)\r
- .show();\r
- };\r
- \r
- EYE.register(initLayout, 'init');\r
+(function($){
+ var initLayout = function() {
+ var hash = window.location.hash.replace('#', '');
+ var currentTab = $('ul.navigationTabs a')
+ .bind('click', showTab)
+ .filter('a[rel=' + hash + ']');
+ if (currentTab.size() == 0) {
+ currentTab = $('ul.navigationTabs a:first');
+ }
+ showTab.apply(currentTab.get(0));
+ $('#colorpickerHolder').ColorPicker({flat: true});
+ $('#colorpickerHolder2').ColorPicker({
+ flat: true,
+ color: '#00ff00',
+ onSubmit: function(hsb, hex, rgb) {
+ $('#colorSelector2 div').css('backgroundColor', '#' + hex);
+ }
+ });
+ $('#colorpickerHolder2>div').css('position', 'absolute');
+ var widt = false;
+ $('#colorSelector2').bind('click', function() {
+ $('#colorpickerHolder2').stop().animate({height: widt ? 0 : 173}, 500);
+ widt = !widt;
+ });
+ $('#colorpickerField1, #colorpickerField2, #colorpickerField3').ColorPicker({
+ onSubmit: function(hsb, hex, rgb, el) {
+ $(el).val(hex);
+ $(el).ColorPickerHide();
+ },
+ onBeforeShow: function () {
+ $(this).ColorPickerSetColor(this.value);
+ }
+ })
+ .bind('keyup', function(){
+ $(this).ColorPickerSetColor(this.value);
+ });
+ $('#colorSelector').ColorPicker({
+ color: '#0000ff',
+ onShow: function (colpkr) {
+ $(colpkr).fadeIn(500);
+ return false;
+ },
+ onHide: function (colpkr) {
+ $(colpkr).fadeOut(500);
+ return false;
+ },
+ onChange: function (hsb, hex, rgb) {
+ $('#colorSelector div').css('backgroundColor', '#' + hex);
+ }
+ });
+ };
+
+ var showTab = function(e) {
+ var tabIndex = $('ul.navigationTabs a')
+ .removeClass('active')
+ .index(this);
+ $(this)
+ .addClass('active')
+ .blur();
+ $('div.tab')
+ .hide()
+ .eq(tabIndex)
+ .show();
+ };
+
+ EYE.register(initLayout, 'init');
})(jQuery)
\ No newline at end of file
-/**\r
- *\r
- * Utilities\r
- * Author: Stefan Petre www.eyecon.ro\r
- * \r
- */\r
-(function($) {\r
-EYE.extend({\r
- getPosition : function(e, forceIt)\r
- {\r
- var x = 0;\r
- var y = 0;\r
- var es = e.style;\r
- var restoreStyles = false;\r
- if (forceIt && jQuery.curCSS(e,'display') == 'none') {\r
- var oldVisibility = es.visibility;\r
- var oldPosition = es.position;\r
- restoreStyles = true;\r
- es.visibility = 'hidden';\r
- es.display = 'block';\r
- es.position = 'absolute';\r
- }\r
- var el = e;\r
- if (el.getBoundingClientRect) { // IE\r
- var box = el.getBoundingClientRect();\r
- x = box.left + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft) - 2;\r
- y = box.top + Math.max(document.documentElement.scrollTop, document.body.scrollTop) - 2;\r
- } else {\r
- x = el.offsetLeft;\r
- y = el.offsetTop;\r
- el = el.offsetParent;\r
- if (e != el) {\r
- while (el) {\r
- x += el.offsetLeft;\r
- y += el.offsetTop;\r
- el = el.offsetParent;\r
- }\r
- }\r
- if (jQuery.browser.safari && jQuery.curCSS(e, 'position') == 'absolute' ) {\r
- x -= document.body.offsetLeft;\r
- y -= document.body.offsetTop;\r
- }\r
- el = e.parentNode;\r
- while (el && el.tagName.toUpperCase() != 'BODY' && el.tagName.toUpperCase() != 'HTML') \r
- {\r
- if (jQuery.curCSS(el, 'display') != 'inline') {\r
- x -= el.scrollLeft;\r
- y -= el.scrollTop;\r
- }\r
- el = el.parentNode;\r
- }\r
- }\r
- if (restoreStyles == true) {\r
- es.display = 'none';\r
- es.position = oldPosition;\r
- es.visibility = oldVisibility;\r
- }\r
- return {x:x, y:y};\r
- },\r
- getSize : function(e)\r
- {\r
- var w = parseInt(jQuery.curCSS(e,'width'), 10);\r
- var h = parseInt(jQuery.curCSS(e,'height'), 10);\r
- var wb = 0;\r
- var hb = 0;\r
- if (jQuery.curCSS(e, 'display') != 'none') {\r
- wb = e.offsetWidth;\r
- hb = e.offsetHeight;\r
- } else {\r
- var es = e.style;\r
- var oldVisibility = es.visibility;\r
- var oldPosition = es.position;\r
- es.visibility = 'hidden';\r
- es.display = 'block';\r
- es.position = 'absolute';\r
- wb = e.offsetWidth;\r
- hb = e.offsetHeight;\r
- es.display = 'none';\r
- es.position = oldPosition;\r
- es.visibility = oldVisibility;\r
- }\r
- return {w:w, h:h, wb:wb, hb:hb};\r
- },\r
- getClient : function(e)\r
- {\r
- var h, w;\r
- if (e) {\r
- w = e.clientWidth;\r
- h = e.clientHeight;\r
- } else {\r
- var de = document.documentElement;\r
- w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;\r
- h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;\r
- }\r
- return {w:w,h:h};\r
- },\r
- getScroll : function (e)\r
- {\r
- var t=0, l=0, w=0, h=0, iw=0, ih=0;\r
- if (e && e.nodeName.toLowerCase() != 'body') {\r
- t = e.scrollTop;\r
- l = e.scrollLeft;\r
- w = e.scrollWidth;\r
- h = e.scrollHeight;\r
- } else {\r
- if (document.documentElement) {\r
- t = document.documentElement.scrollTop;\r
- l = document.documentElement.scrollLeft;\r
- w = document.documentElement.scrollWidth;\r
- h = document.documentElement.scrollHeight;\r
- } else if (document.body) {\r
- t = document.body.scrollTop;\r
- l = document.body.scrollLeft;\r
- w = document.body.scrollWidth;\r
- h = document.body.scrollHeight;\r
- }\r
- if (typeof pageYOffset != 'undefined') {\r
- t = pageYOffset;\r
- l = pageXOffset;\r
- }\r
- iw = self.innerWidth||document.documentElement.clientWidth||document.body.clientWidth||0;\r
- ih = self.innerHeight||document.documentElement.clientHeight||document.body.clientHeight||0;\r
- }\r
- return { t: t, l: l, w: w, h: h, iw: iw, ih: ih };\r
- },\r
- getMargins : function(e, toInteger)\r
- {\r
- var t = jQuery.curCSS(e,'marginTop') || '';\r
- var r = jQuery.curCSS(e,'marginRight') || '';\r
- var b = jQuery.curCSS(e,'marginBottom') || '';\r
- var l = jQuery.curCSS(e,'marginLeft') || '';\r
- if (toInteger)\r
- return {\r
- t: parseInt(t, 10)||0,\r
- r: parseInt(r, 10)||0,\r
- b: parseInt(b, 10)||0,\r
- l: parseInt(l, 10)\r
- };\r
- else\r
- return {t: t, r: r, b: b, l: l};\r
- },\r
- getPadding : function(e, toInteger)\r
- {\r
- var t = jQuery.curCSS(e,'paddingTop') || '';\r
- var r = jQuery.curCSS(e,'paddingRight') || '';\r
- var b = jQuery.curCSS(e,'paddingBottom') || '';\r
- var l = jQuery.curCSS(e,'paddingLeft') || '';\r
- if (toInteger)\r
- return {\r
- t: parseInt(t, 10)||0,\r
- r: parseInt(r, 10)||0,\r
- b: parseInt(b, 10)||0,\r
- l: parseInt(l, 10)\r
- };\r
- else\r
- return {t: t, r: r, b: b, l: l};\r
- },\r
- getBorder : function(e, toInteger)\r
- {\r
- var t = jQuery.curCSS(e,'borderTopWidth') || '';\r
- var r = jQuery.curCSS(e,'borderRightWidth') || '';\r
- var b = jQuery.curCSS(e,'borderBottomWidth') || '';\r
- var l = jQuery.curCSS(e,'borderLeftWidth') || '';\r
- if (toInteger)\r
- return {\r
- t: parseInt(t, 10)||0,\r
- r: parseInt(r, 10)||0,\r
- b: parseInt(b, 10)||0,\r
- l: parseInt(l, 10)||0\r
- };\r
- else\r
- return {t: t, r: r, b: b, l: l};\r
- },\r
- traverseDOM : function(nodeEl, func)\r
- {\r
- func(nodeEl);\r
- nodeEl = nodeEl.firstChild;\r
- while(nodeEl){\r
- EYE.traverseDOM(nodeEl, func);\r
- nodeEl = nodeEl.nextSibling;\r
- }\r
- },\r
- getInnerWidth : function(el, scroll) {\r
- var offsetW = el.offsetWidth;\r
- return scroll ? Math.max(el.scrollWidth,offsetW) - offsetW + el.clientWidth:el.clientWidth;\r
- },\r
- getInnerHeight : function(el, scroll) {\r
- var offsetH = el.offsetHeight;\r
- return scroll ? Math.max(el.scrollHeight,offsetH) - offsetH + el.clientHeight:el.clientHeight;\r
- },\r
- getExtraWidth : function(el) {\r
- if($.boxModel)\r
- return (parseInt($.curCSS(el, 'paddingLeft'))||0)\r
- + (parseInt($.curCSS(el, 'paddingRight'))||0)\r
- + (parseInt($.curCSS(el, 'borderLeftWidth'))||0)\r
- + (parseInt($.curCSS(el, 'borderRightWidth'))||0);\r
- return 0;\r
- },\r
- getExtraHeight : function(el) {\r
- if($.boxModel)\r
- return (parseInt($.curCSS(el, 'paddingTop'))||0)\r
- + (parseInt($.curCSS(el, 'paddingBottom'))||0)\r
- + (parseInt($.curCSS(el, 'borderTopWidth'))||0)\r
- + (parseInt($.curCSS(el, 'borderBottomWidth'))||0);\r
- return 0;\r
- },\r
- isChildOf: function(parentEl, el, container) {\r
- if (parentEl == el) {\r
- return true;\r
- }\r
- if (!el || !el.nodeType || el.nodeType != 1) {\r
- return false;\r
- }\r
- if (parentEl.contains && !$.browser.safari) {\r
- return parentEl.contains(el);\r
- }\r
- if ( parentEl.compareDocumentPosition ) {\r
- return !!(parentEl.compareDocumentPosition(el) & 16);\r
- }\r
- var prEl = el.parentNode;\r
- while(prEl && prEl != container) {\r
- if (prEl == parentEl)\r
- return true;\r
- prEl = prEl.parentNode;\r
- }\r
- return false;\r
- },\r
- centerEl : function(el, axis)\r
- {\r
- var clientScroll = EYE.getScroll();\r
- var size = EYE.getSize(el);\r
- if (!axis || axis == 'vertically')\r
- $(el).css(\r
- {\r
- top: clientScroll.t + ((Math.min(clientScroll.h,clientScroll.ih) - size.hb)/2) + 'px'\r
- }\r
- );\r
- if (!axis || axis == 'horizontally')\r
- $(el).css(\r
- {\r
- left: clientScroll.l + ((Math.min(clientScroll.w,clientScroll.iw) - size.wb)/2) + 'px'\r
- }\r
- );\r
- }\r
-});\r
-if (!$.easing.easeout) {\r
- $.easing.easeout = function(p, n, firstNum, delta, duration) {\r
- return -delta * ((n=n/duration-1)*n*n*n - 1) + firstNum;\r
- };\r
-}\r
- \r
+/**
+ *
+ * Utilities
+ * Author: Stefan Petre www.eyecon.ro
+ *
+ */
+(function($) {
+EYE.extend({
+ getPosition : function(e, forceIt)
+ {
+ var x = 0;
+ var y = 0;
+ var es = e.style;
+ var restoreStyles = false;
+ if (forceIt && jQuery.curCSS(e,'display') == 'none') {
+ var oldVisibility = es.visibility;
+ var oldPosition = es.position;
+ restoreStyles = true;
+ es.visibility = 'hidden';
+ es.display = 'block';
+ es.position = 'absolute';
+ }
+ var el = e;
+ if (el.getBoundingClientRect) { // IE
+ var box = el.getBoundingClientRect();
+ x = box.left + Math.max(document.documentElement.scrollLeft, document.body.scrollLeft) - 2;
+ y = box.top + Math.max(document.documentElement.scrollTop, document.body.scrollTop) - 2;
+ } else {
+ x = el.offsetLeft;
+ y = el.offsetTop;
+ el = el.offsetParent;
+ if (e != el) {
+ while (el) {
+ x += el.offsetLeft;
+ y += el.offsetTop;
+ el = el.offsetParent;
+ }
+ }
+ if (jQuery.browser.safari && jQuery.curCSS(e, 'position') == 'absolute' ) {
+ x -= document.body.offsetLeft;
+ y -= document.body.offsetTop;
+ }
+ el = e.parentNode;
+ while (el && el.tagName.toUpperCase() != 'BODY' && el.tagName.toUpperCase() != 'HTML')
+ {
+ if (jQuery.curCSS(el, 'display') != 'inline') {
+ x -= el.scrollLeft;
+ y -= el.scrollTop;
+ }
+ el = el.parentNode;
+ }
+ }
+ if (restoreStyles == true) {
+ es.display = 'none';
+ es.position = oldPosition;
+ es.visibility = oldVisibility;
+ }
+ return {x:x, y:y};
+ },
+ getSize : function(e)
+ {
+ var w = parseInt(jQuery.curCSS(e,'width'), 10);
+ var h = parseInt(jQuery.curCSS(e,'height'), 10);
+ var wb = 0;
+ var hb = 0;
+ if (jQuery.curCSS(e, 'display') != 'none') {
+ wb = e.offsetWidth;
+ hb = e.offsetHeight;
+ } else {
+ var es = e.style;
+ var oldVisibility = es.visibility;
+ var oldPosition = es.position;
+ es.visibility = 'hidden';
+ es.display = 'block';
+ es.position = 'absolute';
+ wb = e.offsetWidth;
+ hb = e.offsetHeight;
+ es.display = 'none';
+ es.position = oldPosition;
+ es.visibility = oldVisibility;
+ }
+ return {w:w, h:h, wb:wb, hb:hb};
+ },
+ getClient : function(e)
+ {
+ var h, w;
+ if (e) {
+ w = e.clientWidth;
+ h = e.clientHeight;
+ } else {
+ var de = document.documentElement;
+ w = window.innerWidth || self.innerWidth || (de&&de.clientWidth) || document.body.clientWidth;
+ h = window.innerHeight || self.innerHeight || (de&&de.clientHeight) || document.body.clientHeight;
+ }
+ return {w:w,h:h};
+ },
+ getScroll : function (e)
+ {
+ var t=0, l=0, w=0, h=0, iw=0, ih=0;
+ if (e && e.nodeName.toLowerCase() != 'body') {
+ t = e.scrollTop;
+ l = e.scrollLeft;
+ w = e.scrollWidth;
+ h = e.scrollHeight;
+ } else {
+ if (document.documentElement) {
+ t = document.documentElement.scrollTop;
+ l = document.documentElement.scrollLeft;
+ w = document.documentElement.scrollWidth;
+ h = document.documentElement.scrollHeight;
+ } else if (document.body) {
+ t = document.body.scrollTop;
+ l = document.body.scrollLeft;
+ w = document.body.scrollWidth;
+ h = document.body.scrollHeight;
+ }
+ if (typeof pageYOffset != 'undefined') {
+ t = pageYOffset;
+ l = pageXOffset;
+ }
+ iw = self.innerWidth||document.documentElement.clientWidth||document.body.clientWidth||0;
+ ih = self.innerHeight||document.documentElement.clientHeight||document.body.clientHeight||0;
+ }
+ return { t: t, l: l, w: w, h: h, iw: iw, ih: ih };
+ },
+ getMargins : function(e, toInteger)
+ {
+ var t = jQuery.curCSS(e,'marginTop') || '';
+ var r = jQuery.curCSS(e,'marginRight') || '';
+ var b = jQuery.curCSS(e,'marginBottom') || '';
+ var l = jQuery.curCSS(e,'marginLeft') || '';
+ if (toInteger)
+ return {
+ t: parseInt(t, 10)||0,
+ r: parseInt(r, 10)||0,
+ b: parseInt(b, 10)||0,
+ l: parseInt(l, 10)
+ };
+ else
+ return {t: t, r: r, b: b, l: l};
+ },
+ getPadding : function(e, toInteger)
+ {
+ var t = jQuery.curCSS(e,'paddingTop') || '';
+ var r = jQuery.curCSS(e,'paddingRight') || '';
+ var b = jQuery.curCSS(e,'paddingBottom') || '';
+ var l = jQuery.curCSS(e,'paddingLeft') || '';
+ if (toInteger)
+ return {
+ t: parseInt(t, 10)||0,
+ r: parseInt(r, 10)||0,
+ b: parseInt(b, 10)||0,
+ l: parseInt(l, 10)
+ };
+ else
+ return {t: t, r: r, b: b, l: l};
+ },
+ getBorder : function(e, toInteger)
+ {
+ var t = jQuery.curCSS(e,'borderTopWidth') || '';
+ var r = jQuery.curCSS(e,'borderRightWidth') || '';
+ var b = jQuery.curCSS(e,'borderBottomWidth') || '';
+ var l = jQuery.curCSS(e,'borderLeftWidth') || '';
+ if (toInteger)
+ return {
+ t: parseInt(t, 10)||0,
+ r: parseInt(r, 10)||0,
+ b: parseInt(b, 10)||0,
+ l: parseInt(l, 10)||0
+ };
+ else
+ return {t: t, r: r, b: b, l: l};
+ },
+ traverseDOM : function(nodeEl, func)
+ {
+ func(nodeEl);
+ nodeEl = nodeEl.firstChild;
+ while(nodeEl){
+ EYE.traverseDOM(nodeEl, func);
+ nodeEl = nodeEl.nextSibling;
+ }
+ },
+ getInnerWidth : function(el, scroll) {
+ var offsetW = el.offsetWidth;
+ return scroll ? Math.max(el.scrollWidth,offsetW) - offsetW + el.clientWidth:el.clientWidth;
+ },
+ getInnerHeight : function(el, scroll) {
+ var offsetH = el.offsetHeight;
+ return scroll ? Math.max(el.scrollHeight,offsetH) - offsetH + el.clientHeight:el.clientHeight;
+ },
+ getExtraWidth : function(el) {
+ if($.boxModel)
+ return (parseInt($.curCSS(el, 'paddingLeft'))||0)
+ + (parseInt($.curCSS(el, 'paddingRight'))||0)
+ + (parseInt($.curCSS(el, 'borderLeftWidth'))||0)
+ + (parseInt($.curCSS(el, 'borderRightWidth'))||0);
+ return 0;
+ },
+ getExtraHeight : function(el) {
+ if($.boxModel)
+ return (parseInt($.curCSS(el, 'paddingTop'))||0)
+ + (parseInt($.curCSS(el, 'paddingBottom'))||0)
+ + (parseInt($.curCSS(el, 'borderTopWidth'))||0)
+ + (parseInt($.curCSS(el, 'borderBottomWidth'))||0);
+ return 0;
+ },
+ isChildOf: function(parentEl, el, container) {
+ if (parentEl == el) {
+ return true;
+ }
+ if (!el || !el.nodeType || el.nodeType != 1) {
+ return false;
+ }
+ if (parentEl.contains && !$.browser.safari) {
+ return parentEl.contains(el);
+ }
+ if ( parentEl.compareDocumentPosition ) {
+ return !!(parentEl.compareDocumentPosition(el) & 16);
+ }
+ var prEl = el.parentNode;
+ while(prEl && prEl != container) {
+ if (prEl == parentEl)
+ return true;
+ prEl = prEl.parentNode;
+ }
+ return false;
+ },
+ centerEl : function(el, axis)
+ {
+ var clientScroll = EYE.getScroll();
+ var size = EYE.getSize(el);
+ if (!axis || axis == 'vertically')
+ $(el).css(
+ {
+ top: clientScroll.t + ((Math.min(clientScroll.h,clientScroll.ih) - size.hb)/2) + 'px'
+ }
+ );
+ if (!axis || axis == 'horizontally')
+ $(el).css(
+ {
+ left: clientScroll.l + ((Math.min(clientScroll.w,clientScroll.iw) - size.wb)/2) + 'px'
+ }
+ );
+ }
+});
+if (!$.easing.easeout) {
+ $.easing.easeout = function(p, n, firstNum, delta, duration) {
+ return -delta * ((n=n/duration-1)*n*n*n - 1) + firstNum;
+ };
+}
+
})(jQuery);
\ No newline at end of file
-\r
-var PixasticEditor = (function () {\r
-\r
- var $frame; // iframe container element\r
- var $editor; // editor container element\r
-\r
- // various UI structures\r
- var accordionElements = {};\r
- var tabElements = {};\r
- var activeTabId;\r
- var $activeTabContent;\r
-\r
- var isRunning = false;\r
-\r
- var $loadingScreen;\r
-\r
- var $imageCanvas; // the canvas holding the current state of the image\r
- var $displayCanvas; // the canvas element displayed on the screen, also the working canvas (where preview operations are performed)\r
- var imageCtx;\r
-\r
- var imageWidth = 0; // dimensions of the current image state\r
- var imageHeight = 0;\r
-\r
- var undoImages = []; // canvas elements holding previous image states\r
- var undoLevels = 10;\r
-\r
- var doc;\r
-\r
- var $;\r
-\r
- // test for valid file formats for toDataURL()\r
- // we do that by calling it with each of the mime types in testFormats\r
- // and then doing string checking on the resulting data: URI to see if it succeeded\r
- var saveFormats = [];\r
- var testFormats = [["image/jpeg", "JPEG"], ["image/png", "PNG"]];\r
- var testCanvas = document.createElement("canvas");\r
- if (testCanvas.toDataURL) {\r
- testCanvas.width = testCanvas.height = 1;\r
- for (var i=0;i<testFormats.length;i++) {\r
- var data = testCanvas.toDataURL(testFormats[i][0]);\r
- if (data.substr(0, 5 + testFormats[i][0].length) == "data:" + testFormats[i][0])\r
- saveFormats.push({mime:testFormats[i][0], name:testFormats[i][1]});\r
- }\r
- }\r
-\r
-\r
- // pops up an error dialog with the specified text (errTxt),\r
- // if no context is provided, the name of the calling function is used.\r
- // The final message is returned for easy throwing of actual errors\r
- function errorDialog(errTxt, context) {\r
- if (!($editor && $editor.get && $editor.get(0)))\r
- throw new Error("errorDialog(): $editor doesn't exist");\r
-\r
- var caller = errorDialog.caller.toString().split(" ")[1];\r
- caller = caller.substring(0, caller.indexOf("("));\r
- context = context || caller;\r
- errTxt = context + "(): " + errTxt;\r
- var dialog = $j("<div></div>", doc)\r
- .addClass("error-dialog")\r
- .attr("title", "Oops!")\r
- .html(errTxt)\r
- .dialog();\r
- // the dialog is added outside the Pixastic container, so get it back in.\r
- var dialogParent = $j(dialog.get(0).parentNode);\r
- dialogParent.appendTo($editor);\r
-\r
- return errTxt;\r
- }\r
- \r
- function enableTab(id, refresh) {\r
- if (id == activeTabId && !refresh)\r
- return;\r
-\r
- activeTabId = id;\r
-\r
- var activeIndex = 0;\r
-\r
- if ($activeTabContent) {\r
- if ($activeTabContent.get(0)) {\r
- var $parent = $j($activeTabContent.get(0).parentNode);\r
- activeIndex = $parent.data("accordionindex");\r
- if ($parent.data("ondeactivate")) {\r
- $parent.data("ondeactivate")();\r
- }\r
- if ($parent.data("previewCheckbox"))\r
- $parent.data("previewCheckbox").attr("checked", false);\r
- $parent.data("uidesc").previewEnabled = false;\r
- if ($parent.data("uidesc").forcePreview)\r
- $parent.data("uidesc").previewEnabled = true;\r
- }\r
- }\r
-\r
-\r
- for (var a in accordionElements) {\r
- if (accordionElements.hasOwnProperty(a)) {\r
- accordionElements[a].accordion("option", "animated", false);\r
- accordionElements[a].accordion("activate", -1);\r
- accordionElements[a].hide();\r
- tabElements[a].removeClass("active");\r
-\r
- }\r
- }\r
-\r
- accordionElements[id].accordion("option", "animated", false);\r
- accordionElements[id].accordion("activate", refresh ? activeIndex : 0);\r
- tabElements[id].addClass("active");\r
- accordionElements[id].show();\r
- accordionElements[id].accordion("option", "animated", "slide");\r
- resetDisplayCanvas();\r
- }\r
-\r
- // revert to a previous image state\r
- function undo(idx) {\r
- var undoImage = undoImages[idx];\r
-\r
- if (!undoImage) \r
- throw new Error(errorDialog("Invalid undo state"));\r
- if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))\r
- throw new Error(errorDialog("$imageCanvas doesn't exist"));\r
-\r
- var canvas = $imageCanvas.get(0);\r
- addUndo(canvas);\r
- canvas.width = imageWidth = undoImage.width;\r
- canvas.height = imageHeight = undoImage.height;\r
- canvas.getContext("2d").drawImage(undoImage,0,0);\r
-\r
- enableTab(activeTabId, true);\r
- resetDisplayCanvas();\r
- }\r
-\r
- function addUndo(canvasElement) {\r
- if (!canvasElement)\r
- throw new Error(errorDialog("No undo image state provided"));\r
-\r
- if (undoImages.length == undoLevels) {\r
- undoImages.shift();\r
- }\r
- var undoCanvas = document.createElement("canvas");\r
- undoCanvas.width = canvasElement.width;\r
- undoCanvas.height = canvasElement.height;\r
- undoCanvas.getContext("2d").drawImage(canvasElement,0,0);\r
- $j(undoCanvas).addClass("undo-canvas");\r
- undoImages.push(undoCanvas);\r
- updateUndoList();\r
- }\r
-\r
- function updateUndoList() {\r
- var $listCtr = $j("#undo-bar", doc)\r
- .html("");\r
-\r
- var ctrHeight = $listCtr.height();\r
-\r
- var $testCanvas = $j("<canvas></canvas>", doc)\r
- .addClass("undo-canvas-small")\r
- .addClass("far-far-away")\r
- .appendTo("body");\r
-\r
- var canvasHeight = $testCanvas.height();\r
- var canvasWidth = $testCanvas.width();\r
- var canvasCSSHeight = canvasHeight + parseInt($testCanvas.css("margin-top"),10) + parseInt($testCanvas.css("margin-bottom"),10);\r
-\r
- $testCanvas.remove();\r
-\r
- var undoRatio = canvasWidth / canvasHeight;\r
-\r
- for (var i=undoImages.length-1;i>=0;i--) {\r
- (function(){\r
- var canvas = document.createElement("canvas");\r
- $j(canvas)\r
- .addClass("undo-canvas-small")\r
- .attr("width", canvasWidth)\r
- .attr("height", canvasHeight);\r
-\r
- var image = undoImages[i];\r
- $j(image).show();\r
- \r
- var undoWidth, undoHeight;\r
- var imageRatio = image.width / image.height;\r
-\r
- if (imageRatio > undoRatio) { // image too wide\r
- undoWidth = canvasWidth;\r
- undoHeight = canvasWidth / imageRatio;\r
- } else {\r
- undoWidth = canvasHeight * imageRatio;\r
- undoHeight = canvasHeight;\r
- }\r
-\r
- var restWidth = canvasWidth - undoWidth;\r
- var restHeight = canvasHeight - undoHeight;\r
-\r
- canvas.getContext("2d").drawImage(\r
- image,\r
- 0,0,image.width,image.height,\r
- restWidth*0.5, restHeight*0.5,\r
- undoWidth, undoHeight\r
- );\r
-\r
-\r
- $link = $j("<a href='#'></a>", doc)\r
- .addClass("undo-link")\r
- .appendTo($listCtr)\r
- .mouseover(function(){ $j(this).addClass("hover") })\r
- .mouseout(function(){ $j(this).removeClass("hover") });\r
- $j(canvas).appendTo($link);\r
-\r
- var displayShowing;\r
- var undoIndex = i;\r
- $link.click(function() {\r
- $j(image).hide();\r
- $j(image).remove();\r
- undo(undoIndex);\r
- if (displayShowing)\r
- $displayCanvas.show();\r
- $j(".jcrop-holder", doc).show();\r
- });\r
-\r
- $link.mouseover(function() {\r
- displayShowing = $displayCanvas.css("display") != "none";\r
- var $imagectr = $j("#image-container", doc);\r
-\r
- $j(".jcrop-holder", doc).hide();\r
- $displayCanvas.hide();\r
- $j(image).appendTo($imagectr);\r
-\r
- var h1 = $j("#image-area", doc).height();\r
- var h2 = image.height;\r
- var m = Math.max(0, (h1 - h2) / 2);\r
- $imagectr.css("marginTop", m);\r
- \r
- $imagectr.height(image.height);\r
- });\r
-\r
- $link.mouseout(function() {\r
- $j(image).remove();\r
- if (displayShowing)\r
- $displayCanvas.show();\r
- $j(".jcrop-holder", doc).show();\r
- updateDisplayCanvas();\r
- });\r
-\r
-\r
- $j(canvas).attr("title", "Click to revert to this previous image");\r
-\r
- })();\r
- }\r
- }\r
-\r
-\r
- function applyAction(id, options, afteraction) {\r
- if (!Pixastic.Actions[id])\r
- throw new Error("applyAction(): unknown action [" + id + "]");\r
-\r
- $j("#action-bar-overlay", doc).show();\r
-\r
- setTimeout(function() {\r
- options.leaveDOM = true;\r
- var canvasElement = $imageCanvas.get(0);\r
- addUndo(canvasElement)\r
- \r
- var res = Pixastic.process(\r
- canvasElement, id, options,\r
- function(resCanvas) {\r
- canvasElement.width = imageWidth = resCanvas.width;\r
- canvasElement.height = imageHeight = resCanvas.height;\r
- \r
- var ctx = canvasElement.getContext("2d");\r
- ctx.clearRect(0,0,imageWidth,imageHeight);\r
- ctx.drawImage(resCanvas,0,0);\r
- $imageCanvas = $j(canvasElement);\r
- resetDisplayCanvas();\r
- \r
- $j("#action-bar-overlay", doc).hide();\r
-\r
- if (afteraction)\r
- afteraction();\r
- }\r
- );\r
- if (!res)\r
- throw new Error("applyAction(): Pixastic.process() failed for action [" + id + "]");\r
- },1);\r
- }\r
-\r
-\r
- function previewAction(id, options, afteraction) {\r
- if (!Pixastic.Actions[id])\r
- throw new Error("applyAction(): unknown action [" + id + "]");\r
-\r
- $j("#action-bar-overlay", doc).show();\r
-\r
- resetDisplayCanvas();\r
-\r
- options.leaveDOM = true;\r
- var canvasElement = $displayCanvas.get(0);\r
-\r
- var res = Pixastic.process(\r
- canvasElement, id, options,\r
- function(resCanvas) {\r
-\r
- canvasElement.width = resCanvas.width;\r
- canvasElement.height = resCanvas.height;\r
-\r
- var ctx = canvasElement.getContext("2d");\r
- ctx.clearRect(0,0,canvasElement.width,canvasElement.height);\r
- ctx.drawImage(resCanvas,0,0);\r
- updateDisplayCanvas();\r
- updateOverlay();\r
-\r
- $j("#action-bar-overlay", doc).hide();\r
-\r
- if (afteraction)\r
- afteraction();\r
- }\r
- );\r
- }\r
-\r
- var onwindowresize = function() {\r
- updateDisplayCanvas();\r
- updateOverlay();\r
- }\r
-\r
- var baseUrl = ""\r
-\r
- function buildEditor() {\r
- var styles = [\r
- "jquery-ui-1.7.1.custom.css",\r
- "jquery.Jcrop.css",\r
- "pixastic.css"\r
- ];\r
-\r
- for (var i=0;i<styles.length;i++) {\r
- var s = doc.createElement("link");\r
- s.href = baseUrl + styles[i];\r
- s.type = "text/css";\r
- s.rel = "stylesheet";\r
- doc.getElementsByTagName("head")[0].appendChild( s );\r
- }\r
-\r
- undoImages = [];\r
- accordionElements = {};\r
- tabElements = {};\r
- activeTabId = -1;\r
- $activeTabContent = null;\r
-\r
- // setup DOM UI skeleton\r
- $editor = $j("<div />", doc)\r
- .attr("id", "pixastic-editor")\r
- .appendTo($j(doc.body));\r
-\r
- $editor.append(\r
- $j("<div id='background' />", doc),\r
- $j("<div id='edit-ctr-1' />", doc).append(\r
- $j("<div id='edit-ctr-2' />", doc).append(\r
- $j("<div id='controls-bar' />", doc).append(\r
- $j("<div id='action-bar' />", doc).append(\r
- $j("<div id='action-bar-overlay' />", doc)\r
- ),\r
- $j("<div id='undo-bar' />", doc)\r
- ),\r
- $j("<div id='image-area' />", doc).append(\r
- $j("<div id='image-area-sub' />", doc).append(\r
- $j("<div id='image-container' />", doc),\r
- $j("<div id='image-overlay-container' />", doc).append(\r
- $j("<div id='image-overlay' />", doc)\r
- )\r
- )\r
- )\r
- )\r
- ),\r
- $j("<div id='main-bar' />", doc),\r
- $j("<div id='powered-by-pixastic'><a href=\"http://www.pixastic.com/\" target=\"_blank\">Powered by Pixastic</a></div>", doc)\r
- );\r
-\r
- $j("#image-container", doc).append(\r
- $displayCanvas = $j("<canvas />", doc)\r
- .addClass("display-canvas")\r
- );\r
-\r
- // loop through all defined UI action controls\r
- var tabs = PixasticEditor.UI.data.tabs;\r
-\r
- for (var i=0;i<tabs.length;i++) {\r
- (function() {\r
- \r
- var tab = tabs[i];\r
-\r
- var $tabElement = $j("<a href=\"#\">" + tab.title + "</a>", doc)\r
- .attr("id", "main-tab-button-" + tab.id)\r
- .addClass("main-tab")\r
- .click(function() {\r
- enableTab(tab.id);\r
- })\r
- .mouseover(function(){ $j(this).addClass("hover") })\r
- .mouseout(function(){ $j(this).removeClass("hover") });\r
- \r
- $j("#main-bar", doc).append($tabElement);\r
-\r
- tabElements[tab.id] = $tabElement;\r
-\r
- var $menu = $j("<div/>", doc);\r
- accordionElements[tab.id] = $menu;\r
-\r
- for (var j=0;j<tab.actions.length;j++) {\r
- (function() {\r
-\r
- var action = tab.actions[j];\r
-\r
- var $actionElement = $j("<div><h3><a href=\"#\">" + action.title + "</a></h3></div>", doc)\r
-\r
- $menu.append($actionElement);\r
-\r
- var $content = $j("<div></div>", doc)\r
- .attr("id", "pixastic-action-tab-content-" + action.id)\r
- .appendTo($actionElement);\r
-\r
- var controlOptions = [];\r
-\r
- action.previewEnabled = false;\r
- if (action.forcePreview)\r
- action.previewEnabled = true;\r
-\r
- function togglePreview(enable, doAction) {\r
- if (enable && !action.previewEnabled && doAction)\r
- doAction(true);\r
- if (!enable && action.previewEnabled)\r
- resetDisplayCanvas();\r
- \r
- action.previewEnabled = enable;\r
- }\r
-\r
- var reset = function() {\r
- for (var i in controlOptions) {\r
- if (controlOptions.hasOwnProperty(i)) {\r
- controlOptions[i].reset();\r
- }\r
- }\r
- if (action.previewEnabled)\r
- doAction(true);\r
- }\r
- var doAction = function(isPreview) {\r
- var options = {};\r
- for (var i in controlOptions) {\r
- if (controlOptions.hasOwnProperty(i)) {\r
- options[i] = controlOptions[i].valueField.val();\r
- }\r
- }\r
-\r
- var afteraction = function() {\r
- if (action.onafteraction)\r
- action.onafteraction(action, isPreview);\r
- if (!isPreview)\r
- resetDisplayCanvas();\r
- \r
- if (!isPreview && !action.forcePreview) {\r
- $j("#pixastic-input-preview-" + action.id, doc).attr("checked", false);\r
- togglePreview(false);\r
- reset();\r
- }\r
- }\r
-\r
- if (isPreview) {\r
- previewAction(action.id, options, afteraction);\r
- } else {\r
- applyAction(action.id, options, afteraction);\r
- }\r
-\r
- }\r
-\r
- var hadInputs = false;\r
-\r
- if (action.controls) {\r
- var onChange = function() {};\r
- if (action.isAction && action.preview) {\r
- onChange = function() {\r
- if (action.previewEnabled)\r
- doAction(true)\r
- };\r
- }\r
-\r
- for (var k=0;k<action.controls.length;k++) {\r
- var control = action.controls[k];\r
- if (typeof control.defaultValue != "function") {\r
- (function(){\r
- var defVal = control.defaultValue;\r
- control.defaultValue = function() {\r
- return defVal;\r
- }\r
- })();\r
- }\r
- var controlId = action.id + "-" + control.option;\r
-\r
- if (control.type != "output")\r
- hadInputs = true;\r
-\r
- switch (control.type) {\r
- case "number" :\r
- switch (control.ui) {\r
- case "slider" : \r
- var slider = PixasticEditor.UI.makeSlider(\r
- control.label, controlId, \r
- control.range[0], control.range[1], control.step, control.defaultValue, onChange\r
- );\r
- \r
- slider.container.appendTo($content);\r
- controlOptions[control.option] = slider;\r
- break;\r
- case "text" : \r
- var text = PixasticEditor.UI.makeNumericInput(\r
- control.label, control.labelRight, controlId, \r
- control.range[0], control.range[1], control.step, control.defaultValue, onChange\r
- );\r
- text.container.appendTo($content);\r
- controlOptions[control.option] = text;\r
- break;\r
- }\r
- break;\r
- case "boolean" :\r
- switch (control.ui) {\r
- case "checkbox" : \r
- var checkbox = PixasticEditor.UI.makeCheckbox(\r
- control.label, controlId, control.defaultValue, onChange\r
- );\r
- \r
- checkbox.container.appendTo($content);\r
- controlOptions[control.option] = checkbox;\r
- break;\r
- }\r
- case "string" :\r
- switch (control.ui) {\r
- case "select" : \r
- var select = PixasticEditor.UI.makeSelect(\r
- control.label, controlId, control.values, control.defaultValue, onChange\r
- );\r
- \r
- select.container.appendTo($content);\r
- controlOptions[control.option] = select;\r
- break;\r
- }\r
- break;\r
- case "output" :\r
- var outputText = $j("<div></div>", doc)\r
- .addClass("ui-action-output")\r
- .html(control.content)\r
- .appendTo($content);\r
- break;\r
- }\r
- }\r
- }\r
-\r
- if (action.isAction) {\r
-\r
- var $applyButton = PixasticEditor.UI.makeButton("Apply")\r
- .addClass("pixastic-option-button-apply")\r
- .click(function() {doAction();});\r
-\r
- $content.append($applyButton);\r
-\r
- if (hadInputs) {\r
- var $resetButton = PixasticEditor.UI.makeButton("Reset")\r
- .addClass("pixastic-option-button-reset")\r
- .click(reset);\r
- \r
- $content.append($resetButton)\r
- }\r
-\r
- if (action.preview && !action.forcePreview) {\r
- var $checkctr = $j("<div></div>", doc)\r
- .addClass("ui-checkbox-container")\r
- .addClass("ui-preview-checkbox-container");\r
-\r
- var $label = $j("<label></label>", doc)\r
- .addClass("ui-checkbox-label")\r
- .attr("for", "pixastic-input-preview-" + action.id)\r
- .html("Preview:")\r
- .appendTo($checkctr);\r
-\r
- var $checkbox = $j("<input type=\"checkbox\"></input>", doc)\r
- .addClass("ui-checkbox")\r
- .attr("id", "pixastic-input-preview-" + action.id)\r
- .appendTo($checkctr)\r
- .change(function() {\r
- togglePreview(this.checked, doAction)\r
- });\r
-\r
- $content.append($checkctr);\r
-\r
- $content.data("previewCheckbox", $checkbox);\r
- }\r
-\r
- }\r
-\r
-\r
- if (typeof action.content == "function") {\r
- action.content($content);\r
- }\r
-\r
- // stupid hack to make it possible to get $content in change event (below)\r
- $j("<span></span>", doc).appendTo($content);\r
-\r
- $content.data("controlOptions", controlOptions);\r
- $content.data("onactivate", action.onactivate);\r
- $content.data("ondeactivate", action.ondeactivate);\r
- $content.data("onoverlayupdate", action.onoverlayupdate);\r
- $content.data("accordionindex", j);\r
- $content.data("uidesc", action);\r
-\r
- })();\r
- }\r
- \r
- $j("#action-bar", doc).append($menu);\r
-\r
- $menu.hide().accordion({\r
- header: "h3",\r
- autoHeight : false,\r
- collapsible : true,\r
- active: -1\r
- })\r
- .bind("accordionchange", \r
- function(event, ui) {\r
- resetDisplayCanvas();\r
-\r
- // oldContent / newContent are arrays of whatever elements are present in the content area\r
- // We need the parent element (the one holding the content) but if there is no content, how do we get it?\r
- // fixed above by always appending a <span> but that's ugly and needs to be done in some other way\r
- if (ui.oldContent.get(0)) {\r
- var $parent = $j(ui.oldContent.get(0).parentNode);\r
- if ($parent.data("ondeactivate")) {\r
- $parent.data("ondeactivate")();\r
- }\r
- }\r
- $activeTabContent = ui.newContent;\r
-\r
- if (ui.newContent.get(0)) {\r
- var $parent = $j(ui.newContent.get(0).parentNode);\r
- if ($parent.data("previewCheckbox"))\r
- $parent.data("previewCheckbox").attr("checked", false);\r
- $parent.data("uidesc").previewEnabled = false;\r
- if ($parent.data("uidesc").forcePreview)\r
- $parent.data("uidesc").previewEnabled = true;\r
-\r
- var controlOptions = $parent.data("controlOptions");\r
- for (var i in controlOptions) {\r
- if (controlOptions.hasOwnProperty(i)) {\r
- controlOptions[i].reset();\r
- }\r
- }\r
- if ($parent.data("onactivate")) {\r
- $parent.data("onactivate")();\r
- }\r
- }\r
- updateDisplayCanvas();\r
-\r
- }\r
- );\r
-\r
- \r
- })();\r
- }\r
-\r
- $j(window).bind("resize", onwindowresize);\r
- }\r
-\r
- function showLoadingScreen() {\r
- if ($loadingScreen) {\r
- $loadingScreen.show();\r
- return;\r
- }\r
- $loadingScreen = $j("<div id=\"loading-screen\" />")\r
- var $ctr = $j("<div id=\"loading-screen-cell\" />");\r
- $j("<div />")\r
- .addClass("spinner")\r
- .appendTo($ctr);\r
- $loadingScreen.append($ctr);\r
- $loadingScreen.appendTo("body");\r
- }\r
-\r
- function hideLoadingScreen() {\r
- setTimeout(function() {\r
- $loadingScreen.hide();\r
- }, 1);\r
- }\r
-\r
- var oldScrollLeft;\r
- var oldScrollTop;\r
- var oldOverflow;\r
-\r
- // fire it up\r
- function init(callback) {\r
- isRunning = true;\r
-\r
- showLoadingScreen();\r
-\r
- oldScrollLeft = document.body.scrollLeft;\r
- oldScrollTop = document.body.scrollTop;\r
- oldOverflow = document.body.style.overflow;\r
-\r
- document.body.scrollLeft = 0;\r
- document.body.scrollTop = 0;\r
- document.body.style.overflow = "hidden";\r
-\r
- $frame = $j("<iframe />");\r
- $frame.hide();\r
- $frame.css({\r
- position : "absolute",\r
- left : document.body.scrollLeft + "px",\r
- top : document.body.scrollTop + "px",\r
- width : "100%",\r
- height : "100%",\r
- zIndex : "11"\r
- });\r
- $frame.load(function(){\r
- doc = $frame.get(0).contentDocument;\r
-\r
- buildEditor();\r
- callback();\r
- $frame.show();\r
- hideLoadingScreen();\r
- setTimeout(function(){\r
- updateDisplayCanvas();\r
- },10);\r
- });\r
- $frame.appendTo("body");\r
- }\r
-\r
- // unload the editor, remove all elements added to the page and restore whatever properties we messed with\r
- function unload() {\r
- $j(window).unbind("resize", onwindowresize);\r
- $frame.hide();\r
- $editor.hide();\r
- $editor.remove();\r
- $frame.remove();\r
-\r
- document.body.scrollLeft = oldScrollLeft;\r
- document.body.scrollTop = oldScrollTop;\r
- document.body.style.overflow = oldOverflow;\r
-\r
- isRunning = false;\r
- }\r
-\r
-\r
- // resets the display canvas (clears the canvas and repaints the current state)\r
- // then updates display and overlay\r
- function resetDisplayCanvas() {\r
- if (!($displayCanvas && $displayCanvas.get)) throw new Error(errorDialog("$displayCanvas doesn't exist"));\r
- if (!($imageCanvas && $imageCanvas.get)) throw new Error(errorDialog("$imageCanvas doesn't exist"));\r
-\r
- var display = $displayCanvas.get(0);\r
- var image = $imageCanvas.get(0);\r
-\r
- if (!display) throw new Error(errorDialog("resetDisplayCanvas(): No elements in $displayCanvas"));\r
- if (!image) throw new Error(errorDialog("resetDisplayCanvas(): No elements in $imageCanvas"));\r
-\r
- display.width = imageWidth;\r
- display.height = imageHeight;\r
- display.getContext("2d").drawImage( image, 0, 0 );\r
-\r
- updateDisplayCanvas();\r
- updateOverlay();\r
- }\r
-\r
- // updates the display by resetting the height and margin of the image container\r
- // this is mainly to keep vertical centering\r
- function updateDisplayCanvas() {\r
- var $imageCtr = $j("#image-container", doc);\r
- var $editArea = $j("#image-area", doc);\r
-\r
- if (!$imageCtr.get(0)) throw new Error(errorDialog("updateDisplayCanvas(): $imageCtr doesn't exist"));\r
- if (!$displayCanvas.get(0)) throw new Error(errorDialog("updateDisplayCanvas(): $displayCanvas doesn't exist"));\r
- if (!$editArea.get(0)) throw new Error(errorDialog("updateDisplayCanvas(): $editArea doesn't exist"));\r
-\r
- var h2 = $displayCanvas.get(0).height;\r
- var h1 = $j("#image-area", doc).height();\r
- var m = Math.max(0, (h1 - h2) / 2);\r
- $imageCtr.height(h2);\r
- $imageCtr.css("marginTop", m);\r
- }\r
-\r
- // basically the same as updateDisplayCanvas but for the image overlay\r
- function updateOverlay() {\r
- var $overlay = $j("#image-overlay-container", doc);\r
- var $imagectr = $j("#image-container", doc);\r
- $overlay.height($imagectr.height());\r
- $overlay.css("marginTop", $imagectr.css("marginTop"));\r
-\r
- if ($activeTabContent && $activeTabContent.get(0)) {\r
- var $tabContent = $j($activeTabContent.get(0).parentNode);\r
- if (typeof $tabContent.data("onoverlayupdate") == "function")\r
- $tabContent.data("onoverlayupdate")();\r
- }\r
- }\r
-\r
- var imageIsLoading = false;\r
- var originalImageElement;\r
- var $tmpImg;\r
-\r
- function loadImage(imgEl) {\r
- if (imageIsLoading) \r
- return;\r
-\r
- imageIsLoading = true;\r
-\r
- originalImageElement = imgEl;\r
-\r
- $imageCanvas = $j("<canvas />", doc);\r
- imageCtx = $imageCanvas.get(0).getContext("2d");\r
-\r
- imageWidth = 0;\r
- imageHeight = 0;\r
- $imageCanvas.attr("width", 0);\r
- $imageCanvas.attr("height", 0);\r
-\r
- if (imgEl.tagName.toLowerCase() == "img" && !imgEl._pixasticCanvas) {\r
- var onload = function(el) {\r
- imageWidth = el.offsetWidth;\r
- imageHeight = el.offsetHeight;\r
- $imageCanvas.attr("width", imageWidth);\r
- $imageCanvas.attr("height", imageHeight);\r
- imageCtx.drawImage(el,0,0);\r
- $tmpImg.remove();\r
- imageIsLoading = false;\r
- enableTab("reshape");\r
- setTimeout(function() {\r
- resetDisplayCanvas();\r
- }, 10);\r
- }\r
- $tmpImg = $j("<img />", doc)\r
- .css("position", "absolute")\r
- .css("left", "-9999px")\r
- .css("top", "-9999px")\r
- .appendTo("body")\r
- .load(function(){onload(this);})\r
- .error(function(){\r
- throw new Error("Could not load temporary copy image. Is provided image valid?");\r
- unload();\r
- })\r
- .attr("src", imgEl.src);\r
- if ($tmpImg.attr("complete")) {\r
- onload($tmpImg.get(0));\r
- }\r
- } else {\r
- var $canvas = imgEl._pixasticCanvas || imgEl;\r
- imageWidth = $canvas.attr("width");\r
- imageHeight = $canvas.attr("height");\r
- $imageCanvas.attr("width", imageWidth);\r
- $imageCanvas.attr("height", imageHeight);\r
- imageCtx.drawImage($canvas.get(0), 0, 0);\r
- imageIsLoading = false;\r
- enableTab("reshape");\r
- resetDisplayCanvas();\r
- }\r
- }\r
-\r
- // return public interface\r
- return {\r
- /*\r
- // don't call. For now we must load the image immediately via load()\r
- loadImage : function(imgEl) {\r
- if (!isRunning) return false;\r
- loadImage(imgEl);\r
- },\r
- */\r
- saveToPage : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::saveToPage(): Editor is not running");\r
-\r
- var $canvas = PixasticEditor.getImageCanvas();\r
- var img = PixasticEditor.getOriginalImage();\r
- if (img.tagName.toLowerCase() == "canvas") {\r
- img.width = $canvas.attr("width");\r
- img.height = $canvas.attr("height");\r
- img.getContext("2d").drawImage($canvas.get(0), 0, 0);\r
- } else {\r
- img.src = PixasticEditor.getDataURI();\r
- }\r
- img._pixasticCanvas = PixasticEditor.getImageCanvas();\r
- },\r
- load : function(img, customBaseUrl) {\r
- if (isRunning) return false;\r
-\r
- if (!img)\r
- throw new Error("Must be called with an image or canvas as its first argument", "PixasticEditor::load")\r
-\r
- $ = PixasticEditor.jQuery;\r
-\r
- baseUrl = customBaseUrl || "http://www.pixastic.com/editor-test/";\r
-\r
- init(function() {\r
- if (img && img.tagName.toLowerCase() == "img" || img.tagName.toLowerCase() == "canvas") {\r
- loadImage(img);\r
- }\r
- });\r
- },\r
-\r
- unload : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::unload(): Editor is not running");\r
- unload();\r
- },\r
-\r
- getDocument : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::getDocument(): Editor is not running");\r
-\r
- return doc;\r
- },\r
-\r
- validSaveFormats : function() {\r
- return saveFormats;\r
- },\r
-\r
- getOriginalImage : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::getOriginalImage(): Editor is not running");\r
- return originalImageElement;\r
- },\r
-\r
- getDataURI : function(mime) {\r
- if (!isRunning) throw new Error("PixasticEditor::getDataURI(): Editor is not running");\r
-\r
- if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))\r
- throw new Error(errorDialog("$imageCanvas doesn't exist", "getImageCanvas"));\r
-\r
- return $imageCanvas.get(0).toDataURL(mime||"image/png");\r
- },\r
-\r
- getImageCanvas : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::getImageCanvas(): Editor is not running");\r
-\r
- if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))\r
- throw new Error(errorDialog("$imageCanvas doesn't exist", "getImageCanvas"));\r
-\r
- return $imageCanvas;\r
- },\r
- getOverlay : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::getOverlay(): Editor is not running");\r
-\r
- return $j("#image-overlay", doc);\r
- },\r
- getDisplayCanvas : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::getDisplayCanvas(): Editor is not running");\r
-\r
- if (!($displayCanvas && $displayCanvas.get && $displayCanvas.get(0)))\r
- throw new Error(errorDialog("$displayCanvas doesn't exist", "getDisplayCanvas"));\r
- return $displayCanvas;\r
- },\r
- getDisplayWidth : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::getDisplayWidth(): Editor is not running");\r
-\r
- return displayWidth;\r
- },\r
- getDisplayHeight : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::getDisplayHeight(): Editor is not running");\r
-\r
- return displayHeight;\r
- },\r
- getImageWidth : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::getImageWidth(): Editor is not running");\r
-\r
- return imageWidth;\r
- },\r
- getImageHeight : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::getImageHeight(): Editor is not running");\r
-\r
- return imageHeight;\r
- },\r
- errorDialog : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::errorDialog(): Editor is not running");\r
-\r
- return errorDialog.apply(null, arguments);\r
- }\r
- }\r
-\r
+
+var PixasticEditor = (function () {
+
+ var $frame; // iframe container element
+ var $editor; // editor container element
+
+ // various UI structures
+ var accordionElements = {};
+ var tabElements = {};
+ var activeTabId;
+ var $activeTabContent;
+
+ var isRunning = false;
+
+ var $loadingScreen;
+
+ var $imageCanvas; // the canvas holding the current state of the image
+ var $displayCanvas; // the canvas element displayed on the screen, also the working canvas (where preview operations are performed)
+ var imageCtx;
+
+ var imageWidth = 0; // dimensions of the current image state
+ var imageHeight = 0;
+
+ var undoImages = []; // canvas elements holding previous image states
+ var undoLevels = 10;
+
+ var doc;
+
+ var $;
+
+ // test for valid file formats for toDataURL()
+ // we do that by calling it with each of the mime types in testFormats
+ // and then doing string checking on the resulting data: URI to see if it succeeded
+ var saveFormats = [];
+ var testFormats = [["image/jpeg", "JPEG"], ["image/png", "PNG"]];
+ var testCanvas = document.createElement("canvas");
+ if (testCanvas.toDataURL) {
+ testCanvas.width = testCanvas.height = 1;
+ for (var i=0;i<testFormats.length;i++) {
+ var data = testCanvas.toDataURL(testFormats[i][0]);
+ if (data.substr(0, 5 + testFormats[i][0].length) == "data:" + testFormats[i][0])
+ saveFormats.push({mime:testFormats[i][0], name:testFormats[i][1]});
+ }
+ }
+
+
+ // pops up an error dialog with the specified text (errTxt),
+ // if no context is provided, the name of the calling function is used.
+ // The final message is returned for easy throwing of actual errors
+ function errorDialog(errTxt, context) {
+ if (!($editor && $editor.get && $editor.get(0)))
+ throw new Error("errorDialog(): $editor doesn't exist");
+
+ var caller = errorDialog.caller.toString().split(" ")[1];
+ caller = caller.substring(0, caller.indexOf("("));
+ context = context || caller;
+ errTxt = context + "(): " + errTxt;
+ var dialog = $j("<div></div>", doc)
+ .addClass("error-dialog")
+ .attr("title", "Oops!")
+ .html(errTxt)
+ .dialog();
+ // the dialog is added outside the Pixastic container, so get it back in.
+ var dialogParent = $j(dialog.get(0).parentNode);
+ dialogParent.appendTo($editor);
+
+ return errTxt;
+ }
+
+ function enableTab(id, refresh) {
+ if (id == activeTabId && !refresh)
+ return;
+
+ activeTabId = id;
+
+ var activeIndex = 0;
+
+ if ($activeTabContent) {
+ if ($activeTabContent.get(0)) {
+ var $parent = $j($activeTabContent.get(0).parentNode);
+ activeIndex = $parent.data("accordionindex");
+ if ($parent.data("ondeactivate")) {
+ $parent.data("ondeactivate")();
+ }
+ if ($parent.data("previewCheckbox"))
+ $parent.data("previewCheckbox").attr("checked", false);
+ $parent.data("uidesc").previewEnabled = false;
+ if ($parent.data("uidesc").forcePreview)
+ $parent.data("uidesc").previewEnabled = true;
+ }
+ }
+
+
+ for (var a in accordionElements) {
+ if (accordionElements.hasOwnProperty(a)) {
+ accordionElements[a].accordion("option", "animated", false);
+ accordionElements[a].accordion("activate", -1);
+ accordionElements[a].hide();
+ tabElements[a].removeClass("active");
+
+ }
+ }
+
+ accordionElements[id].accordion("option", "animated", false);
+ accordionElements[id].accordion("activate", refresh ? activeIndex : 0);
+ tabElements[id].addClass("active");
+ accordionElements[id].show();
+ accordionElements[id].accordion("option", "animated", "slide");
+ resetDisplayCanvas();
+ }
+
+ // revert to a previous image state
+ function undo(idx) {
+ var undoImage = undoImages[idx];
+
+ if (!undoImage)
+ throw new Error(errorDialog("Invalid undo state"));
+ if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))
+ throw new Error(errorDialog("$imageCanvas doesn't exist"));
+
+ var canvas = $imageCanvas.get(0);
+ addUndo(canvas);
+ canvas.width = imageWidth = undoImage.width;
+ canvas.height = imageHeight = undoImage.height;
+ canvas.getContext("2d").drawImage(undoImage,0,0);
+
+ enableTab(activeTabId, true);
+ resetDisplayCanvas();
+ }
+
+ function addUndo(canvasElement) {
+ if (!canvasElement)
+ throw new Error(errorDialog("No undo image state provided"));
+
+ if (undoImages.length == undoLevels) {
+ undoImages.shift();
+ }
+ var undoCanvas = document.createElement("canvas");
+ undoCanvas.width = canvasElement.width;
+ undoCanvas.height = canvasElement.height;
+ undoCanvas.getContext("2d").drawImage(canvasElement,0,0);
+ $j(undoCanvas).addClass("undo-canvas");
+ undoImages.push(undoCanvas);
+ updateUndoList();
+ }
+
+ function updateUndoList() {
+ var $listCtr = $j("#undo-bar", doc)
+ .html("");
+
+ var ctrHeight = $listCtr.height();
+
+ var $testCanvas = $j("<canvas></canvas>", doc)
+ .addClass("undo-canvas-small")
+ .addClass("far-far-away")
+ .appendTo("body");
+
+ var canvasHeight = $testCanvas.height();
+ var canvasWidth = $testCanvas.width();
+ var canvasCSSHeight = canvasHeight + parseInt($testCanvas.css("margin-top"),10) + parseInt($testCanvas.css("margin-bottom"),10);
+
+ $testCanvas.remove();
+
+ var undoRatio = canvasWidth / canvasHeight;
+
+ for (var i=undoImages.length-1;i>=0;i--) {
+ (function(){
+ var canvas = document.createElement("canvas");
+ $j(canvas)
+ .addClass("undo-canvas-small")
+ .attr("width", canvasWidth)
+ .attr("height", canvasHeight);
+
+ var image = undoImages[i];
+ $j(image).show();
+
+ var undoWidth, undoHeight;
+ var imageRatio = image.width / image.height;
+
+ if (imageRatio > undoRatio) { // image too wide
+ undoWidth = canvasWidth;
+ undoHeight = canvasWidth / imageRatio;
+ } else {
+ undoWidth = canvasHeight * imageRatio;
+ undoHeight = canvasHeight;
+ }
+
+ var restWidth = canvasWidth - undoWidth;
+ var restHeight = canvasHeight - undoHeight;
+
+ canvas.getContext("2d").drawImage(
+ image,
+ 0,0,image.width,image.height,
+ restWidth*0.5, restHeight*0.5,
+ undoWidth, undoHeight
+ );
+
+
+ $link = $j("<a href='#'></a>", doc)
+ .addClass("undo-link")
+ .appendTo($listCtr)
+ .mouseover(function(){ $j(this).addClass("hover") })
+ .mouseout(function(){ $j(this).removeClass("hover") });
+ $j(canvas).appendTo($link);
+
+ var displayShowing;
+ var undoIndex = i;
+ $link.click(function() {
+ $j(image).hide();
+ $j(image).remove();
+ undo(undoIndex);
+ if (displayShowing)
+ $displayCanvas.show();
+ $j(".jcrop-holder", doc).show();
+ });
+
+ $link.mouseover(function() {
+ displayShowing = $displayCanvas.css("display") != "none";
+ var $imagectr = $j("#image-container", doc);
+
+ $j(".jcrop-holder", doc).hide();
+ $displayCanvas.hide();
+ $j(image).appendTo($imagectr);
+
+ var h1 = $j("#image-area", doc).height();
+ var h2 = image.height;
+ var m = Math.max(0, (h1 - h2) / 2);
+ $imagectr.css("marginTop", m);
+
+ $imagectr.height(image.height);
+ });
+
+ $link.mouseout(function() {
+ $j(image).remove();
+ if (displayShowing)
+ $displayCanvas.show();
+ $j(".jcrop-holder", doc).show();
+ updateDisplayCanvas();
+ });
+
+
+ $j(canvas).attr("title", "Click to revert to this previous image");
+
+ })();
+ }
+ }
+
+
+ function applyAction(id, options, afteraction) {
+ if (!Pixastic.Actions[id])
+ throw new Error("applyAction(): unknown action [" + id + "]");
+
+ $j("#action-bar-overlay", doc).show();
+
+ setTimeout(function() {
+ options.leaveDOM = true;
+ var canvasElement = $imageCanvas.get(0);
+ addUndo(canvasElement)
+
+ var res = Pixastic.process(
+ canvasElement, id, options,
+ function(resCanvas) {
+ canvasElement.width = imageWidth = resCanvas.width;
+ canvasElement.height = imageHeight = resCanvas.height;
+
+ var ctx = canvasElement.getContext("2d");
+ ctx.clearRect(0,0,imageWidth,imageHeight);
+ ctx.drawImage(resCanvas,0,0);
+ $imageCanvas = $j(canvasElement);
+ resetDisplayCanvas();
+
+ $j("#action-bar-overlay", doc).hide();
+
+ if (afteraction)
+ afteraction();
+ }
+ );
+ if (!res)
+ throw new Error("applyAction(): Pixastic.process() failed for action [" + id + "]");
+ },1);
+ }
+
+
+ function previewAction(id, options, afteraction) {
+ if (!Pixastic.Actions[id])
+ throw new Error("applyAction(): unknown action [" + id + "]");
+
+ $j("#action-bar-overlay", doc).show();
+
+ resetDisplayCanvas();
+
+ options.leaveDOM = true;
+ var canvasElement = $displayCanvas.get(0);
+
+ var res = Pixastic.process(
+ canvasElement, id, options,
+ function(resCanvas) {
+
+ canvasElement.width = resCanvas.width;
+ canvasElement.height = resCanvas.height;
+
+ var ctx = canvasElement.getContext("2d");
+ ctx.clearRect(0,0,canvasElement.width,canvasElement.height);
+ ctx.drawImage(resCanvas,0,0);
+ updateDisplayCanvas();
+ updateOverlay();
+
+ $j("#action-bar-overlay", doc).hide();
+
+ if (afteraction)
+ afteraction();
+ }
+ );
+ }
+
+ var onwindowresize = function() {
+ updateDisplayCanvas();
+ updateOverlay();
+ }
+
+ var baseUrl = ""
+
+ function buildEditor() {
+ var styles = [
+ "jquery-ui-1.7.1.custom.css",
+ "jquery.Jcrop.css",
+ "pixastic.css"
+ ];
+
+ for (var i=0;i<styles.length;i++) {
+ var s = doc.createElement("link");
+ s.href = baseUrl + styles[i];
+ s.type = "text/css";
+ s.rel = "stylesheet";
+ doc.getElementsByTagName("head")[0].appendChild( s );
+ }
+
+ undoImages = [];
+ accordionElements = {};
+ tabElements = {};
+ activeTabId = -1;
+ $activeTabContent = null;
+
+ // setup DOM UI skeleton
+ $editor = $j("<div />", doc)
+ .attr("id", "pixastic-editor")
+ .appendTo($j(doc.body));
+
+ $editor.append(
+ $j("<div id='background' />", doc),
+ $j("<div id='edit-ctr-1' />", doc).append(
+ $j("<div id='edit-ctr-2' />", doc).append(
+ $j("<div id='controls-bar' />", doc).append(
+ $j("<div id='action-bar' />", doc).append(
+ $j("<div id='action-bar-overlay' />", doc)
+ ),
+ $j("<div id='undo-bar' />", doc)
+ ),
+ $j("<div id='image-area' />", doc).append(
+ $j("<div id='image-area-sub' />", doc).append(
+ $j("<div id='image-container' />", doc),
+ $j("<div id='image-overlay-container' />", doc).append(
+ $j("<div id='image-overlay' />", doc)
+ )
+ )
+ )
+ )
+ ),
+ $j("<div id='main-bar' />", doc),
+ $j("<div id='powered-by-pixastic'><a href=\"http://www.pixastic.com/\" target=\"_blank\">Powered by Pixastic</a></div>", doc)
+ );
+
+ $j("#image-container", doc).append(
+ $displayCanvas = $j("<canvas />", doc)
+ .addClass("display-canvas")
+ );
+
+ // loop through all defined UI action controls
+ var tabs = PixasticEditor.UI.data.tabs;
+
+ for (var i=0;i<tabs.length;i++) {
+ (function() {
+
+ var tab = tabs[i];
+
+ var $tabElement = $j("<a href=\"#\">" + tab.title + "</a>", doc)
+ .attr("id", "main-tab-button-" + tab.id)
+ .addClass("main-tab")
+ .click(function() {
+ enableTab(tab.id);
+ })
+ .mouseover(function(){ $j(this).addClass("hover") })
+ .mouseout(function(){ $j(this).removeClass("hover") });
+
+ $j("#main-bar", doc).append($tabElement);
+
+ tabElements[tab.id] = $tabElement;
+
+ var $menu = $j("<div/>", doc);
+ accordionElements[tab.id] = $menu;
+
+ for (var j=0;j<tab.actions.length;j++) {
+ (function() {
+
+ var action = tab.actions[j];
+
+ var $actionElement = $j("<div><h3><a href=\"#\">" + action.title + "</a></h3></div>", doc)
+
+ $menu.append($actionElement);
+
+ var $content = $j("<div></div>", doc)
+ .attr("id", "pixastic-action-tab-content-" + action.id)
+ .appendTo($actionElement);
+
+ var controlOptions = [];
+
+ action.previewEnabled = false;
+ if (action.forcePreview)
+ action.previewEnabled = true;
+
+ function togglePreview(enable, doAction) {
+ if (enable && !action.previewEnabled && doAction)
+ doAction(true);
+ if (!enable && action.previewEnabled)
+ resetDisplayCanvas();
+
+ action.previewEnabled = enable;
+ }
+
+ var reset = function() {
+ for (var i in controlOptions) {
+ if (controlOptions.hasOwnProperty(i)) {
+ controlOptions[i].reset();
+ }
+ }
+ if (action.previewEnabled)
+ doAction(true);
+ }
+ var doAction = function(isPreview) {
+ var options = {};
+ for (var i in controlOptions) {
+ if (controlOptions.hasOwnProperty(i)) {
+ options[i] = controlOptions[i].valueField.val();
+ }
+ }
+
+ var afteraction = function() {
+ if (action.onafteraction)
+ action.onafteraction(action, isPreview);
+ if (!isPreview)
+ resetDisplayCanvas();
+
+ if (!isPreview && !action.forcePreview) {
+ $j("#pixastic-input-preview-" + action.id, doc).attr("checked", false);
+ togglePreview(false);
+ reset();
+ }
+ }
+
+ if (isPreview) {
+ previewAction(action.id, options, afteraction);
+ } else {
+ applyAction(action.id, options, afteraction);
+ }
+
+ }
+
+ var hadInputs = false;
+
+ if (action.controls) {
+ var onChange = function() {};
+ if (action.isAction && action.preview) {
+ onChange = function() {
+ if (action.previewEnabled)
+ doAction(true)
+ };
+ }
+
+ for (var k=0;k<action.controls.length;k++) {
+ var control = action.controls[k];
+ if (typeof control.defaultValue != "function") {
+ (function(){
+ var defVal = control.defaultValue;
+ control.defaultValue = function() {
+ return defVal;
+ }
+ })();
+ }
+ var controlId = action.id + "-" + control.option;
+
+ if (control.type != "output")
+ hadInputs = true;
+
+ switch (control.type) {
+ case "number" :
+ switch (control.ui) {
+ case "slider" :
+ var slider = PixasticEditor.UI.makeSlider(
+ control.label, controlId,
+ control.range[0], control.range[1], control.step, control.defaultValue, onChange
+ );
+
+ slider.container.appendTo($content);
+ controlOptions[control.option] = slider;
+ break;
+ case "text" :
+ var text = PixasticEditor.UI.makeNumericInput(
+ control.label, control.labelRight, controlId,
+ control.range[0], control.range[1], control.step, control.defaultValue, onChange
+ );
+ text.container.appendTo($content);
+ controlOptions[control.option] = text;
+ break;
+ }
+ break;
+ case "boolean" :
+ switch (control.ui) {
+ case "checkbox" :
+ var checkbox = PixasticEditor.UI.makeCheckbox(
+ control.label, controlId, control.defaultValue, onChange
+ );
+
+ checkbox.container.appendTo($content);
+ controlOptions[control.option] = checkbox;
+ break;
+ }
+ case "string" :
+ switch (control.ui) {
+ case "select" :
+ var select = PixasticEditor.UI.makeSelect(
+ control.label, controlId, control.values, control.defaultValue, onChange
+ );
+
+ select.container.appendTo($content);
+ controlOptions[control.option] = select;
+ break;
+ }
+ break;
+ case "output" :
+ var outputText = $j("<div></div>", doc)
+ .addClass("ui-action-output")
+ .html(control.content)
+ .appendTo($content);
+ break;
+ }
+ }
+ }
+
+ if (action.isAction) {
+
+ var $applyButton = PixasticEditor.UI.makeButton("Apply")
+ .addClass("pixastic-option-button-apply")
+ .click(function() {doAction();});
+
+ $content.append($applyButton);
+
+ if (hadInputs) {
+ var $resetButton = PixasticEditor.UI.makeButton("Reset")
+ .addClass("pixastic-option-button-reset")
+ .click(reset);
+
+ $content.append($resetButton)
+ }
+
+ if (action.preview && !action.forcePreview) {
+ var $checkctr = $j("<div></div>", doc)
+ .addClass("ui-checkbox-container")
+ .addClass("ui-preview-checkbox-container");
+
+ var $label = $j("<label></label>", doc)
+ .addClass("ui-checkbox-label")
+ .attr("for", "pixastic-input-preview-" + action.id)
+ .html("Preview:")
+ .appendTo($checkctr);
+
+ var $checkbox = $j("<input type=\"checkbox\"></input>", doc)
+ .addClass("ui-checkbox")
+ .attr("id", "pixastic-input-preview-" + action.id)
+ .appendTo($checkctr)
+ .change(function() {
+ togglePreview(this.checked, doAction)
+ });
+
+ $content.append($checkctr);
+
+ $content.data("previewCheckbox", $checkbox);
+ }
+
+ }
+
+
+ if (typeof action.content == "function") {
+ action.content($content);
+ }
+
+ // stupid hack to make it possible to get $content in change event (below)
+ $j("<span></span>", doc).appendTo($content);
+
+ $content.data("controlOptions", controlOptions);
+ $content.data("onactivate", action.onactivate);
+ $content.data("ondeactivate", action.ondeactivate);
+ $content.data("onoverlayupdate", action.onoverlayupdate);
+ $content.data("accordionindex", j);
+ $content.data("uidesc", action);
+
+ })();
+ }
+
+ $j("#action-bar", doc).append($menu);
+
+ $menu.hide().accordion({
+ header: "h3",
+ autoHeight : false,
+ collapsible : true,
+ active: -1
+ })
+ .bind("accordionchange",
+ function(event, ui) {
+ resetDisplayCanvas();
+
+ // oldContent / newContent are arrays of whatever elements are present in the content area
+ // We need the parent element (the one holding the content) but if there is no content, how do we get it?
+ // fixed above by always appending a <span> but that's ugly and needs to be done in some other way
+ if (ui.oldContent.get(0)) {
+ var $parent = $j(ui.oldContent.get(0).parentNode);
+ if ($parent.data("ondeactivate")) {
+ $parent.data("ondeactivate")();
+ }
+ }
+ $activeTabContent = ui.newContent;
+
+ if (ui.newContent.get(0)) {
+ var $parent = $j(ui.newContent.get(0).parentNode);
+ if ($parent.data("previewCheckbox"))
+ $parent.data("previewCheckbox").attr("checked", false);
+ $parent.data("uidesc").previewEnabled = false;
+ if ($parent.data("uidesc").forcePreview)
+ $parent.data("uidesc").previewEnabled = true;
+
+ var controlOptions = $parent.data("controlOptions");
+ for (var i in controlOptions) {
+ if (controlOptions.hasOwnProperty(i)) {
+ controlOptions[i].reset();
+ }
+ }
+ if ($parent.data("onactivate")) {
+ $parent.data("onactivate")();
+ }
+ }
+ updateDisplayCanvas();
+
+ }
+ );
+
+
+ })();
+ }
+
+ $j(window).bind("resize", onwindowresize);
+ }
+
+ function showLoadingScreen() {
+ if ($loadingScreen) {
+ $loadingScreen.show();
+ return;
+ }
+ $loadingScreen = $j("<div id=\"loading-screen\" />")
+ var $ctr = $j("<div id=\"loading-screen-cell\" />");
+ $j("<div />")
+ .addClass("spinner")
+ .appendTo($ctr);
+ $loadingScreen.append($ctr);
+ $loadingScreen.appendTo("body");
+ }
+
+ function hideLoadingScreen() {
+ setTimeout(function() {
+ $loadingScreen.hide();
+ }, 1);
+ }
+
+ var oldScrollLeft;
+ var oldScrollTop;
+ var oldOverflow;
+
+ // fire it up
+ function init(callback) {
+ isRunning = true;
+
+ showLoadingScreen();
+
+ oldScrollLeft = document.body.scrollLeft;
+ oldScrollTop = document.body.scrollTop;
+ oldOverflow = document.body.style.overflow;
+
+ document.body.scrollLeft = 0;
+ document.body.scrollTop = 0;
+ document.body.style.overflow = "hidden";
+
+ $frame = $j("<iframe />");
+ $frame.hide();
+ $frame.css({
+ position : "absolute",
+ left : document.body.scrollLeft + "px",
+ top : document.body.scrollTop + "px",
+ width : "100%",
+ height : "100%",
+ zIndex : "11"
+ });
+ $frame.load(function(){
+ doc = $frame.get(0).contentDocument;
+
+ buildEditor();
+ callback();
+ $frame.show();
+ hideLoadingScreen();
+ setTimeout(function(){
+ updateDisplayCanvas();
+ },10);
+ });
+ $frame.appendTo("body");
+ }
+
+ // unload the editor, remove all elements added to the page and restore whatever properties we messed with
+ function unload() {
+ $j(window).unbind("resize", onwindowresize);
+ $frame.hide();
+ $editor.hide();
+ $editor.remove();
+ $frame.remove();
+
+ document.body.scrollLeft = oldScrollLeft;
+ document.body.scrollTop = oldScrollTop;
+ document.body.style.overflow = oldOverflow;
+
+ isRunning = false;
+ }
+
+
+ // resets the display canvas (clears the canvas and repaints the current state)
+ // then updates display and overlay
+ function resetDisplayCanvas() {
+ if (!($displayCanvas && $displayCanvas.get)) throw new Error(errorDialog("$displayCanvas doesn't exist"));
+ if (!($imageCanvas && $imageCanvas.get)) throw new Error(errorDialog("$imageCanvas doesn't exist"));
+
+ var display = $displayCanvas.get(0);
+ var image = $imageCanvas.get(0);
+
+ if (!display) throw new Error(errorDialog("resetDisplayCanvas(): No elements in $displayCanvas"));
+ if (!image) throw new Error(errorDialog("resetDisplayCanvas(): No elements in $imageCanvas"));
+
+ display.width = imageWidth;
+ display.height = imageHeight;
+ display.getContext("2d").drawImage( image, 0, 0 );
+
+ updateDisplayCanvas();
+ updateOverlay();
+ }
+
+ // updates the display by resetting the height and margin of the image container
+ // this is mainly to keep vertical centering
+ function updateDisplayCanvas() {
+ var $imageCtr = $j("#image-container", doc);
+ var $editArea = $j("#image-area", doc);
+
+ if (!$imageCtr.get(0)) throw new Error(errorDialog("updateDisplayCanvas(): $imageCtr doesn't exist"));
+ if (!$displayCanvas.get(0)) throw new Error(errorDialog("updateDisplayCanvas(): $displayCanvas doesn't exist"));
+ if (!$editArea.get(0)) throw new Error(errorDialog("updateDisplayCanvas(): $editArea doesn't exist"));
+
+ var h2 = $displayCanvas.get(0).height;
+ var h1 = $j("#image-area", doc).height();
+ var m = Math.max(0, (h1 - h2) / 2);
+ $imageCtr.height(h2);
+ $imageCtr.css("marginTop", m);
+ }
+
+ // basically the same as updateDisplayCanvas but for the image overlay
+ function updateOverlay() {
+ var $overlay = $j("#image-overlay-container", doc);
+ var $imagectr = $j("#image-container", doc);
+ $overlay.height($imagectr.height());
+ $overlay.css("marginTop", $imagectr.css("marginTop"));
+
+ if ($activeTabContent && $activeTabContent.get(0)) {
+ var $tabContent = $j($activeTabContent.get(0).parentNode);
+ if (typeof $tabContent.data("onoverlayupdate") == "function")
+ $tabContent.data("onoverlayupdate")();
+ }
+ }
+
+ var imageIsLoading = false;
+ var originalImageElement;
+ var $tmpImg;
+
+ function loadImage(imgEl) {
+ if (imageIsLoading)
+ return;
+
+ imageIsLoading = true;
+
+ originalImageElement = imgEl;
+
+ $imageCanvas = $j("<canvas />", doc);
+ imageCtx = $imageCanvas.get(0).getContext("2d");
+
+ imageWidth = 0;
+ imageHeight = 0;
+ $imageCanvas.attr("width", 0);
+ $imageCanvas.attr("height", 0);
+
+ if (imgEl.tagName.toLowerCase() == "img" && !imgEl._pixasticCanvas) {
+ var onload = function(el) {
+ imageWidth = el.offsetWidth;
+ imageHeight = el.offsetHeight;
+ $imageCanvas.attr("width", imageWidth);
+ $imageCanvas.attr("height", imageHeight);
+ imageCtx.drawImage(el,0,0);
+ $tmpImg.remove();
+ imageIsLoading = false;
+ enableTab("reshape");
+ setTimeout(function() {
+ resetDisplayCanvas();
+ }, 10);
+ }
+ $tmpImg = $j("<img />", doc)
+ .css("position", "absolute")
+ .css("left", "-9999px")
+ .css("top", "-9999px")
+ .appendTo("body")
+ .load(function(){onload(this);})
+ .error(function(){
+ throw new Error("Could not load temporary copy image. Is provided image valid?");
+ unload();
+ })
+ .attr("src", imgEl.src);
+ if ($tmpImg.attr("complete")) {
+ onload($tmpImg.get(0));
+ }
+ } else {
+ var $canvas = imgEl._pixasticCanvas || imgEl;
+ imageWidth = $canvas.attr("width");
+ imageHeight = $canvas.attr("height");
+ $imageCanvas.attr("width", imageWidth);
+ $imageCanvas.attr("height", imageHeight);
+ imageCtx.drawImage($canvas.get(0), 0, 0);
+ imageIsLoading = false;
+ enableTab("reshape");
+ resetDisplayCanvas();
+ }
+ }
+
+ // return public interface
+ return {
+ /*
+ // don't call. For now we must load the image immediately via load()
+ loadImage : function(imgEl) {
+ if (!isRunning) return false;
+ loadImage(imgEl);
+ },
+ */
+ saveToPage : function() {
+ if (!isRunning) throw new Error("PixasticEditor::saveToPage(): Editor is not running");
+
+ var $canvas = PixasticEditor.getImageCanvas();
+ var img = PixasticEditor.getOriginalImage();
+ if (img.tagName.toLowerCase() == "canvas") {
+ img.width = $canvas.attr("width");
+ img.height = $canvas.attr("height");
+ img.getContext("2d").drawImage($canvas.get(0), 0, 0);
+ } else {
+ img.src = PixasticEditor.getDataURI();
+ }
+ img._pixasticCanvas = PixasticEditor.getImageCanvas();
+ },
+ load : function(img, customBaseUrl) {
+ if (isRunning) return false;
+
+ if (!img)
+ throw new Error("Must be called with an image or canvas as its first argument", "PixasticEditor::load")
+
+ $ = PixasticEditor.jQuery;
+
+ baseUrl = customBaseUrl || "http://www.pixastic.com/editor-test/";
+
+ init(function() {
+ if (img && img.tagName.toLowerCase() == "img" || img.tagName.toLowerCase() == "canvas") {
+ loadImage(img);
+ }
+ });
+ },
+
+ unload : function() {
+ if (!isRunning) throw new Error("PixasticEditor::unload(): Editor is not running");
+ unload();
+ },
+
+ getDocument : function() {
+ if (!isRunning) throw new Error("PixasticEditor::getDocument(): Editor is not running");
+
+ return doc;
+ },
+
+ validSaveFormats : function() {
+ return saveFormats;
+ },
+
+ getOriginalImage : function() {
+ if (!isRunning) throw new Error("PixasticEditor::getOriginalImage(): Editor is not running");
+ return originalImageElement;
+ },
+
+ getDataURI : function(mime) {
+ if (!isRunning) throw new Error("PixasticEditor::getDataURI(): Editor is not running");
+
+ if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))
+ throw new Error(errorDialog("$imageCanvas doesn't exist", "getImageCanvas"));
+
+ return $imageCanvas.get(0).toDataURL(mime||"image/png");
+ },
+
+ getImageCanvas : function() {
+ if (!isRunning) throw new Error("PixasticEditor::getImageCanvas(): Editor is not running");
+
+ if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))
+ throw new Error(errorDialog("$imageCanvas doesn't exist", "getImageCanvas"));
+
+ return $imageCanvas;
+ },
+ getOverlay : function() {
+ if (!isRunning) throw new Error("PixasticEditor::getOverlay(): Editor is not running");
+
+ return $j("#image-overlay", doc);
+ },
+ getDisplayCanvas : function() {
+ if (!isRunning) throw new Error("PixasticEditor::getDisplayCanvas(): Editor is not running");
+
+ if (!($displayCanvas && $displayCanvas.get && $displayCanvas.get(0)))
+ throw new Error(errorDialog("$displayCanvas doesn't exist", "getDisplayCanvas"));
+ return $displayCanvas;
+ },
+ getDisplayWidth : function() {
+ if (!isRunning) throw new Error("PixasticEditor::getDisplayWidth(): Editor is not running");
+
+ return displayWidth;
+ },
+ getDisplayHeight : function() {
+ if (!isRunning) throw new Error("PixasticEditor::getDisplayHeight(): Editor is not running");
+
+ return displayHeight;
+ },
+ getImageWidth : function() {
+ if (!isRunning) throw new Error("PixasticEditor::getImageWidth(): Editor is not running");
+
+ return imageWidth;
+ },
+ getImageHeight : function() {
+ if (!isRunning) throw new Error("PixasticEditor::getImageHeight(): Editor is not running");
+
+ return imageHeight;
+ },
+ errorDialog : function() {
+ if (!isRunning) throw new Error("PixasticEditor::errorDialog(): Editor is not running");
+
+ return errorDialog.apply(null, arguments);
+ }
+ }
+
})();
\ No newline at end of file
-/*\r
- * Pixastic Lib - Core Functions - v0.1.3\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-var Pixastic = (function() {\r
-\r
-\r
- function addEvent(el, event, handler) {\r
- if (el.addEventListener)\r
- el.addEventListener(event, handler, false); \r
- else if (el.attachEvent)\r
- el.attachEvent("on" + event, handler); \r
- }\r
-\r
- function onready(handler) {\r
- var handlerDone = false;\r
- var execHandler = function() {\r
- if (!handlerDone) {\r
- handlerDone = true;\r
- handler();\r
- }\r
- }\r
- document.write("<"+"script defer src=\"//:\" id=\"__onload_ie_sumbox__\"></"+"script>");\r
- var script = document.getElementById("__onload_ie_sumbox__");\r
- script.onreadystatechange = function() {\r
- if (script.readyState == "complete") {\r
- script.parentNode.removeChild(script);\r
- execHandler();\r
- }\r
- }\r
- if (document.addEventListener)\r
- document.addEventListener("DOMContentLoaded", execHandler, false); \r
- addEvent(window, "load", execHandler);\r
- }\r
-\r
- function init() {\r
- if (!Pixastic.parseOnLoad) return;\r
- var imgEls = getElementsByClass("pixastic", null, "img");\r
- var canvasEls = getElementsByClass("pixastic", null, "canvas");\r
- var elements = imgEls.concat(canvasEls);\r
- for (var i=0;i<elements.length;i++) {\r
- (function() {\r
-\r
- var el = elements[i];\r
- var actions = [];\r
- var classes = el.className.split(" ");\r
- for (var c=0;c<classes.length;c++) {\r
- var cls = classes[c];\r
- if (cls.substring(0,9) == "pixastic-") {\r
- var actionName = cls.substring(9);\r
- if (actionName != "")\r
- actions.push(actionName);\r
- }\r
- }\r
- if (actions.length) {\r
- if (el.tagName.toLowerCase() == "img") {\r
- var dataImg = new Image();\r
- dataImg.src = el.src;\r
- if (dataImg.complete) {\r
- for (var a=0;a<actions.length;a++) {\r
- var res = Pixastic.applyAction(el, el, actions[a], null);\r
- if (res) \r
- el = res;\r
- }\r
- } else {\r
- dataImg.onload = function() {\r
- for (var a=0;a<actions.length;a++) {\r
- var res = Pixastic.applyAction(el, el, actions[a], null)\r
- if (res) \r
- el = res;\r
- }\r
- }\r
- }\r
- } else {\r
- setTimeout(function() {\r
- for (var a=0;a<actions.length;a++) {\r
- var res = Pixastic.applyAction(\r
- el, el, actions[a], null\r
- );\r
- if (res) \r
- el = res;\r
- }\r
- },1);\r
- }\r
- }\r
-\r
- })();\r
- }\r
- }\r
-\r
-// if (typeof pixastic_no_onready == "undefined") // yuck.\r
-// onready(init);\r
-\r
- // getElementsByClass by Dustin Diaz, http://www.dustindiaz.com/getelementsbyclass/\r
- function getElementsByClass(searchClass,node,tag) {\r
- var classElements = new Array();\r
- if ( node == null )\r
- node = document;\r
- if ( tag == null )\r
- tag = '*';\r
-\r
- var els = node.getElementsByTagName(tag);\r
- var elsLen = els.length;\r
- var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");\r
- for (i = 0, j = 0; i < elsLen; i++) {\r
- if ( pattern.test(els[i].className) ) {\r
- classElements[j] = els[i];\r
- j++;\r
- }\r
- }\r
- return classElements;\r
- }\r
-\r
- var debugElement;\r
-\r
- function writeDebug(text, level) {\r
- if (!Pixastic.debug) return;\r
- try {\r
- switch (level) {\r
- case "warn" : \r
- console.warn("Pixastic:", text);\r
- break;\r
- case "error" :\r
- console.error("Pixastic:", text);\r
- break;\r
- default:\r
- console.log("Pixastic:", text);\r
- }\r
- } catch(e) {\r
- }\r
- if (!debugElement) {\r
- \r
- }\r
- }\r
-\r
-\r
- return {\r
-\r
- parseOnLoad : false,\r
-\r
- debug : false,\r
- \r
- applyAction : function(img, dataImg, actionName, options) {\r
-\r
- options = options || {};\r
-\r
- var imageIsCanvas = (img.tagName.toLowerCase() == "canvas");\r
- if (imageIsCanvas && Pixastic.Client.isIE()) {\r
- if (Pixastic.debug) writeDebug("Tried to process a canvas element but browser is IE.");\r
- return false;\r
- }\r
-\r
- var canvas, ctx;\r
- if (Pixastic.Client.hasCanvas()) {\r
- canvas = document.createElement("canvas");\r
- ctx = canvas.getContext("2d");\r
- }\r
-\r
- var w = parseInt(img.offsetWidth);\r
- var h = parseInt(img.offsetHeight);\r
-\r
- if (imageIsCanvas) {\r
- w = img.width;\r
- h = img.height;\r
- }\r
-\r
- if (actionName.indexOf("(") > -1) {\r
- var tmp = actionName;\r
- actionName = tmp.substr(0, tmp.indexOf("("));\r
- var arg = tmp.match(/\((.*?)\)/);\r
- if (arg[1]) {\r
- arg = arg[1].split(";");\r
- for (var a=0;a<arg.length;a++) {\r
- thisArg = arg[a].split("=");\r
- if (thisArg.length == 2) {\r
- if (thisArg[0] == "rect") {\r
- var rectVal = thisArg[1].split(",");\r
- options[thisArg[0]] = {\r
- left : parseInt(rectVal[0],10)||0,\r
- top : parseInt(rectVal[1],10)||0,\r
- width : parseInt(rectVal[2],10)||0,\r
- height : parseInt(rectVal[3],10)||0\r
- }\r
- } else {\r
- options[thisArg[0]] = thisArg[1];\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- if (!options.rect) {\r
- options.rect = {\r
- left : 0, top : 0, width : w, height : h\r
- };\r
- }\r
- var validAction = false;\r
- if (Pixastic.Actions[actionName] && typeof Pixastic.Actions[actionName].process == "function") {\r
- validAction = true;\r
- }\r
- if (!validAction) {\r
- if (Pixastic.debug) writeDebug("Invalid action \"" + actionName + "\". Maybe file not included?");\r
- return false;\r
- }\r
- if (!Pixastic.Actions[actionName].checkSupport()) {\r
- if (Pixastic.debug) writeDebug("Action \"" + actionName + "\" not supported by this browser.");\r
- return false;\r
- }\r
-\r
- if (Pixastic.Client.hasCanvas()) {\r
- canvas.width = w;\r
- canvas.height = h;\r
- canvas.style.width = w+"px";\r
- canvas.style.height = h+"px";\r
- ctx.drawImage(dataImg,0,0,w,h);\r
-\r
- if (!img.__pixastic_org_image) {\r
- canvas.__pixastic_org_image = img;\r
- canvas.__pixastic_org_width = w;\r
- canvas.__pixastic_org_height = h;\r
- } else {\r
- canvas.__pixastic_org_image = img.__pixastic_org_image;\r
- canvas.__pixastic_org_width = img.__pixastic_org_width;\r
- canvas.__pixastic_org_height = img.__pixastic_org_height;\r
- }\r
-\r
- } else if (Pixastic.Client.isIE() && typeof img.__pixastic_org_style == "undefined") {\r
- img.__pixastic_org_style = img.style.cssText;\r
- }\r
-\r
- var params = {\r
- image : img,\r
- canvas : canvas,\r
- width : w,\r
- height : h,\r
- useData : true,\r
- options : options\r
- }\r
-\r
- // Ok, let's do it!\r
-\r
- var res = Pixastic.Actions[actionName].process(params);\r
-\r
- if (!res) {\r
- return false;\r
- }\r
-\r
- if (Pixastic.Client.hasCanvas()) {\r
- if (params.useData) {\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- canvas.getContext("2d").putImageData(params.canvasData, options.rect.left, options.rect.top);\r
-\r
- // Opera doesn't seem to update the canvas until we draw something on it, lets draw a 0x0 rectangle.\r
- canvas.getContext("2d").fillRect(0,0,0,0);\r
- }\r
- }\r
-\r
- if (!options.leaveDOM) {\r
- // copy properties and stuff from the source image\r
- canvas.title = img.title;\r
- canvas.imgsrc = img.imgsrc;\r
- if (!imageIsCanvas) canvas.alt = img.alt;\r
- if (!imageIsCanvas) canvas.imgsrc = img.src;\r
- canvas.className = img.className;\r
- canvas.style.cssText = img.style.cssText;\r
- canvas.name = img.name;\r
- canvas.tabIndex = img.tabIndex;\r
- canvas.id = img.id;\r
- if (img.parentNode && img.parentNode.replaceChild) {\r
- img.parentNode.replaceChild(canvas, img);\r
- }\r
- }\r
-\r
- options.resultCanvas = canvas;\r
-\r
- return canvas;\r
- }\r
-\r
- return img;\r
- },\r
-\r
- prepareData : function(params, getCopy) {\r
- var ctx = params.canvas.getContext("2d");\r
- var rect = params.options.rect;\r
- var dataDesc = ctx.getImageData(rect.left, rect.top, rect.width, rect.height);\r
- var data = dataDesc.data;\r
- if (!getCopy) params.canvasData = dataDesc;\r
- return data;\r
- },\r
-\r
- // load the image file\r
- process : function(img, actionName, options, callback)\r
- {\r
- if (img.tagName.toLowerCase() == "img") {\r
- var dataImg = new Image();\r
- dataImg.src = img.src;\r
- if (dataImg.complete) {\r
- var res = Pixastic.applyAction(img, dataImg, actionName, options);\r
- if (callback) callback(res);\r
- return res;\r
- } else {\r
- dataImg.onload = function() {\r
- var res = Pixastic.applyAction(img, dataImg, actionName, options)\r
- if (callback) callback(res);\r
- }\r
- }\r
- }\r
- if (img.tagName.toLowerCase() == "canvas") {\r
- var res = Pixastic.applyAction(img, img, actionName, options);\r
- if (callback) callback(res);\r
- return res;\r
- }\r
- },\r
-\r
- revert : function(img) {\r
- if (Pixastic.Client.hasCanvas()) {\r
- if (img.tagName.toLowerCase() == "canvas" && img.__pixastic_org_image) {\r
- img.width = img.__pixastic_org_width;\r
- img.height = img.__pixastic_org_height;\r
- img.getContext("2d").drawImage(img.__pixastic_org_image, 0, 0);\r
-\r
- if (img.parentNode && img.parentNode.replaceChild) {\r
- img.parentNode.replaceChild(img.__pixastic_org_image, img);\r
- }\r
-\r
- return img;\r
- }\r
- } else if (Pixastic.Client.isIE() && typeof img.__pixastic_org_style != "undefined") {\r
- img.style.cssText = img.__pixastic_org_style;\r
- }\r
- },\r
-\r
- Client : {\r
- hasCanvas : (function() {\r
- var c = document.createElement("canvas");\r
- var val = false;\r
- try {\r
- val = !!((typeof c.getContext == "function") && c.getContext("2d"));\r
- } catch(e) {}\r
- return function() {\r
- return val;\r
- }\r
- })(),\r
-\r
- hasCanvasImageData : (function() {\r
- var c = document.createElement("canvas");\r
- var val = false;\r
- var ctx;\r
- try {\r
- if (typeof c.getContext == "function" && (ctx = c.getContext("2d"))) {\r
- val = (typeof ctx.getImageData == "function");\r
- }\r
- } catch(e) {}\r
- return function() {\r
- return val;\r
- }\r
- })(),\r
-\r
- isIE : function() {\r
- return !!document.all && !!window.attachEvent && !window.opera;\r
- }\r
- },\r
-\r
- Actions : {}\r
- }\r
-\r
-\r
-})();\r
-/*\r
- * Pixastic Lib - jQuery plugin\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-if (typeof jQuery != "undefined" && jQuery && jQuery.fn) {\r
- jQuery.fn.pixastic = function(action, options) {\r
- var newElements = [];\r
- this.each(\r
- function () {\r
- if (this.tagName.toLowerCase() == "img" && !this.complete) {\r
- return;\r
- }\r
- var res = Pixastic.process(this, action, options);\r
- if (res) {\r
- newElements.push(res);\r
- }\r
- }\r
- );\r
- if (newElements.length > 0)\r
- return jQuery(newElements);\r
- else\r
- return this;\r
- };\r
-\r
-};\r
-/*\r
- * Pixastic Lib - Blend - v0.1.1\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.blend = {\r
-\r
- process : function(params) {\r
- var amount = parseFloat(params.options.amount);\r
- var mode = (params.options.mode || "normal").toLowerCase();\r
- var image = params.options.image;\r
-\r
- amount = Math.max(0,Math.min(1,amount));\r
-\r
- if (!image) return false;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var rect = params.options.rect;\r
- var data = Pixastic.prepareData(params);\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- params.useData = false;\r
-\r
- var otherCanvas = document.createElement("canvas");\r
- otherCanvas.width = params.canvas.width;\r
- otherCanvas.height = params.canvas.height;\r
- var otherCtx = otherCanvas.getContext("2d");\r
- otherCtx.drawImage(image,0,0);\r
-\r
- var params2 = {canvas:otherCanvas,options:params.options};\r
- var data2 = Pixastic.prepareData(params2);\r
- var dataDesc2 = params2.canvasData;\r
-\r
- var p = w*h;\r
- var pix = p*4;\r
- var pix1, pix2;\r
- var r1, g1, b1;\r
- var r2, g2, b2;\r
- var r3, g3, b3;\r
- var r4, g4, b4;\r
-\r
- var dataChanged = false;\r
-\r
- switch (mode) {\r
- case "normal" : \r
- //while (p--) {\r
- // data2[pix-=4] = data2[pix];\r
- // data2[pix1=pix+1] = data2[pix1];\r
- // data2[pix2=pix+2] = data2[pix2];\r
- //}\r
- break;\r
-\r
- case "multiply" : \r
- while (p--) {\r
- data2[pix-=4] = data[pix] * data2[pix] / 255;\r
- data2[pix1=pix+1] = data[pix1] * data2[pix1] / 255;\r
- data2[pix2=pix+2] = data[pix2] * data2[pix2] / 255;\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "lighten" : \r
- while (p--) {\r
- if ((r1 = data[pix-=4]) > data2[pix])\r
- data2[pix] = r1;\r
- if ((g1 = data[pix1=pix+1]) > data2[pix1])\r
- data2[pix1] = g1;\r
- if ((b1 = data[pix2=pix+2]) > data2[pix2])\r
- data2[pix2] = b1;\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "darken" : \r
- while (p--) {\r
- if ((r1 = data[pix-=4]) < data2[pix])\r
- data2[pix] = r1;\r
- if ((g1 = data[pix1=pix+1]) < data2[pix1])\r
- data2[pix1] = g1;\r
- if ((b1 = data[pix2=pix+2]) < data2[pix2])\r
- data2[pix2] = b1;\r
-\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "darkercolor" : \r
- while (p--) {\r
- 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)) {\r
- data2[pix] = r1;\r
- data2[pix1] = g1;\r
- data2[pix2] = b1;\r
- }\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "lightercolor" : \r
- while (p--) {\r
- 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)) {\r
- data2[pix] = r1;\r
- data2[pix1] = g1;\r
- data2[pix2] = b1;\r
- }\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "lineardodge" : \r
- otherCtx.globalCompositeOperation = "source-over";\r
- otherCtx.drawImage(params.canvas, 0, 0);\r
- otherCtx.globalCompositeOperation = "lighter";\r
- otherCtx.drawImage(image, 0, 0);\r
-\r
- /*\r
- while (p--) {\r
- if ((r3 = data[pix-=4] + data2[pix]) > 255)\r
- data2[pix] = 255;\r
- else\r
- data2[pix] = r3;\r
- if ((g3 = data[pix1=pix+1] + data2[pix1]) > 255)\r
- data2[pix1] = 255;\r
- else\r
- data2[pix1] = g3;\r
- if ((b3 = data[pix2=pix+2] + data2[pix2]) > 255)\r
- data2[pix2] = 255;\r
- else\r
- data2[pix2] = b3;\r
- }\r
- dataChanged = true;\r
- */\r
-\r
- break;\r
-\r
- case "linearburn" : \r
- while (p--) {\r
- if ((r3 = data[pix-=4] + data2[pix]) < 255)\r
- data2[pix] = 0;\r
- else\r
- data2[pix] = (r3 - 255);\r
- if ((g3 = data[pix1=pix+1] + data2[pix1]) < 255)\r
- data2[pix1] = 0;\r
- else\r
- data2[pix1] = (g3 - 255);\r
- if ((b3 = data[pix2=pix+2] + data2[pix2]) < 255)\r
- data2[pix2] = 0;\r
- else\r
- data2[pix2] = (b3 - 255);\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "difference" : \r
- while (p--) {\r
- if ((r3 = data[pix-=4] - data2[pix]) < 0)\r
- data2[pix] = -r3;\r
- else\r
- data2[pix] = r3;\r
- if ((g3 = data[pix1=pix+1] - data2[pix1]) < 0)\r
- data2[pix1] = -g3;\r
- else\r
- data2[pix1] = g3;\r
- if ((b3 = data[pix2=pix+2] - data2[pix2]) < 0)\r
- data2[pix2] = -b3;\r
- else\r
- data2[pix2] = b3;\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "screen" : \r
- while (p--) {\r
- data2[pix-=4] = (255 - ( ((255-data2[pix])*(255-data[pix])) >> 8));\r
- data2[pix1=pix+1] = (255 - ( ((255-data2[pix1])*(255-data[pix1])) >> 8));\r
- data2[pix2=pix+2] = (255 - ( ((255-data2[pix2])*(255-data[pix2])) >> 8));\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "exclusion" : \r
- var div_2_255 = 2 / 255;\r
- while (p--) {\r
- data2[pix-=4] = (r1 = data[pix]) - (r1 * div_2_255 - 1) * data2[pix];\r
- data2[pix1=pix+1] = (g1 = data[pix1]) - (g1 * div_2_255 - 1) * data2[pix1];\r
- data2[pix2=pix+2] = (b1 = data[pix2]) - (b1 * div_2_255 - 1) * data2[pix2];\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "overlay" : \r
- var div_2_255 = 2 / 255;\r
- while (p--) {\r
- if ((r1 = data[pix-=4]) < 128)\r
- data2[pix] = data2[pix]*r1*div_2_255;\r
- else\r
- data2[pix] = 255 - (255-data2[pix])*(255-r1)*div_2_255;\r
-\r
- if ((g1 = data[pix1=pix+1]) < 128)\r
- data2[pix1] = data2[pix1]*g1*div_2_255;\r
- else\r
- data2[pix1] = 255 - (255-data2[pix1])*(255-g1)*div_2_255;\r
-\r
- if ((b1 = data[pix2=pix+2]) < 128)\r
- data2[pix2] = data2[pix2]*b1*div_2_255;\r
- else\r
- data2[pix2] = 255 - (255-data2[pix2])*(255-b1)*div_2_255;\r
-\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "softlight" : \r
- var div_2_255 = 2 / 255;\r
- while (p--) {\r
- if ((r1 = data[pix-=4]) < 128)\r
- data2[pix] = ((data2[pix]>>1) + 64) * r1 * div_2_255;\r
- else\r
- data2[pix] = 255 - (191 - (data2[pix]>>1)) * (255-r1) * div_2_255;\r
-\r
- if ((g1 = data[pix1=pix+1]) < 128)\r
- data2[pix1] = ((data2[pix1]>>1)+64) * g1 * div_2_255;\r
- else\r
- data2[pix1] = 255 - (191 - (data2[pix1]>>1)) * (255-g1) * div_2_255;\r
-\r
- if ((b1 = data[pix2=pix+2]) < 128)\r
- data2[pix2] = ((data2[pix2]>>1)+64) * b1 * div_2_255;\r
- else\r
- data2[pix2] = 255 - (191 - (data2[pix2]>>1)) * (255-b1) * div_2_255;\r
-\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "hardlight" : \r
- var div_2_255 = 2 / 255;\r
- while (p--) {\r
- if ((r2 = data2[pix-=4]) < 128)\r
- data2[pix] = data[pix] * r2 * div_2_255;\r
- else\r
- data2[pix] = 255 - (255-data[pix]) * (255-r2) * div_2_255;\r
-\r
- if ((g2 = data2[pix1=pix+1]) < 128)\r
- data2[pix1] = data[pix1] * g2 * div_2_255;\r
- else\r
- data2[pix1] = 255 - (255-data[pix1]) * (255-g2) * div_2_255;\r
-\r
- if ((b2 = data2[pix2=pix+2]) < 128)\r
- data2[pix2] = data[pix2] * b2 * div_2_255;\r
- else\r
- data2[pix2] = 255 - (255-data[pix2]) * (255-b2) * div_2_255;\r
-\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "colordodge" : \r
- while (p--) {\r
- if ((r3 = (data[pix-=4]<<8)/(255-(r2 = data2[pix]))) > 255 || r2 == 255)\r
- data2[pix] = 255;\r
- else\r
- data2[pix] = r3;\r
-\r
- if ((g3 = (data[pix1=pix+1]<<8)/(255-(g2 = data2[pix1]))) > 255 || g2 == 255)\r
- data2[pix1] = 255;\r
- else\r
- data2[pix1] = g3;\r
-\r
- if ((b3 = (data[pix2=pix+2]<<8)/(255-(b2 = data2[pix2]))) > 255 || b2 == 255)\r
- data2[pix2] = 255;\r
- else\r
- data2[pix2] = b3;\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "colorburn" : \r
- while (p--) {\r
- if ((r3 = 255-((255-data[pix-=4])<<8)/data2[pix]) < 0 || data2[pix] == 0)\r
- data2[pix] = 0;\r
- else\r
- data2[pix] = r3;\r
-\r
- if ((g3 = 255-((255-data[pix1=pix+1])<<8)/data2[pix1]) < 0 || data2[pix1] == 0)\r
- data2[pix1] = 0;\r
- else\r
- data2[pix1] = g3;\r
-\r
- if ((b3 = 255-((255-data[pix2=pix+2])<<8)/data2[pix2]) < 0 || data2[pix2] == 0)\r
- data2[pix2] = 0;\r
- else\r
- data2[pix2] = b3;\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "linearlight" : \r
- while (p--) {\r
- if ( ((r3 = 2*(r2=data2[pix-=4])+data[pix]-256) < 0) || (r2 < 128 && r3 < 0)) {\r
- data2[pix] = 0\r
- } else {\r
- if (r3 > 255)\r
- data2[pix] = 255;\r
- else\r
- data2[pix] = r3;\r
- }\r
- if ( ((g3 = 2*(g2=data2[pix1=pix+1])+data[pix1]-256) < 0) || (g2 < 128 && g3 < 0)) {\r
- data2[pix1] = 0\r
- } else {\r
- if (g3 > 255)\r
- data2[pix1] = 255;\r
- else\r
- data2[pix1] = g3;\r
- }\r
- if ( ((b3 = 2*(b2=data2[pix2=pix+2])+data[pix2]-256) < 0) || (b2 < 128 && b3 < 0)) {\r
- data2[pix2] = 0\r
- } else {\r
- if (b3 > 255)\r
- data2[pix2] = 255;\r
- else\r
- data2[pix2] = b3;\r
- }\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "vividlight" : \r
- while (p--) {\r
- if ((r2=data2[pix-=4]) < 128) {\r
- if (r2) {\r
- if ((r3 = 255 - ((255-data[pix])<<8) / (2*r2)) < 0) \r
- data2[pix] = 0;\r
- else\r
- data2[pix] = r3\r
- } else {\r
- data2[pix] = 0;\r
- }\r
- } else if ((r3 = (r4=2*r2-256)) < 255) {\r
- if ((r3 = (data[pix]<<8)/(255-r4)) > 255) \r
- data2[pix] = 255;\r
- else\r
- data2[pix] = r3;\r
- } else {\r
- if (r3 < 0) \r
- data2[pix] = 0;\r
- else\r
- data2[pix] = r3\r
- }\r
-\r
- if ((g2=data2[pix1=pix+1]) < 128) {\r
- if (g2) {\r
- if ((g3 = 255 - ((255-data[pix1])<<8) / (2*g2)) < 0) \r
- data2[pix1] = 0;\r
- else\r
- data2[pix1] = g3;\r
- } else {\r
- data2[pix1] = 0;\r
- }\r
- } else if ((g3 = (g4=2*g2-256)) < 255) {\r
- if ((g3 = (data[pix1]<<8)/(255-g4)) > 255)\r
- data2[pix1] = 255;\r
- else\r
- data2[pix1] = g3;\r
- } else {\r
- if (g3 < 0) \r
- data2[pix1] = 0;\r
- else\r
- data2[pix1] = g3;\r
- }\r
-\r
- if ((b2=data2[pix2=pix+2]) < 128) {\r
- if (b2) {\r
- if ((b3 = 255 - ((255-data[pix2])<<8) / (2*b2)) < 0) \r
- data2[pix2] = 0;\r
- else\r
- data2[pix2] = b3;\r
- } else {\r
- data2[pix2] = 0;\r
- }\r
- } else if ((b3 = (b4=2*b2-256)) < 255) {\r
- if ((b3 = (data[pix2]<<8)/(255-b4)) > 255) \r
- data2[pix2] = 255;\r
- else\r
- data2[pix2] = b3;\r
- } else {\r
- if (b3 < 0) \r
- data2[pix2] = 0;\r
- else\r
- data2[pix2] = b3;\r
- }\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "pinlight" : \r
- while (p--) {\r
- if ((r2=data2[pix-=4]) < 128)\r
- if ((r1=data[pix]) < (r4=2*r2))\r
- data2[pix] = r1;\r
- else\r
- data2[pix] = r4;\r
- else\r
- if ((r1=data[pix]) > (r4=2*r2-256))\r
- data2[pix] = r1;\r
- else\r
- data2[pix] = r4;\r
-\r
- if ((g2=data2[pix1=pix+1]) < 128)\r
- if ((g1=data[pix1]) < (g4=2*g2))\r
- data2[pix1] = g1;\r
- else\r
- data2[pix1] = g4;\r
- else\r
- if ((g1=data[pix1]) > (g4=2*g2-256))\r
- data2[pix1] = g1;\r
- else\r
- data2[pix1] = g4;\r
-\r
- if ((r2=data2[pix2=pix+2]) < 128)\r
- if ((r1=data[pix2]) < (r4=2*r2))\r
- data2[pix2] = r1;\r
- else\r
- data2[pix2] = r4;\r
- else\r
- if ((r1=data[pix2]) > (r4=2*r2-256))\r
- data2[pix2] = r1;\r
- else\r
- data2[pix2] = r4;\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "hardmix" : \r
- while (p--) {\r
- if ((r2 = data2[pix-=4]) < 128)\r
- if (255 - ((255-data[pix])<<8)/(2*r2) < 128 || r2 == 0)\r
- data2[pix] = 0;\r
- else\r
- data2[pix] = 255;\r
- else if ((r4=2*r2-256) < 255 && (data[pix]<<8)/(255-r4) < 128)\r
- data2[pix] = 0;\r
- else\r
- data2[pix] = 255;\r
-\r
- if ((g2 = data2[pix1=pix+1]) < 128)\r
- if (255 - ((255-data[pix1])<<8)/(2*g2) < 128 || g2 == 0)\r
- data2[pix1] = 0;\r
- else\r
- data2[pix1] = 255;\r
- else if ((g4=2*g2-256) < 255 && (data[pix1]<<8)/(255-g4) < 128)\r
- data2[pix1] = 0;\r
- else\r
- data2[pix1] = 255;\r
-\r
- if ((b2 = data2[pix2=pix+2]) < 128)\r
- if (255 - ((255-data[pix2])<<8)/(2*b2) < 128 || b2 == 0)\r
- data2[pix2] = 0;\r
- else\r
- data2[pix2] = 255;\r
- else if ((b4=2*b2-256) < 255 && (data[pix2]<<8)/(255-b4) < 128)\r
- data2[pix2] = 0;\r
- else\r
- data2[pix2] = 255;\r
- }\r
- dataChanged = true;\r
- break;\r
- }\r
-\r
- if (dataChanged) \r
- otherCtx.putImageData(dataDesc2,0,0);\r
-\r
- var ctx = params.canvas.getContext("2d");\r
- ctx.save();\r
- ctx.globalAlpha = amount;\r
- ctx.drawImage(\r
- otherCanvas,\r
- 0,0,rect.width,rect.height,\r
- rect.left,rect.top,rect.width,rect.height\r
- );\r
- ctx.globalAlpha = 1;\r
- ctx.restore();\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}/*\r
- * Pixastic Lib - Blur filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.blur = {\r
- process : function(params) {\r
-\r
- if (typeof params.options.fixMargin == "undefined")\r
- params.options.fixMargin = true;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var dataCopy = Pixastic.prepareData(params, true)\r
-\r
- /*\r
- var kernel = [\r
- [0.5, 1, 0.5],\r
- [1, 2, 1],\r
- [0.5, 1, 0.5]\r
- ];\r
- */\r
-\r
- var kernel = [\r
- [0, 1, 0],\r
- [1, 2, 1],\r
- [0, 1, 0]\r
- ];\r
-\r
- var weight = 0;\r
- for (var i=0;i<3;i++) {\r
- for (var j=0;j<3;j++) {\r
- weight += kernel[i][j];\r
- }\r
- }\r
-\r
- weight = 1 / (weight*2);\r
-\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
-\r
- var prevY = (y == 1) ? 0 : y-2;\r
- var nextY = (y == h) ? y - 1 : y;\r
-\r
- var offsetYPrev = prevY*w*4;\r
- var offsetYNext = nextY*w*4;\r
-\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x*4-4);\r
-\r
- var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;\r
- var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;\r
- \r
- data[offset] = (\r
- /*\r
- dataCopy[offsetPrev - 4]\r
- + dataCopy[offsetPrev+4] \r
- + dataCopy[offsetNext - 4]\r
- + dataCopy[offsetNext+4]\r
- + \r
- */\r
- (dataCopy[offsetPrev]\r
- + dataCopy[offset-4]\r
- + dataCopy[offset+4]\r
- + dataCopy[offsetNext]) * 2\r
- + dataCopy[offset] * 4\r
- ) * weight;\r
-\r
- data[offset+1] = (\r
- /*\r
- dataCopy[offsetPrev - 3]\r
- + dataCopy[offsetPrev+5] \r
- + dataCopy[offsetNext - 3] \r
- + dataCopy[offsetNext+5]\r
- + \r
- */\r
- (dataCopy[offsetPrev+1]\r
- + dataCopy[offset-3]\r
- + dataCopy[offset+5]\r
- + dataCopy[offsetNext+1]) * 2\r
- + dataCopy[offset+1] * 4\r
- ) * weight;\r
-\r
- data[offset+2] = (\r
- /*\r
- dataCopy[offsetPrev - 2] \r
- + dataCopy[offsetPrev+6] \r
- + dataCopy[offsetNext - 2] \r
- + dataCopy[offsetNext+6]\r
- + \r
- */\r
- (dataCopy[offsetPrev+2]\r
- + dataCopy[offset-2]\r
- + dataCopy[offset+6]\r
- + dataCopy[offsetNext+2]) * 2\r
- + dataCopy[offset+2] * 4\r
- ) * weight;\r
-\r
- } while (--x);\r
- } while (--y);\r
-\r
- return true;\r
-\r
- } else if (Pixastic.Client.isIE()) {\r
- params.image.style.filter += " progid:DXImageTransform.Microsoft.Blur(pixelradius=1.5)";\r
-\r
- if (params.options.fixMargin) {\r
- params.image.style.marginLeft = (parseInt(params.image.style.marginLeft,10)||0) - 2 + "px";\r
- params.image.style.marginTop = (parseInt(params.image.style.marginTop,10)||0) - 2 + "px";\r
- }\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());\r
- }\r
-}/*\r
- * Pixastic Lib - Blur Fast - v0.1.1\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.blurfast = {\r
- process : function(params) {\r
-\r
- var amount = parseFloat(params.options.amount)||0;\r
- var clear = !!(params.options.clear && params.options.clear != "false");\r
-\r
- amount = Math.max(0,Math.min(5,amount));\r
-\r
- if (Pixastic.Client.hasCanvas()) {\r
- var rect = params.options.rect;\r
-\r
- var ctx = params.canvas.getContext("2d");\r
- ctx.save();\r
- ctx.beginPath();\r
- ctx.rect(rect.left, rect.top, rect.width, rect.height);\r
- ctx.clip();\r
-\r
- var scale = 2;\r
- var smallWidth = Math.round(params.width / scale);\r
- var smallHeight = Math.round(params.height / scale);\r
-\r
- var copy = document.createElement("canvas");\r
- copy.width = smallWidth;\r
- copy.height = smallHeight;\r
-\r
- var clear = false;\r
- var steps = Math.round(amount * 20);\r
-\r
- var copyCtx = copy.getContext("2d");\r
- for (var i=0;i<steps;i++) {\r
- var scaledWidth = Math.max(1,Math.round(smallWidth - i));\r
- var scaledHeight = Math.max(1,Math.round(smallHeight - i));\r
- \r
- copyCtx.clearRect(0,0,smallWidth,smallHeight);\r
- \r
- copyCtx.drawImage(\r
- params.canvas,\r
- 0,0,params.width,params.height,\r
- 0,0,scaledWidth,scaledHeight\r
- );\r
- \r
- if (clear)\r
- ctx.clearRect(rect.left,rect.top,rect.width,rect.height);\r
- \r
- ctx.drawImage(\r
- copy,\r
- 0,0,scaledWidth,scaledHeight,\r
- 0,0,params.width,params.height\r
- );\r
- }\r
-\r
- ctx.restore();\r
-\r
- params.useData = false;\r
- return true;\r
- } else if (Pixastic.Client.isIE()) {\r
- var radius = 10 * amount;\r
- params.image.style.filter += " progid:DXImageTransform.Microsoft.Blur(pixelradius=" + radius + ")";\r
-\r
- if (params.options.fixMargin || 1) {\r
- params.image.style.marginLeft = (parseInt(params.image.style.marginLeft,10)||0) - Math.round(radius) + "px";\r
- params.image.style.marginTop = (parseInt(params.image.style.marginTop,10)||0) - Math.round(radius) + "px";\r
- }\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());\r
- }\r
-}\r
-/*\r
- * Pixastic Lib - Brightness/Contrast filter - v0.1.1\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.brightness = {\r
-\r
- process : function(params) {\r
-\r
- var brightness = parseInt(params.options.brightness,10) || 0;\r
- var contrast = parseFloat(params.options.contrast)||0;\r
- var legacy = !!(params.options.legacy && params.options.legacy != "false");\r
-\r
- if (legacy) {\r
- brightness = Math.min(150,Math.max(-150,brightness));\r
- } else {\r
- var brightMul = 1 + Math.min(150,Math.max(-150,brightness)) / 150;\r
- }\r
- contrast = Math.max(0,contrast+1);\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var p = w*h;\r
- var pix = p*4, pix1, pix2;\r
-\r
- var mul, add;\r
- if (contrast != 1) {\r
- if (legacy) {\r
- mul = contrast;\r
- add = (brightness - 128) * contrast + 128;\r
- } else {\r
- mul = brightMul * contrast;\r
- add = - contrast * 128 + 128;\r
- }\r
- } else { // this if-then is not necessary anymore, is it?\r
- if (legacy) {\r
- mul = 1;\r
- add = brightness;\r
- } else {\r
- mul = brightMul;\r
- add = 0;\r
- }\r
- }\r
- var r, g, b;\r
- while (p--) {\r
- if ((r = data[pix-=4] * mul + add) > 255 )\r
- data[pix] = 255;\r
- else if (r < 0)\r
- data[pix] = 0;\r
- else\r
- data[pix] = r;\r
-\r
- if ((g = data[pix1=pix+1] * mul + add) > 255 ) \r
- data[pix1] = 255;\r
- else if (g < 0)\r
- data[pix1] = 0;\r
- else\r
- data[pix1] = g;\r
-\r
- if ((b = data[pix2=pix+2] * mul + add) > 255 ) \r
- data[pix2] = 255;\r
- else if (b < 0)\r
- data[pix2] = 0;\r
- else\r
- data[pix2] = b;\r
- }\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}\r
-\r
-/*\r
- * Pixastic Lib - Color adjust filter - v0.1.1\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.coloradjust = {\r
-\r
- process : function(params) {\r
- var red = parseFloat(params.options.red) || 0;\r
- var green = parseFloat(params.options.green) || 0;\r
- var blue = parseFloat(params.options.blue) || 0;\r
-\r
- red = Math.round(red*255);\r
- green = Math.round(green*255);\r
- blue = Math.round(blue*255);\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var rect = params.options.rect;\r
-\r
- var p = rect.width*rect.height;\r
- var pix = p*4, pix1, pix2;\r
-\r
- var r, g, b;\r
- while (p--) {\r
- pix -= 4;\r
-\r
- if (red) {\r
- if ((r = data[pix] + red) < 0 ) \r
- data[pix] = 0;\r
- else if (r > 255 ) \r
- data[pix] = 255;\r
- else\r
- data[pix] = r;\r
- }\r
-\r
- if (green) {\r
- if ((g = data[pix1=pix+1] + green) < 0 ) \r
- data[pix1] = 0;\r
- else if (g > 255 ) \r
- data[pix1] = 255;\r
- else\r
- data[pix1] = g;\r
- }\r
-\r
- if (blue) {\r
- if ((b = data[pix2=pix+2] + blue) < 0 ) \r
- data[pix2] = 0;\r
- else if (b > 255 ) \r
- data[pix2] = 255;\r
- else\r
- data[pix2] = b;\r
- }\r
- }\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvasImageData());\r
- }\r
-}\r
-/*\r
- * Pixastic Lib - Histogram - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-\r
-Pixastic.Actions.colorhistogram = {\r
-\r
- array256 : function(default_value) {\r
- arr = [];\r
- for (var i=0; i<256; i++) { arr[i] = default_value; }\r
- return arr\r
- },\r
- \r
- process : function(params) {\r
- var values = [];\r
- if (typeof params.options.returnValue != "object") {\r
- params.options.returnValue = {rvals:[], gvals:[], bvals:[]};\r
- }\r
- var paint = !!(params.options.paint);\r
-\r
- var returnValue = params.options.returnValue;\r
- if (typeof returnValue.values != "array") {\r
- returnValue.rvals = [];\r
- returnValue.gvals = [];\r
- returnValue.bvals = [];\r
- }\r
- \r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- params.useData = false;\r
- \r
- var rvals = this.array256(0);\r
- var gvals = this.array256(0);\r
- var bvals = this.array256(0);\r
- \r
- var rect = params.options.rect;\r
-\r
- var p = rect.width*rect.height;\r
- var pix = p*4;\r
- while (p--) {\r
- rvals[data[pix-=4]]++;\r
- gvals[data[pix+1]]++;\r
- bvals[data[pix+2]]++;\r
- }\r
- \r
- returnValue.rvals = rvals;\r
- returnValue.gvals = gvals;\r
- returnValue.bvals = bvals;\r
-\r
- if (paint) {\r
- var ctx = params.canvas.getContext("2d");\r
- var vals = [rvals, gvals, bvals];\r
- for (var v=0;v<3;v++) {\r
- var yoff = (v+1) * params.height / 3;\r
- var maxValue = 0;\r
- for (var i=0;i<256;i++) {\r
- if (vals[v][i] > maxValue)\r
- maxValue = vals[v][i];\r
- }\r
- var heightScale = params.height / 3 / maxValue;\r
- var widthScale = params.width / 256;\r
- if (v==0) ctx.fillStyle = "rgba(255,0,0,0.5)";\r
- else if (v==1) ctx.fillStyle = "rgba(0,255,0,0.5)";\r
- else if (v==2) ctx.fillStyle = "rgba(0,0,255,0.5)";\r
- for (var i=0;i<256;i++) {\r
- ctx.fillRect(\r
- i * widthScale, params.height - heightScale * vals[v][i] - params.height + yoff,\r
- widthScale, vals[v][i] * heightScale\r
- );\r
- }\r
- }\r
- }\r
- return true;\r
- }\r
- },\r
-\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}/*\r
- * Pixastic Lib - Crop - v0.1.1\r
- * Copyright (c) 2008-2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.crop = {\r
- process : function(params) {\r
- if (Pixastic.Client.hasCanvas()) {\r
- var rect = params.options.rect;\r
-\r
- var width = rect.width;\r
- var height = rect.height;\r
- var top = rect.top;\r
- var left = rect.left;\r
-\r
- if (typeof params.options.left != "undefined")\r
- left = parseInt(params.options.left,10);\r
- if (typeof params.options.top != "undefined")\r
- top = parseInt(params.options.top,10);\r
- if (typeof params.options.height != "undefined")\r
- width = parseInt(params.options.width,10);\r
- if (typeof params.options.height != "undefined")\r
- height = parseInt(params.options.height,10);\r
-\r
- if (left < 0) left = 0;\r
- if (left > params.width-1) left = params.width-1;\r
-\r
- if (top < 0) top = 0;\r
- if (top > params.height-1) top = params.height-1;\r
-\r
- if (width < 1) width = 1;\r
- if (left + width > params.width)\r
- width = params.width - left;\r
-\r
- if (height < 1) height = 1;\r
- if (top + height > params.height)\r
- height = params.height - top;\r
-\r
- var copy = document.createElement("canvas");\r
- copy.width = params.width;\r
- copy.height = params.height;\r
- copy.getContext("2d").drawImage(params.canvas,0,0);\r
-\r
- params.canvas.width = width;\r
- params.canvas.height = height;\r
- params.canvas.getContext("2d").clearRect(0,0,width,height);\r
-\r
- params.canvas.getContext("2d").drawImage(copy,\r
- left,top,width,height,\r
- 0,0,width,height\r
- );\r
-\r
- params.useData = false;\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvas();\r
- }\r
-}\r
-\r
-\r
-/*\r
- * Pixastic Lib - Desaturation filter - v0.1.1\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.desaturate = {\r
-\r
- process : function(params) {\r
- var useAverage = !!(params.options.average && params.options.average != "false");\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var p = w*h;\r
- var pix = p*4, pix1, pix2;\r
-\r
- if (useAverage) {\r
- while (p--) \r
- data[pix-=4] = data[pix1=pix+1] = data[pix2=pix+2] = (data[pix]+data[pix1]+data[pix2])/3\r
- } else {\r
- while (p--)\r
- data[pix-=4] = data[pix1=pix+1] = data[pix2=pix+2] = (data[pix]*0.3 + data[pix1]*0.59 + data[pix2]*0.11);\r
- }\r
- return true;\r
- } else if (Pixastic.Client.isIE()) {\r
- params.image.style.filter += " gray";\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());\r
- }\r
-}/*\r
- * Pixastic Lib - Edge detection filter - v0.1.1\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.edges = {\r
- process : function(params) {\r
-\r
- var mono = !!(params.options.mono && params.options.mono != "false");\r
- var invert = !!(params.options.invert && params.options.invert != "false");\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var dataCopy = Pixastic.prepareData(params, true)\r
-\r
- var c = -1/8;\r
- var kernel = [\r
- [c, c, c],\r
- [c, 1, c],\r
- [c, c, c]\r
- ];\r
-\r
- weight = 1/c;\r
-\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
-\r
- var nextY = (y == h) ? y - 1 : y;\r
- var prevY = (y == 1) ? 0 : y-2;\r
-\r
- var offsetYPrev = prevY*w*4;\r
- var offsetYNext = nextY*w*4;\r
-\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x*4-4);\r
-\r
- var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;\r
- var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;\r
- \r
- var r = ((dataCopy[offsetPrev-4]\r
- + dataCopy[offsetPrev]\r
- + dataCopy[offsetPrev+4]\r
- + dataCopy[offset-4]\r
- + dataCopy[offset+4]\r
- + dataCopy[offsetNext-4]\r
- + dataCopy[offsetNext]\r
- + dataCopy[offsetNext+4]) * c\r
- + dataCopy[offset]\r
- ) \r
- * weight;\r
- \r
- var g = ((dataCopy[offsetPrev-3]\r
- + dataCopy[offsetPrev+1]\r
- + dataCopy[offsetPrev+5]\r
- + dataCopy[offset-3]\r
- + dataCopy[offset+5]\r
- + dataCopy[offsetNext-3]\r
- + dataCopy[offsetNext+1]\r
- + dataCopy[offsetNext+5]) * c\r
- + dataCopy[offset+1])\r
- * weight;\r
- \r
- var b = ((dataCopy[offsetPrev-2]\r
- + dataCopy[offsetPrev+2]\r
- + dataCopy[offsetPrev+6]\r
- + dataCopy[offset-2]\r
- + dataCopy[offset+6]\r
- + dataCopy[offsetNext-2]\r
- + dataCopy[offsetNext+2]\r
- + dataCopy[offsetNext+6]) * c\r
- + dataCopy[offset+2])\r
- * weight;\r
-\r
- if (mono) {\r
- var brightness = (r*0.3 + g*0.59 + b*0.11)||0;\r
- if (invert) brightness = 255 - brightness;\r
- if (brightness < 0 ) brightness = 0;\r
- if (brightness > 255 ) brightness = 255;\r
- r = g = b = brightness;\r
- } else {\r
- if (invert) {\r
- r = 255 - r;\r
- g = 255 - g;\r
- b = 255 - b;\r
- }\r
- if (r < 0 ) r = 0;\r
- if (g < 0 ) g = 0;\r
- if (b < 0 ) b = 0;\r
- if (r > 255 ) r = 255;\r
- if (g > 255 ) g = 255;\r
- if (b > 255 ) b = 255;\r
- }\r
-\r
- data[offset] = r;\r
- data[offset+1] = g;\r
- data[offset+2] = b;\r
-\r
- } while (--x);\r
- } while (--y);\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}/*\r
- * Pixastic Lib - Edge detection 2 - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- * \r
- * Contribution by Oliver Hunt (http://nerget.com/, http://nerget.com/canvas/edgeDetection.js). Thanks Oliver!\r
- *\r
- */\r
-\r
-Pixastic.Actions.edges2 = {\r
- process : function(params) {\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var dataCopy = Pixastic.prepareData(params, true)\r
-\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var w4 = w * 4;\r
- var pixel = w4 + 4; // Start at (1,1)\r
- var hm1 = h - 1;\r
- var wm1 = w - 1;\r
- for (var y = 1; y < hm1; ++y) {\r
- // Prepare initial cached values for current row\r
- var centerRow = pixel - 4;\r
- var priorRow = centerRow - w4;\r
- var nextRow = centerRow + w4;\r
- \r
- var r1 = - dataCopy[priorRow] - dataCopy[centerRow] - dataCopy[nextRow];\r
- var g1 = - dataCopy[++priorRow] - dataCopy[++centerRow] - dataCopy[++nextRow];\r
- var b1 = - dataCopy[++priorRow] - dataCopy[++centerRow] - dataCopy[++nextRow];\r
- \r
- var rp = dataCopy[priorRow += 2];\r
- var gp = dataCopy[++priorRow];\r
- var bp = dataCopy[++priorRow];\r
- \r
- var rc = dataCopy[centerRow += 2];\r
- var gc = dataCopy[++centerRow];\r
- var bc = dataCopy[++centerRow];\r
- \r
- var rn = dataCopy[nextRow += 2];\r
- var gn = dataCopy[++nextRow];\r
- var bn = dataCopy[++nextRow];\r
- \r
- var r2 = - rp - rc - rn;\r
- var g2 = - gp - gc - gn;\r
- var b2 = - bp - bc - bn;\r
- \r
- // Main convolution loop\r
- for (var x = 1; x < wm1; ++x) {\r
- centerRow = pixel + 4;\r
- priorRow = centerRow - w4;\r
- nextRow = centerRow + w4;\r
- \r
- var r = 127 + r1 - rp - (rc * -8) - rn;\r
- var g = 127 + g1 - gp - (gc * -8) - gn;\r
- var b = 127 + b1 - bp - (bc * -8) - bn;\r
- \r
- r1 = r2;\r
- g1 = g2;\r
- b1 = b2;\r
- \r
- rp = dataCopy[ priorRow];\r
- gp = dataCopy[++priorRow];\r
- bp = dataCopy[++priorRow];\r
- \r
- rc = dataCopy[ centerRow];\r
- gc = dataCopy[++centerRow];\r
- bc = dataCopy[++centerRow];\r
- \r
- rn = dataCopy[ nextRow];\r
- gn = dataCopy[++nextRow];\r
- bn = dataCopy[++nextRow];\r
- \r
- r += (r2 = - rp - rc - rn);\r
- g += (g2 = - gp - gc - gn);\r
- b += (b2 = - bp - bc - bn);\r
-\r
- if (r > 255) r = 255;\r
- if (g > 255) g = 255;\r
- if (b > 255) b = 255;\r
- if (r < 0) r = 0;\r
- if (g < 0) g = 0;\r
- if (b < 0) b = 0;\r
-\r
- data[pixel] = r;\r
- data[++pixel] = g;\r
- data[++pixel] = b;\r
- //data[++pixel] = 255; // alpha\r
-\r
- pixel+=2;\r
- }\r
- pixel += 8;\r
- }\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}/*\r
- * Pixastic Lib - Emboss filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.emboss = {\r
- process : function(params) {\r
-\r
- var strength = parseFloat(params.options.strength)||1;\r
- var greyLevel = typeof params.options.greyLevel != "undefined" ? parseInt(params.options.greyLevel) : 180;\r
- var direction = params.options.direction||"topleft";\r
- var blend = !!(params.options.blend && params.options.blend != "false");\r
-\r
- var dirY = 0;\r
- var dirX = 0;\r
-\r
- switch (direction) {\r
- case "topleft": // top left\r
- dirY = -1;\r
- dirX = -1;\r
- break;\r
- case "top": // top\r
- dirY = -1;\r
- dirX = 0;\r
- break;\r
- case "topright": // top right\r
- dirY = -1;\r
- dirX = 1;\r
- break;\r
- case "right": // right\r
- dirY = 0;\r
- dirX = 1;\r
- break;\r
- case "bottomright": // bottom right\r
- dirY = 1;\r
- dirX = 1;\r
- break;\r
- case "bottom": // bottom\r
- dirY = 1;\r
- dirX = 0;\r
- break;\r
- case "bottomleft": // bottom left\r
- dirY = 1;\r
- dirX = -1;\r
- break;\r
- case "left": // left\r
- dirY = 0;\r
- dirX = -1;\r
- break;\r
- }\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var dataCopy = Pixastic.prepareData(params, true)\r
-\r
- var invertAlpha = !!params.options.invertAlpha;\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
-\r
- var otherY = dirY;\r
- if (y + otherY < 1) otherY = 0;\r
- if (y + otherY > h) otherY = 0;\r
-\r
- var offsetYOther = (y-1+otherY)*w*4;\r
-\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x-1)*4;\r
-\r
- var otherX = dirX;\r
- if (x + otherX < 1) otherX = 0;\r
- if (x + otherX > w) otherX = 0;\r
-\r
- var offsetOther = offsetYOther + (x-1+otherX)*4;\r
-\r
- var dR = dataCopy[offset] - dataCopy[offsetOther];\r
- var dG = dataCopy[offset+1] - dataCopy[offsetOther+1];\r
- var dB = dataCopy[offset+2] - dataCopy[offsetOther+2];\r
-\r
- var dif = dR;\r
- var absDif = dif > 0 ? dif : -dif;\r
-\r
- var absG = dG > 0 ? dG : -dG;\r
- var absB = dB > 0 ? dB : -dB;\r
-\r
- if (absG > absDif) {\r
- dif = dG;\r
- }\r
- if (absB > absDif) {\r
- dif = dB;\r
- }\r
-\r
- dif *= strength;\r
-\r
- if (blend) {\r
- var r = data[offset] + dif;\r
- var g = data[offset+1] + dif;\r
- var b = data[offset+2] + dif;\r
-\r
- data[offset] = (r > 255) ? 255 : (r < 0 ? 0 : r);\r
- data[offset+1] = (g > 255) ? 255 : (g < 0 ? 0 : g);\r
- data[offset+2] = (b > 255) ? 255 : (b < 0 ? 0 : b);\r
- } else {\r
- var grey = greyLevel - dif;\r
- if (grey < 0) {\r
- grey = 0;\r
- } else if (grey > 255) {\r
- grey = 255;\r
- }\r
-\r
- data[offset] = data[offset+1] = data[offset+2] = grey;\r
- }\r
-\r
- } while (--x);\r
- } while (--y);\r
- return true;\r
-\r
- } else if (Pixastic.Client.isIE()) {\r
- params.image.style.filter += " progid:DXImageTransform.Microsoft.emboss()";\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());\r
- }\r
-\r
-}\r
-/*\r
- * Pixastic Lib - Flip - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.flip = {\r
- process : function(params) {\r
- var rect = params.options.rect;\r
- var copyCanvas = document.createElement("canvas");\r
- copyCanvas.width = rect.width;\r
- copyCanvas.height = rect.height;\r
- copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);\r
-\r
- var ctx = params.canvas.getContext("2d");\r
- ctx.clearRect(rect.left, rect.top, rect.width, rect.height);\r
-\r
- if (params.options.axis == "horizontal") {\r
- ctx.scale(-1,1);\r
- ctx.drawImage(copyCanvas, -rect.left-rect.width, rect.top, rect.width, rect.height)\r
- } else {\r
- ctx.scale(1,-1);\r
- ctx.drawImage(copyCanvas, rect.left, -rect.top-rect.height, rect.width, rect.height)\r
- }\r
-\r
- params.useData = false;\r
-\r
- return true; \r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvas();\r
- }\r
-}\r
-\r
-/*\r
- * Pixastic Lib - Horizontal flip - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.fliph = {\r
- process : function(params) {\r
- if (Pixastic.Client.hasCanvas()) {\r
- var rect = params.options.rect;\r
- var copyCanvas = document.createElement("canvas");\r
- copyCanvas.width = rect.width;\r
- copyCanvas.height = rect.height;\r
- copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);\r
-\r
- var ctx = params.canvas.getContext("2d");\r
- ctx.clearRect(rect.left, rect.top, rect.width, rect.height);\r
- ctx.scale(-1,1);\r
- ctx.drawImage(copyCanvas, -rect.left-rect.width, rect.top, rect.width, rect.height)\r
- params.useData = false;\r
-\r
- return true; \r
-\r
- } else if (Pixastic.Client.isIE()) {\r
- params.image.style.filter += " fliph";\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());\r
- }\r
-}\r
-\r
-/*\r
- * Pixastic Lib - Vertical flip - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.flipv = {\r
- process : function(params) {\r
- if (Pixastic.Client.hasCanvas()) {\r
- var rect = params.options.rect;\r
- var copyCanvas = document.createElement("canvas");\r
- copyCanvas.width = rect.width;\r
- copyCanvas.height = rect.height;\r
- copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);\r
-\r
- var ctx = params.canvas.getContext("2d");\r
- ctx.clearRect(rect.left, rect.top, rect.width, rect.height);\r
- ctx.scale(1,-1);\r
- ctx.drawImage(copyCanvas, rect.left, -rect.top-rect.height, rect.width, rect.height)\r
- params.useData = false;\r
-\r
- return true; \r
-\r
- } else if (Pixastic.Client.isIE()) {\r
- params.image.style.filter += " flipv";\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());\r
- }\r
-}\r
-\r
-/*\r
- * Pixastic Lib - Glow - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-\r
-Pixastic.Actions.glow = {\r
- process : function(params) {\r
-\r
- var amount = (parseFloat(params.options.amount)||0);\r
- var blurAmount = parseFloat(params.options.radius)||0;\r
-\r
- amount = Math.min(1,Math.max(0,amount));\r
- blurAmount = Math.min(5,Math.max(0,blurAmount));\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var rect = params.options.rect;\r
-\r
- var blurCanvas = document.createElement("canvas");\r
- blurCanvas.width = params.width;\r
- blurCanvas.height = params.height;\r
- var blurCtx = blurCanvas.getContext("2d");\r
- blurCtx.drawImage(params.canvas,0,0);\r
-\r
- var scale = 2;\r
- var smallWidth = Math.round(params.width / scale);\r
- var smallHeight = Math.round(params.height / scale);\r
-\r
- var copy = document.createElement("canvas");\r
- copy.width = smallWidth;\r
- copy.height = smallHeight;\r
-\r
- var clear = true;\r
- var steps = Math.round(blurAmount * 20);\r
-\r
- var copyCtx = copy.getContext("2d");\r
- for (var i=0;i<steps;i++) {\r
- var scaledWidth = Math.max(1,Math.round(smallWidth - i));\r
- var scaledHeight = Math.max(1,Math.round(smallHeight - i));\r
- \r
- copyCtx.clearRect(0,0,smallWidth,smallHeight);\r
- \r
- copyCtx.drawImage(\r
- blurCanvas,\r
- 0,0,params.width,params.height,\r
- 0,0,scaledWidth,scaledHeight\r
- );\r
- \r
- blurCtx.clearRect(0,0,params.width,params.height);\r
- \r
- blurCtx.drawImage(\r
- copy,\r
- 0,0,scaledWidth,scaledHeight,\r
- 0,0,params.width,params.height\r
- );\r
- }\r
-\r
- var data = Pixastic.prepareData(params);\r
- var blurData = Pixastic.prepareData({canvas:blurCanvas,options:params.options});\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x*4-4);\r
-\r
- var r = data[offset] + amount * blurData[offset];\r
- var g = data[offset+1] + amount * blurData[offset+1];\r
- var b = data[offset+2] + amount * blurData[offset+2];\r
- \r
- if (r > 255) r = 255;\r
- if (g > 255) g = 255;\r
- if (b > 255) b = 255;\r
- if (r < 0) r = 0;\r
- if (g < 0) g = 0;\r
- if (b < 0) b = 0;\r
-\r
- data[offset] = r;\r
- data[offset+1] = g;\r
- data[offset+2] = b;\r
-\r
- } while (--x);\r
- } while (--y);\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}\r
-\r
-\r
-\r
-/*\r
- * Pixastic Lib - Histogram - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.histogram = {\r
- process : function(params) {\r
-\r
- var average = !!(params.options.average && params.options.average != "false");\r
- var paint = !!(params.options.paint && params.options.paint != "false");\r
- var color = params.options.color || "rgba(255,255,255,0.5)";\r
- var values = [];\r
- if (typeof params.options.returnValue != "object") {\r
- params.options.returnValue = {values:[]};\r
- }\r
- var returnValue = params.options.returnValue;\r
- if (typeof returnValue.values != "array") {\r
- returnValue.values = [];\r
- }\r
- values = returnValue.values;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- params.useData = false;\r
-\r
- for (var i=0;i<256;i++) {\r
- values[i] = 0;\r
- }\r
-\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x*4-4);\r
- var brightness = average ? \r
- Math.round((data[offset]+data[offset+1]+data[offset+2])/3)\r
- : Math.round(data[offset]*0.3 + data[offset+1]*0.59 + data[offset+2]*0.11);\r
- values[brightness]++;\r
-\r
- } while (--x);\r
- } while (--y);\r
-\r
- if (paint) {\r
- var maxValue = 0;\r
- for (var i=0;i<256;i++) {\r
- if (values[i] > maxValue) {\r
- maxValue = values[i];\r
- }\r
- }\r
- var heightScale = params.height / maxValue;\r
- var widthScale = params.width / 256;\r
- var ctx = params.canvas.getContext("2d");\r
- ctx.fillStyle = color;\r
- for (var i=0;i<256;i++) {\r
- ctx.fillRect(\r
- i * widthScale, params.height - heightScale * values[i],\r
- widthScale, values[i] * heightScale\r
- );\r
- }\r
- }\r
-\r
- returnValue.values = values;\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}\r
-/*\r
- * Pixastic Lib - HSL Adjust - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.hsl = {\r
- process : function(params) {\r
-\r
- var hue = parseInt(params.options.hue,10)||0;\r
- var saturation = (parseInt(params.options.saturation,10)||0) / 100;\r
- var lightness = (parseInt(params.options.lightness,10)||0) / 100;\r
-\r
-\r
- // this seems to give the same result as Photoshop\r
- if (saturation < 0) {\r
- var satMul = 1+saturation;\r
- } else {\r
- var satMul = 1+saturation*2;\r
- }\r
-\r
- hue = (hue%360) / 360;\r
- var hue6 = hue * 6;\r
-\r
- var rgbDiv = 1 / 255;\r
-\r
- var light255 = lightness * 255;\r
- var lightp1 = 1 + lightness;\r
- var lightm1 = 1 - lightness;\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
-\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var w4 = w*4;\r
- var y = h;\r
-\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x*4-4);\r
-\r
- var r = data[offset];\r
- var g = data[offset+1];\r
- var b = data[offset+2];\r
-\r
- if (hue != 0 || saturation != 0) {\r
- // ok, here comes rgb to hsl + adjust + hsl to rgb, all in one jumbled mess. \r
- // It's not so pretty, but it's been optimized to get somewhat decent performance.\r
- // The transforms were originally adapted from the ones found in Graphics Gems, but have been heavily modified.\r
- var vs = r;\r
- if (g > vs) vs = g;\r
- if (b > vs) vs = b;\r
- var ms = r;\r
- if (g < ms) ms = g;\r
- if (b < ms) ms = b;\r
- var vm = (vs-ms);\r
- var l = (ms+vs)/255 * 0.5;\r
- if (l > 0) {\r
- if (vm > 0) {\r
- if (l <= 0.5) {\r
- var s = vm / (vs+ms) * satMul;\r
- if (s > 1) s = 1;\r
- var v = (l * (1+s));\r
- } else {\r
- var s = vm / (510-vs-ms) * satMul;\r
- if (s > 1) s = 1;\r
- var v = (l+s - l*s);\r
- }\r
- if (r == vs) {\r
- if (g == ms)\r
- var h = 5 + ((vs-b)/vm) + hue6;\r
- else\r
- var h = 1 - ((vs-g)/vm) + hue6;\r
- } else if (g == vs) {\r
- if (b == ms)\r
- var h = 1 + ((vs-r)/vm) + hue6;\r
- else\r
- var h = 3 - ((vs-b)/vm) + hue6;\r
- } else {\r
- if (r == ms)\r
- var h = 3 + ((vs-g)/vm) + hue6;\r
- else\r
- var h = 5 - ((vs-r)/vm) + hue6;\r
- }\r
- if (h < 0) h+=6;\r
- if (h >= 6) h-=6;\r
- var m = (l+l-v);\r
- var sextant = h>>0;\r
- switch (sextant) {\r
- case 0: r = v*255; g = (m+((v-m)*(h-sextant)))*255; b = m*255; break;\r
- case 1: r = (v-((v-m)*(h-sextant)))*255; g = v*255; b = m*255; break;\r
- case 2: r = m*255; g = v*255; b = (m+((v-m)*(h-sextant)))*255; break;\r
- case 3: r = m*255; g = (v-((v-m)*(h-sextant)))*255; b = v*255; break;\r
- case 4: r = (m+((v-m)*(h-sextant)))*255; g = m*255; b = v*255; break;\r
- case 5: r = v*255; g = m*255; b = (v-((v-m)*(h-sextant)))*255; break;\r
- }\r
- }\r
- }\r
- }\r
-\r
- if (lightness < 0) {\r
- r *= lightp1;\r
- g *= lightp1;\r
- b *= lightp1;\r
- } else if (lightness > 0) {\r
- r = r * lightm1 + light255;\r
- g = g * lightm1 + light255;\r
- b = b * lightm1 + light255;\r
- }\r
-\r
- if (r < 0) r = 0;\r
- if (g < 0) g = 0;\r
- if (b < 0) b = 0;\r
- if (r > 255) r = 255;\r
- if (g > 255) g = 255;\r
- if (b > 255) b = 255;\r
-\r
- data[offset] = r;\r
- data[offset+1] = g;\r
- data[offset+2] = b;\r
-\r
- } while (--x);\r
- } while (--y);\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-\r
-}\r
-/*\r
- * Pixastic Lib - Invert filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.invert = {\r
- process : function(params) {\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
-\r
- var invertAlpha = !!params.options.invertAlpha;\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x-1)*4;\r
- data[offset] = 255 - data[offset];\r
- data[offset+1] = 255 - data[offset+1];\r
- data[offset+2] = 255 - data[offset+2];\r
- if (invertAlpha) data[offset+3] = 255 - data[offset+3];\r
- } while (--x);\r
- } while (--y);\r
-\r
- return true;\r
- } else if (Pixastic.Client.isIE()) {\r
- params.image.style.filter += " invert";\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());\r
- }\r
-}\r
-/*\r
- * Pixastic Lib - Laplace filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.laplace = {\r
- process : function(params) {\r
-\r
- var strength = 1.0;\r
- var invert = !!(params.options.invert && params.options.invert != "false");\r
- var contrast = parseFloat(params.options.edgeStrength)||0;\r
-\r
- var greyLevel = parseInt(params.options.greyLevel)||0;\r
-\r
- contrast = -contrast;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var dataCopy = Pixastic.prepareData(params, true)\r
-\r
- var kernel = [\r
- [-1, -1, -1],\r
- [-1, 8, -1],\r
- [-1, -1, -1]\r
- ];\r
-\r
- var weight = 1/8;\r
-\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
-\r
- var nextY = (y == h) ? y - 1 : y;\r
- var prevY = (y == 1) ? 0 : y-2;\r
-\r
- var offsetYPrev = prevY*w*4;\r
- var offsetYNext = nextY*w*4;\r
-\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x*4-4);\r
-\r
- var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;\r
- var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;\r
- \r
- var r = ((-dataCopy[offsetPrev-4]\r
- - dataCopy[offsetPrev]\r
- - dataCopy[offsetPrev+4]\r
- - dataCopy[offset-4]\r
- - dataCopy[offset+4]\r
- - dataCopy[offsetNext-4]\r
- - dataCopy[offsetNext]\r
- - dataCopy[offsetNext+4])\r
- + dataCopy[offset] * 8) \r
- * weight;\r
- \r
- var g = ((-dataCopy[offsetPrev-3]\r
- - dataCopy[offsetPrev+1]\r
- - dataCopy[offsetPrev+5]\r
- - dataCopy[offset-3]\r
- - dataCopy[offset+5]\r
- - dataCopy[offsetNext-3]\r
- - dataCopy[offsetNext+1]\r
- - dataCopy[offsetNext+5])\r
- + dataCopy[offset+1] * 8)\r
- * weight;\r
- \r
- var b = ((-dataCopy[offsetPrev-2]\r
- - dataCopy[offsetPrev+2]\r
- - dataCopy[offsetPrev+6]\r
- - dataCopy[offset-2]\r
- - dataCopy[offset+6]\r
- - dataCopy[offsetNext-2]\r
- - dataCopy[offsetNext+2]\r
- - dataCopy[offsetNext+6])\r
- + dataCopy[offset+2] * 8)\r
- * weight;\r
-\r
- var brightness = ((r + g + b)/3) + greyLevel;\r
-\r
- if (contrast != 0) {\r
- if (brightness > 127) {\r
- brightness += ((brightness + 1) - 128) * contrast;\r
- } else if (brightness < 127) {\r
- brightness -= (brightness + 1) * contrast;\r
- }\r
- }\r
- if (invert) {\r
- brightness = 255 - brightness;\r
- }\r
- if (brightness < 0 ) brightness = 0;\r
- if (brightness > 255 ) brightness = 255;\r
-\r
- data[offset] = data[offset+1] = data[offset+2] = brightness;\r
-\r
- } while (--x);\r
- } while (--y);\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}\r
-\r
-/*\r
- * Pixastic Lib - Lighten filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.lighten = {\r
-\r
- process : function(params) {\r
- var amount = parseFloat(params.options.amount) || 0;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x-1)*4;\r
-\r
- var r = data[offset];\r
- var g = data[offset+1];\r
- var b = data[offset+2];\r
-\r
- r += r*amount;\r
- g += g*amount;\r
- b += b*amount;\r
-\r
- if (r < 0 ) r = 0;\r
- if (g < 0 ) g = 0;\r
- if (b < 0 ) b = 0;\r
- if (r > 255 ) r = 255;\r
- if (g > 255 ) g = 255;\r
- if (b > 255 ) b = 255;\r
-\r
- data[offset] = r;\r
- data[offset+1] = g;\r
- data[offset+2] = b;\r
-\r
- } while (--x);\r
- } while (--y);\r
- return true;\r
-\r
- } else if (Pixastic.Client.isIE()) {\r
- var img = params.image;\r
- if (amount < 0) {\r
- img.style.filter += " light()";\r
- img.filters[img.filters.length-1].addAmbient(\r
- 255,255,255,\r
- 100 * -amount\r
- );\r
- } else if (amount > 0) {\r
- img.style.filter += " light()";\r
- img.filters[img.filters.length-1].addAmbient(\r
- 255,255,255,\r
- 100\r
- );\r
- img.filters[img.filters.length-1].addAmbient(\r
- 255,255,255,\r
- 100 * amount\r
- );\r
- }\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());\r
- }\r
-}\r
-/*\r
- * Pixastic Lib - Mosaic filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.mosaic = {\r
-\r
- process : function(params) {\r
- var blockSize = Math.max(1,parseInt(params.options.blockSize,10));\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
-\r
- var ctx = params.canvas.getContext("2d");\r
-\r
- var pixel = document.createElement("canvas");\r
- pixel.width = pixel.height = 1;\r
- var pixelCtx = pixel.getContext("2d");\r
-\r
- var copy = document.createElement("canvas");\r
- copy.width = w;\r
- copy.height = h;\r
- var copyCtx = copy.getContext("2d");\r
- copyCtx.drawImage(params.canvas,rect.left,rect.top,w,h, 0,0,w,h);\r
-\r
- for (var y=0;y<h;y+=blockSize) {\r
- for (var x=0;x<w;x+=blockSize) {\r
- var blockSizeX = blockSize;\r
- var blockSizeY = blockSize;\r
- \r
- if (blockSizeX + x > w)\r
- blockSizeX = w - x;\r
- if (blockSizeY + y > h)\r
- blockSizeY = h - y;\r
-\r
- pixelCtx.drawImage(copy, x, y, blockSizeX, blockSizeY, 0, 0, 1, 1);\r
- var data = pixelCtx.getImageData(0,0,1,1).data;\r
- ctx.fillStyle = "rgb(" + data[0] + "," + data[1] + "," + data[2] + ")";\r
- ctx.fillRect(rect.left + x, rect.top + y, blockSize, blockSize);\r
- }\r
- }\r
- params.useData = false;\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvasImageData());\r
- }\r
-}/*\r
- * Pixastic Lib - Noise filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.noise = {\r
-\r
- process : function(params) {\r
- var amount = 0;\r
- var strength = 0;\r
- var mono = false;\r
-\r
- if (typeof params.options.amount != "undefined")\r
- amount = parseFloat(params.options.amount)||0;\r
- if (typeof params.options.strength != "undefined")\r
- strength = parseFloat(params.options.strength)||0;\r
- if (typeof params.options.mono != "undefined")\r
- mono = !!(params.options.mono && params.options.mono != "false");\r
-\r
- amount = Math.max(0,Math.min(1,amount));\r
- strength = Math.max(0,Math.min(1,strength));\r
-\r
- var noise = 128 * strength;\r
- var noise2 = noise / 2;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
- var random = Math.random;\r
-\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x-1)*4;\r
- if (random() < amount) {\r
- if (mono) {\r
- var pixelNoise = - noise2 + random() * noise;\r
- var r = data[offset] + pixelNoise;\r
- var g = data[offset+1] + pixelNoise;\r
- var b = data[offset+2] + pixelNoise;\r
- } else {\r
- var r = data[offset] - noise2 + (random() * noise);\r
- var g = data[offset+1] - noise2 + (random() * noise);\r
- var b = data[offset+2] - noise2 + (random() * noise);\r
- }\r
-\r
- if (r < 0 ) r = 0;\r
- if (g < 0 ) g = 0;\r
- if (b < 0 ) b = 0;\r
- if (r > 255 ) r = 255;\r
- if (g > 255 ) g = 255;\r
- if (b > 255 ) b = 255;\r
-\r
- data[offset] = r;\r
- data[offset+1] = g;\r
- data[offset+2] = b;\r
- }\r
- } while (--x);\r
- } while (--y);\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}\r
-\r
-/*\r
- * Pixastic Lib - Posterize effect - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.posterize = {\r
-\r
- process : function(params) {\r
-\r
- \r
- var numLevels = 256;\r
- if (typeof params.options.levels != "undefined")\r
- numLevels = parseInt(params.options.levels,10)||1;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
-\r
- numLevels = Math.max(2,Math.min(256,numLevels));\r
- \r
- var numAreas = 256 / numLevels;\r
- var numValues = 256 / (numLevels-1);\r
-\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x-1)*4;\r
-\r
- var r = numValues * ((data[offset] / numAreas)>>0);\r
- var g = numValues * ((data[offset+1] / numAreas)>>0);\r
- var b = numValues * ((data[offset+2] / numAreas)>>0);\r
-\r
- if (r > 255) r = 255;\r
- if (g > 255) g = 255;\r
- if (b > 255) b = 255;\r
-\r
- data[offset] = r;\r
- data[offset+1] = g;\r
- data[offset+2] = b;\r
-\r
- } while (--x);\r
- } while (--y);\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}\r
-\r
-\r
-/*\r
- * Pixastic Lib - Pointillize filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.pointillize = {\r
-\r
- process : function(params) {\r
- var radius = Math.max(1,parseInt(params.options.radius,10));\r
- var density = Math.min(5,Math.max(0,parseFloat(params.options.density)||0));\r
- var noise = Math.max(0,parseFloat(params.options.noise)||0);\r
- var transparent = !!(params.options.transparent && params.options.transparent != "false");\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
-\r
- var ctx = params.canvas.getContext("2d");\r
- var canvasWidth = params.canvas.width;\r
- var canvasHeight = params.canvas.height;\r
-\r
- var pixel = document.createElement("canvas");\r
- pixel.width = pixel.height = 1;\r
- var pixelCtx = pixel.getContext("2d");\r
-\r
- var copy = document.createElement("canvas");\r
- copy.width = w;\r
- copy.height = h;\r
- var copyCtx = copy.getContext("2d");\r
- copyCtx.drawImage(params.canvas,rect.left,rect.top,w,h, 0,0,w,h);\r
-\r
- var diameter = radius * 2;\r
-\r
- if (transparent)\r
- ctx.clearRect(rect.left, rect.top, rect.width, rect.height);\r
-\r
- var noiseRadius = radius * noise;\r
-\r
- var dist = 1 / density;\r
-\r
- for (var y=0;y<h+radius;y+=diameter*dist) {\r
- for (var x=0;x<w+radius;x+=diameter*dist) {\r
- rndX = noise ? (x+((Math.random()*2-1) * noiseRadius))>>0 : x;\r
- rndY = noise ? (y+((Math.random()*2-1) * noiseRadius))>>0 : y;\r
-\r
- var pixX = rndX - radius;\r
- var pixY = rndY - radius;\r
- if (pixX < 0) pixX = 0;\r
- if (pixY < 0) pixY = 0;\r
-\r
- var cx = rndX + rect.left;\r
- var cy = rndY + rect.top;\r
- if (cx < 0) cx = 0;\r
- if (cx > canvasWidth) cx = canvasWidth;\r
- if (cy < 0) cy = 0;\r
- if (cy > canvasHeight) cy = canvasHeight;\r
-\r
- var diameterX = diameter;\r
- var diameterY = diameter;\r
-\r
- if (diameterX + pixX > w)\r
- diameterX = w - pixX;\r
- if (diameterY + pixY > h)\r
- diameterY = h - pixY;\r
- if (diameterX < 1) diameterX = 1;\r
- if (diameterY < 1) diameterY = 1;\r
-\r
- pixelCtx.drawImage(copy, pixX, pixY, diameterX, diameterY, 0, 0, 1, 1);\r
- var data = pixelCtx.getImageData(0,0,1,1).data;\r
-\r
- ctx.fillStyle = "rgb(" + data[0] + "," + data[1] + "," + data[2] + ")";\r
- ctx.beginPath();\r
- ctx.arc(cx, cy, radius, 0, Math.PI*2, true);\r
- ctx.closePath();\r
- ctx.fill();\r
- }\r
- }\r
-\r
- params.useData = false;\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvasImageData());\r
- }\r
-}/*\r
- * Pixastic Lib - Resize - v0.1.0\r
- * Copyright (c) 2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.resize = {\r
- process : function(params) {\r
- if (Pixastic.Client.hasCanvas()) {\r
- var width = parseInt(params.options.width,10);\r
- var height = parseInt(params.options.height,10);\r
- var canvas = params.canvas;\r
-\r
- if (width < 1) width = 1;\r
- if (width < 2) width = 2;\r
-\r
- var copy = document.createElement("canvas");\r
- copy.width = width;\r
- copy.height = height;\r
-\r
- copy.getContext("2d").drawImage(canvas,0,0,width,height);\r
- canvas.width = width;\r
- canvas.height = height;\r
-\r
- canvas.getContext("2d").drawImage(copy,0,0);\r
-\r
- params.useData = false;\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvas();\r
- }\r
-}\r
-\r
-\r
-/*\r
- * Pixastic Lib - Remove noise - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.removenoise = {\r
- process : function(params) {\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
-\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
-\r
- var nextY = (y == h) ? y - 1 : y;\r
- var prevY = (y == 1) ? 0 : y-2;\r
-\r
- var offsetYPrev = prevY*w*4;\r
- var offsetYNext = nextY*w*4;\r
-\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x*4-4);\r
-\r
- var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;\r
- var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;\r
-\r
- var minR, maxR, minG, maxG, minB, maxB;\r
-\r
- minR = maxR = data[offsetPrev];\r
- var r1 = data[offset-4], r2 = data[offset+4], r3 = data[offsetNext];\r
- if (r1 < minR) minR = r1;\r
- if (r2 < minR) minR = r2;\r
- if (r3 < minR) minR = r3;\r
- if (r1 > maxR) maxR = r1;\r
- if (r2 > maxR) maxR = r2;\r
- if (r3 > maxR) maxR = r3;\r
-\r
- minG = maxG = data[offsetPrev+1];\r
- var g1 = data[offset-3], g2 = data[offset+5], g3 = data[offsetNext+1];\r
- if (g1 < minG) minG = g1;\r
- if (g2 < minG) minG = g2;\r
- if (g3 < minG) minG = g3;\r
- if (g1 > maxG) maxG = g1;\r
- if (g2 > maxG) maxG = g2;\r
- if (g3 > maxG) maxG = g3;\r
-\r
- minB = maxB = data[offsetPrev+2];\r
- var b1 = data[offset-2], b2 = data[offset+6], b3 = data[offsetNext+2];\r
- if (b1 < minB) minB = b1;\r
- if (b2 < minB) minB = b2;\r
- if (b3 < minB) minB = b3;\r
- if (b1 > maxB) maxB = b1;\r
- if (b2 > maxB) maxB = b2;\r
- if (b3 > maxB) maxB = b3;\r
-\r
- if (data[offset] > maxR) {\r
- data[offset] = maxR;\r
- } else if (data[offset] < minR) {\r
- data[offset] = minR;\r
- }\r
- if (data[offset+1] > maxG) {\r
- data[offset+1] = maxG;\r
- } else if (data[offset+1] < minG) {\r
- data[offset+1] = minG;\r
- }\r
- if (data[offset+2] > maxB) {\r
- data[offset+2] = maxB;\r
- } else if (data[offset+2] < minB) {\r
- data[offset+2] = minB;\r
- }\r
-\r
- } while (--x);\r
- } while (--y);\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}/*\r
- * Pixastic Lib - Rotate - v0.1.0\r
- * Copyright (c) 2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.rotate = {\r
- process : function(params) {\r
- if (Pixastic.Client.hasCanvas()) {\r
- var canvas = params.canvas;\r
-\r
- var width = params.width;\r
- var height = params.height;\r
-\r
- var copy = document.createElement("canvas");\r
- copy.width = width;\r
- copy.height = height;\r
- copy.getContext("2d").drawImage(canvas,0,0,width,height);\r
-\r
- var angle = -parseFloat(params.options.angle) * Math.PI / 180;\r
-\r
- var dimAngle = angle;\r
- if (dimAngle > Math.PI*0.5)\r
- dimAngle = Math.PI - dimAngle;\r
- if (dimAngle < -Math.PI*0.5)\r
- dimAngle = -Math.PI - dimAngle;\r
-\r
- var diag = Math.sqrt(width*width + height*height);\r
-\r
- var diagAngle1 = Math.abs(dimAngle) - Math.abs(Math.atan2(height, width));\r
- var diagAngle2 = Math.abs(dimAngle) + Math.abs(Math.atan2(height, width));\r
-\r
- var newWidth = Math.abs(Math.cos(diagAngle1) * diag);\r
- var newHeight = Math.abs(Math.sin(diagAngle2) * diag);\r
-\r
- canvas.width = newWidth;\r
- canvas.height = newHeight;\r
-\r
- var ctx = canvas.getContext("2d");\r
- ctx.translate(newWidth/2, newHeight/2);\r
- ctx.rotate(angle);\r
- ctx.drawImage(copy,-width/2,-height/2);\r
-\r
- params.useData = false;\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvas();\r
- }\r
-}\r
-\r
-\r
-/*\r
- * Pixastic Lib - Sepia filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.sepia = {\r
-\r
- process : function(params) {\r
- var mode = (parseInt(params.options.mode,10)||0);\r
- if (mode < 0) mode = 0;\r
- if (mode > 1) mode = 1;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x-1)*4;\r
-\r
- if (mode) {\r
- // a bit faster, but not as good\r
- var d = data[offset] * 0.299 + data[offset+1] * 0.587 + data[offset+2] * 0.114;\r
- var r = (d + 39);\r
- var g = (d + 14);\r
- var b = (d - 36);\r
- } else {\r
- // Microsoft\r
- var or = data[offset];\r
- var og = data[offset+1];\r
- var ob = data[offset+2];\r
- \r
- var r = (or * 0.393 + og * 0.769 + ob * 0.189);\r
- var g = (or * 0.349 + og * 0.686 + ob * 0.168);\r
- var b = (or * 0.272 + og * 0.534 + ob * 0.131);\r
- }\r
-\r
- if (r < 0) r = 0; if (r > 255) r = 255;\r
- if (g < 0) g = 0; if (g > 255) g = 255;\r
- if (b < 0) b = 0; if (b > 255) b = 255;\r
-\r
- data[offset] = r;\r
- data[offset+1] = g;\r
- data[offset+2] = b;\r
-\r
- } while (--x);\r
- } while (--y);\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}/*\r
- * Pixastic Lib - Sharpen filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.sharpen = {\r
- process : function(params) {\r
-\r
- var strength = 0;\r
- if (typeof params.options.amount != "undefined")\r
- strength = parseFloat(params.options.amount)||0;\r
-\r
- if (strength < 0) strength = 0;\r
- if (strength > 1) strength = 1;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var dataCopy = Pixastic.prepareData(params, true)\r
-\r
- var mul = 15;\r
- var mulOther = 1 + 3*strength;\r
-\r
- var kernel = [\r
- [0, -mulOther, 0],\r
- [-mulOther, mul, -mulOther],\r
- [0, -mulOther, 0]\r
- ];\r
-\r
- var weight = 0;\r
- for (var i=0;i<3;i++) {\r
- for (var j=0;j<3;j++) {\r
- weight += kernel[i][j];\r
- }\r
- }\r
-\r
- weight = 1 / weight;\r
-\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- mul *= weight;\r
- mulOther *= weight;\r
-\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
-\r
- var nextY = (y == h) ? y - 1 : y;\r
- var prevY = (y == 1) ? 0 : y-2;\r
-\r
- var offsetYPrev = prevY*w4;\r
- var offsetYNext = nextY*w4;\r
-\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x*4-4);\r
-\r
- var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;\r
- var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;\r
-\r
- var r = ((\r
- - dataCopy[offsetPrev]\r
- - dataCopy[offset-4]\r
- - dataCopy[offset+4]\r
- - dataCopy[offsetNext]) * mulOther\r
- + dataCopy[offset] * mul\r
- );\r
-\r
- var g = ((\r
- - dataCopy[offsetPrev+1]\r
- - dataCopy[offset-3]\r
- - dataCopy[offset+5]\r
- - dataCopy[offsetNext+1]) * mulOther\r
- + dataCopy[offset+1] * mul\r
- );\r
-\r
- var b = ((\r
- - dataCopy[offsetPrev+2]\r
- - dataCopy[offset-2]\r
- - dataCopy[offset+6]\r
- - dataCopy[offsetNext+2]) * mulOther\r
- + dataCopy[offset+2] * mul\r
- );\r
-\r
-\r
- if (r < 0 ) r = 0;\r
- if (g < 0 ) g = 0;\r
- if (b < 0 ) b = 0;\r
- if (r > 255 ) r = 255;\r
- if (g > 255 ) g = 255;\r
- if (b > 255 ) b = 255;\r
-\r
- data[offset] = r;\r
- data[offset+1] = g;\r
- data[offset+2] = b;\r
-\r
- } while (--x);\r
- } while (--y);\r
-\r
- return true;\r
-\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}\r
-/*\r
- * Pixastic Lib - Solarize filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.solarize = {\r
-\r
- process : function(params) {\r
- var useAverage = !!(params.options.average && params.options.average != "false");\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x-1)*4;\r
-\r
- var r = data[offset];\r
- var g = data[offset+1];\r
- var b = data[offset+2];\r
-\r
- if (r > 127) r = 255 - r;\r
- if (g > 127) g = 255 - g;\r
- if (b > 127) b = 255 - b;\r
-\r
- data[offset] = r;\r
- data[offset+1] = g;\r
- data[offset+2] = b;\r
-\r
- } while (--x);\r
- } while (--y);\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvasImageData());\r
- }\r
-}/*\r
- * Pixastic Lib - USM - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-\r
-Pixastic.Actions.unsharpmask = {\r
- process : function(params) {\r
-\r
- var amount = (parseFloat(params.options.amount)||0);\r
- var blurAmount = parseFloat(params.options.radius)||0;\r
- var threshold = parseFloat(params.options.threshold)||0;\r
-\r
- amount = Math.min(500,Math.max(0,amount)) / 2;\r
- blurAmount = Math.min(5,Math.max(0,blurAmount)) / 10;\r
- threshold = Math.min(255,Math.max(0,threshold));\r
-\r
- threshold--;\r
- var thresholdNeg = -threshold;\r
-\r
- amount *= 0.016;\r
- amount++;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var rect = params.options.rect;\r
-\r
- var blurCanvas = document.createElement("canvas");\r
- blurCanvas.width = params.width;\r
- blurCanvas.height = params.height;\r
- var blurCtx = blurCanvas.getContext("2d");\r
- blurCtx.drawImage(params.canvas,0,0);\r
-\r
- var scale = 2;\r
- var smallWidth = Math.round(params.width / scale);\r
- var smallHeight = Math.round(params.height / scale);\r
-\r
- var copy = document.createElement("canvas");\r
- copy.width = smallWidth;\r
- copy.height = smallHeight;\r
-\r
- var steps = Math.round(blurAmount * 20);\r
-\r
- var copyCtx = copy.getContext("2d");\r
- for (var i=0;i<steps;i++) {\r
- var scaledWidth = Math.max(1,Math.round(smallWidth - i));\r
- var scaledHeight = Math.max(1,Math.round(smallHeight - i));\r
-\r
- copyCtx.clearRect(0,0,smallWidth,smallHeight);\r
-\r
- copyCtx.drawImage(\r
- blurCanvas,\r
- 0,0,params.width,params.height,\r
- 0,0,scaledWidth,scaledHeight\r
- );\r
- \r
- blurCtx.clearRect(0,0,params.width,params.height);\r
- \r
- blurCtx.drawImage(\r
- copy,\r
- 0,0,scaledWidth,scaledHeight,\r
- 0,0,params.width,params.height\r
- );\r
- }\r
-\r
- var data = Pixastic.prepareData(params);\r
- var blurData = Pixastic.prepareData({canvas:blurCanvas,options:params.options});\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x*4-4);\r
-\r
- var difR = data[offset] - blurData[offset];\r
- if (difR > threshold || difR < thresholdNeg) {\r
- var blurR = blurData[offset];\r
- blurR = amount * difR + blurR;\r
- data[offset] = blurR > 255 ? 255 : (blurR < 0 ? 0 : blurR);\r
- }\r
-\r
- var difG = data[offset+1] - blurData[offset+1];\r
- if (difG > threshold || difG < thresholdNeg) {\r
- var blurG = blurData[offset+1];\r
- blurG = amount * difG + blurG;\r
- data[offset+1] = blurG > 255 ? 255 : (blurG < 0 ? 0 : blurG);\r
- }\r
-\r
- var difB = data[offset+2] - blurData[offset+2];\r
- if (difB > threshold || difB < thresholdNeg) {\r
- var blurB = blurData[offset+2];\r
- blurB = amount * difB + blurB;\r
- data[offset+2] = blurB > 255 ? 255 : (blurB < 0 ? 0 : blurB);\r
- }\r
-\r
- } while (--x);\r
- } while (--y);\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}\r
-\r
-\r
-\r
-\r
+/*
+ * Pixastic Lib - Core Functions - v0.1.3
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+var Pixastic = (function() {
+
+
+ function addEvent(el, event, handler) {
+ if (el.addEventListener)
+ el.addEventListener(event, handler, false);
+ else if (el.attachEvent)
+ el.attachEvent("on" + event, handler);
+ }
+
+ function onready(handler) {
+ var handlerDone = false;
+ var execHandler = function() {
+ if (!handlerDone) {
+ handlerDone = true;
+ handler();
+ }
+ }
+ document.write("<"+"script defer src=\"//:\" id=\"__onload_ie_sumbox__\"></"+"script>");
+ var script = document.getElementById("__onload_ie_sumbox__");
+ script.onreadystatechange = function() {
+ if (script.readyState == "complete") {
+ script.parentNode.removeChild(script);
+ execHandler();
+ }
+ }
+ if (document.addEventListener)
+ document.addEventListener("DOMContentLoaded", execHandler, false);
+ addEvent(window, "load", execHandler);
+ }
+
+ function init() {
+ if (!Pixastic.parseOnLoad) return;
+ var imgEls = getElementsByClass("pixastic", null, "img");
+ var canvasEls = getElementsByClass("pixastic", null, "canvas");
+ var elements = imgEls.concat(canvasEls);
+ for (var i=0;i<elements.length;i++) {
+ (function() {
+
+ var el = elements[i];
+ var actions = [];
+ var classes = el.className.split(" ");
+ for (var c=0;c<classes.length;c++) {
+ var cls = classes[c];
+ if (cls.substring(0,9) == "pixastic-") {
+ var actionName = cls.substring(9);
+ if (actionName != "")
+ actions.push(actionName);
+ }
+ }
+ if (actions.length) {
+ if (el.tagName.toLowerCase() == "img") {
+ var dataImg = new Image();
+ dataImg.src = el.src;
+ if (dataImg.complete) {
+ for (var a=0;a<actions.length;a++) {
+ var res = Pixastic.applyAction(el, el, actions[a], null);
+ if (res)
+ el = res;
+ }
+ } else {
+ dataImg.onload = function() {
+ for (var a=0;a<actions.length;a++) {
+ var res = Pixastic.applyAction(el, el, actions[a], null)
+ if (res)
+ el = res;
+ }
+ }
+ }
+ } else {
+ setTimeout(function() {
+ for (var a=0;a<actions.length;a++) {
+ var res = Pixastic.applyAction(
+ el, el, actions[a], null
+ );
+ if (res)
+ el = res;
+ }
+ },1);
+ }
+ }
+
+ })();
+ }
+ }
+
+// if (typeof pixastic_no_onready == "undefined") // yuck.
+// onready(init);
+
+ // getElementsByClass by Dustin Diaz, http://www.dustindiaz.com/getelementsbyclass/
+ function getElementsByClass(searchClass,node,tag) {
+ var classElements = new Array();
+ if ( node == null )
+ node = document;
+ if ( tag == null )
+ tag = '*';
+
+ var els = node.getElementsByTagName(tag);
+ var elsLen = els.length;
+ var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
+ for (i = 0, j = 0; i < elsLen; i++) {
+ if ( pattern.test(els[i].className) ) {
+ classElements[j] = els[i];
+ j++;
+ }
+ }
+ return classElements;
+ }
+
+ var debugElement;
+
+ function writeDebug(text, level) {
+ if (!Pixastic.debug) return;
+ try {
+ switch (level) {
+ case "warn" :
+ console.warn("Pixastic:", text);
+ break;
+ case "error" :
+ console.error("Pixastic:", text);
+ break;
+ default:
+ console.log("Pixastic:", text);
+ }
+ } catch(e) {
+ }
+ if (!debugElement) {
+
+ }
+ }
+
+
+ return {
+
+ parseOnLoad : false,
+
+ debug : false,
+
+ applyAction : function(img, dataImg, actionName, options) {
+
+ options = options || {};
+
+ var imageIsCanvas = (img.tagName.toLowerCase() == "canvas");
+ if (imageIsCanvas && Pixastic.Client.isIE()) {
+ if (Pixastic.debug) writeDebug("Tried to process a canvas element but browser is IE.");
+ return false;
+ }
+
+ var canvas, ctx;
+ if (Pixastic.Client.hasCanvas()) {
+ canvas = document.createElement("canvas");
+ ctx = canvas.getContext("2d");
+ }
+
+ var w = parseInt(img.offsetWidth);
+ var h = parseInt(img.offsetHeight);
+
+ if (imageIsCanvas) {
+ w = img.width;
+ h = img.height;
+ }
+
+ if (actionName.indexOf("(") > -1) {
+ var tmp = actionName;
+ actionName = tmp.substr(0, tmp.indexOf("("));
+ var arg = tmp.match(/\((.*?)\)/);
+ if (arg[1]) {
+ arg = arg[1].split(";");
+ for (var a=0;a<arg.length;a++) {
+ thisArg = arg[a].split("=");
+ if (thisArg.length == 2) {
+ if (thisArg[0] == "rect") {
+ var rectVal = thisArg[1].split(",");
+ options[thisArg[0]] = {
+ left : parseInt(rectVal[0],10)||0,
+ top : parseInt(rectVal[1],10)||0,
+ width : parseInt(rectVal[2],10)||0,
+ height : parseInt(rectVal[3],10)||0
+ }
+ } else {
+ options[thisArg[0]] = thisArg[1];
+ }
+ }
+ }
+ }
+ }
+
+ if (!options.rect) {
+ options.rect = {
+ left : 0, top : 0, width : w, height : h
+ };
+ }
+ var validAction = false;
+ if (Pixastic.Actions[actionName] && typeof Pixastic.Actions[actionName].process == "function") {
+ validAction = true;
+ }
+ if (!validAction) {
+ if (Pixastic.debug) writeDebug("Invalid action \"" + actionName + "\". Maybe file not included?");
+ return false;
+ }
+ if (!Pixastic.Actions[actionName].checkSupport()) {
+ if (Pixastic.debug) writeDebug("Action \"" + actionName + "\" not supported by this browser.");
+ return false;
+ }
+
+ if (Pixastic.Client.hasCanvas()) {
+ canvas.width = w;
+ canvas.height = h;
+ canvas.style.width = w+"px";
+ canvas.style.height = h+"px";
+ ctx.drawImage(dataImg,0,0,w,h);
+
+ if (!img.__pixastic_org_image) {
+ canvas.__pixastic_org_image = img;
+ canvas.__pixastic_org_width = w;
+ canvas.__pixastic_org_height = h;
+ } else {
+ canvas.__pixastic_org_image = img.__pixastic_org_image;
+ canvas.__pixastic_org_width = img.__pixastic_org_width;
+ canvas.__pixastic_org_height = img.__pixastic_org_height;
+ }
+
+ } else if (Pixastic.Client.isIE() && typeof img.__pixastic_org_style == "undefined") {
+ img.__pixastic_org_style = img.style.cssText;
+ }
+
+ var params = {
+ image : img,
+ canvas : canvas,
+ width : w,
+ height : h,
+ useData : true,
+ options : options
+ }
+
+ // Ok, let's do it!
+
+ var res = Pixastic.Actions[actionName].process(params);
+
+ if (!res) {
+ return false;
+ }
+
+ if (Pixastic.Client.hasCanvas()) {
+ if (params.useData) {
+ if (Pixastic.Client.hasCanvasImageData()) {
+ canvas.getContext("2d").putImageData(params.canvasData, options.rect.left, options.rect.top);
+
+ // Opera doesn't seem to update the canvas until we draw something on it, lets draw a 0x0 rectangle.
+ canvas.getContext("2d").fillRect(0,0,0,0);
+ }
+ }
+
+ if (!options.leaveDOM) {
+ // copy properties and stuff from the source image
+ canvas.title = img.title;
+ canvas.imgsrc = img.imgsrc;
+ if (!imageIsCanvas) canvas.alt = img.alt;
+ if (!imageIsCanvas) canvas.imgsrc = img.src;
+ canvas.className = img.className;
+ canvas.style.cssText = img.style.cssText;
+ canvas.name = img.name;
+ canvas.tabIndex = img.tabIndex;
+ canvas.id = img.id;
+ if (img.parentNode && img.parentNode.replaceChild) {
+ img.parentNode.replaceChild(canvas, img);
+ }
+ }
+
+ options.resultCanvas = canvas;
+
+ return canvas;
+ }
+
+ return img;
+ },
+
+ prepareData : function(params, getCopy) {
+ var ctx = params.canvas.getContext("2d");
+ var rect = params.options.rect;
+ var dataDesc = ctx.getImageData(rect.left, rect.top, rect.width, rect.height);
+ var data = dataDesc.data;
+ if (!getCopy) params.canvasData = dataDesc;
+ return data;
+ },
+
+ // load the image file
+ process : function(img, actionName, options, callback)
+ {
+ if (img.tagName.toLowerCase() == "img") {
+ var dataImg = new Image();
+ dataImg.src = img.src;
+ if (dataImg.complete) {
+ var res = Pixastic.applyAction(img, dataImg, actionName, options);
+ if (callback) callback(res);
+ return res;
+ } else {
+ dataImg.onload = function() {
+ var res = Pixastic.applyAction(img, dataImg, actionName, options)
+ if (callback) callback(res);
+ }
+ }
+ }
+ if (img.tagName.toLowerCase() == "canvas") {
+ var res = Pixastic.applyAction(img, img, actionName, options);
+ if (callback) callback(res);
+ return res;
+ }
+ },
+
+ revert : function(img) {
+ if (Pixastic.Client.hasCanvas()) {
+ if (img.tagName.toLowerCase() == "canvas" && img.__pixastic_org_image) {
+ img.width = img.__pixastic_org_width;
+ img.height = img.__pixastic_org_height;
+ img.getContext("2d").drawImage(img.__pixastic_org_image, 0, 0);
+
+ if (img.parentNode && img.parentNode.replaceChild) {
+ img.parentNode.replaceChild(img.__pixastic_org_image, img);
+ }
+
+ return img;
+ }
+ } else if (Pixastic.Client.isIE() && typeof img.__pixastic_org_style != "undefined") {
+ img.style.cssText = img.__pixastic_org_style;
+ }
+ },
+
+ Client : {
+ hasCanvas : (function() {
+ var c = document.createElement("canvas");
+ var val = false;
+ try {
+ val = !!((typeof c.getContext == "function") && c.getContext("2d"));
+ } catch(e) {}
+ return function() {
+ return val;
+ }
+ })(),
+
+ hasCanvasImageData : (function() {
+ var c = document.createElement("canvas");
+ var val = false;
+ var ctx;
+ try {
+ if (typeof c.getContext == "function" && (ctx = c.getContext("2d"))) {
+ val = (typeof ctx.getImageData == "function");
+ }
+ } catch(e) {}
+ return function() {
+ return val;
+ }
+ })(),
+
+ isIE : function() {
+ return !!document.all && !!window.attachEvent && !window.opera;
+ }
+ },
+
+ Actions : {}
+ }
+
+
+})();
+/*
+ * Pixastic Lib - jQuery plugin
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+if (typeof jQuery != "undefined" && jQuery && jQuery.fn) {
+ jQuery.fn.pixastic = function(action, options) {
+ var newElements = [];
+ this.each(
+ function () {
+ if (this.tagName.toLowerCase() == "img" && !this.complete) {
+ return;
+ }
+ var res = Pixastic.process(this, action, options);
+ if (res) {
+ newElements.push(res);
+ }
+ }
+ );
+ if (newElements.length > 0)
+ return jQuery(newElements);
+ else
+ return this;
+ };
+
+};
+/*
+ * Pixastic Lib - Blend - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.blend = {
+
+ process : function(params) {
+ var amount = parseFloat(params.options.amount);
+ var mode = (params.options.mode || "normal").toLowerCase();
+ var image = params.options.image;
+
+ amount = Math.max(0,Math.min(1,amount));
+
+ if (!image) return false;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var rect = params.options.rect;
+ var data = Pixastic.prepareData(params);
+ var w = rect.width;
+ var h = rect.height;
+
+ params.useData = false;
+
+ var otherCanvas = document.createElement("canvas");
+ otherCanvas.width = params.canvas.width;
+ otherCanvas.height = params.canvas.height;
+ var otherCtx = otherCanvas.getContext("2d");
+ otherCtx.drawImage(image,0,0);
+
+ var params2 = {canvas:otherCanvas,options:params.options};
+ var data2 = Pixastic.prepareData(params2);
+ var dataDesc2 = params2.canvasData;
+
+ var p = w*h;
+ var pix = p*4;
+ var pix1, pix2;
+ var r1, g1, b1;
+ var r2, g2, b2;
+ var r3, g3, b3;
+ var r4, g4, b4;
+
+ var dataChanged = false;
+
+ switch (mode) {
+ case "normal" :
+ //while (p--) {
+ // data2[pix-=4] = data2[pix];
+ // data2[pix1=pix+1] = data2[pix1];
+ // data2[pix2=pix+2] = data2[pix2];
+ //}
+ break;
+
+ case "multiply" :
+ while (p--) {
+ data2[pix-=4] = data[pix] * data2[pix] / 255;
+ data2[pix1=pix+1] = data[pix1] * data2[pix1] / 255;
+ data2[pix2=pix+2] = data[pix2] * data2[pix2] / 255;
+ }
+ dataChanged = true;
+ break;
+
+ case "lighten" :
+ while (p--) {
+ if ((r1 = data[pix-=4]) > data2[pix])
+ data2[pix] = r1;
+ if ((g1 = data[pix1=pix+1]) > data2[pix1])
+ data2[pix1] = g1;
+ if ((b1 = data[pix2=pix+2]) > data2[pix2])
+ data2[pix2] = b1;
+ }
+ dataChanged = true;
+ break;
+
+ case "darken" :
+ while (p--) {
+ if ((r1 = data[pix-=4]) < data2[pix])
+ data2[pix] = r1;
+ if ((g1 = data[pix1=pix+1]) < data2[pix1])
+ data2[pix1] = g1;
+ if ((b1 = data[pix2=pix+2]) < data2[pix2])
+ data2[pix2] = b1;
+
+ }
+ dataChanged = true;
+ break;
+
+ case "darkercolor" :
+ while (p--) {
+ 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)) {
+ data2[pix] = r1;
+ data2[pix1] = g1;
+ data2[pix2] = b1;
+ }
+ }
+ dataChanged = true;
+ break;
+
+ case "lightercolor" :
+ while (p--) {
+ 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)) {
+ data2[pix] = r1;
+ data2[pix1] = g1;
+ data2[pix2] = b1;
+ }
+ }
+ dataChanged = true;
+ break;
+
+ case "lineardodge" :
+ otherCtx.globalCompositeOperation = "source-over";
+ otherCtx.drawImage(params.canvas, 0, 0);
+ otherCtx.globalCompositeOperation = "lighter";
+ otherCtx.drawImage(image, 0, 0);
+
+ /*
+ while (p--) {
+ if ((r3 = data[pix-=4] + data2[pix]) > 255)
+ data2[pix] = 255;
+ else
+ data2[pix] = r3;
+ if ((g3 = data[pix1=pix+1] + data2[pix1]) > 255)
+ data2[pix1] = 255;
+ else
+ data2[pix1] = g3;
+ if ((b3 = data[pix2=pix+2] + data2[pix2]) > 255)
+ data2[pix2] = 255;
+ else
+ data2[pix2] = b3;
+ }
+ dataChanged = true;
+ */
+
+ break;
+
+ case "linearburn" :
+ while (p--) {
+ if ((r3 = data[pix-=4] + data2[pix]) < 255)
+ data2[pix] = 0;
+ else
+ data2[pix] = (r3 - 255);
+ if ((g3 = data[pix1=pix+1] + data2[pix1]) < 255)
+ data2[pix1] = 0;
+ else
+ data2[pix1] = (g3 - 255);
+ if ((b3 = data[pix2=pix+2] + data2[pix2]) < 255)
+ data2[pix2] = 0;
+ else
+ data2[pix2] = (b3 - 255);
+ }
+ dataChanged = true;
+ break;
+
+ case "difference" :
+ while (p--) {
+ if ((r3 = data[pix-=4] - data2[pix]) < 0)
+ data2[pix] = -r3;
+ else
+ data2[pix] = r3;
+ if ((g3 = data[pix1=pix+1] - data2[pix1]) < 0)
+ data2[pix1] = -g3;
+ else
+ data2[pix1] = g3;
+ if ((b3 = data[pix2=pix+2] - data2[pix2]) < 0)
+ data2[pix2] = -b3;
+ else
+ data2[pix2] = b3;
+ }
+ dataChanged = true;
+ break;
+
+ case "screen" :
+ while (p--) {
+ data2[pix-=4] = (255 - ( ((255-data2[pix])*(255-data[pix])) >> 8));
+ data2[pix1=pix+1] = (255 - ( ((255-data2[pix1])*(255-data[pix1])) >> 8));
+ data2[pix2=pix+2] = (255 - ( ((255-data2[pix2])*(255-data[pix2])) >> 8));
+ }
+ dataChanged = true;
+ break;
+
+ case "exclusion" :
+ var div_2_255 = 2 / 255;
+ while (p--) {
+ data2[pix-=4] = (r1 = data[pix]) - (r1 * div_2_255 - 1) * data2[pix];
+ data2[pix1=pix+1] = (g1 = data[pix1]) - (g1 * div_2_255 - 1) * data2[pix1];
+ data2[pix2=pix+2] = (b1 = data[pix2]) - (b1 * div_2_255 - 1) * data2[pix2];
+ }
+ dataChanged = true;
+ break;
+
+ case "overlay" :
+ var div_2_255 = 2 / 255;
+ while (p--) {
+ if ((r1 = data[pix-=4]) < 128)
+ data2[pix] = data2[pix]*r1*div_2_255;
+ else
+ data2[pix] = 255 - (255-data2[pix])*(255-r1)*div_2_255;
+
+ if ((g1 = data[pix1=pix+1]) < 128)
+ data2[pix1] = data2[pix1]*g1*div_2_255;
+ else
+ data2[pix1] = 255 - (255-data2[pix1])*(255-g1)*div_2_255;
+
+ if ((b1 = data[pix2=pix+2]) < 128)
+ data2[pix2] = data2[pix2]*b1*div_2_255;
+ else
+ data2[pix2] = 255 - (255-data2[pix2])*(255-b1)*div_2_255;
+
+ }
+ dataChanged = true;
+ break;
+
+ case "softlight" :
+ var div_2_255 = 2 / 255;
+ while (p--) {
+ if ((r1 = data[pix-=4]) < 128)
+ data2[pix] = ((data2[pix]>>1) + 64) * r1 * div_2_255;
+ else
+ data2[pix] = 255 - (191 - (data2[pix]>>1)) * (255-r1) * div_2_255;
+
+ if ((g1 = data[pix1=pix+1]) < 128)
+ data2[pix1] = ((data2[pix1]>>1)+64) * g1 * div_2_255;
+ else
+ data2[pix1] = 255 - (191 - (data2[pix1]>>1)) * (255-g1) * div_2_255;
+
+ if ((b1 = data[pix2=pix+2]) < 128)
+ data2[pix2] = ((data2[pix2]>>1)+64) * b1 * div_2_255;
+ else
+ data2[pix2] = 255 - (191 - (data2[pix2]>>1)) * (255-b1) * div_2_255;
+
+ }
+ dataChanged = true;
+ break;
+
+ case "hardlight" :
+ var div_2_255 = 2 / 255;
+ while (p--) {
+ if ((r2 = data2[pix-=4]) < 128)
+ data2[pix] = data[pix] * r2 * div_2_255;
+ else
+ data2[pix] = 255 - (255-data[pix]) * (255-r2) * div_2_255;
+
+ if ((g2 = data2[pix1=pix+1]) < 128)
+ data2[pix1] = data[pix1] * g2 * div_2_255;
+ else
+ data2[pix1] = 255 - (255-data[pix1]) * (255-g2) * div_2_255;
+
+ if ((b2 = data2[pix2=pix+2]) < 128)
+ data2[pix2] = data[pix2] * b2 * div_2_255;
+ else
+ data2[pix2] = 255 - (255-data[pix2]) * (255-b2) * div_2_255;
+
+ }
+ dataChanged = true;
+ break;
+
+ case "colordodge" :
+ while (p--) {
+ if ((r3 = (data[pix-=4]<<8)/(255-(r2 = data2[pix]))) > 255 || r2 == 255)
+ data2[pix] = 255;
+ else
+ data2[pix] = r3;
+
+ if ((g3 = (data[pix1=pix+1]<<8)/(255-(g2 = data2[pix1]))) > 255 || g2 == 255)
+ data2[pix1] = 255;
+ else
+ data2[pix1] = g3;
+
+ if ((b3 = (data[pix2=pix+2]<<8)/(255-(b2 = data2[pix2]))) > 255 || b2 == 255)
+ data2[pix2] = 255;
+ else
+ data2[pix2] = b3;
+ }
+ dataChanged = true;
+ break;
+
+ case "colorburn" :
+ while (p--) {
+ if ((r3 = 255-((255-data[pix-=4])<<8)/data2[pix]) < 0 || data2[pix] == 0)
+ data2[pix] = 0;
+ else
+ data2[pix] = r3;
+
+ if ((g3 = 255-((255-data[pix1=pix+1])<<8)/data2[pix1]) < 0 || data2[pix1] == 0)
+ data2[pix1] = 0;
+ else
+ data2[pix1] = g3;
+
+ if ((b3 = 255-((255-data[pix2=pix+2])<<8)/data2[pix2]) < 0 || data2[pix2] == 0)
+ data2[pix2] = 0;
+ else
+ data2[pix2] = b3;
+ }
+ dataChanged = true;
+ break;
+
+ case "linearlight" :
+ while (p--) {
+ if ( ((r3 = 2*(r2=data2[pix-=4])+data[pix]-256) < 0) || (r2 < 128 && r3 < 0)) {
+ data2[pix] = 0
+ } else {
+ if (r3 > 255)
+ data2[pix] = 255;
+ else
+ data2[pix] = r3;
+ }
+ if ( ((g3 = 2*(g2=data2[pix1=pix+1])+data[pix1]-256) < 0) || (g2 < 128 && g3 < 0)) {
+ data2[pix1] = 0
+ } else {
+ if (g3 > 255)
+ data2[pix1] = 255;
+ else
+ data2[pix1] = g3;
+ }
+ if ( ((b3 = 2*(b2=data2[pix2=pix+2])+data[pix2]-256) < 0) || (b2 < 128 && b3 < 0)) {
+ data2[pix2] = 0
+ } else {
+ if (b3 > 255)
+ data2[pix2] = 255;
+ else
+ data2[pix2] = b3;
+ }
+ }
+ dataChanged = true;
+ break;
+
+ case "vividlight" :
+ while (p--) {
+ if ((r2=data2[pix-=4]) < 128) {
+ if (r2) {
+ if ((r3 = 255 - ((255-data[pix])<<8) / (2*r2)) < 0)
+ data2[pix] = 0;
+ else
+ data2[pix] = r3
+ } else {
+ data2[pix] = 0;
+ }
+ } else if ((r3 = (r4=2*r2-256)) < 255) {
+ if ((r3 = (data[pix]<<8)/(255-r4)) > 255)
+ data2[pix] = 255;
+ else
+ data2[pix] = r3;
+ } else {
+ if (r3 < 0)
+ data2[pix] = 0;
+ else
+ data2[pix] = r3
+ }
+
+ if ((g2=data2[pix1=pix+1]) < 128) {
+ if (g2) {
+ if ((g3 = 255 - ((255-data[pix1])<<8) / (2*g2)) < 0)
+ data2[pix1] = 0;
+ else
+ data2[pix1] = g3;
+ } else {
+ data2[pix1] = 0;
+ }
+ } else if ((g3 = (g4=2*g2-256)) < 255) {
+ if ((g3 = (data[pix1]<<8)/(255-g4)) > 255)
+ data2[pix1] = 255;
+ else
+ data2[pix1] = g3;
+ } else {
+ if (g3 < 0)
+ data2[pix1] = 0;
+ else
+ data2[pix1] = g3;
+ }
+
+ if ((b2=data2[pix2=pix+2]) < 128) {
+ if (b2) {
+ if ((b3 = 255 - ((255-data[pix2])<<8) / (2*b2)) < 0)
+ data2[pix2] = 0;
+ else
+ data2[pix2] = b3;
+ } else {
+ data2[pix2] = 0;
+ }
+ } else if ((b3 = (b4=2*b2-256)) < 255) {
+ if ((b3 = (data[pix2]<<8)/(255-b4)) > 255)
+ data2[pix2] = 255;
+ else
+ data2[pix2] = b3;
+ } else {
+ if (b3 < 0)
+ data2[pix2] = 0;
+ else
+ data2[pix2] = b3;
+ }
+ }
+ dataChanged = true;
+ break;
+
+ case "pinlight" :
+ while (p--) {
+ if ((r2=data2[pix-=4]) < 128)
+ if ((r1=data[pix]) < (r4=2*r2))
+ data2[pix] = r1;
+ else
+ data2[pix] = r4;
+ else
+ if ((r1=data[pix]) > (r4=2*r2-256))
+ data2[pix] = r1;
+ else
+ data2[pix] = r4;
+
+ if ((g2=data2[pix1=pix+1]) < 128)
+ if ((g1=data[pix1]) < (g4=2*g2))
+ data2[pix1] = g1;
+ else
+ data2[pix1] = g4;
+ else
+ if ((g1=data[pix1]) > (g4=2*g2-256))
+ data2[pix1] = g1;
+ else
+ data2[pix1] = g4;
+
+ if ((r2=data2[pix2=pix+2]) < 128)
+ if ((r1=data[pix2]) < (r4=2*r2))
+ data2[pix2] = r1;
+ else
+ data2[pix2] = r4;
+ else
+ if ((r1=data[pix2]) > (r4=2*r2-256))
+ data2[pix2] = r1;
+ else
+ data2[pix2] = r4;
+ }
+ dataChanged = true;
+ break;
+
+ case "hardmix" :
+ while (p--) {
+ if ((r2 = data2[pix-=4]) < 128)
+ if (255 - ((255-data[pix])<<8)/(2*r2) < 128 || r2 == 0)
+ data2[pix] = 0;
+ else
+ data2[pix] = 255;
+ else if ((r4=2*r2-256) < 255 && (data[pix]<<8)/(255-r4) < 128)
+ data2[pix] = 0;
+ else
+ data2[pix] = 255;
+
+ if ((g2 = data2[pix1=pix+1]) < 128)
+ if (255 - ((255-data[pix1])<<8)/(2*g2) < 128 || g2 == 0)
+ data2[pix1] = 0;
+ else
+ data2[pix1] = 255;
+ else if ((g4=2*g2-256) < 255 && (data[pix1]<<8)/(255-g4) < 128)
+ data2[pix1] = 0;
+ else
+ data2[pix1] = 255;
+
+ if ((b2 = data2[pix2=pix+2]) < 128)
+ if (255 - ((255-data[pix2])<<8)/(2*b2) < 128 || b2 == 0)
+ data2[pix2] = 0;
+ else
+ data2[pix2] = 255;
+ else if ((b4=2*b2-256) < 255 && (data[pix2]<<8)/(255-b4) < 128)
+ data2[pix2] = 0;
+ else
+ data2[pix2] = 255;
+ }
+ dataChanged = true;
+ break;
+ }
+
+ if (dataChanged)
+ otherCtx.putImageData(dataDesc2,0,0);
+
+ var ctx = params.canvas.getContext("2d");
+ ctx.save();
+ ctx.globalAlpha = amount;
+ ctx.drawImage(
+ otherCanvas,
+ 0,0,rect.width,rect.height,
+ rect.left,rect.top,rect.width,rect.height
+ );
+ ctx.globalAlpha = 1;
+ ctx.restore();
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}/*
+ * Pixastic Lib - Blur filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.blur = {
+ process : function(params) {
+
+ if (typeof params.options.fixMargin == "undefined")
+ params.options.fixMargin = true;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var dataCopy = Pixastic.prepareData(params, true)
+
+ /*
+ var kernel = [
+ [0.5, 1, 0.5],
+ [1, 2, 1],
+ [0.5, 1, 0.5]
+ ];
+ */
+
+ var kernel = [
+ [0, 1, 0],
+ [1, 2, 1],
+ [0, 1, 0]
+ ];
+
+ var weight = 0;
+ for (var i=0;i<3;i++) {
+ for (var j=0;j<3;j++) {
+ weight += kernel[i][j];
+ }
+ }
+
+ weight = 1 / (weight*2);
+
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+
+ var prevY = (y == 1) ? 0 : y-2;
+ var nextY = (y == h) ? y - 1 : y;
+
+ var offsetYPrev = prevY*w*4;
+ var offsetYNext = nextY*w*4;
+
+ var x = w;
+ do {
+ var offset = offsetY + (x*4-4);
+
+ var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+ var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+
+ data[offset] = (
+ /*
+ dataCopy[offsetPrev - 4]
+ + dataCopy[offsetPrev+4]
+ + dataCopy[offsetNext - 4]
+ + dataCopy[offsetNext+4]
+ +
+ */
+ (dataCopy[offsetPrev]
+ + dataCopy[offset-4]
+ + dataCopy[offset+4]
+ + dataCopy[offsetNext]) * 2
+ + dataCopy[offset] * 4
+ ) * weight;
+
+ data[offset+1] = (
+ /*
+ dataCopy[offsetPrev - 3]
+ + dataCopy[offsetPrev+5]
+ + dataCopy[offsetNext - 3]
+ + dataCopy[offsetNext+5]
+ +
+ */
+ (dataCopy[offsetPrev+1]
+ + dataCopy[offset-3]
+ + dataCopy[offset+5]
+ + dataCopy[offsetNext+1]) * 2
+ + dataCopy[offset+1] * 4
+ ) * weight;
+
+ data[offset+2] = (
+ /*
+ dataCopy[offsetPrev - 2]
+ + dataCopy[offsetPrev+6]
+ + dataCopy[offsetNext - 2]
+ + dataCopy[offsetNext+6]
+ +
+ */
+ (dataCopy[offsetPrev+2]
+ + dataCopy[offset-2]
+ + dataCopy[offset+6]
+ + dataCopy[offsetNext+2]) * 2
+ + dataCopy[offset+2] * 4
+ ) * weight;
+
+ } while (--x);
+ } while (--y);
+
+ return true;
+
+ } else if (Pixastic.Client.isIE()) {
+ params.image.style.filter += " progid:DXImageTransform.Microsoft.Blur(pixelradius=1.5)";
+
+ if (params.options.fixMargin) {
+ params.image.style.marginLeft = (parseInt(params.image.style.marginLeft,10)||0) - 2 + "px";
+ params.image.style.marginTop = (parseInt(params.image.style.marginTop,10)||0) - 2 + "px";
+ }
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+ }
+}/*
+ * Pixastic Lib - Blur Fast - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.blurfast = {
+ process : function(params) {
+
+ var amount = parseFloat(params.options.amount)||0;
+ var clear = !!(params.options.clear && params.options.clear != "false");
+
+ amount = Math.max(0,Math.min(5,amount));
+
+ if (Pixastic.Client.hasCanvas()) {
+ var rect = params.options.rect;
+
+ var ctx = params.canvas.getContext("2d");
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(rect.left, rect.top, rect.width, rect.height);
+ ctx.clip();
+
+ var scale = 2;
+ var smallWidth = Math.round(params.width / scale);
+ var smallHeight = Math.round(params.height / scale);
+
+ var copy = document.createElement("canvas");
+ copy.width = smallWidth;
+ copy.height = smallHeight;
+
+ var clear = false;
+ var steps = Math.round(amount * 20);
+
+ var copyCtx = copy.getContext("2d");
+ for (var i=0;i<steps;i++) {
+ var scaledWidth = Math.max(1,Math.round(smallWidth - i));
+ var scaledHeight = Math.max(1,Math.round(smallHeight - i));
+
+ copyCtx.clearRect(0,0,smallWidth,smallHeight);
+
+ copyCtx.drawImage(
+ params.canvas,
+ 0,0,params.width,params.height,
+ 0,0,scaledWidth,scaledHeight
+ );
+
+ if (clear)
+ ctx.clearRect(rect.left,rect.top,rect.width,rect.height);
+
+ ctx.drawImage(
+ copy,
+ 0,0,scaledWidth,scaledHeight,
+ 0,0,params.width,params.height
+ );
+ }
+
+ ctx.restore();
+
+ params.useData = false;
+ return true;
+ } else if (Pixastic.Client.isIE()) {
+ var radius = 10 * amount;
+ params.image.style.filter += " progid:DXImageTransform.Microsoft.Blur(pixelradius=" + radius + ")";
+
+ if (params.options.fixMargin || 1) {
+ params.image.style.marginLeft = (parseInt(params.image.style.marginLeft,10)||0) - Math.round(radius) + "px";
+ params.image.style.marginTop = (parseInt(params.image.style.marginTop,10)||0) - Math.round(radius) + "px";
+ }
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
+ }
+}
+/*
+ * Pixastic Lib - Brightness/Contrast filter - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.brightness = {
+
+ process : function(params) {
+
+ var brightness = parseInt(params.options.brightness,10) || 0;
+ var contrast = parseFloat(params.options.contrast)||0;
+ var legacy = !!(params.options.legacy && params.options.legacy != "false");
+
+ if (legacy) {
+ brightness = Math.min(150,Math.max(-150,brightness));
+ } else {
+ var brightMul = 1 + Math.min(150,Math.max(-150,brightness)) / 150;
+ }
+ contrast = Math.max(0,contrast+1);
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var p = w*h;
+ var pix = p*4, pix1, pix2;
+
+ var mul, add;
+ if (contrast != 1) {
+ if (legacy) {
+ mul = contrast;
+ add = (brightness - 128) * contrast + 128;
+ } else {
+ mul = brightMul * contrast;
+ add = - contrast * 128 + 128;
+ }
+ } else { // this if-then is not necessary anymore, is it?
+ if (legacy) {
+ mul = 1;
+ add = brightness;
+ } else {
+ mul = brightMul;
+ add = 0;
+ }
+ }
+ var r, g, b;
+ while (p--) {
+ if ((r = data[pix-=4] * mul + add) > 255 )
+ data[pix] = 255;
+ else if (r < 0)
+ data[pix] = 0;
+ else
+ data[pix] = r;
+
+ if ((g = data[pix1=pix+1] * mul + add) > 255 )
+ data[pix1] = 255;
+ else if (g < 0)
+ data[pix1] = 0;
+ else
+ data[pix1] = g;
+
+ if ((b = data[pix2=pix+2] * mul + add) > 255 )
+ data[pix2] = 255;
+ else if (b < 0)
+ data[pix2] = 0;
+ else
+ data[pix2] = b;
+ }
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}
+
+/*
+ * Pixastic Lib - Color adjust filter - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.coloradjust = {
+
+ process : function(params) {
+ var red = parseFloat(params.options.red) || 0;
+ var green = parseFloat(params.options.green) || 0;
+ var blue = parseFloat(params.options.blue) || 0;
+
+ red = Math.round(red*255);
+ green = Math.round(green*255);
+ blue = Math.round(blue*255);
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var rect = params.options.rect;
+
+ var p = rect.width*rect.height;
+ var pix = p*4, pix1, pix2;
+
+ var r, g, b;
+ while (p--) {
+ pix -= 4;
+
+ if (red) {
+ if ((r = data[pix] + red) < 0 )
+ data[pix] = 0;
+ else if (r > 255 )
+ data[pix] = 255;
+ else
+ data[pix] = r;
+ }
+
+ if (green) {
+ if ((g = data[pix1=pix+1] + green) < 0 )
+ data[pix1] = 0;
+ else if (g > 255 )
+ data[pix1] = 255;
+ else
+ data[pix1] = g;
+ }
+
+ if (blue) {
+ if ((b = data[pix2=pix+2] + blue) < 0 )
+ data[pix2] = 0;
+ else if (b > 255 )
+ data[pix2] = 255;
+ else
+ data[pix2] = b;
+ }
+ }
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvasImageData());
+ }
+}
+/*
+ * Pixastic Lib - Histogram - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+
+Pixastic.Actions.colorhistogram = {
+
+ array256 : function(default_value) {
+ arr = [];
+ for (var i=0; i<256; i++) { arr[i] = default_value; }
+ return arr
+ },
+
+ process : function(params) {
+ var values = [];
+ if (typeof params.options.returnValue != "object") {
+ params.options.returnValue = {rvals:[], gvals:[], bvals:[]};
+ }
+ var paint = !!(params.options.paint);
+
+ var returnValue = params.options.returnValue;
+ if (typeof returnValue.values != "array") {
+ returnValue.rvals = [];
+ returnValue.gvals = [];
+ returnValue.bvals = [];
+ }
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ params.useData = false;
+
+ var rvals = this.array256(0);
+ var gvals = this.array256(0);
+ var bvals = this.array256(0);
+
+ var rect = params.options.rect;
+
+ var p = rect.width*rect.height;
+ var pix = p*4;
+ while (p--) {
+ rvals[data[pix-=4]]++;
+ gvals[data[pix+1]]++;
+ bvals[data[pix+2]]++;
+ }
+
+ returnValue.rvals = rvals;
+ returnValue.gvals = gvals;
+ returnValue.bvals = bvals;
+
+ if (paint) {
+ var ctx = params.canvas.getContext("2d");
+ var vals = [rvals, gvals, bvals];
+ for (var v=0;v<3;v++) {
+ var yoff = (v+1) * params.height / 3;
+ var maxValue = 0;
+ for (var i=0;i<256;i++) {
+ if (vals[v][i] > maxValue)
+ maxValue = vals[v][i];
+ }
+ var heightScale = params.height / 3 / maxValue;
+ var widthScale = params.width / 256;
+ if (v==0) ctx.fillStyle = "rgba(255,0,0,0.5)";
+ else if (v==1) ctx.fillStyle = "rgba(0,255,0,0.5)";
+ else if (v==2) ctx.fillStyle = "rgba(0,0,255,0.5)";
+ for (var i=0;i<256;i++) {
+ ctx.fillRect(
+ i * widthScale, params.height - heightScale * vals[v][i] - params.height + yoff,
+ widthScale, vals[v][i] * heightScale
+ );
+ }
+ }
+ }
+ return true;
+ }
+ },
+
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}/*
+ * Pixastic Lib - Crop - v0.1.1
+ * Copyright (c) 2008-2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.crop = {
+ process : function(params) {
+ if (Pixastic.Client.hasCanvas()) {
+ var rect = params.options.rect;
+
+ var width = rect.width;
+ var height = rect.height;
+ var top = rect.top;
+ var left = rect.left;
+
+ if (typeof params.options.left != "undefined")
+ left = parseInt(params.options.left,10);
+ if (typeof params.options.top != "undefined")
+ top = parseInt(params.options.top,10);
+ if (typeof params.options.height != "undefined")
+ width = parseInt(params.options.width,10);
+ if (typeof params.options.height != "undefined")
+ height = parseInt(params.options.height,10);
+
+ if (left < 0) left = 0;
+ if (left > params.width-1) left = params.width-1;
+
+ if (top < 0) top = 0;
+ if (top > params.height-1) top = params.height-1;
+
+ if (width < 1) width = 1;
+ if (left + width > params.width)
+ width = params.width - left;
+
+ if (height < 1) height = 1;
+ if (top + height > params.height)
+ height = params.height - top;
+
+ var copy = document.createElement("canvas");
+ copy.width = params.width;
+ copy.height = params.height;
+ copy.getContext("2d").drawImage(params.canvas,0,0);
+
+ params.canvas.width = width;
+ params.canvas.height = height;
+ params.canvas.getContext("2d").clearRect(0,0,width,height);
+
+ params.canvas.getContext("2d").drawImage(copy,
+ left,top,width,height,
+ 0,0,width,height
+ );
+
+ params.useData = false;
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvas();
+ }
+}
+
+
+/*
+ * Pixastic Lib - Desaturation filter - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.desaturate = {
+
+ process : function(params) {
+ var useAverage = !!(params.options.average && params.options.average != "false");
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var p = w*h;
+ var pix = p*4, pix1, pix2;
+
+ if (useAverage) {
+ while (p--)
+ data[pix-=4] = data[pix1=pix+1] = data[pix2=pix+2] = (data[pix]+data[pix1]+data[pix2])/3
+ } else {
+ while (p--)
+ data[pix-=4] = data[pix1=pix+1] = data[pix2=pix+2] = (data[pix]*0.3 + data[pix1]*0.59 + data[pix2]*0.11);
+ }
+ return true;
+ } else if (Pixastic.Client.isIE()) {
+ params.image.style.filter += " gray";
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+ }
+}/*
+ * Pixastic Lib - Edge detection filter - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.edges = {
+ process : function(params) {
+
+ var mono = !!(params.options.mono && params.options.mono != "false");
+ var invert = !!(params.options.invert && params.options.invert != "false");
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var dataCopy = Pixastic.prepareData(params, true)
+
+ var c = -1/8;
+ var kernel = [
+ [c, c, c],
+ [c, 1, c],
+ [c, c, c]
+ ];
+
+ weight = 1/c;
+
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+
+ var nextY = (y == h) ? y - 1 : y;
+ var prevY = (y == 1) ? 0 : y-2;
+
+ var offsetYPrev = prevY*w*4;
+ var offsetYNext = nextY*w*4;
+
+ var x = w;
+ do {
+ var offset = offsetY + (x*4-4);
+
+ var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+ var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+
+ var r = ((dataCopy[offsetPrev-4]
+ + dataCopy[offsetPrev]
+ + dataCopy[offsetPrev+4]
+ + dataCopy[offset-4]
+ + dataCopy[offset+4]
+ + dataCopy[offsetNext-4]
+ + dataCopy[offsetNext]
+ + dataCopy[offsetNext+4]) * c
+ + dataCopy[offset]
+ )
+ * weight;
+
+ var g = ((dataCopy[offsetPrev-3]
+ + dataCopy[offsetPrev+1]
+ + dataCopy[offsetPrev+5]
+ + dataCopy[offset-3]
+ + dataCopy[offset+5]
+ + dataCopy[offsetNext-3]
+ + dataCopy[offsetNext+1]
+ + dataCopy[offsetNext+5]) * c
+ + dataCopy[offset+1])
+ * weight;
+
+ var b = ((dataCopy[offsetPrev-2]
+ + dataCopy[offsetPrev+2]
+ + dataCopy[offsetPrev+6]
+ + dataCopy[offset-2]
+ + dataCopy[offset+6]
+ + dataCopy[offsetNext-2]
+ + dataCopy[offsetNext+2]
+ + dataCopy[offsetNext+6]) * c
+ + dataCopy[offset+2])
+ * weight;
+
+ if (mono) {
+ var brightness = (r*0.3 + g*0.59 + b*0.11)||0;
+ if (invert) brightness = 255 - brightness;
+ if (brightness < 0 ) brightness = 0;
+ if (brightness > 255 ) brightness = 255;
+ r = g = b = brightness;
+ } else {
+ if (invert) {
+ r = 255 - r;
+ g = 255 - g;
+ b = 255 - b;
+ }
+ if (r < 0 ) r = 0;
+ if (g < 0 ) g = 0;
+ if (b < 0 ) b = 0;
+ if (r > 255 ) r = 255;
+ if (g > 255 ) g = 255;
+ if (b > 255 ) b = 255;
+ }
+
+ data[offset] = r;
+ data[offset+1] = g;
+ data[offset+2] = b;
+
+ } while (--x);
+ } while (--y);
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}/*
+ * Pixastic Lib - Edge detection 2 - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ *
+ * Contribution by Oliver Hunt (http://nerget.com/, http://nerget.com/canvas/edgeDetection.js). Thanks Oliver!
+ *
+ */
+
+Pixastic.Actions.edges2 = {
+ process : function(params) {
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var dataCopy = Pixastic.prepareData(params, true)
+
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var w4 = w * 4;
+ var pixel = w4 + 4; // Start at (1,1)
+ var hm1 = h - 1;
+ var wm1 = w - 1;
+ for (var y = 1; y < hm1; ++y) {
+ // Prepare initial cached values for current row
+ var centerRow = pixel - 4;
+ var priorRow = centerRow - w4;
+ var nextRow = centerRow + w4;
+
+ var r1 = - dataCopy[priorRow] - dataCopy[centerRow] - dataCopy[nextRow];
+ var g1 = - dataCopy[++priorRow] - dataCopy[++centerRow] - dataCopy[++nextRow];
+ var b1 = - dataCopy[++priorRow] - dataCopy[++centerRow] - dataCopy[++nextRow];
+
+ var rp = dataCopy[priorRow += 2];
+ var gp = dataCopy[++priorRow];
+ var bp = dataCopy[++priorRow];
+
+ var rc = dataCopy[centerRow += 2];
+ var gc = dataCopy[++centerRow];
+ var bc = dataCopy[++centerRow];
+
+ var rn = dataCopy[nextRow += 2];
+ var gn = dataCopy[++nextRow];
+ var bn = dataCopy[++nextRow];
+
+ var r2 = - rp - rc - rn;
+ var g2 = - gp - gc - gn;
+ var b2 = - bp - bc - bn;
+
+ // Main convolution loop
+ for (var x = 1; x < wm1; ++x) {
+ centerRow = pixel + 4;
+ priorRow = centerRow - w4;
+ nextRow = centerRow + w4;
+
+ var r = 127 + r1 - rp - (rc * -8) - rn;
+ var g = 127 + g1 - gp - (gc * -8) - gn;
+ var b = 127 + b1 - bp - (bc * -8) - bn;
+
+ r1 = r2;
+ g1 = g2;
+ b1 = b2;
+
+ rp = dataCopy[ priorRow];
+ gp = dataCopy[++priorRow];
+ bp = dataCopy[++priorRow];
+
+ rc = dataCopy[ centerRow];
+ gc = dataCopy[++centerRow];
+ bc = dataCopy[++centerRow];
+
+ rn = dataCopy[ nextRow];
+ gn = dataCopy[++nextRow];
+ bn = dataCopy[++nextRow];
+
+ r += (r2 = - rp - rc - rn);
+ g += (g2 = - gp - gc - gn);
+ b += (b2 = - bp - bc - bn);
+
+ if (r > 255) r = 255;
+ if (g > 255) g = 255;
+ if (b > 255) b = 255;
+ if (r < 0) r = 0;
+ if (g < 0) g = 0;
+ if (b < 0) b = 0;
+
+ data[pixel] = r;
+ data[++pixel] = g;
+ data[++pixel] = b;
+ //data[++pixel] = 255; // alpha
+
+ pixel+=2;
+ }
+ pixel += 8;
+ }
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}/*
+ * Pixastic Lib - Emboss filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.emboss = {
+ process : function(params) {
+
+ var strength = parseFloat(params.options.strength)||1;
+ var greyLevel = typeof params.options.greyLevel != "undefined" ? parseInt(params.options.greyLevel) : 180;
+ var direction = params.options.direction||"topleft";
+ var blend = !!(params.options.blend && params.options.blend != "false");
+
+ var dirY = 0;
+ var dirX = 0;
+
+ switch (direction) {
+ case "topleft": // top left
+ dirY = -1;
+ dirX = -1;
+ break;
+ case "top": // top
+ dirY = -1;
+ dirX = 0;
+ break;
+ case "topright": // top right
+ dirY = -1;
+ dirX = 1;
+ break;
+ case "right": // right
+ dirY = 0;
+ dirX = 1;
+ break;
+ case "bottomright": // bottom right
+ dirY = 1;
+ dirX = 1;
+ break;
+ case "bottom": // bottom
+ dirY = 1;
+ dirX = 0;
+ break;
+ case "bottomleft": // bottom left
+ dirY = 1;
+ dirX = -1;
+ break;
+ case "left": // left
+ dirY = 0;
+ dirX = -1;
+ break;
+ }
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var dataCopy = Pixastic.prepareData(params, true)
+
+ var invertAlpha = !!params.options.invertAlpha;
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+
+ var otherY = dirY;
+ if (y + otherY < 1) otherY = 0;
+ if (y + otherY > h) otherY = 0;
+
+ var offsetYOther = (y-1+otherY)*w*4;
+
+ var x = w;
+ do {
+ var offset = offsetY + (x-1)*4;
+
+ var otherX = dirX;
+ if (x + otherX < 1) otherX = 0;
+ if (x + otherX > w) otherX = 0;
+
+ var offsetOther = offsetYOther + (x-1+otherX)*4;
+
+ var dR = dataCopy[offset] - dataCopy[offsetOther];
+ var dG = dataCopy[offset+1] - dataCopy[offsetOther+1];
+ var dB = dataCopy[offset+2] - dataCopy[offsetOther+2];
+
+ var dif = dR;
+ var absDif = dif > 0 ? dif : -dif;
+
+ var absG = dG > 0 ? dG : -dG;
+ var absB = dB > 0 ? dB : -dB;
+
+ if (absG > absDif) {
+ dif = dG;
+ }
+ if (absB > absDif) {
+ dif = dB;
+ }
+
+ dif *= strength;
+
+ if (blend) {
+ var r = data[offset] + dif;
+ var g = data[offset+1] + dif;
+ var b = data[offset+2] + dif;
+
+ data[offset] = (r > 255) ? 255 : (r < 0 ? 0 : r);
+ data[offset+1] = (g > 255) ? 255 : (g < 0 ? 0 : g);
+ data[offset+2] = (b > 255) ? 255 : (b < 0 ? 0 : b);
+ } else {
+ var grey = greyLevel - dif;
+ if (grey < 0) {
+ grey = 0;
+ } else if (grey > 255) {
+ grey = 255;
+ }
+
+ data[offset] = data[offset+1] = data[offset+2] = grey;
+ }
+
+ } while (--x);
+ } while (--y);
+ return true;
+
+ } else if (Pixastic.Client.isIE()) {
+ params.image.style.filter += " progid:DXImageTransform.Microsoft.emboss()";
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+ }
+
+}
+/*
+ * Pixastic Lib - Flip - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.flip = {
+ process : function(params) {
+ var rect = params.options.rect;
+ var copyCanvas = document.createElement("canvas");
+ copyCanvas.width = rect.width;
+ copyCanvas.height = rect.height;
+ copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);
+
+ var ctx = params.canvas.getContext("2d");
+ ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
+
+ if (params.options.axis == "horizontal") {
+ ctx.scale(-1,1);
+ ctx.drawImage(copyCanvas, -rect.left-rect.width, rect.top, rect.width, rect.height)
+ } else {
+ ctx.scale(1,-1);
+ ctx.drawImage(copyCanvas, rect.left, -rect.top-rect.height, rect.width, rect.height)
+ }
+
+ params.useData = false;
+
+ return true;
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvas();
+ }
+}
+
+/*
+ * Pixastic Lib - Horizontal flip - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.fliph = {
+ process : function(params) {
+ if (Pixastic.Client.hasCanvas()) {
+ var rect = params.options.rect;
+ var copyCanvas = document.createElement("canvas");
+ copyCanvas.width = rect.width;
+ copyCanvas.height = rect.height;
+ copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);
+
+ var ctx = params.canvas.getContext("2d");
+ ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
+ ctx.scale(-1,1);
+ ctx.drawImage(copyCanvas, -rect.left-rect.width, rect.top, rect.width, rect.height)
+ params.useData = false;
+
+ return true;
+
+ } else if (Pixastic.Client.isIE()) {
+ params.image.style.filter += " fliph";
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
+ }
+}
+
+/*
+ * Pixastic Lib - Vertical flip - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.flipv = {
+ process : function(params) {
+ if (Pixastic.Client.hasCanvas()) {
+ var rect = params.options.rect;
+ var copyCanvas = document.createElement("canvas");
+ copyCanvas.width = rect.width;
+ copyCanvas.height = rect.height;
+ copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);
+
+ var ctx = params.canvas.getContext("2d");
+ ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
+ ctx.scale(1,-1);
+ ctx.drawImage(copyCanvas, rect.left, -rect.top-rect.height, rect.width, rect.height)
+ params.useData = false;
+
+ return true;
+
+ } else if (Pixastic.Client.isIE()) {
+ params.image.style.filter += " flipv";
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
+ }
+}
+
+/*
+ * Pixastic Lib - Glow - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+
+Pixastic.Actions.glow = {
+ process : function(params) {
+
+ var amount = (parseFloat(params.options.amount)||0);
+ var blurAmount = parseFloat(params.options.radius)||0;
+
+ amount = Math.min(1,Math.max(0,amount));
+ blurAmount = Math.min(5,Math.max(0,blurAmount));
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var rect = params.options.rect;
+
+ var blurCanvas = document.createElement("canvas");
+ blurCanvas.width = params.width;
+ blurCanvas.height = params.height;
+ var blurCtx = blurCanvas.getContext("2d");
+ blurCtx.drawImage(params.canvas,0,0);
+
+ var scale = 2;
+ var smallWidth = Math.round(params.width / scale);
+ var smallHeight = Math.round(params.height / scale);
+
+ var copy = document.createElement("canvas");
+ copy.width = smallWidth;
+ copy.height = smallHeight;
+
+ var clear = true;
+ var steps = Math.round(blurAmount * 20);
+
+ var copyCtx = copy.getContext("2d");
+ for (var i=0;i<steps;i++) {
+ var scaledWidth = Math.max(1,Math.round(smallWidth - i));
+ var scaledHeight = Math.max(1,Math.round(smallHeight - i));
+
+ copyCtx.clearRect(0,0,smallWidth,smallHeight);
+
+ copyCtx.drawImage(
+ blurCanvas,
+ 0,0,params.width,params.height,
+ 0,0,scaledWidth,scaledHeight
+ );
+
+ blurCtx.clearRect(0,0,params.width,params.height);
+
+ blurCtx.drawImage(
+ copy,
+ 0,0,scaledWidth,scaledHeight,
+ 0,0,params.width,params.height
+ );
+ }
+
+ var data = Pixastic.prepareData(params);
+ var blurData = Pixastic.prepareData({canvas:blurCanvas,options:params.options});
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x*4-4);
+
+ var r = data[offset] + amount * blurData[offset];
+ var g = data[offset+1] + amount * blurData[offset+1];
+ var b = data[offset+2] + amount * blurData[offset+2];
+
+ if (r > 255) r = 255;
+ if (g > 255) g = 255;
+ if (b > 255) b = 255;
+ if (r < 0) r = 0;
+ if (g < 0) g = 0;
+ if (b < 0) b = 0;
+
+ data[offset] = r;
+ data[offset+1] = g;
+ data[offset+2] = b;
+
+ } while (--x);
+ } while (--y);
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}
+
+
+
+/*
+ * Pixastic Lib - Histogram - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.histogram = {
+ process : function(params) {
+
+ var average = !!(params.options.average && params.options.average != "false");
+ var paint = !!(params.options.paint && params.options.paint != "false");
+ var color = params.options.color || "rgba(255,255,255,0.5)";
+ var values = [];
+ if (typeof params.options.returnValue != "object") {
+ params.options.returnValue = {values:[]};
+ }
+ var returnValue = params.options.returnValue;
+ if (typeof returnValue.values != "array") {
+ returnValue.values = [];
+ }
+ values = returnValue.values;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ params.useData = false;
+
+ for (var i=0;i<256;i++) {
+ values[i] = 0;
+ }
+
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x*4-4);
+ var brightness = average ?
+ Math.round((data[offset]+data[offset+1]+data[offset+2])/3)
+ : Math.round(data[offset]*0.3 + data[offset+1]*0.59 + data[offset+2]*0.11);
+ values[brightness]++;
+
+ } while (--x);
+ } while (--y);
+
+ if (paint) {
+ var maxValue = 0;
+ for (var i=0;i<256;i++) {
+ if (values[i] > maxValue) {
+ maxValue = values[i];
+ }
+ }
+ var heightScale = params.height / maxValue;
+ var widthScale = params.width / 256;
+ var ctx = params.canvas.getContext("2d");
+ ctx.fillStyle = color;
+ for (var i=0;i<256;i++) {
+ ctx.fillRect(
+ i * widthScale, params.height - heightScale * values[i],
+ widthScale, values[i] * heightScale
+ );
+ }
+ }
+
+ returnValue.values = values;
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}
+/*
+ * Pixastic Lib - HSL Adjust - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.hsl = {
+ process : function(params) {
+
+ var hue = parseInt(params.options.hue,10)||0;
+ var saturation = (parseInt(params.options.saturation,10)||0) / 100;
+ var lightness = (parseInt(params.options.lightness,10)||0) / 100;
+
+
+ // this seems to give the same result as Photoshop
+ if (saturation < 0) {
+ var satMul = 1+saturation;
+ } else {
+ var satMul = 1+saturation*2;
+ }
+
+ hue = (hue%360) / 360;
+ var hue6 = hue * 6;
+
+ var rgbDiv = 1 / 255;
+
+ var light255 = lightness * 255;
+ var lightp1 = 1 + lightness;
+ var lightm1 = 1 - lightness;
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var w4 = w*4;
+ var y = h;
+
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x*4-4);
+
+ var r = data[offset];
+ var g = data[offset+1];
+ var b = data[offset+2];
+
+ if (hue != 0 || saturation != 0) {
+ // ok, here comes rgb to hsl + adjust + hsl to rgb, all in one jumbled mess.
+ // It's not so pretty, but it's been optimized to get somewhat decent performance.
+ // The transforms were originally adapted from the ones found in Graphics Gems, but have been heavily modified.
+ var vs = r;
+ if (g > vs) vs = g;
+ if (b > vs) vs = b;
+ var ms = r;
+ if (g < ms) ms = g;
+ if (b < ms) ms = b;
+ var vm = (vs-ms);
+ var l = (ms+vs)/255 * 0.5;
+ if (l > 0) {
+ if (vm > 0) {
+ if (l <= 0.5) {
+ var s = vm / (vs+ms) * satMul;
+ if (s > 1) s = 1;
+ var v = (l * (1+s));
+ } else {
+ var s = vm / (510-vs-ms) * satMul;
+ if (s > 1) s = 1;
+ var v = (l+s - l*s);
+ }
+ if (r == vs) {
+ if (g == ms)
+ var h = 5 + ((vs-b)/vm) + hue6;
+ else
+ var h = 1 - ((vs-g)/vm) + hue6;
+ } else if (g == vs) {
+ if (b == ms)
+ var h = 1 + ((vs-r)/vm) + hue6;
+ else
+ var h = 3 - ((vs-b)/vm) + hue6;
+ } else {
+ if (r == ms)
+ var h = 3 + ((vs-g)/vm) + hue6;
+ else
+ var h = 5 - ((vs-r)/vm) + hue6;
+ }
+ if (h < 0) h+=6;
+ if (h >= 6) h-=6;
+ var m = (l+l-v);
+ var sextant = h>>0;
+ switch (sextant) {
+ case 0: r = v*255; g = (m+((v-m)*(h-sextant)))*255; b = m*255; break;
+ case 1: r = (v-((v-m)*(h-sextant)))*255; g = v*255; b = m*255; break;
+ case 2: r = m*255; g = v*255; b = (m+((v-m)*(h-sextant)))*255; break;
+ case 3: r = m*255; g = (v-((v-m)*(h-sextant)))*255; b = v*255; break;
+ case 4: r = (m+((v-m)*(h-sextant)))*255; g = m*255; b = v*255; break;
+ case 5: r = v*255; g = m*255; b = (v-((v-m)*(h-sextant)))*255; break;
+ }
+ }
+ }
+ }
+
+ if (lightness < 0) {
+ r *= lightp1;
+ g *= lightp1;
+ b *= lightp1;
+ } else if (lightness > 0) {
+ r = r * lightm1 + light255;
+ g = g * lightm1 + light255;
+ b = b * lightm1 + light255;
+ }
+
+ if (r < 0) r = 0;
+ if (g < 0) g = 0;
+ if (b < 0) b = 0;
+ if (r > 255) r = 255;
+ if (g > 255) g = 255;
+ if (b > 255) b = 255;
+
+ data[offset] = r;
+ data[offset+1] = g;
+ data[offset+2] = b;
+
+ } while (--x);
+ } while (--y);
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+
+}
+/*
+ * Pixastic Lib - Invert filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.invert = {
+ process : function(params) {
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+
+ var invertAlpha = !!params.options.invertAlpha;
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x-1)*4;
+ data[offset] = 255 - data[offset];
+ data[offset+1] = 255 - data[offset+1];
+ data[offset+2] = 255 - data[offset+2];
+ if (invertAlpha) data[offset+3] = 255 - data[offset+3];
+ } while (--x);
+ } while (--y);
+
+ return true;
+ } else if (Pixastic.Client.isIE()) {
+ params.image.style.filter += " invert";
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+ }
+}
+/*
+ * Pixastic Lib - Laplace filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.laplace = {
+ process : function(params) {
+
+ var strength = 1.0;
+ var invert = !!(params.options.invert && params.options.invert != "false");
+ var contrast = parseFloat(params.options.edgeStrength)||0;
+
+ var greyLevel = parseInt(params.options.greyLevel)||0;
+
+ contrast = -contrast;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var dataCopy = Pixastic.prepareData(params, true)
+
+ var kernel = [
+ [-1, -1, -1],
+ [-1, 8, -1],
+ [-1, -1, -1]
+ ];
+
+ var weight = 1/8;
+
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+
+ var nextY = (y == h) ? y - 1 : y;
+ var prevY = (y == 1) ? 0 : y-2;
+
+ var offsetYPrev = prevY*w*4;
+ var offsetYNext = nextY*w*4;
+
+ var x = w;
+ do {
+ var offset = offsetY + (x*4-4);
+
+ var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+ var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+
+ var r = ((-dataCopy[offsetPrev-4]
+ - dataCopy[offsetPrev]
+ - dataCopy[offsetPrev+4]
+ - dataCopy[offset-4]
+ - dataCopy[offset+4]
+ - dataCopy[offsetNext-4]
+ - dataCopy[offsetNext]
+ - dataCopy[offsetNext+4])
+ + dataCopy[offset] * 8)
+ * weight;
+
+ var g = ((-dataCopy[offsetPrev-3]
+ - dataCopy[offsetPrev+1]
+ - dataCopy[offsetPrev+5]
+ - dataCopy[offset-3]
+ - dataCopy[offset+5]
+ - dataCopy[offsetNext-3]
+ - dataCopy[offsetNext+1]
+ - dataCopy[offsetNext+5])
+ + dataCopy[offset+1] * 8)
+ * weight;
+
+ var b = ((-dataCopy[offsetPrev-2]
+ - dataCopy[offsetPrev+2]
+ - dataCopy[offsetPrev+6]
+ - dataCopy[offset-2]
+ - dataCopy[offset+6]
+ - dataCopy[offsetNext-2]
+ - dataCopy[offsetNext+2]
+ - dataCopy[offsetNext+6])
+ + dataCopy[offset+2] * 8)
+ * weight;
+
+ var brightness = ((r + g + b)/3) + greyLevel;
+
+ if (contrast != 0) {
+ if (brightness > 127) {
+ brightness += ((brightness + 1) - 128) * contrast;
+ } else if (brightness < 127) {
+ brightness -= (brightness + 1) * contrast;
+ }
+ }
+ if (invert) {
+ brightness = 255 - brightness;
+ }
+ if (brightness < 0 ) brightness = 0;
+ if (brightness > 255 ) brightness = 255;
+
+ data[offset] = data[offset+1] = data[offset+2] = brightness;
+
+ } while (--x);
+ } while (--y);
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}
+
+/*
+ * Pixastic Lib - Lighten filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.lighten = {
+
+ process : function(params) {
+ var amount = parseFloat(params.options.amount) || 0;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x-1)*4;
+
+ var r = data[offset];
+ var g = data[offset+1];
+ var b = data[offset+2];
+
+ r += r*amount;
+ g += g*amount;
+ b += b*amount;
+
+ if (r < 0 ) r = 0;
+ if (g < 0 ) g = 0;
+ if (b < 0 ) b = 0;
+ if (r > 255 ) r = 255;
+ if (g > 255 ) g = 255;
+ if (b > 255 ) b = 255;
+
+ data[offset] = r;
+ data[offset+1] = g;
+ data[offset+2] = b;
+
+ } while (--x);
+ } while (--y);
+ return true;
+
+ } else if (Pixastic.Client.isIE()) {
+ var img = params.image;
+ if (amount < 0) {
+ img.style.filter += " light()";
+ img.filters[img.filters.length-1].addAmbient(
+ 255,255,255,
+ 100 * -amount
+ );
+ } else if (amount > 0) {
+ img.style.filter += " light()";
+ img.filters[img.filters.length-1].addAmbient(
+ 255,255,255,
+ 100
+ );
+ img.filters[img.filters.length-1].addAmbient(
+ 255,255,255,
+ 100 * amount
+ );
+ }
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+ }
+}
+/*
+ * Pixastic Lib - Mosaic filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.mosaic = {
+
+ process : function(params) {
+ var blockSize = Math.max(1,parseInt(params.options.blockSize,10));
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+
+ var ctx = params.canvas.getContext("2d");
+
+ var pixel = document.createElement("canvas");
+ pixel.width = pixel.height = 1;
+ var pixelCtx = pixel.getContext("2d");
+
+ var copy = document.createElement("canvas");
+ copy.width = w;
+ copy.height = h;
+ var copyCtx = copy.getContext("2d");
+ copyCtx.drawImage(params.canvas,rect.left,rect.top,w,h, 0,0,w,h);
+
+ for (var y=0;y<h;y+=blockSize) {
+ for (var x=0;x<w;x+=blockSize) {
+ var blockSizeX = blockSize;
+ var blockSizeY = blockSize;
+
+ if (blockSizeX + x > w)
+ blockSizeX = w - x;
+ if (blockSizeY + y > h)
+ blockSizeY = h - y;
+
+ pixelCtx.drawImage(copy, x, y, blockSizeX, blockSizeY, 0, 0, 1, 1);
+ var data = pixelCtx.getImageData(0,0,1,1).data;
+ ctx.fillStyle = "rgb(" + data[0] + "," + data[1] + "," + data[2] + ")";
+ ctx.fillRect(rect.left + x, rect.top + y, blockSize, blockSize);
+ }
+ }
+ params.useData = false;
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvasImageData());
+ }
+}/*
+ * Pixastic Lib - Noise filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.noise = {
+
+ process : function(params) {
+ var amount = 0;
+ var strength = 0;
+ var mono = false;
+
+ if (typeof params.options.amount != "undefined")
+ amount = parseFloat(params.options.amount)||0;
+ if (typeof params.options.strength != "undefined")
+ strength = parseFloat(params.options.strength)||0;
+ if (typeof params.options.mono != "undefined")
+ mono = !!(params.options.mono && params.options.mono != "false");
+
+ amount = Math.max(0,Math.min(1,amount));
+ strength = Math.max(0,Math.min(1,strength));
+
+ var noise = 128 * strength;
+ var noise2 = noise / 2;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+ var random = Math.random;
+
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x-1)*4;
+ if (random() < amount) {
+ if (mono) {
+ var pixelNoise = - noise2 + random() * noise;
+ var r = data[offset] + pixelNoise;
+ var g = data[offset+1] + pixelNoise;
+ var b = data[offset+2] + pixelNoise;
+ } else {
+ var r = data[offset] - noise2 + (random() * noise);
+ var g = data[offset+1] - noise2 + (random() * noise);
+ var b = data[offset+2] - noise2 + (random() * noise);
+ }
+
+ if (r < 0 ) r = 0;
+ if (g < 0 ) g = 0;
+ if (b < 0 ) b = 0;
+ if (r > 255 ) r = 255;
+ if (g > 255 ) g = 255;
+ if (b > 255 ) b = 255;
+
+ data[offset] = r;
+ data[offset+1] = g;
+ data[offset+2] = b;
+ }
+ } while (--x);
+ } while (--y);
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}
+
+/*
+ * Pixastic Lib - Posterize effect - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.posterize = {
+
+ process : function(params) {
+
+
+ var numLevels = 256;
+ if (typeof params.options.levels != "undefined")
+ numLevels = parseInt(params.options.levels,10)||1;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+
+ numLevels = Math.max(2,Math.min(256,numLevels));
+
+ var numAreas = 256 / numLevels;
+ var numValues = 256 / (numLevels-1);
+
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x-1)*4;
+
+ var r = numValues * ((data[offset] / numAreas)>>0);
+ var g = numValues * ((data[offset+1] / numAreas)>>0);
+ var b = numValues * ((data[offset+2] / numAreas)>>0);
+
+ if (r > 255) r = 255;
+ if (g > 255) g = 255;
+ if (b > 255) b = 255;
+
+ data[offset] = r;
+ data[offset+1] = g;
+ data[offset+2] = b;
+
+ } while (--x);
+ } while (--y);
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}
+
+
+/*
+ * Pixastic Lib - Pointillize filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.pointillize = {
+
+ process : function(params) {
+ var radius = Math.max(1,parseInt(params.options.radius,10));
+ var density = Math.min(5,Math.max(0,parseFloat(params.options.density)||0));
+ var noise = Math.max(0,parseFloat(params.options.noise)||0);
+ var transparent = !!(params.options.transparent && params.options.transparent != "false");
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+
+ var ctx = params.canvas.getContext("2d");
+ var canvasWidth = params.canvas.width;
+ var canvasHeight = params.canvas.height;
+
+ var pixel = document.createElement("canvas");
+ pixel.width = pixel.height = 1;
+ var pixelCtx = pixel.getContext("2d");
+
+ var copy = document.createElement("canvas");
+ copy.width = w;
+ copy.height = h;
+ var copyCtx = copy.getContext("2d");
+ copyCtx.drawImage(params.canvas,rect.left,rect.top,w,h, 0,0,w,h);
+
+ var diameter = radius * 2;
+
+ if (transparent)
+ ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
+
+ var noiseRadius = radius * noise;
+
+ var dist = 1 / density;
+
+ for (var y=0;y<h+radius;y+=diameter*dist) {
+ for (var x=0;x<w+radius;x+=diameter*dist) {
+ rndX = noise ? (x+((Math.random()*2-1) * noiseRadius))>>0 : x;
+ rndY = noise ? (y+((Math.random()*2-1) * noiseRadius))>>0 : y;
+
+ var pixX = rndX - radius;
+ var pixY = rndY - radius;
+ if (pixX < 0) pixX = 0;
+ if (pixY < 0) pixY = 0;
+
+ var cx = rndX + rect.left;
+ var cy = rndY + rect.top;
+ if (cx < 0) cx = 0;
+ if (cx > canvasWidth) cx = canvasWidth;
+ if (cy < 0) cy = 0;
+ if (cy > canvasHeight) cy = canvasHeight;
+
+ var diameterX = diameter;
+ var diameterY = diameter;
+
+ if (diameterX + pixX > w)
+ diameterX = w - pixX;
+ if (diameterY + pixY > h)
+ diameterY = h - pixY;
+ if (diameterX < 1) diameterX = 1;
+ if (diameterY < 1) diameterY = 1;
+
+ pixelCtx.drawImage(copy, pixX, pixY, diameterX, diameterY, 0, 0, 1, 1);
+ var data = pixelCtx.getImageData(0,0,1,1).data;
+
+ ctx.fillStyle = "rgb(" + data[0] + "," + data[1] + "," + data[2] + ")";
+ ctx.beginPath();
+ ctx.arc(cx, cy, radius, 0, Math.PI*2, true);
+ ctx.closePath();
+ ctx.fill();
+ }
+ }
+
+ params.useData = false;
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvasImageData());
+ }
+}/*
+ * Pixastic Lib - Resize - v0.1.0
+ * Copyright (c) 2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.resize = {
+ process : function(params) {
+ if (Pixastic.Client.hasCanvas()) {
+ var width = parseInt(params.options.width,10);
+ var height = parseInt(params.options.height,10);
+ var canvas = params.canvas;
+
+ if (width < 1) width = 1;
+ if (width < 2) width = 2;
+
+ var copy = document.createElement("canvas");
+ copy.width = width;
+ copy.height = height;
+
+ copy.getContext("2d").drawImage(canvas,0,0,width,height);
+ canvas.width = width;
+ canvas.height = height;
+
+ canvas.getContext("2d").drawImage(copy,0,0);
+
+ params.useData = false;
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvas();
+ }
+}
+
+
+/*
+ * Pixastic Lib - Remove noise - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.removenoise = {
+ process : function(params) {
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+
+ var nextY = (y == h) ? y - 1 : y;
+ var prevY = (y == 1) ? 0 : y-2;
+
+ var offsetYPrev = prevY*w*4;
+ var offsetYNext = nextY*w*4;
+
+ var x = w;
+ do {
+ var offset = offsetY + (x*4-4);
+
+ var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+ var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+
+ var minR, maxR, minG, maxG, minB, maxB;
+
+ minR = maxR = data[offsetPrev];
+ var r1 = data[offset-4], r2 = data[offset+4], r3 = data[offsetNext];
+ if (r1 < minR) minR = r1;
+ if (r2 < minR) minR = r2;
+ if (r3 < minR) minR = r3;
+ if (r1 > maxR) maxR = r1;
+ if (r2 > maxR) maxR = r2;
+ if (r3 > maxR) maxR = r3;
+
+ minG = maxG = data[offsetPrev+1];
+ var g1 = data[offset-3], g2 = data[offset+5], g3 = data[offsetNext+1];
+ if (g1 < minG) minG = g1;
+ if (g2 < minG) minG = g2;
+ if (g3 < minG) minG = g3;
+ if (g1 > maxG) maxG = g1;
+ if (g2 > maxG) maxG = g2;
+ if (g3 > maxG) maxG = g3;
+
+ minB = maxB = data[offsetPrev+2];
+ var b1 = data[offset-2], b2 = data[offset+6], b3 = data[offsetNext+2];
+ if (b1 < minB) minB = b1;
+ if (b2 < minB) minB = b2;
+ if (b3 < minB) minB = b3;
+ if (b1 > maxB) maxB = b1;
+ if (b2 > maxB) maxB = b2;
+ if (b3 > maxB) maxB = b3;
+
+ if (data[offset] > maxR) {
+ data[offset] = maxR;
+ } else if (data[offset] < minR) {
+ data[offset] = minR;
+ }
+ if (data[offset+1] > maxG) {
+ data[offset+1] = maxG;
+ } else if (data[offset+1] < minG) {
+ data[offset+1] = minG;
+ }
+ if (data[offset+2] > maxB) {
+ data[offset+2] = maxB;
+ } else if (data[offset+2] < minB) {
+ data[offset+2] = minB;
+ }
+
+ } while (--x);
+ } while (--y);
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}/*
+ * Pixastic Lib - Rotate - v0.1.0
+ * Copyright (c) 2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.rotate = {
+ process : function(params) {
+ if (Pixastic.Client.hasCanvas()) {
+ var canvas = params.canvas;
+
+ var width = params.width;
+ var height = params.height;
+
+ var copy = document.createElement("canvas");
+ copy.width = width;
+ copy.height = height;
+ copy.getContext("2d").drawImage(canvas,0,0,width,height);
+
+ var angle = -parseFloat(params.options.angle) * Math.PI / 180;
+
+ var dimAngle = angle;
+ if (dimAngle > Math.PI*0.5)
+ dimAngle = Math.PI - dimAngle;
+ if (dimAngle < -Math.PI*0.5)
+ dimAngle = -Math.PI - dimAngle;
+
+ var diag = Math.sqrt(width*width + height*height);
+
+ var diagAngle1 = Math.abs(dimAngle) - Math.abs(Math.atan2(height, width));
+ var diagAngle2 = Math.abs(dimAngle) + Math.abs(Math.atan2(height, width));
+
+ var newWidth = Math.abs(Math.cos(diagAngle1) * diag);
+ var newHeight = Math.abs(Math.sin(diagAngle2) * diag);
+
+ canvas.width = newWidth;
+ canvas.height = newHeight;
+
+ var ctx = canvas.getContext("2d");
+ ctx.translate(newWidth/2, newHeight/2);
+ ctx.rotate(angle);
+ ctx.drawImage(copy,-width/2,-height/2);
+
+ params.useData = false;
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvas();
+ }
+}
+
+
+/*
+ * Pixastic Lib - Sepia filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.sepia = {
+
+ process : function(params) {
+ var mode = (parseInt(params.options.mode,10)||0);
+ if (mode < 0) mode = 0;
+ if (mode > 1) mode = 1;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x-1)*4;
+
+ if (mode) {
+ // a bit faster, but not as good
+ var d = data[offset] * 0.299 + data[offset+1] * 0.587 + data[offset+2] * 0.114;
+ var r = (d + 39);
+ var g = (d + 14);
+ var b = (d - 36);
+ } else {
+ // Microsoft
+ var or = data[offset];
+ var og = data[offset+1];
+ var ob = data[offset+2];
+
+ var r = (or * 0.393 + og * 0.769 + ob * 0.189);
+ var g = (or * 0.349 + og * 0.686 + ob * 0.168);
+ var b = (or * 0.272 + og * 0.534 + ob * 0.131);
+ }
+
+ if (r < 0) r = 0; if (r > 255) r = 255;
+ if (g < 0) g = 0; if (g > 255) g = 255;
+ if (b < 0) b = 0; if (b > 255) b = 255;
+
+ data[offset] = r;
+ data[offset+1] = g;
+ data[offset+2] = b;
+
+ } while (--x);
+ } while (--y);
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}/*
+ * Pixastic Lib - Sharpen filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.sharpen = {
+ process : function(params) {
+
+ var strength = 0;
+ if (typeof params.options.amount != "undefined")
+ strength = parseFloat(params.options.amount)||0;
+
+ if (strength < 0) strength = 0;
+ if (strength > 1) strength = 1;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var dataCopy = Pixastic.prepareData(params, true)
+
+ var mul = 15;
+ var mulOther = 1 + 3*strength;
+
+ var kernel = [
+ [0, -mulOther, 0],
+ [-mulOther, mul, -mulOther],
+ [0, -mulOther, 0]
+ ];
+
+ var weight = 0;
+ for (var i=0;i<3;i++) {
+ for (var j=0;j<3;j++) {
+ weight += kernel[i][j];
+ }
+ }
+
+ weight = 1 / weight;
+
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ mul *= weight;
+ mulOther *= weight;
+
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+
+ var nextY = (y == h) ? y - 1 : y;
+ var prevY = (y == 1) ? 0 : y-2;
+
+ var offsetYPrev = prevY*w4;
+ var offsetYNext = nextY*w4;
+
+ var x = w;
+ do {
+ var offset = offsetY + (x*4-4);
+
+ var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+ var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+
+ var r = ((
+ - dataCopy[offsetPrev]
+ - dataCopy[offset-4]
+ - dataCopy[offset+4]
+ - dataCopy[offsetNext]) * mulOther
+ + dataCopy[offset] * mul
+ );
+
+ var g = ((
+ - dataCopy[offsetPrev+1]
+ - dataCopy[offset-3]
+ - dataCopy[offset+5]
+ - dataCopy[offsetNext+1]) * mulOther
+ + dataCopy[offset+1] * mul
+ );
+
+ var b = ((
+ - dataCopy[offsetPrev+2]
+ - dataCopy[offset-2]
+ - dataCopy[offset+6]
+ - dataCopy[offsetNext+2]) * mulOther
+ + dataCopy[offset+2] * mul
+ );
+
+
+ if (r < 0 ) r = 0;
+ if (g < 0 ) g = 0;
+ if (b < 0 ) b = 0;
+ if (r > 255 ) r = 255;
+ if (g > 255 ) g = 255;
+ if (b > 255 ) b = 255;
+
+ data[offset] = r;
+ data[offset+1] = g;
+ data[offset+2] = b;
+
+ } while (--x);
+ } while (--y);
+
+ return true;
+
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}
+/*
+ * Pixastic Lib - Solarize filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.solarize = {
+
+ process : function(params) {
+ var useAverage = !!(params.options.average && params.options.average != "false");
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x-1)*4;
+
+ var r = data[offset];
+ var g = data[offset+1];
+ var b = data[offset+2];
+
+ if (r > 127) r = 255 - r;
+ if (g > 127) g = 255 - g;
+ if (b > 127) b = 255 - b;
+
+ data[offset] = r;
+ data[offset+1] = g;
+ data[offset+2] = b;
+
+ } while (--x);
+ } while (--y);
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvasImageData());
+ }
+}/*
+ * Pixastic Lib - USM - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+
+Pixastic.Actions.unsharpmask = {
+ process : function(params) {
+
+ var amount = (parseFloat(params.options.amount)||0);
+ var blurAmount = parseFloat(params.options.radius)||0;
+ var threshold = parseFloat(params.options.threshold)||0;
+
+ amount = Math.min(500,Math.max(0,amount)) / 2;
+ blurAmount = Math.min(5,Math.max(0,blurAmount)) / 10;
+ threshold = Math.min(255,Math.max(0,threshold));
+
+ threshold--;
+ var thresholdNeg = -threshold;
+
+ amount *= 0.016;
+ amount++;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var rect = params.options.rect;
+
+ var blurCanvas = document.createElement("canvas");
+ blurCanvas.width = params.width;
+ blurCanvas.height = params.height;
+ var blurCtx = blurCanvas.getContext("2d");
+ blurCtx.drawImage(params.canvas,0,0);
+
+ var scale = 2;
+ var smallWidth = Math.round(params.width / scale);
+ var smallHeight = Math.round(params.height / scale);
+
+ var copy = document.createElement("canvas");
+ copy.width = smallWidth;
+ copy.height = smallHeight;
+
+ var steps = Math.round(blurAmount * 20);
+
+ var copyCtx = copy.getContext("2d");
+ for (var i=0;i<steps;i++) {
+ var scaledWidth = Math.max(1,Math.round(smallWidth - i));
+ var scaledHeight = Math.max(1,Math.round(smallHeight - i));
+
+ copyCtx.clearRect(0,0,smallWidth,smallHeight);
+
+ copyCtx.drawImage(
+ blurCanvas,
+ 0,0,params.width,params.height,
+ 0,0,scaledWidth,scaledHeight
+ );
+
+ blurCtx.clearRect(0,0,params.width,params.height);
+
+ blurCtx.drawImage(
+ copy,
+ 0,0,scaledWidth,scaledHeight,
+ 0,0,params.width,params.height
+ );
+ }
+
+ var data = Pixastic.prepareData(params);
+ var blurData = Pixastic.prepareData({canvas:blurCanvas,options:params.options});
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x*4-4);
+
+ var difR = data[offset] - blurData[offset];
+ if (difR > threshold || difR < thresholdNeg) {
+ var blurR = blurData[offset];
+ blurR = amount * difR + blurR;
+ data[offset] = blurR > 255 ? 255 : (blurR < 0 ? 0 : blurR);
+ }
+
+ var difG = data[offset+1] - blurData[offset+1];
+ if (difG > threshold || difG < thresholdNeg) {
+ var blurG = blurData[offset+1];
+ blurG = amount * difG + blurG;
+ data[offset+1] = blurG > 255 ? 255 : (blurG < 0 ? 0 : blurG);
+ }
+
+ var difB = data[offset+2] - blurData[offset+2];
+ if (difB > threshold || difB < thresholdNeg) {
+ var blurB = blurData[offset+2];
+ blurB = amount * difB + blurB;
+ data[offset+2] = blurB > 255 ? 255 : (blurB < 0 ? 0 : blurB);
+ }
+
+ } while (--x);
+ } while (--y);
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}
+
+
+
+
-/* http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/ */\r
-\r
-html, body, div, span, applet, object, iframe,\r
-h1, h2, h3, h4, h5, h6, p, blockquote, pre,\r
-a, abbr, acronym, address, big, cite, code,\r
-del, dfn, em, font, img, ins, kbd, q, s, samp,\r
-small, strike, strong, sub, sup, tt, var,\r
-dl, dt, dd, ol, ul, li,\r
-fieldset, form, label, legend,\r
-table, caption, tbody, tfoot, thead, tr, th, td {\r
- margin: 0;\r
- padding: 0;\r
- border: 0;\r
- outline: 0;\r
- font-weight: inherit;\r
- font-style: inherit;\r
- font-size: 100%;\r
- font-family: inherit;\r
- vertical-align: baseline;\r
-}\r
-/* remember to define focus styles! */\r
-:focus {\r
- outline: 0;\r
-}\r
-body {\r
- line-height: 1;\r
- color: black;\r
- background: white;\r
-}\r
-ol, ul {\r
- list-style: none;\r
-}\r
-/* tables still need 'cellspacing="0"' in the markup */\r
-table {\r
- border-collapse: separate;\r
- border-spacing: 0;\r
-}\r
-caption, th, td {\r
- text-align: left;\r
- font-weight: normal;\r
-}\r
-blockquote:before, blockquote:after,\r
-q:before, q:after {\r
- content: "";\r
-}\r
-blockquote, q {\r
- quotes: "" "";\r
-}\r
-/* end reset */\r
-\r
-/* -----------------------\r
- * Base\r
- * -----------------------\r
- */\r
-\r
-/* main container element for editor app */\r
-#pixastic-editor {\r
- margin : 0;\r
- position : absolute;\r
- left : 0;\r
- top : 0;\r
- padding: 0px;\r
- width: 100%;\r
- height: 100%;\r
- font-family : Helvetica,Arial,sans-serif;\r
- overflow : hidden;\r
- z-index : 10000000;\r
-} \r
-\r
-\r
-/* -----------------------\r
- * Loading screen\r
- * -----------------------\r
- */\r
-\r
-/* container for loading screen */\r
-#loading-screen {\r
- margin : 0;\r
- position : absolute;\r
- left : 0;\r
- top : 0;\r
- padding: 0px;\r
- width: 100%;\r
- height: 100%;\r
- font-family : Helvetica,Arial,sans-serif;\r
- overflow : hidden;\r
- z-index : 10000000;\r
- background-color : #111;\r
- opacity : 0.9;\r
- display : table;\r
- text-align : center;\r
-} \r
-\r
-/* container for spinner in loading screen */\r
-#loading-screen-cell {\r
- display : table-cell;\r
- vertical-align : middle;\r
- text-align : center;\r
-}\r
-\r
-\r
-/* -----------------------\r
- * Misc\r
- * -----------------------\r
- */\r
-\r
-\r
-// UI error dialog\r
-.ui-dialog .error-dialog {\r
- background-color : #544;\r
-}\r
-\r
-/* loading spinner */\r
-.spinner {\r
- width : 31px;\r
- height : 31px;\r
- display : inline-block;\r
- background: url(spinner.gif);\r
- overflow : hidden;\r
-}\r
-\r
-canvas.display-canvas,\r
-canvas.undo-canvas {\r
- /*\r
- background : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC1JREFUeNpiPHPmDAM2YGxsjFWciYFEMKqBGMD4//9/rBJnz54dDSX6aQAIMABCtQiAsDRF+wAAAABJRU5ErkJggg==');\r
- */\r
- background : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC5JREFUeNpiPHPmTAMDHmBsbIxPmoGJgUIwasBgMICFUDyfPXt2NBCHvwEAAQYAICIGn294LYEAAAAASUVORK5CYII=');\r
-\r
-}\r
-\r
-.far-far-away {\r
- position : absolute;\r
- left : -9999px;\r
- top : -9999px;\r
-}\r
-\r
-#powered-by-pixastic {\r
- position : absolute;\r
- bottom : 0px;\r
- margin-bottom : 23px;\r
- margin-left : 42px;\r
-}\r
-#powered-by-pixastic a {\r
- font-size : 12px;\r
- font-family : Helvetica,Arial,sans-serif;\r
- letter-spacing : 0.1em;\r
- color : rgb(100,100,100);\r
- color : rgba(255,255,255,0.2);\r
- text-decoration : none;\r
-}\r
-\r
-#powered-by-pixastic a:hover {\r
- color : rgb(200,200,200);\r
- color : rgba(255,255,255,0.7);\r
- text-decoration : underline;\r
-}\r
-\r
-\r
-/* -----------------------\r
- * Skeleton structure\r
- * -----------------------\r
- */\r
-\r
-/* editor background underlay */\r
-#background {\r
- background-color : #111;\r
- opacity : 0.9;\r
- width : 100%;\r
- height : 100%;\r
- position : absolute;\r
- z-index : -1;\r
-}\r
-\r
-#image-area {\r
- position : relative;\r
- background-color : #222;\r
- border : 1px solid #444;\r
- width : 100%;\r
- height : 100%;\r
- -moz-box-sizing:border-box;\r
- overflow : auto;\r
- text-align : center;\r
-}\r
-\r
-#image-area-sub {\r
-}\r
-\r
-#image-container {\r
-}\r
-\r
-#image-overlay-container {\r
- -moz-box-sizing:border-box;\r
- width:100%;\r
- height:100%;\r
- position:absolute;\r
- top:0;\r
- left:0;\r
-}\r
-\r
-#image-overlay {\r
-}\r
-\r
-\r
-/* structure elements */\r
-#edit-ctr-1 {\r
- position : absolute;\r
- top : 0;\r
- left : 0;\r
- width : 100%;\r
- height : 100%;\r
-}\r
-\r
-#edit-ctr-2 {\r
- -moz-box-sizing : border-box;\r
- box-sizing : border-box;\r
- padding-left:40px;\r
- padding-right:420px;\r
- padding-top:70px;\r
- padding-bottom : 40px;\r
- height : 100%;\r
- width : 100%;\r
-}\r
-\r
-\r
-/* main menu bar */\r
-#main-bar {\r
- position : absolute;\r
- width : 100%;\r
- text-align : right;\r
- margin-top : 20px;\r
- margin-right : 30px;\r
-}\r
-\r
-/* area on the right with accordion widgets and undo bar */\r
-#controls-bar {\r
- margin-right : -385px;\r
- width : 372px;\r
- float : right;\r
- height : 100%;\r
-}\r
-\r
-/* accordion area */\r
-#action-bar {\r
- padding : 10px;\r
- width : 290px;\r
- background-color : #222;\r
- border : 1px solid #444;\r
- -moz-box-sizing : border-box;\r
- box-sizing : border-box;\r
- height : 100%;\r
- overflow-x : hidden;\r
- overflow-y : auto;\r
- float: right; \r
- position : relative;\r
-}\r
-\r
-#action-bar-overlay {\r
- position : absolute;\r
- z-index : 1000000;\r
- width : 100%;\r
- height : 100%;\r
- left : 0;\r
- top : 0;\r
- background-color : #444;\r
- opacity : 0.2;\r
- display : none;\r
-}\r
-\r
-\r
-/* vertical bar with undo image states */\r
-#undo-bar {\r
- -moz-box-sizing : border-box;\r
- box-sizing : border-box;\r
- background-color : #222;\r
- border : 1px solid #444;\r
- width: 70px; \r
- height: 100%;\r
- overflow: hidden;\r
- padding-top : 3px;\r
-}\r
-\r
-\r
-\r
-/* -----------------------\r
- * Main menu styles\r
- * -----------------------\r
- */\r
-\r
-.main-tab {\r
- color : #999;\r
- display : inline-block;\r
- width : 150px;\r
- text-transform : lowercase;\r
- font-size : 22px;\r
- cursor : pointer;\r
- text-align : center;\r
- text-decoration : none;\r
- padding-top : 4px;\r
- padding-bottom : 5px;\r
- outline : 0;\r
-}\r
-\r
-.main-tab.hover {\r
- color : white !important;\r
-}\r
-\r
-.main-tab.active {\r
- color : white;\r
-}\r
-\r
-\r
-\r
-/* -----------------------\r
- * Undo list\r
- * -----------------------\r
- */\r
-\r
-\r
-.undo-canvas-small {\r
- width : 60px;\r
- height : 40px;\r
- cursor : pointer;\r
-}\r
-\r
-.undo-link {\r
- width : 60px;\r
- height : 40px;\r
- display : block;\r
- margin : 4px;\r
- cursor : pointer;\r
- opacity : 0.8;\r
-}\r
-\r
-.undo-link.hover {\r
- opacity : 1;\r
-}\r
-\r
-\r
-\r
-/* -----------------------\r
- * Action UI controls\r
- * -----------------------\r
- */\r
-\r
-\r
-.ui-slider-label, \r
-.ui-checkbox-label, \r
-.ui-textinput-label, \r
-.ui-select-label {\r
- width : 70px;\r
- text-align : right;\r
- margin-right : 5px;\r
- display : inline-block;\r
-}\r
-\r
-.ui-textinput-label-right {\r
- margin-left : 5px;\r
-}\r
-\r
-.ui-textinput {\r
-}\r
-\r
-.ui-numericinput {\r
- width : 35px;\r
-}\r
-\r
-.ui-slider {\r
- width : 125px;\r
- display : inline-block;\r
- margin-left : 3px;\r
- background-color : #222;\r
-}\r
-\r
-.ui-slider-value {\r
- font-size : 11px;\r
- width : 25px;\r
- display : inline-block;\r
- margin-left : 10px;\r
-}\r
-\r
-.ui-action-output {\r
- margin-bottom : 10px;\r
-}\r
-\r
-.ui-accordion .ui-accordion-content-active {\r
- font-size : 11px;\r
- overflow : hidden;\r
-}\r
-\r
-.ui-slider-horizontal {\r
-}\r
-\r
-.ui-slider-container, \r
-.ui-checkbox-container, \r
-.ui-textinput-container, \r
-.ui-select-container {\r
- margin-top : 0px;\r
- margin-bottom : 10px;\r
- white-space : nowrap;\r
-}\r
-\r
-.ui-preview-checkbox-container {\r
- display : inline-block;\r
-}\r
-\r
-.ui-checkbox {\r
- margin-bottom:3px;\r
- margin-left:5px;\r
- margin-right:5px;\r
- margin-top:0px;\r
- vertical-align:middle;\r
-}\r
-\r
-input::-moz-focus-inner { border: 0; }\r
-\r
-.action-output-text {\r
- margin-bottom : 5px;\r
-}\r
-\r
-button {\r
- margin-right : 5px;\r
-}\r
-\r
+/* http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/ */
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, font, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ outline: 0;
+ font-weight: inherit;
+ font-style: inherit;
+ font-size: 100%;
+ font-family: inherit;
+ vertical-align: baseline;
+}
+/* remember to define focus styles! */
+:focus {
+ outline: 0;
+}
+body {
+ line-height: 1;
+ color: black;
+ background: white;
+}
+ol, ul {
+ list-style: none;
+}
+/* tables still need 'cellspacing="0"' in the markup */
+table {
+ border-collapse: separate;
+ border-spacing: 0;
+}
+caption, th, td {
+ text-align: left;
+ font-weight: normal;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+ content: "";
+}
+blockquote, q {
+ quotes: "" "";
+}
+/* end reset */
+
+/* -----------------------
+ * Base
+ * -----------------------
+ */
+
+/* main container element for editor app */
+#pixastic-editor {
+ margin : 0;
+ position : absolute;
+ left : 0;
+ top : 0;
+ padding: 0px;
+ width: 100%;
+ height: 100%;
+ font-family : Helvetica,Arial,sans-serif;
+ overflow : hidden;
+ z-index : 10000000;
+}
+
+
+/* -----------------------
+ * Loading screen
+ * -----------------------
+ */
+
+/* container for loading screen */
+#loading-screen {
+ margin : 0;
+ position : absolute;
+ left : 0;
+ top : 0;
+ padding: 0px;
+ width: 100%;
+ height: 100%;
+ font-family : Helvetica,Arial,sans-serif;
+ overflow : hidden;
+ z-index : 10000000;
+ background-color : #111;
+ opacity : 0.9;
+ display : table;
+ text-align : center;
+}
+
+/* container for spinner in loading screen */
+#loading-screen-cell {
+ display : table-cell;
+ vertical-align : middle;
+ text-align : center;
+}
+
+
+/* -----------------------
+ * Misc
+ * -----------------------
+ */
+
+
+// UI error dialog
+.ui-dialog .error-dialog {
+ background-color : #544;
+}
+
+/* loading spinner */
+.spinner {
+ width : 31px;
+ height : 31px;
+ display : inline-block;
+ background: url(spinner.gif);
+ overflow : hidden;
+}
+
+canvas.display-canvas,
+canvas.undo-canvas {
+ /*
+ background : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC1JREFUeNpiPHPmDAM2YGxsjFWciYFEMKqBGMD4//9/rBJnz54dDSX6aQAIMABCtQiAsDRF+wAAAABJRU5ErkJggg==');
+ */
+ background : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC5JREFUeNpiPHPmTAMDHmBsbIxPmoGJgUIwasBgMICFUDyfPXt2NBCHvwEAAQYAICIGn294LYEAAAAASUVORK5CYII=');
+
+}
+
+.far-far-away {
+ position : absolute;
+ left : -9999px;
+ top : -9999px;
+}
+
+#powered-by-pixastic {
+ position : absolute;
+ bottom : 0px;
+ margin-bottom : 23px;
+ margin-left : 42px;
+}
+#powered-by-pixastic a {
+ font-size : 12px;
+ font-family : Helvetica,Arial,sans-serif;
+ letter-spacing : 0.1em;
+ color : rgb(100,100,100);
+ color : rgba(255,255,255,0.2);
+ text-decoration : none;
+}
+
+#powered-by-pixastic a:hover {
+ color : rgb(200,200,200);
+ color : rgba(255,255,255,0.7);
+ text-decoration : underline;
+}
+
+
+/* -----------------------
+ * Skeleton structure
+ * -----------------------
+ */
+
+/* editor background underlay */
+#background {
+ background-color : #111;
+ opacity : 0.9;
+ width : 100%;
+ height : 100%;
+ position : absolute;
+ z-index : -1;
+}
+
+#image-area {
+ position : relative;
+ background-color : #222;
+ border : 1px solid #444;
+ width : 100%;
+ height : 100%;
+ -moz-box-sizing:border-box;
+ overflow : auto;
+ text-align : center;
+}
+
+#image-area-sub {
+}
+
+#image-container {
+}
+
+#image-overlay-container {
+ -moz-box-sizing:border-box;
+ width:100%;
+ height:100%;
+ position:absolute;
+ top:0;
+ left:0;
+}
+
+#image-overlay {
+}
+
+
+/* structure elements */
+#edit-ctr-1 {
+ position : absolute;
+ top : 0;
+ left : 0;
+ width : 100%;
+ height : 100%;
+}
+
+#edit-ctr-2 {
+ -moz-box-sizing : border-box;
+ box-sizing : border-box;
+ padding-left:40px;
+ padding-right:420px;
+ padding-top:70px;
+ padding-bottom : 40px;
+ height : 100%;
+ width : 100%;
+}
+
+
+/* main menu bar */
+#main-bar {
+ position : absolute;
+ width : 100%;
+ text-align : right;
+ margin-top : 20px;
+ margin-right : 30px;
+}
+
+/* area on the right with accordion widgets and undo bar */
+#controls-bar {
+ margin-right : -385px;
+ width : 372px;
+ float : right;
+ height : 100%;
+}
+
+/* accordion area */
+#action-bar {
+ padding : 10px;
+ width : 290px;
+ background-color : #222;
+ border : 1px solid #444;
+ -moz-box-sizing : border-box;
+ box-sizing : border-box;
+ height : 100%;
+ overflow-x : hidden;
+ overflow-y : auto;
+ float: right;
+ position : relative;
+}
+
+#action-bar-overlay {
+ position : absolute;
+ z-index : 1000000;
+ width : 100%;
+ height : 100%;
+ left : 0;
+ top : 0;
+ background-color : #444;
+ opacity : 0.2;
+ display : none;
+}
+
+
+/* vertical bar with undo image states */
+#undo-bar {
+ -moz-box-sizing : border-box;
+ box-sizing : border-box;
+ background-color : #222;
+ border : 1px solid #444;
+ width: 70px;
+ height: 100%;
+ overflow: hidden;
+ padding-top : 3px;
+}
+
+
+
+/* -----------------------
+ * Main menu styles
+ * -----------------------
+ */
+
+.main-tab {
+ color : #999;
+ display : inline-block;
+ width : 150px;
+ text-transform : lowercase;
+ font-size : 22px;
+ cursor : pointer;
+ text-align : center;
+ text-decoration : none;
+ padding-top : 4px;
+ padding-bottom : 5px;
+ outline : 0;
+}
+
+.main-tab.hover {
+ color : white !important;
+}
+
+.main-tab.active {
+ color : white;
+}
+
+
+
+/* -----------------------
+ * Undo list
+ * -----------------------
+ */
+
+
+.undo-canvas-small {
+ width : 60px;
+ height : 40px;
+ cursor : pointer;
+}
+
+.undo-link {
+ width : 60px;
+ height : 40px;
+ display : block;
+ margin : 4px;
+ cursor : pointer;
+ opacity : 0.8;
+}
+
+.undo-link.hover {
+ opacity : 1;
+}
+
+
+
+/* -----------------------
+ * Action UI controls
+ * -----------------------
+ */
+
+
+.ui-slider-label,
+.ui-checkbox-label,
+.ui-textinput-label,
+.ui-select-label {
+ width : 70px;
+ text-align : right;
+ margin-right : 5px;
+ display : inline-block;
+}
+
+.ui-textinput-label-right {
+ margin-left : 5px;
+}
+
+.ui-textinput {
+}
+
+.ui-numericinput {
+ width : 35px;
+}
+
+.ui-slider {
+ width : 125px;
+ display : inline-block;
+ margin-left : 3px;
+ background-color : #222;
+}
+
+.ui-slider-value {
+ font-size : 11px;
+ width : 25px;
+ display : inline-block;
+ margin-left : 10px;
+}
+
+.ui-action-output {
+ margin-bottom : 10px;
+}
+
+.ui-accordion .ui-accordion-content-active {
+ font-size : 11px;
+ overflow : hidden;
+}
+
+.ui-slider-horizontal {
+}
+
+.ui-slider-container,
+.ui-checkbox-container,
+.ui-textinput-container,
+.ui-select-container {
+ margin-top : 0px;
+ margin-bottom : 10px;
+ white-space : nowrap;
+}
+
+.ui-preview-checkbox-container {
+ display : inline-block;
+}
+
+.ui-checkbox {
+ margin-bottom:3px;
+ margin-left:5px;
+ margin-right:5px;
+ margin-top:0px;
+ vertical-align:middle;
+}
+
+input::-moz-focus-inner { border: 0; }
+
+.action-output-text {
+ margin-bottom : 5px;
+}
+
+button {
+ margin-right : 5px;
+}
+
-(function($) {\r
-\r
- var PE = PixasticEditor;\r
-\r
- function makeSlider(label, id, min, max, step, defaultVal, onChange) {\r
- var $ctr = $j("<div></div>", PE.getDocument())\r
- .addClass("ui-slider-container");\r
-\r
- var $label = $j("<label></label>", PE.getDocument())\r
- .addClass("ui-slider-label")\r
- .attr("for", "input-slider-" + id)\r
- .html(label + ":")\r
- .appendTo($ctr);\r
-\r
- var $value = $j("<div></div>", PE.getDocument())\r
- .addClass("ui-slider-value")\r
- .html(defaultVal());\r
-\r
- var $valueField = $j("<input type='hidden'>", PE.getDocument())\r
- .attr("id", "input-hidden-" + id)\r
- .val(defaultVal())\r
- .appendTo($ctr);\r
-\r
- var performOnChange = true;\r
-\r
- var $slider = $j("<div class='ui-slider'><div class='ui-slider-handle'></div><div class='ui-slider-range'></div></div>", PE.getDocument())\r
- .appendTo($ctr)\r
- .attr("id", "input-slider-" + id)\r
- .slider({\r
- slide: function() {\r
- $value.html($j(this).slider("value"));\r
- $valueField.val($j(this).slider("value"));\r
- },\r
- change : function() {\r
- $value.html($j(this).slider("value"));\r
- $valueField.val($j(this).slider("value"));\r
- if (onChange && performOnChange)\r
- onChange();\r
- },\r
- min : min,\r
- max : max,\r
- step : step,\r
- value : defaultVal()\r
- });\r
-\r
- $value.appendTo($ctr);\r
-\r
- return {\r
- container : $ctr,\r
- label : $label,\r
- slider : $slider,\r
- valueText : $value,\r
- valueField : $valueField,\r
- reset : function() {\r
- performOnChange = false;\r
- $value.html(defaultVal());\r
- $valueField.val(defaultVal());\r
- $slider.slider("value", defaultVal());\r
- performOnChange = true;\r
- }\r
- };\r
- }\r
-\r
- function makeCheckbox(label, id, defaultVal, onChange) {\r
- var $ctr = $j("<div></div>", PE.getDocument())\r
- .addClass("ui-checkbox-container");\r
-\r
- var $label = $j("<label></label>", PE.getDocument())\r
- .addClass("ui-checkbox-label")\r
- .attr("for", "input-checkbox-" + id)\r
- .html(label + ":")\r
- .appendTo($ctr);\r
-\r
- var $valueField = $j("<input type='hidden'>", PE.getDocument())\r
- .attr("id", "input-hidden-" + id)\r
- .val(defaultVal())\r
- .appendTo($ctr);\r
-\r
- var performOnChange = true;\r
-\r
- var $checkbox = $j("<input type=\"checkbox\"></input>", PE.getDocument())\r
- .addClass("ui-checkbox")\r
- .attr("id", "input-checkbox-" + id)\r
- .attr("checked", defaultVal())\r
- .appendTo($ctr)\r
- .change(function() {\r
- $valueField.val(this.checked);\r
- if (onChange && performOnChange)\r
- onChange();\r
- });\r
-\r
- return {\r
- container : $ctr,\r
- label : $label,\r
- checkbox : $checkbox,\r
- valueField : $valueField,\r
- reset : function() {\r
- performOnChange = false;\r
- $checkbox.attr("checked", defaultVal());\r
- $valueField.val(defaultVal());\r
- performOnChange = true;\r
- }\r
- };\r
- }\r
-\r
- function makeSelect(label, id, values, defaultVal, onChange) {\r
- var $ctr = $j("<div></div>", PE.getDocument())\r
- .addClass("ui-select-container");\r
-\r
- var $label = $j("<label></label>", PE.getDocument())\r
- .addClass("ui-checkbox-label")\r
- .attr("for", "input-checkbox-" + id)\r
- .html(label + ":")\r
- .appendTo($ctr);\r
-\r
- var $valueField = $j("<input type='hidden'>", PE.getDocument())\r
- .attr("id", "input-hidden-" + id)\r
- .val(defaultVal())\r
- .appendTo($ctr);\r
-\r
- var selectHtml = "<select>";\r
- for (var i=0;i<values.length;i++) {\r
- selectHtml += "<option value='" + values[i].value + "' " \r
- + (defaultVal() == values[i].value ? "selected" : "") \r
- + ">" + values[i].name + "</option>";\r
- }\r
- selectHtml += "</select>";\r
-\r
- var $select = $j(selectHtml).appendTo($ctr);\r
-\r
- var performOnChange = true;\r
-\r
- $select.change(\r
- function() {\r
- $valueField.val(this.options[this.selectedIndex].value);\r
- if (onChange && performOnChange)\r
- onChange();\r
- }\r
- );\r
-\r
- return {\r
- container : $ctr,\r
- label : $label,\r
- select : $select,\r
- valueField : $valueField,\r
- reset : function() {\r
- performOnChange = false;\r
- var defVal = defaultVal();\r
- $select.val(defVal);\r
- $valueField.val(defVal);\r
- performOnChange = true;\r
- }\r
- };\r
- }\r
-\r
- function makeNumericInput(label, labelRight, id, min, max, step, defaultVal, onChange) {\r
- var $ctr = $j("<div></div>", PE.getDocument())\r
- .addClass("ui-textinput-container");\r
-\r
- var $label = $j("<label></label>", PE.getDocument())\r
- .addClass("ui-textinput-label")\r
- .attr("for", "input-numeric-" + id)\r
- .html(label + ":")\r
- .appendTo($ctr);\r
-\r
- var $valueField = $j("<input type='hidden'>", PE.getDocument())\r
- .attr("id", "input-hidden-" + id)\r
- .val(defaultVal())\r
- .appendTo($ctr);\r
-\r
- var performOnChange = true;\r
-\r
- function setVal(val) {\r
- val = Math.min(max, val);\r
- val = Math.max(min, val);\r
- $textInput.val(val);\r
- $valueField.val(val);\r
- }\r
-\r
- var $textInput = $j("<input type=\"text\"></input>", PE.getDocument())\r
- .addClass("ui-textinput")\r
- .addClass("ui-numericinput")\r
- .appendTo($ctr)\r
- .val(defaultVal())\r
- .attr("id", "input-numeric-" + id)\r
- .change(function() {\r
- var val = parseFloat(this.value);\r
- setVal(val);\r
- if (onChange && performOnChange)\r
- onChange();\r
- })\r
- .keydown(function(e) {\r
- var val = parseFloat($j(this).val());\r
- if (e.keyCode == 38) { // up\r
- setVal(val + step);\r
- }\r
- if (e.keyCode == 40) { // down\r
- setVal(val - step);\r
- }\r
- });\r
-\r
- if (labelRight) {\r
- var $labelRight = $j("<label></label>", PE.getDocument())\r
- .addClass("ui-textinput-label-right")\r
- .html(labelRight)\r
- .appendTo($ctr);\r
- }\r
-\r
- return {\r
- container : $ctr,\r
- label : $label,\r
- textinput : $textInput,\r
- valueField : $valueField,\r
- reset : function() {\r
- performOnChange = false;\r
- setVal(defaultVal());\r
- performOnChange = true;\r
- }\r
- };\r
- }\r
-\r
- function makeButton(text) {\r
- var $button = $j("<button></button>", PE.getDocument()).html(text);\r
- return $button;\r
- }\r
-\r
-\r
- PE.UI = {\r
- makeSlider : makeSlider,\r
- makeCheckbox : makeCheckbox,\r
- makeNumericInput : makeNumericInput,\r
- makeSelect : makeSelect,\r
- makeButton : makeButton\r
- }\r
-\r
-})(PixasticEditor.jQuery);\r
-\r
+(function($) {
+
+ var PE = PixasticEditor;
+
+ function makeSlider(label, id, min, max, step, defaultVal, onChange) {
+ var $ctr = $j("<div></div>", PE.getDocument())
+ .addClass("ui-slider-container");
+
+ var $label = $j("<label></label>", PE.getDocument())
+ .addClass("ui-slider-label")
+ .attr("for", "input-slider-" + id)
+ .html(label + ":")
+ .appendTo($ctr);
+
+ var $value = $j("<div></div>", PE.getDocument())
+ .addClass("ui-slider-value")
+ .html(defaultVal());
+
+ var $valueField = $j("<input type='hidden'>", PE.getDocument())
+ .attr("id", "input-hidden-" + id)
+ .val(defaultVal())
+ .appendTo($ctr);
+
+ var performOnChange = true;
+
+ var $slider = $j("<div class='ui-slider'><div class='ui-slider-handle'></div><div class='ui-slider-range'></div></div>", PE.getDocument())
+ .appendTo($ctr)
+ .attr("id", "input-slider-" + id)
+ .slider({
+ slide: function() {
+ $value.html($j(this).slider("value"));
+ $valueField.val($j(this).slider("value"));
+ },
+ change : function() {
+ $value.html($j(this).slider("value"));
+ $valueField.val($j(this).slider("value"));
+ if (onChange && performOnChange)
+ onChange();
+ },
+ min : min,
+ max : max,
+ step : step,
+ value : defaultVal()
+ });
+
+ $value.appendTo($ctr);
+
+ return {
+ container : $ctr,
+ label : $label,
+ slider : $slider,
+ valueText : $value,
+ valueField : $valueField,
+ reset : function() {
+ performOnChange = false;
+ $value.html(defaultVal());
+ $valueField.val(defaultVal());
+ $slider.slider("value", defaultVal());
+ performOnChange = true;
+ }
+ };
+ }
+
+ function makeCheckbox(label, id, defaultVal, onChange) {
+ var $ctr = $j("<div></div>", PE.getDocument())
+ .addClass("ui-checkbox-container");
+
+ var $label = $j("<label></label>", PE.getDocument())
+ .addClass("ui-checkbox-label")
+ .attr("for", "input-checkbox-" + id)
+ .html(label + ":")
+ .appendTo($ctr);
+
+ var $valueField = $j("<input type='hidden'>", PE.getDocument())
+ .attr("id", "input-hidden-" + id)
+ .val(defaultVal())
+ .appendTo($ctr);
+
+ var performOnChange = true;
+
+ var $checkbox = $j("<input type=\"checkbox\"></input>", PE.getDocument())
+ .addClass("ui-checkbox")
+ .attr("id", "input-checkbox-" + id)
+ .attr("checked", defaultVal())
+ .appendTo($ctr)
+ .change(function() {
+ $valueField.val(this.checked);
+ if (onChange && performOnChange)
+ onChange();
+ });
+
+ return {
+ container : $ctr,
+ label : $label,
+ checkbox : $checkbox,
+ valueField : $valueField,
+ reset : function() {
+ performOnChange = false;
+ $checkbox.attr("checked", defaultVal());
+ $valueField.val(defaultVal());
+ performOnChange = true;
+ }
+ };
+ }
+
+ function makeSelect(label, id, values, defaultVal, onChange) {
+ var $ctr = $j("<div></div>", PE.getDocument())
+ .addClass("ui-select-container");
+
+ var $label = $j("<label></label>", PE.getDocument())
+ .addClass("ui-checkbox-label")
+ .attr("for", "input-checkbox-" + id)
+ .html(label + ":")
+ .appendTo($ctr);
+
+ var $valueField = $j("<input type='hidden'>", PE.getDocument())
+ .attr("id", "input-hidden-" + id)
+ .val(defaultVal())
+ .appendTo($ctr);
+
+ var selectHtml = "<select>";
+ for (var i=0;i<values.length;i++) {
+ selectHtml += "<option value='" + values[i].value + "' "
+ + (defaultVal() == values[i].value ? "selected" : "")
+ + ">" + values[i].name + "</option>";
+ }
+ selectHtml += "</select>";
+
+ var $select = $j(selectHtml).appendTo($ctr);
+
+ var performOnChange = true;
+
+ $select.change(
+ function() {
+ $valueField.val(this.options[this.selectedIndex].value);
+ if (onChange && performOnChange)
+ onChange();
+ }
+ );
+
+ return {
+ container : $ctr,
+ label : $label,
+ select : $select,
+ valueField : $valueField,
+ reset : function() {
+ performOnChange = false;
+ var defVal = defaultVal();
+ $select.val(defVal);
+ $valueField.val(defVal);
+ performOnChange = true;
+ }
+ };
+ }
+
+ function makeNumericInput(label, labelRight, id, min, max, step, defaultVal, onChange) {
+ var $ctr = $j("<div></div>", PE.getDocument())
+ .addClass("ui-textinput-container");
+
+ var $label = $j("<label></label>", PE.getDocument())
+ .addClass("ui-textinput-label")
+ .attr("for", "input-numeric-" + id)
+ .html(label + ":")
+ .appendTo($ctr);
+
+ var $valueField = $j("<input type='hidden'>", PE.getDocument())
+ .attr("id", "input-hidden-" + id)
+ .val(defaultVal())
+ .appendTo($ctr);
+
+ var performOnChange = true;
+
+ function setVal(val) {
+ val = Math.min(max, val);
+ val = Math.max(min, val);
+ $textInput.val(val);
+ $valueField.val(val);
+ }
+
+ var $textInput = $j("<input type=\"text\"></input>", PE.getDocument())
+ .addClass("ui-textinput")
+ .addClass("ui-numericinput")
+ .appendTo($ctr)
+ .val(defaultVal())
+ .attr("id", "input-numeric-" + id)
+ .change(function() {
+ var val = parseFloat(this.value);
+ setVal(val);
+ if (onChange && performOnChange)
+ onChange();
+ })
+ .keydown(function(e) {
+ var val = parseFloat($j(this).val());
+ if (e.keyCode == 38) { // up
+ setVal(val + step);
+ }
+ if (e.keyCode == 40) { // down
+ setVal(val - step);
+ }
+ });
+
+ if (labelRight) {
+ var $labelRight = $j("<label></label>", PE.getDocument())
+ .addClass("ui-textinput-label-right")
+ .html(labelRight)
+ .appendTo($ctr);
+ }
+
+ return {
+ container : $ctr,
+ label : $label,
+ textinput : $textInput,
+ valueField : $valueField,
+ reset : function() {
+ performOnChange = false;
+ setVal(defaultVal());
+ performOnChange = true;
+ }
+ };
+ }
+
+ function makeButton(text) {
+ var $button = $j("<button></button>", PE.getDocument()).html(text);
+ return $button;
+ }
+
+
+ PE.UI = {
+ makeSlider : makeSlider,
+ makeCheckbox : makeCheckbox,
+ makeNumericInput : makeNumericInput,
+ makeSelect : makeSelect,
+ makeButton : makeButton
+ }
+
+})(PixasticEditor.jQuery);
+
-(function($) {\r
-\r
-var PE = PixasticEditor;\r
-\r
-PE.UI.data = {\r
- tabs : [\r
- {\r
- title : "Reshape",\r
- id : "reshape",\r
- actions : [\r
- {\r
- title : "Resize",\r
- id : "resize",\r
- isAction : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Enter new dimensions below."\r
- },\r
- {\r
- label : "Width",\r
- labelRight : "px",\r
- option : "width",\r
- type : "number", \r
- range : [1,10000], \r
- step : 1,\r
- defaultValue : function() { return PE.getImageWidth(); },\r
- ui : "text"\r
- },\r
- {\r
- label : "Height",\r
- labelRight : "px",\r
- option : "height",\r
- type : "number", \r
- range : [1,10000], \r
- step : 1,\r
- defaultValue : function() { return PE.getImageHeight(); },\r
- ui : "text"\r
- }\r
- ]\r
- },\r
- {\r
- title : "Crop",\r
- id : "crop",\r
- isAction : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Enter new crop values below or use mouse to select crop area."\r
- },\r
- {\r
- label : "X",\r
- labelRight : "px",\r
- option : "left",\r
- type : "number", \r
- range : [0,10000], \r
- step : 1,\r
- defaultValue : 0,\r
- ui : "text"\r
- },\r
- {\r
- label : "Y",\r
- labelRight : "px",\r
- option : "top",\r
- type : "number", \r
- range : [0,10000], \r
- step : 1,\r
- defaultValue : 0,\r
- ui : "text"\r
- },\r
- {\r
- label : "Width",\r
- labelRight : "px",\r
- option : "width",\r
- type : "number", \r
- range : [1,10000], \r
- step : 1,\r
- defaultValue : function() { return PE.getImageWidth(); },\r
- ui : "text"\r
- },\r
- {\r
- label : "Height",\r
- labelRight : "px",\r
- option : "height",\r
- type : "number", \r
- range : [1,10000], \r
- step : 1,\r
- defaultValue : function() { return PE.getImageHeight(); },\r
- ui : "text"\r
- }\r
- ],\r
- onactivate : function() {\r
- var $canvas = PE.getDisplayCanvas();\r
- var onchange = function(c) {\r
- var doc = PE.getDocument();\r
- $j("#input-numeric-crop-left", doc).val(c.x).change();\r
- $j("#input-numeric-crop-top", doc).val(c.y).change();\r
- $j("#input-numeric-crop-width", doc).val(c.w).change();\r
- $j("#input-numeric-crop-height", doc).val(c.h).change();\r
- $j("#input-hidden-crop-left", doc).val(c.x).change();\r
- $j("#input-hidden-crop-top", doc).val(c.y).change();\r
- $j("#input-hidden-crop-width", doc).val(c.w).change();\r
- $j("#input-hidden-crop-height", doc).val(c.h).change();\r
- }\r
- $canvas.data("Jcrop-onchange", onchange);\r
- $canvas.Jcrop({onChange:onchange}, PE.getDocument());\r
- },\r
- ondeactivate : function() {\r
- var $canvas = PE.getDisplayCanvas();\r
- if ($canvas.data("Jcrop") && $canvas.data("Jcrop").destroy)\r
- $canvas.data("Jcrop").destroy();\r
- },\r
- onafteraction : function(action, isPreview) {\r
- action.ondeactivate();\r
- action.onactivate();\r
- /*\r
- var $canvas = PE.getDisplayCanvas();\r
- if ($canvas.data("Jcrop") && $canvas.data("Jcrop").destroy)\r
- $canvas.data("Jcrop").destroy();\r
- var onchange = $canvas.data("Jcrop-onchange");\r
- $canvas.Jcrop({onChange:onchange});\r
- */\r
- }\r
- },\r
- {\r
- title : "Rotate",\r
- id : "rotate",\r
- isAction : true,\r
- preview : true,\r
- forcePreview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Enter the angle (-180° to 180°) you want to rotate the picture. Use negative values for clockwise rotation, positive for counterclockwise."\r
- },\r
- {\r
- label : "Angle",\r
- labelRight : "°",\r
- option : "angle",\r
- type : "number", \r
- range : [-180,180], \r
- step : 1,\r
- defaultValue : 0,\r
- ui : "text"\r
- }\r
- ],\r
- onactivate : function() {\r
- var doc = PE.getDocument();\r
- var $displayCanvas = PE.getDisplayCanvas();\r
- var dim = Math.min($displayCanvas.attr("height"), 200);\r
- var $canvas = $j("<canvas></canvas>", doc);\r
- PE.getOverlay().append($canvas);\r
-\r
- $canvas.attr("width", dim);\r
- $canvas.attr("height", dim);\r
- $canvas.width(dim);\r
- $canvas.height(dim);\r
-\r
- $canvas.css("marginTop", (($displayCanvas.attr("height") - dim) * 0.5) + "px");\r
-\r
- var lineWidth = 20;\r
- var radius = dim/2 - lineWidth;\r
- if (radius < 1) radius = 1;\r
-\r
- var ctx = $canvas.get(0).getContext("2d");\r
- ctx.beginPath()\r
- ctx.arc(dim/2, dim/2, radius, 0, Math.PI*2, true);\r
- ctx.closePath();\r
- ctx.fillStyle = "rgba(200,200,200,0.2)";\r
- ctx.fill();\r
- ctx.strokeStyle = "rgba(200,200,200,0.5)";\r
- ctx.lineWidth = 20;\r
- ctx.stroke();\r
-\r
- $j("#image-area", doc).css("cursor", "move");\r
-\r
- $overlay = PE.getOverlay();\r
-\r
- $canvas.get(0).ondragstart = function() {return false;}\r
- $canvas.get(0).onselectstart = function() {return false;}\r
-\r
- var mx = 0, my = 0;\r
- var startMouseAngle = 0;\r
- var startAngle = 0;\r
- var deltaAngle = 0;\r
- var angle = 0;\r
-\r
- var mouseIsDown = false;\r
- var onmousedown = function(e) {\r
- mouseIsDown = true;\r
- var offset = $displayCanvas.offset();\r
- mx = (e.pageX - offset.left) - $displayCanvas.attr("width")*0.5;\r
- my = (e.pageY - offset.top) - $displayCanvas.attr("height")*0.5;\r
- startMouseAngle = Math.atan2(my, mx);\r
- startAngle = parseInt($j("#input-numeric-rotate-angle", doc).val(), 10) * Math.PI / 180;\r
- }\r
- var onmousemove = function(e) {\r
- if (!mouseIsDown) return;\r
-\r
- var offset = $displayCanvas.offset();\r
- mx = (e.pageX - offset.left) - $displayCanvas.attr("width")*0.5;\r
- my = (e.pageY - offset.top) - $displayCanvas.attr("height")*0.5;\r
- deltaAngle = Math.atan2(my, mx) - startMouseAngle;\r
- angle = startAngle - deltaAngle;\r
- if (angle < -Math.PI) angle += 2*Math.PI;\r
- if (angle > Math.PI) angle -= 2*Math.PI;\r
- $j("#input-numeric-rotate-angle", doc).val(Math.round(angle * 180 / Math.PI));\r
- $j("#input-numeric-rotate-angle", doc).change();\r
- }\r
- var onmouseup = function() {\r
- mouseIsDown = false;\r
- }\r
-\r
- $j("#image-area", doc).bind("mousedown", onmousedown);\r
- $j("#image-area", doc).bind("mousemove", onmousemove);\r
- $j("#image-area", doc).bind("mouseup", onmouseup);\r
- $canvas.data("onmousedown", onmousedown);\r
- $canvas.data("onmousemove", onmousemove);\r
- $canvas.data("onmouseup", onmouseup);\r
- $displayCanvas.data("rotateCanvas", $canvas);\r
- },\r
- ondeactivate : function() {\r
- var doc = PE.getDocument();\r
- var $displayCanvas = PE.getDisplayCanvas();\r
- $overlay = PE.getOverlay();\r
- $j("#image-area", doc).css("cursor", "default");\r
-\r
- var $canvas = $displayCanvas.data("rotateCanvas");\r
-\r
- $j("#image-area", doc).unbind("mousedown", $canvas.data("onmousedown"));\r
- $j("#image-area", doc).unbind("mousemove", $canvas.data("onmousemove"));\r
- $j("#image-area", doc).unbind("mouseup", $canvas.data("onmouseup"));\r
- $displayCanvas.removeData("rotateCanvas");\r
- $canvas.remove();\r
- },\r
- onafteraction : function(action, isPreview) {\r
- if (!isPreview) { // rebuild the rotate widget\r
- action.ondeactivate();\r
- action.onactivate();\r
- }\r
- },\r
- onoverlayupdate : function() {\r
- var $canvas = PE.getDisplayCanvas().data("rotateCanvas");\r
- if ($canvas) {\r
- $canvas.css("marginTop", ((PE.getDisplayCanvas().get(0).height - $canvas.get(0).height) * 0.5) + "px");\r
- }\r
- }\r
- },\r
- {\r
- title : "Flip",\r
- id : "flip",\r
- isAction : true,\r
- controls : [\r
- {\r
- label : "Axis",\r
- option : "axis",\r
- type : "string", \r
- values : [\r
- {name:"Horizontal", value:"horizontal"},\r
- {name:"Vertical", value:"vertical"}\r
- ],\r
- defaultValue : "vertical",\r
- ui : "select"\r
- }\r
- ]\r
- }\r
- ]\r
- },\r
- {\r
- title : "Develop",\r
- id : "develop",\r
- actions : [\r
- {\r
- title : "Brightness & Contrast",\r
- id : "brightness",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Use the sliders below to adjust the brightness and/or contrast of the image."\r
- },\r
- {\r
- label : "Brightness",\r
- option : "brightness",\r
- type : "number", \r
- range : [-100,100], \r
- defaultValue : 0,\r
- ui : "slider",\r
- step : 1\r
- },\r
- {\r
- label : "Contrast",\r
- option : "contrast",\r
- type : "number", \r
- range : [-1,1], \r
- defaultValue : 0,\r
- ui : "slider",\r
- step : 0.01\r
- },\r
- {\r
- label : "Legacy mode",\r
- option : "legacy",\r
- type : "boolean", \r
- defaultValue : false,\r
- ui : "checkbox"\r
- }\r
- ]\r
- },\r
- {\r
- title : "Hue/Saturation/Lightness",\r
- id : "hsl",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Use the sliders below to adjust the hue, saturation and/or lightness of the image."\r
- },\r
- {\r
- label : "Hue",\r
- option : "hue",\r
- type : "number", \r
- range : [-180,180], \r
- defaultValue : 0,\r
- ui : "slider",\r
- step : 1\r
- },\r
- {\r
- label : "Saturation",\r
- option : "saturation",\r
- type : "number", \r
- range : [-100,100], \r
- defaultValue : 0,\r
- ui : "slider",\r
- step : 1\r
- },\r
- {\r
- label : "Lightness",\r
- option : "lightness",\r
- type : "number", \r
- range : [-100,100], \r
- defaultValue : 0,\r
- ui : "slider",\r
- step : 1\r
- }\r
- ]\r
- },\r
- {\r
- title : "Adjust colors",\r
- id : "coloradjust",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Use the sliders below to shift the R, G and B channels of the image."\r
- },\r
- {\r
- label : "Red",\r
- option : "red",\r
- type : "number", \r
- range : [-1,1], \r
- defaultValue : 0,\r
- ui : "slider",\r
- step : 0.01\r
- },\r
- {\r
- label : "Green",\r
- option : "green",\r
- type : "number", \r
- range : [-1,1], \r
- defaultValue : 0,\r
- ui : "slider",\r
- step : 0.01\r
- },\r
- {\r
- label : "Blue",\r
- option : "blue",\r
- type : "number", \r
- range : [-1,1], \r
- defaultValue : 0,\r
- ui : "slider",\r
- step : 0.01\r
- }\r
- ]\r
- },\r
- {\r
- title : "Desaturate",\r
- id : "desaturate",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- 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."\r
- },\r
- {\r
- label : "Use average",\r
- option : "average",\r
- type : "boolean", \r
- defaultValue : false,\r
- ui : "checkbox"\r
- }\r
- ]\r
- },\r
- {\r
- title : "Sepia toning",\r
- id : "sepia",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Applies a sepia toning effect to the image."\r
- }\r
- ]\r
- },\r
- {\r
- title : "Invert",\r
- id : "invert",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "This will invert the colors of the image."\r
- }\r
- ]\r
- },\r
- {\r
- title : "Lighten",\r
- id : "lighten",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Use the slider below to lighten or darken the image."\r
- },\r
- {\r
- label : "Amount",\r
- option : "amount",\r
- type : "number", \r
- range : [-1,1], \r
- defaultValue : 0,\r
- ui : "slider",\r
- step : 0.01\r
- }\r
- ]\r
- },\r
- {\r
- title : "Unsharp mask",\r
- id : "unsharpmask",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Use the sliders below to adjust the unsharp mask parameters."\r
- },\r
- {\r
- label : "Amount",\r
- option : "amount",\r
- type : "number", \r
- range : [0,500], \r
- defaultValue : 200,\r
- ui : "slider",\r
- step : 2\r
- },\r
- {\r
- label : "Radius",\r
- option : "radius",\r
- type : "number", \r
- range : [0,5], \r
- defaultValue : 2,\r
- ui : "slider",\r
- step : 0.1\r
- },\r
- {\r
- label : "Threshold",\r
- option : "amount",\r
- type : "number", \r
- range : [0,255], \r
- defaultValue : 25,\r
- ui : "slider",\r
- step : 1\r
- }\r
- ]\r
- }\r
-\r
- ]\r
- },\r
- {\r
- title : "Effects",\r
- id : "effects",\r
- actions : [\r
- {\r
- title : "Blur",\r
- id : "blurfast",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Use the slider to set the blur amount."\r
- },\r
- {\r
- label : "Amount",\r
- option : "amount",\r
- type : "number", \r
- range : [0,1], \r
- defaultValue : 0.5,\r
- ui : "slider",\r
- step : 0.01\r
- }\r
- ]\r
-\r
- },\r
- {\r
- title : "Edge detection",\r
- id : "edges",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Performs edge detection on the image."\r
- },\r
- {\r
- label : "Greyscale",\r
- option : "mono",\r
- type : "boolean", \r
- defaultValue : false,\r
- ui : "checkbox"\r
- },\r
- {\r
- label : "Invert",\r
- option : "invert",\r
- type : "boolean", \r
- defaultValue : false,\r
- ui : "checkbox"\r
- }\r
- ]\r
- },\r
- {\r
- title : "Emboss",\r
- id : "emboss",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- 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."\r
- },\r
- {\r
- label : "Strength",\r
- option : "strength",\r
- type : "number", \r
- range : [0,10], \r
- defaultValue : 1,\r
- ui : "slider",\r
- step : 0.1\r
- },\r
- {\r
- label : "Grey level",\r
- option : "greyLevel",\r
- type : "number", \r
- range : [0,255], \r
- defaultValue : 180,\r
- ui : "slider",\r
- step : 1\r
- },\r
- {\r
- label : "Direction",\r
- option : "direction",\r
- type : "string", \r
- values : [\r
- {name:"Top left", value:"topleft"},\r
- {name:"Top", value:"top"},\r
- {name:"Top right", value:"topright"},\r
- {name:"Right", value:"right"},\r
- {name:"Bottom right", value:"bottomright"},\r
- {name:"Bottom", value:"bottom"},\r
- {name:"Bottom left", value:"bottomleft"},\r
- {name:"Left", value:"left"}\r
- ],\r
- defaultValue : "topleft",\r
- ui : "select"\r
- },\r
- {\r
- label : "Blend",\r
- option : "blend",\r
- type : "boolean", \r
- defaultValue : false,\r
- ui : "checkbox"\r
- }\r
- ]\r
-\r
- },\r
- {\r
- title : "Glow",\r
- id : "glow",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Creates a glowing effect on the image."\r
- },\r
- {\r
- label : "Amount",\r
- option : "amount",\r
- type : "number", \r
- range : [0,1], \r
- defaultValue : 0.5,\r
- ui : "slider",\r
- step : 0.01\r
- },\r
- {\r
- label : "Radius",\r
- option : "radius",\r
- type : "number", \r
- range : [0,1], \r
- defaultValue : 0.5,\r
- ui : "slider",\r
- step : 0.01\r
- }\r
- ]\r
- },\r
- {\r
- title : "Add noise",\r
- id : "noise",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Add random noise to the image."\r
- },\r
- {\r
- label : "Amount",\r
- option : "amount",\r
- type : "number", \r
- range : [0,1], \r
- defaultValue : 0.5,\r
- ui : "slider",\r
- step : 0.01\r
- },\r
- {\r
- label : "Strength",\r
- option : "strength",\r
- type : "number", \r
- range : [0,1], \r
- defaultValue : 0.5,\r
- ui : "slider",\r
- step : 0.01\r
- },\r
- {\r
- label : "Greyscale",\r
- option : "mono",\r
- type : "boolean", \r
- defaultValue : false,\r
- ui : "checkbox"\r
- }\r
- ]\r
- },\r
- {\r
- title : "Remove noise",\r
- id : "removenoise",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Attempts to remove noise from the image. Works best for getting rid of single pixels that stand out."\r
- }\r
- ]\r
- },\r
- {\r
- title : "Pointillize",\r
- id : "pointillize",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Paints the picture with circular points."\r
- },\r
- {\r
- label : "Point radius",\r
- option : "radius",\r
- type : "number", \r
- range : [1,50], \r
- defaultValue : 5,\r
- ui : "slider",\r
- step : 1\r
- },\r
- {\r
- label : "Density",\r
- option : "density",\r
- type : "number", \r
- range : [0,5], \r
- defaultValue : 1,\r
- ui : "slider",\r
- step : 0.01\r
- },\r
- {\r
- label : "Noise",\r
- option : "noise",\r
- type : "number", \r
- range : [0,2], \r
- defaultValue : 1,\r
- ui : "slider",\r
- step : 0.01\r
- },\r
- {\r
- label : "Transparent",\r
- option : "transparent",\r
- type : "boolean", \r
- defaultValue : false,\r
- ui : "checkbox"\r
- }\r
- ]\r
- },\r
- {\r
- title : "Posterize",\r
- id : "posterize",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Reduces the number of colours to a specified number of levels."\r
- },\r
- {\r
- label : "Levels",\r
- option : "levels",\r
- type : "number", \r
- range : [1,32], \r
- defaultValue : 5,\r
- ui : "slider",\r
- step : 1\r
- }\r
- ]\r
- },\r
- {\r
- title : "Solarize",\r
- id : "solarize",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Applies a solarize effect to the image."\r
- }\r
- ]\r
- },\r
- {\r
- title : "Mosaic",\r
- id : "mosaic",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Creates a pixelated look."\r
- },\r
- {\r
- label : "Block size",\r
- option : "blockSize",\r
- type : "number", \r
- range : [1,100], \r
- defaultValue : 5,\r
- ui : "slider",\r
- step : 1\r
- }\r
- ]\r
- }\r
-\r
-\r
- ]\r
- },\r
- {\r
- title : "Done",\r
- id : "done",\r
- actions : [\r
- {\r
- title : "Save to page",\r
- id : "savepage",\r
- content : function($ctr) {\r
- var doc = PE.getDocument();\r
- $j("<div></div>", doc)\r
- .addClass("action-output-text")\r
- .html("This will save the image to the page.")\r
- .appendTo($ctr);\r
-\r
- var $buttonCtr = $j("<div></div>", doc).appendTo($ctr);\r
- var $saveButton = $j("<button></button>", doc)\r
- .html("Save image")\r
- .appendTo($buttonCtr)\r
- .click(function() {\r
- PE.saveToPage();\r
- });\r
-\r
- }\r
- },\r
- {\r
- title : "Save to file",\r
- id : "savefile",\r
- content : function(ctr) {\r
- var doc = PE.getDocument();\r
- $j("<div></div>", doc)\r
- .addClass("action-output-text")\r
- .html("This will save the image to your local computer.")\r
- .appendTo(ctr);\r
-\r
- var formats = PE.validSaveFormats();\r
-\r
- var selectHtml = "<select>";\r
- for (var i=0;i<formats.length;i++) {\r
- selectHtml += "<option value='" + formats[i].mime + "'>" + formats[i].name + "</option>";\r
- }\r
- selectHtml += "</select>";\r
-\r
- var selectCtr = $j("<div></div>", doc)\r
- .addClass("ui-select-container");\r
-\r
-\r
- var label = $j("<div></div>", doc)\r
- .addClass("ui-select-label")\r
- .html("Format:")\r
- .appendTo(selectCtr);\r
-\r
- var formatSelect = $j(selectHtml, doc).appendTo(selectCtr);\r
-\r
-\r
- selectCtr.appendTo(ctr);\r
-\r
- var buttonCtr = $j("<div></div>", doc).appendTo(ctr);\r
- var saveButton = $j("<button></button>", doc)\r
- .html("Save file")\r
- .appendTo(buttonCtr)\r
-\r
- saveButton.click(function() {\r
- var selectElement = formatSelect.get(0);\r
- var formatMime = selectElement.options[selectElement.selectedIndex].value;\r
- var dataString = PE.getDataURI(formatMime);\r
-\r
- var dialog = $j("<div></div>", doc)\r
- .attr("id", "save-dialog")\r
- .attr("title", "Download file")\r
- .html(\r
- "Right click the link below and select \"Save as...\" to save your file.<br/>"\r
- + "<br/>"\r
- + "<a href=\"" + dataString + "\">Image Link</a>"\r
- )\r
- .dialog();\r
-\r
- // the dialog is added outside the Pixastic container, so get it back in.\r
- var dialogParent = $j(dialog.get(0).parentNode);\r
- $j("#pixastic-editor", doc).append(dialogParent);\r
- });\r
- }\r
- },\r
- /*\r
- {\r
- title : "Upload to Flickr",\r
- id : "flickrupload",\r
- content : function($ctr) {\r
- var doc = PE.getDocument();\r
-\r
- function flickrAuthed() {\r
- var $text = $j("<div />", doc)\r
- .addClass("action-output-text")\r
- .html("Authorized as: " + PE.Flickr.getAuthName());\r
-\r
- var $buttonCtr = $j("<div></div>", doc);\r
- var $uploadButton = $j("<button></button>", doc)\r
- .html("Upload image")\r
- .appendTo($buttonCtr)\r
-\r
- $uploadButton.click(function() {\r
- PE.Flickr.uploadImage(PE.getDataURI());\r
- });\r
-\r
- $ctr.append($text, $buttonCtr);\r
- }\r
-\r
- var $authCtr = $j("<div />", doc).appendTo($ctr);\r
-\r
- $j("<div />", doc)\r
- .addClass("action-output-text")\r
- .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.")\r
- .appendTo($authCtr);\r
-\r
- var $buttonCtr = $j("<div></div>", doc).appendTo($authCtr);\r
- var $authButton = $j("<button></button>", doc)\r
- .html("Authenticate")\r
- .appendTo($buttonCtr)\r
-\r
- var checkButtonAdded = false;\r
- $authButton.click(function() {\r
- PE.Flickr.auth();\r
- if (!checkButtonAdded) {\r
- checkButtonAdded = true;\r
-\r
- var $text = $j("<div />", doc)\r
- .addClass("action-output-text")\r
- .html("Now click the button below when you have authorized access to your Flickr account.");\r
- \r
- var $buttonCtr = $j("<div></div>", doc);\r
- \r
- $authCtr.append($text, $buttonCtr);\r
- \r
- var $checkButton = $j("<button></button>", doc)\r
- .html("I have authenticated!")\r
- .appendTo($buttonCtr);\r
- \r
- $checkButton.click(function() {\r
- PE.Flickr.checkAuth(function(res) {\r
- if (res.stat == "ok") {\r
- $authCtr.remove();\r
- flickrAuthed();\r
- }\r
- });\r
- });\r
- }\r
-\r
- });\r
- }\r
- },\r
- */\r
- {\r
- title : "Quit",\r
- id : "quit", \r
- content : function(ctr) {\r
- var doc = PE.getDocument();\r
-\r
- $j("<div>Are you sure you want to quit?</div>", doc)\r
- .addClass("action-output-text")\r
- .appendTo(ctr);\r
- var $buttonCtr = $j("<div></div>", doc).appendTo(ctr);\r
-\r
- var $quitButton = PE.UI.makeButton("Yes, quit now!")\r
- .appendTo($buttonCtr)\r
-\r
- $quitButton.click(function() {\r
- PE.unload();\r
- });\r
-\r
- var $saveButton = PE.UI.makeButton("Save to page and quit")\r
- .appendTo($buttonCtr)\r
- .click(function() {\r
- PE.saveToPage();\r
- PE.unload();\r
- });\r
- }\r
- }\r
- ]\r
- }\r
- ]\r
-};\r
-\r
-\r
+(function($) {
+
+var PE = PixasticEditor;
+
+PE.UI.data = {
+ tabs : [
+ {
+ title : "Reshape",
+ id : "reshape",
+ actions : [
+ {
+ title : "Resize",
+ id : "resize",
+ isAction : true,
+ controls : [
+ {
+ type : "output",
+ content : "Enter new dimensions below."
+ },
+ {
+ label : "Width",
+ labelRight : "px",
+ option : "width",
+ type : "number",
+ range : [1,10000],
+ step : 1,
+ defaultValue : function() { return PE.getImageWidth(); },
+ ui : "text"
+ },
+ {
+ label : "Height",
+ labelRight : "px",
+ option : "height",
+ type : "number",
+ range : [1,10000],
+ step : 1,
+ defaultValue : function() { return PE.getImageHeight(); },
+ ui : "text"
+ }
+ ]
+ },
+ {
+ title : "Crop",
+ id : "crop",
+ isAction : true,
+ controls : [
+ {
+ type : "output",
+ content : "Enter new crop values below or use mouse to select crop area."
+ },
+ {
+ label : "X",
+ labelRight : "px",
+ option : "left",
+ type : "number",
+ range : [0,10000],
+ step : 1,
+ defaultValue : 0,
+ ui : "text"
+ },
+ {
+ label : "Y",
+ labelRight : "px",
+ option : "top",
+ type : "number",
+ range : [0,10000],
+ step : 1,
+ defaultValue : 0,
+ ui : "text"
+ },
+ {
+ label : "Width",
+ labelRight : "px",
+ option : "width",
+ type : "number",
+ range : [1,10000],
+ step : 1,
+ defaultValue : function() { return PE.getImageWidth(); },
+ ui : "text"
+ },
+ {
+ label : "Height",
+ labelRight : "px",
+ option : "height",
+ type : "number",
+ range : [1,10000],
+ step : 1,
+ defaultValue : function() { return PE.getImageHeight(); },
+ ui : "text"
+ }
+ ],
+ onactivate : function() {
+ var $canvas = PE.getDisplayCanvas();
+ var onchange = function(c) {
+ var doc = PE.getDocument();
+ $j("#input-numeric-crop-left", doc).val(c.x).change();
+ $j("#input-numeric-crop-top", doc).val(c.y).change();
+ $j("#input-numeric-crop-width", doc).val(c.w).change();
+ $j("#input-numeric-crop-height", doc).val(c.h).change();
+ $j("#input-hidden-crop-left", doc).val(c.x).change();
+ $j("#input-hidden-crop-top", doc).val(c.y).change();
+ $j("#input-hidden-crop-width", doc).val(c.w).change();
+ $j("#input-hidden-crop-height", doc).val(c.h).change();
+ }
+ $canvas.data("Jcrop-onchange", onchange);
+ $canvas.Jcrop({onChange:onchange}, PE.getDocument());
+ },
+ ondeactivate : function() {
+ var $canvas = PE.getDisplayCanvas();
+ if ($canvas.data("Jcrop") && $canvas.data("Jcrop").destroy)
+ $canvas.data("Jcrop").destroy();
+ },
+ onafteraction : function(action, isPreview) {
+ action.ondeactivate();
+ action.onactivate();
+ /*
+ var $canvas = PE.getDisplayCanvas();
+ if ($canvas.data("Jcrop") && $canvas.data("Jcrop").destroy)
+ $canvas.data("Jcrop").destroy();
+ var onchange = $canvas.data("Jcrop-onchange");
+ $canvas.Jcrop({onChange:onchange});
+ */
+ }
+ },
+ {
+ title : "Rotate",
+ id : "rotate",
+ isAction : true,
+ preview : true,
+ forcePreview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Enter the angle (-180° to 180°) you want to rotate the picture. Use negative values for clockwise rotation, positive for counterclockwise."
+ },
+ {
+ label : "Angle",
+ labelRight : "°",
+ option : "angle",
+ type : "number",
+ range : [-180,180],
+ step : 1,
+ defaultValue : 0,
+ ui : "text"
+ }
+ ],
+ onactivate : function() {
+ var doc = PE.getDocument();
+ var $displayCanvas = PE.getDisplayCanvas();
+ var dim = Math.min($displayCanvas.attr("height"), 200);
+ var $canvas = $j("<canvas></canvas>", doc);
+ PE.getOverlay().append($canvas);
+
+ $canvas.attr("width", dim);
+ $canvas.attr("height", dim);
+ $canvas.width(dim);
+ $canvas.height(dim);
+
+ $canvas.css("marginTop", (($displayCanvas.attr("height") - dim) * 0.5) + "px");
+
+ var lineWidth = 20;
+ var radius = dim/2 - lineWidth;
+ if (radius < 1) radius = 1;
+
+ var ctx = $canvas.get(0).getContext("2d");
+ ctx.beginPath()
+ ctx.arc(dim/2, dim/2, radius, 0, Math.PI*2, true);
+ ctx.closePath();
+ ctx.fillStyle = "rgba(200,200,200,0.2)";
+ ctx.fill();
+ ctx.strokeStyle = "rgba(200,200,200,0.5)";
+ ctx.lineWidth = 20;
+ ctx.stroke();
+
+ $j("#image-area", doc).css("cursor", "move");
+
+ $overlay = PE.getOverlay();
+
+ $canvas.get(0).ondragstart = function() {return false;}
+ $canvas.get(0).onselectstart = function() {return false;}
+
+ var mx = 0, my = 0;
+ var startMouseAngle = 0;
+ var startAngle = 0;
+ var deltaAngle = 0;
+ var angle = 0;
+
+ var mouseIsDown = false;
+ var onmousedown = function(e) {
+ mouseIsDown = true;
+ var offset = $displayCanvas.offset();
+ mx = (e.pageX - offset.left) - $displayCanvas.attr("width")*0.5;
+ my = (e.pageY - offset.top) - $displayCanvas.attr("height")*0.5;
+ startMouseAngle = Math.atan2(my, mx);
+ startAngle = parseInt($j("#input-numeric-rotate-angle", doc).val(), 10) * Math.PI / 180;
+ }
+ var onmousemove = function(e) {
+ if (!mouseIsDown) return;
+
+ var offset = $displayCanvas.offset();
+ mx = (e.pageX - offset.left) - $displayCanvas.attr("width")*0.5;
+ my = (e.pageY - offset.top) - $displayCanvas.attr("height")*0.5;
+ deltaAngle = Math.atan2(my, mx) - startMouseAngle;
+ angle = startAngle - deltaAngle;
+ if (angle < -Math.PI) angle += 2*Math.PI;
+ if (angle > Math.PI) angle -= 2*Math.PI;
+ $j("#input-numeric-rotate-angle", doc).val(Math.round(angle * 180 / Math.PI));
+ $j("#input-numeric-rotate-angle", doc).change();
+ }
+ var onmouseup = function() {
+ mouseIsDown = false;
+ }
+
+ $j("#image-area", doc).bind("mousedown", onmousedown);
+ $j("#image-area", doc).bind("mousemove", onmousemove);
+ $j("#image-area", doc).bind("mouseup", onmouseup);
+ $canvas.data("onmousedown", onmousedown);
+ $canvas.data("onmousemove", onmousemove);
+ $canvas.data("onmouseup", onmouseup);
+ $displayCanvas.data("rotateCanvas", $canvas);
+ },
+ ondeactivate : function() {
+ var doc = PE.getDocument();
+ var $displayCanvas = PE.getDisplayCanvas();
+ $overlay = PE.getOverlay();
+ $j("#image-area", doc).css("cursor", "default");
+
+ var $canvas = $displayCanvas.data("rotateCanvas");
+
+ $j("#image-area", doc).unbind("mousedown", $canvas.data("onmousedown"));
+ $j("#image-area", doc).unbind("mousemove", $canvas.data("onmousemove"));
+ $j("#image-area", doc).unbind("mouseup", $canvas.data("onmouseup"));
+ $displayCanvas.removeData("rotateCanvas");
+ $canvas.remove();
+ },
+ onafteraction : function(action, isPreview) {
+ if (!isPreview) { // rebuild the rotate widget
+ action.ondeactivate();
+ action.onactivate();
+ }
+ },
+ onoverlayupdate : function() {
+ var $canvas = PE.getDisplayCanvas().data("rotateCanvas");
+ if ($canvas) {
+ $canvas.css("marginTop", ((PE.getDisplayCanvas().get(0).height - $canvas.get(0).height) * 0.5) + "px");
+ }
+ }
+ },
+ {
+ title : "Flip",
+ id : "flip",
+ isAction : true,
+ controls : [
+ {
+ label : "Axis",
+ option : "axis",
+ type : "string",
+ values : [
+ {name:"Horizontal", value:"horizontal"},
+ {name:"Vertical", value:"vertical"}
+ ],
+ defaultValue : "vertical",
+ ui : "select"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ title : "Develop",
+ id : "develop",
+ actions : [
+ {
+ title : "Brightness & Contrast",
+ id : "brightness",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Use the sliders below to adjust the brightness and/or contrast of the image."
+ },
+ {
+ label : "Brightness",
+ option : "brightness",
+ type : "number",
+ range : [-100,100],
+ defaultValue : 0,
+ ui : "slider",
+ step : 1
+ },
+ {
+ label : "Contrast",
+ option : "contrast",
+ type : "number",
+ range : [-1,1],
+ defaultValue : 0,
+ ui : "slider",
+ step : 0.01
+ },
+ {
+ label : "Legacy mode",
+ option : "legacy",
+ type : "boolean",
+ defaultValue : false,
+ ui : "checkbox"
+ }
+ ]
+ },
+ {
+ title : "Hue/Saturation/Lightness",
+ id : "hsl",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Use the sliders below to adjust the hue, saturation and/or lightness of the image."
+ },
+ {
+ label : "Hue",
+ option : "hue",
+ type : "number",
+ range : [-180,180],
+ defaultValue : 0,
+ ui : "slider",
+ step : 1
+ },
+ {
+ label : "Saturation",
+ option : "saturation",
+ type : "number",
+ range : [-100,100],
+ defaultValue : 0,
+ ui : "slider",
+ step : 1
+ },
+ {
+ label : "Lightness",
+ option : "lightness",
+ type : "number",
+ range : [-100,100],
+ defaultValue : 0,
+ ui : "slider",
+ step : 1
+ }
+ ]
+ },
+ {
+ title : "Adjust colors",
+ id : "coloradjust",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Use the sliders below to shift the R, G and B channels of the image."
+ },
+ {
+ label : "Red",
+ option : "red",
+ type : "number",
+ range : [-1,1],
+ defaultValue : 0,
+ ui : "slider",
+ step : 0.01
+ },
+ {
+ label : "Green",
+ option : "green",
+ type : "number",
+ range : [-1,1],
+ defaultValue : 0,
+ ui : "slider",
+ step : 0.01
+ },
+ {
+ label : "Blue",
+ option : "blue",
+ type : "number",
+ range : [-1,1],
+ defaultValue : 0,
+ ui : "slider",
+ step : 0.01
+ }
+ ]
+ },
+ {
+ title : "Desaturate",
+ id : "desaturate",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ 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."
+ },
+ {
+ label : "Use average",
+ option : "average",
+ type : "boolean",
+ defaultValue : false,
+ ui : "checkbox"
+ }
+ ]
+ },
+ {
+ title : "Sepia toning",
+ id : "sepia",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Applies a sepia toning effect to the image."
+ }
+ ]
+ },
+ {
+ title : "Invert",
+ id : "invert",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "This will invert the colors of the image."
+ }
+ ]
+ },
+ {
+ title : "Lighten",
+ id : "lighten",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Use the slider below to lighten or darken the image."
+ },
+ {
+ label : "Amount",
+ option : "amount",
+ type : "number",
+ range : [-1,1],
+ defaultValue : 0,
+ ui : "slider",
+ step : 0.01
+ }
+ ]
+ },
+ {
+ title : "Unsharp mask",
+ id : "unsharpmask",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Use the sliders below to adjust the unsharp mask parameters."
+ },
+ {
+ label : "Amount",
+ option : "amount",
+ type : "number",
+ range : [0,500],
+ defaultValue : 200,
+ ui : "slider",
+ step : 2
+ },
+ {
+ label : "Radius",
+ option : "radius",
+ type : "number",
+ range : [0,5],
+ defaultValue : 2,
+ ui : "slider",
+ step : 0.1
+ },
+ {
+ label : "Threshold",
+ option : "amount",
+ type : "number",
+ range : [0,255],
+ defaultValue : 25,
+ ui : "slider",
+ step : 1
+ }
+ ]
+ }
+
+ ]
+ },
+ {
+ title : "Effects",
+ id : "effects",
+ actions : [
+ {
+ title : "Blur",
+ id : "blurfast",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Use the slider to set the blur amount."
+ },
+ {
+ label : "Amount",
+ option : "amount",
+ type : "number",
+ range : [0,1],
+ defaultValue : 0.5,
+ ui : "slider",
+ step : 0.01
+ }
+ ]
+
+ },
+ {
+ title : "Edge detection",
+ id : "edges",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Performs edge detection on the image."
+ },
+ {
+ label : "Greyscale",
+ option : "mono",
+ type : "boolean",
+ defaultValue : false,
+ ui : "checkbox"
+ },
+ {
+ label : "Invert",
+ option : "invert",
+ type : "boolean",
+ defaultValue : false,
+ ui : "checkbox"
+ }
+ ]
+ },
+ {
+ title : "Emboss",
+ id : "emboss",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ 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."
+ },
+ {
+ label : "Strength",
+ option : "strength",
+ type : "number",
+ range : [0,10],
+ defaultValue : 1,
+ ui : "slider",
+ step : 0.1
+ },
+ {
+ label : "Grey level",
+ option : "greyLevel",
+ type : "number",
+ range : [0,255],
+ defaultValue : 180,
+ ui : "slider",
+ step : 1
+ },
+ {
+ label : "Direction",
+ option : "direction",
+ type : "string",
+ values : [
+ {name:"Top left", value:"topleft"},
+ {name:"Top", value:"top"},
+ {name:"Top right", value:"topright"},
+ {name:"Right", value:"right"},
+ {name:"Bottom right", value:"bottomright"},
+ {name:"Bottom", value:"bottom"},
+ {name:"Bottom left", value:"bottomleft"},
+ {name:"Left", value:"left"}
+ ],
+ defaultValue : "topleft",
+ ui : "select"
+ },
+ {
+ label : "Blend",
+ option : "blend",
+ type : "boolean",
+ defaultValue : false,
+ ui : "checkbox"
+ }
+ ]
+
+ },
+ {
+ title : "Glow",
+ id : "glow",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Creates a glowing effect on the image."
+ },
+ {
+ label : "Amount",
+ option : "amount",
+ type : "number",
+ range : [0,1],
+ defaultValue : 0.5,
+ ui : "slider",
+ step : 0.01
+ },
+ {
+ label : "Radius",
+ option : "radius",
+ type : "number",
+ range : [0,1],
+ defaultValue : 0.5,
+ ui : "slider",
+ step : 0.01
+ }
+ ]
+ },
+ {
+ title : "Add noise",
+ id : "noise",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Add random noise to the image."
+ },
+ {
+ label : "Amount",
+ option : "amount",
+ type : "number",
+ range : [0,1],
+ defaultValue : 0.5,
+ ui : "slider",
+ step : 0.01
+ },
+ {
+ label : "Strength",
+ option : "strength",
+ type : "number",
+ range : [0,1],
+ defaultValue : 0.5,
+ ui : "slider",
+ step : 0.01
+ },
+ {
+ label : "Greyscale",
+ option : "mono",
+ type : "boolean",
+ defaultValue : false,
+ ui : "checkbox"
+ }
+ ]
+ },
+ {
+ title : "Remove noise",
+ id : "removenoise",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Attempts to remove noise from the image. Works best for getting rid of single pixels that stand out."
+ }
+ ]
+ },
+ {
+ title : "Pointillize",
+ id : "pointillize",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Paints the picture with circular points."
+ },
+ {
+ label : "Point radius",
+ option : "radius",
+ type : "number",
+ range : [1,50],
+ defaultValue : 5,
+ ui : "slider",
+ step : 1
+ },
+ {
+ label : "Density",
+ option : "density",
+ type : "number",
+ range : [0,5],
+ defaultValue : 1,
+ ui : "slider",
+ step : 0.01
+ },
+ {
+ label : "Noise",
+ option : "noise",
+ type : "number",
+ range : [0,2],
+ defaultValue : 1,
+ ui : "slider",
+ step : 0.01
+ },
+ {
+ label : "Transparent",
+ option : "transparent",
+ type : "boolean",
+ defaultValue : false,
+ ui : "checkbox"
+ }
+ ]
+ },
+ {
+ title : "Posterize",
+ id : "posterize",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Reduces the number of colours to a specified number of levels."
+ },
+ {
+ label : "Levels",
+ option : "levels",
+ type : "number",
+ range : [1,32],
+ defaultValue : 5,
+ ui : "slider",
+ step : 1
+ }
+ ]
+ },
+ {
+ title : "Solarize",
+ id : "solarize",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Applies a solarize effect to the image."
+ }
+ ]
+ },
+ {
+ title : "Mosaic",
+ id : "mosaic",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Creates a pixelated look."
+ },
+ {
+ label : "Block size",
+ option : "blockSize",
+ type : "number",
+ range : [1,100],
+ defaultValue : 5,
+ ui : "slider",
+ step : 1
+ }
+ ]
+ }
+
+
+ ]
+ },
+ {
+ title : "Done",
+ id : "done",
+ actions : [
+ {
+ title : "Save to page",
+ id : "savepage",
+ content : function($ctr) {
+ var doc = PE.getDocument();
+ $j("<div></div>", doc)
+ .addClass("action-output-text")
+ .html("This will save the image to the page.")
+ .appendTo($ctr);
+
+ var $buttonCtr = $j("<div></div>", doc).appendTo($ctr);
+ var $saveButton = $j("<button></button>", doc)
+ .html("Save image")
+ .appendTo($buttonCtr)
+ .click(function() {
+ PE.saveToPage();
+ });
+
+ }
+ },
+ {
+ title : "Save to file",
+ id : "savefile",
+ content : function(ctr) {
+ var doc = PE.getDocument();
+ $j("<div></div>", doc)
+ .addClass("action-output-text")
+ .html("This will save the image to your local computer.")
+ .appendTo(ctr);
+
+ var formats = PE.validSaveFormats();
+
+ var selectHtml = "<select>";
+ for (var i=0;i<formats.length;i++) {
+ selectHtml += "<option value='" + formats[i].mime + "'>" + formats[i].name + "</option>";
+ }
+ selectHtml += "</select>";
+
+ var selectCtr = $j("<div></div>", doc)
+ .addClass("ui-select-container");
+
+
+ var label = $j("<div></div>", doc)
+ .addClass("ui-select-label")
+ .html("Format:")
+ .appendTo(selectCtr);
+
+ var formatSelect = $j(selectHtml, doc).appendTo(selectCtr);
+
+
+ selectCtr.appendTo(ctr);
+
+ var buttonCtr = $j("<div></div>", doc).appendTo(ctr);
+ var saveButton = $j("<button></button>", doc)
+ .html("Save file")
+ .appendTo(buttonCtr)
+
+ saveButton.click(function() {
+ var selectElement = formatSelect.get(0);
+ var formatMime = selectElement.options[selectElement.selectedIndex].value;
+ var dataString = PE.getDataURI(formatMime);
+
+ var dialog = $j("<div></div>", doc)
+ .attr("id", "save-dialog")
+ .attr("title", "Download file")
+ .html(
+ "Right click the link below and select \"Save as...\" to save your file.<br/>"
+ + "<br/>"
+ + "<a href=\"" + dataString + "\">Image Link</a>"
+ )
+ .dialog();
+
+ // the dialog is added outside the Pixastic container, so get it back in.
+ var dialogParent = $j(dialog.get(0).parentNode);
+ $j("#pixastic-editor", doc).append(dialogParent);
+ });
+ }
+ },
+ /*
+ {
+ title : "Upload to Flickr",
+ id : "flickrupload",
+ content : function($ctr) {
+ var doc = PE.getDocument();
+
+ function flickrAuthed() {
+ var $text = $j("<div />", doc)
+ .addClass("action-output-text")
+ .html("Authorized as: " + PE.Flickr.getAuthName());
+
+ var $buttonCtr = $j("<div></div>", doc);
+ var $uploadButton = $j("<button></button>", doc)
+ .html("Upload image")
+ .appendTo($buttonCtr)
+
+ $uploadButton.click(function() {
+ PE.Flickr.uploadImage(PE.getDataURI());
+ });
+
+ $ctr.append($text, $buttonCtr);
+ }
+
+ var $authCtr = $j("<div />", doc).appendTo($ctr);
+
+ $j("<div />", doc)
+ .addClass("action-output-text")
+ .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.")
+ .appendTo($authCtr);
+
+ var $buttonCtr = $j("<div></div>", doc).appendTo($authCtr);
+ var $authButton = $j("<button></button>", doc)
+ .html("Authenticate")
+ .appendTo($buttonCtr)
+
+ var checkButtonAdded = false;
+ $authButton.click(function() {
+ PE.Flickr.auth();
+ if (!checkButtonAdded) {
+ checkButtonAdded = true;
+
+ var $text = $j("<div />", doc)
+ .addClass("action-output-text")
+ .html("Now click the button below when you have authorized access to your Flickr account.");
+
+ var $buttonCtr = $j("<div></div>", doc);
+
+ $authCtr.append($text, $buttonCtr);
+
+ var $checkButton = $j("<button></button>", doc)
+ .html("I have authenticated!")
+ .appendTo($buttonCtr);
+
+ $checkButton.click(function() {
+ PE.Flickr.checkAuth(function(res) {
+ if (res.stat == "ok") {
+ $authCtr.remove();
+ flickrAuthed();
+ }
+ });
+ });
+ }
+
+ });
+ }
+ },
+ */
+ {
+ title : "Quit",
+ id : "quit",
+ content : function(ctr) {
+ var doc = PE.getDocument();
+
+ $j("<div>Are you sure you want to quit?</div>", doc)
+ .addClass("action-output-text")
+ .appendTo(ctr);
+ var $buttonCtr = $j("<div></div>", doc).appendTo(ctr);
+
+ var $quitButton = PE.UI.makeButton("Yes, quit now!")
+ .appendTo($buttonCtr)
+
+ $quitButton.click(function() {
+ PE.unload();
+ });
+
+ var $saveButton = PE.UI.makeButton("Save to page and quit")
+ .appendTo($buttonCtr)
+ .click(function() {
+ PE.saveToPage();
+ PE.unload();
+ });
+ }
+ }
+ ]
+ }
+ ]
+};
+
+
})(PixasticEditor.jQuery);
\ No newline at end of file
-\r
-var PixasticEditor = (function () {\r
-\r
- var $frame; // iframe container element\r
- var $editor; // editor container element\r
-\r
- // various UI structures\r
- var accordionElements = {};\r
- var tabElements = {};\r
- var activeTabId;\r
- var $activeTabContent;\r
-\r
- var isRunning = false;\r
-\r
- var $loadingScreen;\r
-\r
- var $imageCanvas; // the canvas holding the current state of the image\r
- var $displayCanvas; // the canvas element displayed on the screen, also the working canvas (where preview operations are performed)\r
- var imageCtx;\r
-\r
- var imageWidth = 0; // dimensions of the current image state\r
- var imageHeight = 0;\r
-\r
- var undoImages = []; // canvas elements holding previous image states\r
- var undoLevels = 10;\r
-\r
- var doc;\r
-\r
- var $;\r
-\r
- // test for valid file formats for toDataURL()\r
- // we do that by calling it with each of the mime types in testFormats\r
- // and then doing string checking on the resulting data: URI to see if it succeeded\r
- var saveFormats = [];\r
- var testFormats = [["image/jpeg", "JPEG"], ["image/png", "PNG"]];\r
- var testCanvas = document.createElement("canvas");\r
- if (testCanvas.toDataURL) {\r
- testCanvas.width = testCanvas.height = 1;\r
- for (var i=0;i<testFormats.length;i++) {\r
- var data = testCanvas.toDataURL(testFormats[i][0]);\r
- if (data.substr(0, 5 + testFormats[i][0].length) == "data:" + testFormats[i][0])\r
- saveFormats.push({mime:testFormats[i][0], name:testFormats[i][1]});\r
- }\r
- }\r
-\r
-\r
- // pops up an error dialog with the specified text (errTxt),\r
- // if no context is provided, the name of the calling function is used.\r
- // The final message is returned for easy throwing of actual errors\r
- function errorDialog(errTxt, context) {\r
- if (!($editor && $editor.get && $editor.get(0)))\r
- throw new Error("errorDialog(): $editor doesn't exist");\r
-\r
- var caller = errorDialog.caller.toString().split(" ")[1];\r
- caller = caller.substring(0, caller.indexOf("("));\r
- context = context || caller;\r
- errTxt = context + "(): " + errTxt;\r
- var dialog = $j("<div></div>", doc)\r
- .addClass("error-dialog")\r
- .attr("title", "Oops!")\r
- .html(errTxt)\r
- .dialog();\r
- // the dialog is added outside the Pixastic container, so get it back in.\r
- var dialogParent = $j(dialog.get(0).parentNode);\r
- dialogParent.appendTo($editor);\r
-\r
- return errTxt;\r
- }\r
- \r
- function enableTab(id, refresh) {\r
- if (id == activeTabId && !refresh)\r
- return;\r
-\r
- activeTabId = id;\r
-\r
- var activeIndex = 0;\r
-\r
- if ($activeTabContent) {\r
- if ($activeTabContent.get(0)) {\r
- var $parent = $j($activeTabContent.get(0).parentNode);\r
- activeIndex = $parent.data("accordionindex");\r
- if ($parent.data("ondeactivate")) {\r
- $parent.data("ondeactivate")();\r
- }\r
- if ($parent.data("previewCheckbox"))\r
- $parent.data("previewCheckbox").attr("checked", false);\r
- $parent.data("uidesc").previewEnabled = false;\r
- if ($parent.data("uidesc").forcePreview)\r
- $parent.data("uidesc").previewEnabled = true;\r
- }\r
- }\r
-\r
-\r
- for (var a in accordionElements) {\r
- if (accordionElements.hasOwnProperty(a)) {\r
- accordionElements[a].accordion("option", "animated", false);\r
- accordionElements[a].accordion("activate", -1);\r
- accordionElements[a].hide();\r
- tabElements[a].removeClass("active");\r
-\r
- }\r
- }\r
-\r
- accordionElements[id].accordion("option", "animated", false);\r
- accordionElements[id].accordion("activate", refresh ? activeIndex : 0);\r
- tabElements[id].addClass("active");\r
- accordionElements[id].show();\r
- accordionElements[id].accordion("option", "animated", "slide");\r
- resetDisplayCanvas();\r
- }\r
-\r
- // revert to a previous image state\r
- function undo(idx) {\r
- var undoImage = undoImages[idx];\r
-\r
- if (!undoImage) \r
- throw new Error(errorDialog("Invalid undo state"));\r
- if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))\r
- throw new Error(errorDialog("$imageCanvas doesn't exist"));\r
-\r
- var canvas = $imageCanvas.get(0);\r
- addUndo(canvas);\r
- canvas.width = imageWidth = undoImage.width;\r
- canvas.height = imageHeight = undoImage.height;\r
- canvas.getContext("2d").drawImage(undoImage,0,0);\r
-\r
- enableTab(activeTabId, true);\r
- resetDisplayCanvas();\r
- }\r
-\r
- function addUndo(canvasElement) {\r
- if (!canvasElement)\r
- throw new Error(errorDialog("No undo image state provided"));\r
-\r
- if (undoImages.length == undoLevels) {\r
- undoImages.shift();\r
- }\r
- var undoCanvas = document.createElement("canvas");\r
- undoCanvas.width = canvasElement.width;\r
- undoCanvas.height = canvasElement.height;\r
- undoCanvas.getContext("2d").drawImage(canvasElement,0,0);\r
- $j(undoCanvas).addClass("undo-canvas");\r
- undoImages.push(undoCanvas);\r
- updateUndoList();\r
- }\r
-\r
- function updateUndoList() {\r
- var $listCtr = $j("#undo-bar", doc)\r
- .html("");\r
-\r
- var ctrHeight = $listCtr.height();\r
-\r
- var $testCanvas = $j("<canvas></canvas>", doc)\r
- .addClass("undo-canvas-small")\r
- .addClass("far-far-away")\r
- .appendTo("body");\r
-\r
- var canvasHeight = $testCanvas.height();\r
- var canvasWidth = $testCanvas.width();\r
- var canvasCSSHeight = canvasHeight + parseInt($testCanvas.css("margin-top"),10) + parseInt($testCanvas.css("margin-bottom"),10);\r
-\r
- $testCanvas.remove();\r
-\r
- var undoRatio = canvasWidth / canvasHeight;\r
-\r
- for (var i=undoImages.length-1;i>=0;i--) {\r
- (function(){\r
- var canvas = document.createElement("canvas");\r
- $j(canvas)\r
- .addClass("undo-canvas-small")\r
- .attr("width", canvasWidth)\r
- .attr("height", canvasHeight);\r
-\r
- var image = undoImages[i];\r
- $j(image).show();\r
- \r
- var undoWidth, undoHeight;\r
- var imageRatio = image.width / image.height;\r
-\r
- if (imageRatio > undoRatio) { // image too wide\r
- undoWidth = canvasWidth;\r
- undoHeight = canvasWidth / imageRatio;\r
- } else {\r
- undoWidth = canvasHeight * imageRatio;\r
- undoHeight = canvasHeight;\r
- }\r
-\r
- var restWidth = canvasWidth - undoWidth;\r
- var restHeight = canvasHeight - undoHeight;\r
-\r
- canvas.getContext("2d").drawImage(\r
- image,\r
- 0,0,image.width,image.height,\r
- restWidth*0.5, restHeight*0.5,\r
- undoWidth, undoHeight\r
- );\r
-\r
-\r
- $link = $j("<a href='#'></a>", doc)\r
- .addClass("undo-link")\r
- .appendTo($listCtr)\r
- .mouseover(function(){ $j(this).addClass("hover") })\r
- .mouseout(function(){ $j(this).removeClass("hover") });\r
- $j(canvas).appendTo($link);\r
-\r
- var displayShowing;\r
- var undoIndex = i;\r
- $link.click(function() {\r
- $j(image).hide();\r
- $j(image).remove();\r
- undo(undoIndex);\r
- if (displayShowing)\r
- $displayCanvas.show();\r
- $j(".jcrop-holder", doc).show();\r
- });\r
-\r
- $link.mouseover(function() {\r
- displayShowing = $displayCanvas.css("display") != "none";\r
- var $imagectr = $j("#image-container", doc);\r
-\r
- $j(".jcrop-holder", doc).hide();\r
- $displayCanvas.hide();\r
- $j(image).appendTo($imagectr);\r
-\r
- var h1 = $j("#image-area", doc).height();\r
- var h2 = image.height;\r
- var m = Math.max(0, (h1 - h2) / 2);\r
- $imagectr.css("marginTop", m);\r
- \r
- $imagectr.height(image.height);\r
- });\r
-\r
- $link.mouseout(function() {\r
- $j(image).remove();\r
- if (displayShowing)\r
- $displayCanvas.show();\r
- $j(".jcrop-holder", doc).show();\r
- updateDisplayCanvas();\r
- });\r
-\r
-\r
- $j(canvas).attr("title", "Click to revert to this previous image");\r
-\r
- })();\r
- }\r
- }\r
-\r
-\r
- function applyAction(id, options, afteraction) {\r
- if (!Pixastic.Actions[id])\r
- throw new Error("applyAction(): unknown action [" + id + "]");\r
-\r
- $j("#action-bar-overlay", doc).show();\r
-\r
- setTimeout(function() {\r
- options.leaveDOM = true;\r
- var canvasElement = $imageCanvas.get(0);\r
- addUndo(canvasElement)\r
- \r
- var res = Pixastic.process(\r
- canvasElement, id, options,\r
- function(resCanvas) {\r
- canvasElement.width = imageWidth = resCanvas.width;\r
- canvasElement.height = imageHeight = resCanvas.height;\r
- \r
- var ctx = canvasElement.getContext("2d");\r
- ctx.clearRect(0,0,imageWidth,imageHeight);\r
- ctx.drawImage(resCanvas,0,0);\r
- $imageCanvas = $j(canvasElement);\r
- resetDisplayCanvas();\r
- \r
- $j("#action-bar-overlay", doc).hide();\r
-\r
- if (afteraction)\r
- afteraction();\r
- }\r
- );\r
- if (!res)\r
- throw new Error("applyAction(): Pixastic.process() failed for action [" + id + "]");\r
- },1);\r
- }\r
-\r
-\r
- function previewAction(id, options, afteraction) {\r
- if (!Pixastic.Actions[id])\r
- throw new Error("applyAction(): unknown action [" + id + "]");\r
-\r
- $j("#action-bar-overlay", doc).show();\r
-\r
- resetDisplayCanvas();\r
-\r
- options.leaveDOM = true;\r
- var canvasElement = $displayCanvas.get(0);\r
-\r
- var res = Pixastic.process(\r
- canvasElement, id, options,\r
- function(resCanvas) {\r
-\r
- canvasElement.width = resCanvas.width;\r
- canvasElement.height = resCanvas.height;\r
-\r
- var ctx = canvasElement.getContext("2d");\r
- ctx.clearRect(0,0,canvasElement.width,canvasElement.height);\r
- ctx.drawImage(resCanvas,0,0);\r
- updateDisplayCanvas();\r
- updateOverlay();\r
-\r
- $j("#action-bar-overlay", doc).hide();\r
-\r
- if (afteraction)\r
- afteraction();\r
- }\r
- );\r
- }\r
-\r
- var onwindowresize = function() {\r
- updateDisplayCanvas();\r
- updateOverlay();\r
- }\r
-\r
- var baseUrl = ""\r
-\r
- function buildEditor() {\r
- var styles = [\r
- "jquery-ui-1.7.1.custom.css",\r
- "jquery.Jcrop.css",\r
- "pixastic.css"\r
- ];\r
-\r
- for (var i=0;i<styles.length;i++) {\r
- var s = doc.createElement("link");\r
- s.href = baseUrl + styles[i];\r
- s.type = "text/css";\r
- s.rel = "stylesheet";\r
- doc.getElementsByTagName("head")[0].appendChild( s );\r
- }\r
-\r
- undoImages = [];\r
- accordionElements = {};\r
- tabElements = {};\r
- activeTabId = -1;\r
- $activeTabContent = null;\r
-\r
- // setup DOM UI skeleton\r
- $editor = $j("<div />", doc)\r
- .attr("id", "pixastic-editor")\r
- .appendTo($j(doc.body));\r
-\r
- $editor.append(\r
- $j("<div id='background' />", doc),\r
- $j("<div id='edit-ctr-1' />", doc).append(\r
- $j("<div id='edit-ctr-2' />", doc).append(\r
- $j("<div id='controls-bar' />", doc).append(\r
- $j("<div id='action-bar' />", doc).append(\r
- $j("<div id='action-bar-overlay' />", doc)\r
- ),\r
- $j("<div id='undo-bar' />", doc)\r
- ),\r
- $j("<div id='image-area' />", doc).append(\r
- $j("<div id='image-area-sub' />", doc).append(\r
- $j("<div id='image-container' />", doc),\r
- $j("<div id='image-overlay-container' />", doc).append(\r
- $j("<div id='image-overlay' />", doc)\r
- )\r
- )\r
- )\r
- )\r
- ),\r
- $j("<div id='main-bar' />", doc),\r
- $j("<div id='powered-by-pixastic'><a href=\"http://www.pixastic.com/\" target=\"_blank\">Powered by Pixastic</a></div>", doc)\r
- );\r
-\r
- $j("#image-container", doc).append(\r
- $displayCanvas = $j("<canvas />", doc)\r
- .addClass("display-canvas")\r
- );\r
-\r
- // loop through all defined UI action controls\r
- var tabs = PixasticEditor.UI.data.tabs;\r
-\r
- for (var i=0;i<tabs.length;i++) {\r
- (function() {\r
- \r
- var tab = tabs[i];\r
-\r
- var $tabElement = $j("<a href=\"#\">" + tab.title + "</a>", doc)\r
- .attr("id", "main-tab-button-" + tab.id)\r
- .addClass("main-tab")\r
- .click(function() {\r
- enableTab(tab.id);\r
- })\r
- .mouseover(function(){ $j(this).addClass("hover") })\r
- .mouseout(function(){ $j(this).removeClass("hover") });\r
- \r
- $j("#main-bar", doc).append($tabElement);\r
-\r
- tabElements[tab.id] = $tabElement;\r
-\r
- var $menu = $j("<div/>", doc);\r
- accordionElements[tab.id] = $menu;\r
-\r
- for (var j=0;j<tab.actions.length;j++) {\r
- (function() {\r
-\r
- var action = tab.actions[j];\r
-\r
- var $actionElement = $j("<div><h3><a href=\"#\">" + action.title + "</a></h3></div>", doc)\r
-\r
- $menu.append($actionElement);\r
-\r
- var $content = $j("<div></div>", doc)\r
- .attr("id", "pixastic-action-tab-content-" + action.id)\r
- .appendTo($actionElement);\r
-\r
- var controlOptions = [];\r
-\r
- action.previewEnabled = false;\r
- if (action.forcePreview)\r
- action.previewEnabled = true;\r
-\r
- function togglePreview(enable, doAction) {\r
- if (enable && !action.previewEnabled && doAction)\r
- doAction(true);\r
- if (!enable && action.previewEnabled)\r
- resetDisplayCanvas();\r
- \r
- action.previewEnabled = enable;\r
- }\r
-\r
- var reset = function() {\r
- for (var i in controlOptions) {\r
- if (controlOptions.hasOwnProperty(i)) {\r
- controlOptions[i].reset();\r
- }\r
- }\r
- if (action.previewEnabled)\r
- doAction(true);\r
- }\r
- var doAction = function(isPreview) {\r
- var options = {};\r
- for (var i in controlOptions) {\r
- if (controlOptions.hasOwnProperty(i)) {\r
- options[i] = controlOptions[i].valueField.val();\r
- }\r
- }\r
-\r
- var afteraction = function() {\r
- if (action.onafteraction)\r
- action.onafteraction(action, isPreview);\r
- if (!isPreview)\r
- resetDisplayCanvas();\r
- \r
- if (!isPreview && !action.forcePreview) {\r
- $j("#pixastic-input-preview-" + action.id, doc).attr("checked", false);\r
- togglePreview(false);\r
- reset();\r
- }\r
- }\r
-\r
- if (isPreview) {\r
- previewAction(action.id, options, afteraction);\r
- } else {\r
- applyAction(action.id, options, afteraction);\r
- }\r
-\r
- }\r
-\r
- var hadInputs = false;\r
-\r
- if (action.controls) {\r
- var onChange = function() {};\r
- if (action.isAction && action.preview) {\r
- onChange = function() {\r
- if (action.previewEnabled)\r
- doAction(true)\r
- };\r
- }\r
-\r
- for (var k=0;k<action.controls.length;k++) {\r
- var control = action.controls[k];\r
- if (typeof control.defaultValue != "function") {\r
- (function(){\r
- var defVal = control.defaultValue;\r
- control.defaultValue = function() {\r
- return defVal;\r
- }\r
- })();\r
- }\r
- var controlId = action.id + "-" + control.option;\r
-\r
- if (control.type != "output")\r
- hadInputs = true;\r
-\r
- switch (control.type) {\r
- case "number" :\r
- switch (control.ui) {\r
- case "slider" : \r
- var slider = PixasticEditor.UI.makeSlider(\r
- control.label, controlId, \r
- control.range[0], control.range[1], control.step, control.defaultValue, onChange\r
- );\r
- \r
- slider.container.appendTo($content);\r
- controlOptions[control.option] = slider;\r
- break;\r
- case "text" : \r
- var text = PixasticEditor.UI.makeNumericInput(\r
- control.label, control.labelRight, controlId, \r
- control.range[0], control.range[1], control.step, control.defaultValue, onChange\r
- );\r
- text.container.appendTo($content);\r
- controlOptions[control.option] = text;\r
- break;\r
- }\r
- break;\r
- case "boolean" :\r
- switch (control.ui) {\r
- case "checkbox" : \r
- var checkbox = PixasticEditor.UI.makeCheckbox(\r
- control.label, controlId, control.defaultValue, onChange\r
- );\r
- \r
- checkbox.container.appendTo($content);\r
- controlOptions[control.option] = checkbox;\r
- break;\r
- }\r
- case "string" :\r
- switch (control.ui) {\r
- case "select" : \r
- var select = PixasticEditor.UI.makeSelect(\r
- control.label, controlId, control.values, control.defaultValue, onChange\r
- );\r
- \r
- select.container.appendTo($content);\r
- controlOptions[control.option] = select;\r
- break;\r
- }\r
- break;\r
- case "output" :\r
- var outputText = $j("<div></div>", doc)\r
- .addClass("ui-action-output")\r
- .html(control.content)\r
- .appendTo($content);\r
- break;\r
- }\r
- }\r
- }\r
-\r
- if (action.isAction) {\r
-\r
- var $applyButton = PixasticEditor.UI.makeButton("Apply")\r
- .addClass("pixastic-option-button-apply")\r
- .click(function() {doAction();});\r
-\r
- $content.append($applyButton);\r
-\r
- if (hadInputs) {\r
- var $resetButton = PixasticEditor.UI.makeButton("Reset")\r
- .addClass("pixastic-option-button-reset")\r
- .click(reset);\r
- \r
- $content.append($resetButton)\r
- }\r
-\r
- if (action.preview && !action.forcePreview) {\r
- var $checkctr = $j("<div></div>", doc)\r
- .addClass("ui-checkbox-container")\r
- .addClass("ui-preview-checkbox-container");\r
-\r
- var $label = $j("<label></label>", doc)\r
- .addClass("ui-checkbox-label")\r
- .attr("for", "pixastic-input-preview-" + action.id)\r
- .html("Preview:")\r
- .appendTo($checkctr);\r
-\r
- var $checkbox = $j("<input type=\"checkbox\"></input>", doc)\r
- .addClass("ui-checkbox")\r
- .attr("id", "pixastic-input-preview-" + action.id)\r
- .appendTo($checkctr)\r
- .change(function() {\r
- togglePreview(this.checked, doAction)\r
- });\r
-\r
- $content.append($checkctr);\r
-\r
- $content.data("previewCheckbox", $checkbox);\r
- }\r
-\r
- }\r
-\r
-\r
- if (typeof action.content == "function") {\r
- action.content($content);\r
- }\r
-\r
- // stupid hack to make it possible to get $content in change event (below)\r
- $j("<span></span>", doc).appendTo($content);\r
-\r
- $content.data("controlOptions", controlOptions);\r
- $content.data("onactivate", action.onactivate);\r
- $content.data("ondeactivate", action.ondeactivate);\r
- $content.data("onoverlayupdate", action.onoverlayupdate);\r
- $content.data("accordionindex", j);\r
- $content.data("uidesc", action);\r
-\r
- })();\r
- }\r
- \r
- $j("#action-bar", doc).append($menu);\r
-\r
- $menu.hide().accordion({\r
- header: "h3",\r
- autoHeight : false,\r
- collapsible : true,\r
- active: -1\r
- })\r
- .bind("accordionchange", \r
- function(event, ui) {\r
- resetDisplayCanvas();\r
-\r
- // oldContent / newContent are arrays of whatever elements are present in the content area\r
- // We need the parent element (the one holding the content) but if there is no content, how do we get it?\r
- // fixed above by always appending a <span> but that's ugly and needs to be done in some other way\r
- if (ui.oldContent.get(0)) {\r
- var $parent = $j(ui.oldContent.get(0).parentNode);\r
- if ($parent.data("ondeactivate")) {\r
- $parent.data("ondeactivate")();\r
- }\r
- }\r
- $activeTabContent = ui.newContent;\r
-\r
- if (ui.newContent.get(0)) {\r
- var $parent = $j(ui.newContent.get(0).parentNode);\r
- if ($parent.data("previewCheckbox"))\r
- $parent.data("previewCheckbox").attr("checked", false);\r
- $parent.data("uidesc").previewEnabled = false;\r
- if ($parent.data("uidesc").forcePreview)\r
- $parent.data("uidesc").previewEnabled = true;\r
-\r
- var controlOptions = $parent.data("controlOptions");\r
- for (var i in controlOptions) {\r
- if (controlOptions.hasOwnProperty(i)) {\r
- controlOptions[i].reset();\r
- }\r
- }\r
- if ($parent.data("onactivate")) {\r
- $parent.data("onactivate")();\r
- }\r
- }\r
- updateDisplayCanvas();\r
-\r
- }\r
- );\r
-\r
- \r
- })();\r
- }\r
-\r
- $j(window).bind("resize", onwindowresize);\r
- }\r
-\r
- function showLoadingScreen() {\r
- if ($loadingScreen) {\r
- $loadingScreen.show();\r
- return;\r
- }\r
- $loadingScreen = $j("<div id=\"loading-screen\" />")\r
- var $ctr = $j("<div id=\"loading-screen-cell\" />");\r
- $j("<div />")\r
- .addClass("spinner")\r
- .appendTo($ctr);\r
- $loadingScreen.append($ctr);\r
- $loadingScreen.appendTo("body");\r
- }\r
-\r
- function hideLoadingScreen() {\r
- setTimeout(function() {\r
- $loadingScreen.hide();\r
- }, 1);\r
- }\r
-\r
- var oldScrollLeft;\r
- var oldScrollTop;\r
- var oldOverflow;\r
-\r
- // fire it up\r
- function init(callback) {\r
- isRunning = true;\r
-\r
- showLoadingScreen();\r
-\r
- oldScrollLeft = document.body.scrollLeft;\r
- oldScrollTop = document.body.scrollTop;\r
- oldOverflow = document.body.style.overflow;\r
-\r
- document.body.scrollLeft = 0;\r
- document.body.scrollTop = 0;\r
- document.body.style.overflow = "hidden";\r
-\r
- $frame = $j("<iframe />");\r
- $frame.hide();\r
- $frame.css({\r
- position : "absolute",\r
- left : document.body.scrollLeft + "px",\r
- top : document.body.scrollTop + "px",\r
- width : "100%",\r
- height : "100%",\r
- zIndex : "11"\r
- });\r
- $frame.load(function(){\r
- doc = $frame.get(0).contentDocument;\r
-\r
- buildEditor();\r
- callback();\r
- $frame.show();\r
- hideLoadingScreen();\r
- setTimeout(function(){\r
- updateDisplayCanvas();\r
- },10);\r
- });\r
- $frame.appendTo("body");\r
- }\r
-\r
- // unload the editor, remove all elements added to the page and restore whatever properties we messed with\r
- function unload() {\r
- $j(window).unbind("resize", onwindowresize);\r
- $frame.hide();\r
- $editor.hide();\r
- $editor.remove();\r
- $frame.remove();\r
-\r
- document.body.scrollLeft = oldScrollLeft;\r
- document.body.scrollTop = oldScrollTop;\r
- document.body.style.overflow = oldOverflow;\r
-\r
- isRunning = false;\r
- }\r
-\r
-\r
- // resets the display canvas (clears the canvas and repaints the current state)\r
- // then updates display and overlay\r
- function resetDisplayCanvas() {\r
- if (!($displayCanvas && $displayCanvas.get)) throw new Error(errorDialog("$displayCanvas doesn't exist"));\r
- if (!($imageCanvas && $imageCanvas.get)) throw new Error(errorDialog("$imageCanvas doesn't exist"));\r
-\r
- var display = $displayCanvas.get(0);\r
- var image = $imageCanvas.get(0);\r
-\r
- if (!display) throw new Error(errorDialog("resetDisplayCanvas(): No elements in $displayCanvas"));\r
- if (!image) throw new Error(errorDialog("resetDisplayCanvas(): No elements in $imageCanvas"));\r
-\r
- display.width = imageWidth;\r
- display.height = imageHeight;\r
- display.getContext("2d").drawImage( image, 0, 0 );\r
-\r
- updateDisplayCanvas();\r
- updateOverlay();\r
- }\r
-\r
- // updates the display by resetting the height and margin of the image container\r
- // this is mainly to keep vertical centering\r
- function updateDisplayCanvas() {\r
- var $imageCtr = $j("#image-container", doc);\r
- var $editArea = $j("#image-area", doc);\r
-\r
- if (!$imageCtr.get(0)) throw new Error(errorDialog("updateDisplayCanvas(): $imageCtr doesn't exist"));\r
- if (!$displayCanvas.get(0)) throw new Error(errorDialog("updateDisplayCanvas(): $displayCanvas doesn't exist"));\r
- if (!$editArea.get(0)) throw new Error(errorDialog("updateDisplayCanvas(): $editArea doesn't exist"));\r
-\r
- var h2 = $displayCanvas.get(0).height;\r
- var h1 = $j("#image-area", doc).height();\r
- var m = Math.max(0, (h1 - h2) / 2);\r
- $imageCtr.height(h2);\r
- $imageCtr.css("marginTop", m);\r
- }\r
-\r
- // basically the same as updateDisplayCanvas but for the image overlay\r
- function updateOverlay() {\r
- var $overlay = $j("#image-overlay-container", doc);\r
- var $imagectr = $j("#image-container", doc);\r
- $overlay.height($imagectr.height());\r
- $overlay.css("marginTop", $imagectr.css("marginTop"));\r
-\r
- if ($activeTabContent && $activeTabContent.get(0)) {\r
- var $tabContent = $j($activeTabContent.get(0).parentNode);\r
- if (typeof $tabContent.data("onoverlayupdate") == "function")\r
- $tabContent.data("onoverlayupdate")();\r
- }\r
- }\r
-\r
- var imageIsLoading = false;\r
- var originalImageElement;\r
- var $tmpImg;\r
-\r
- function loadImage(imgEl) {\r
- if (imageIsLoading) \r
- return;\r
-\r
- imageIsLoading = true;\r
-\r
- originalImageElement = imgEl;\r
-\r
- $imageCanvas = $j("<canvas />", doc);\r
- imageCtx = $imageCanvas.get(0).getContext("2d");\r
-\r
- imageWidth = 0;\r
- imageHeight = 0;\r
- $imageCanvas.attr("width", 0);\r
- $imageCanvas.attr("height", 0);\r
-\r
- if (imgEl.tagName.toLowerCase() == "img" && !imgEl._pixasticCanvas) {\r
- var onload = function(el) {\r
- imageWidth = el.offsetWidth;\r
- imageHeight = el.offsetHeight;\r
- $imageCanvas.attr("width", imageWidth);\r
- $imageCanvas.attr("height", imageHeight);\r
- imageCtx.drawImage(el,0,0);\r
- $tmpImg.remove();\r
- imageIsLoading = false;\r
- enableTab("reshape");\r
- setTimeout(function() {\r
- resetDisplayCanvas();\r
- }, 10);\r
- }\r
- $tmpImg = $j("<img />", doc)\r
- .css("position", "absolute")\r
- .css("left", "-9999px")\r
- .css("top", "-9999px")\r
- .appendTo("body")\r
- .load(function(){onload(this);})\r
- .error(function(){\r
- throw new Error("Could not load temporary copy image. Is provided image valid?");\r
- unload();\r
- })\r
- .attr("src", imgEl.src);\r
- if ($tmpImg.attr("complete")) {\r
- onload($tmpImg.get(0));\r
- }\r
- } else {\r
- var $canvas = imgEl._pixasticCanvas || imgEl;\r
- imageWidth = $canvas.attr("width");\r
- imageHeight = $canvas.attr("height");\r
- $imageCanvas.attr("width", imageWidth);\r
- $imageCanvas.attr("height", imageHeight);\r
- imageCtx.drawImage($canvas.get(0), 0, 0);\r
- imageIsLoading = false;\r
- enableTab("reshape");\r
- resetDisplayCanvas();\r
- }\r
- }\r
-\r
- // return public interface\r
- return {\r
- /*\r
- // don't call. For now we must load the image immediately via load()\r
- loadImage : function(imgEl) {\r
- if (!isRunning) return false;\r
- loadImage(imgEl);\r
- },\r
- */\r
- saveToPage : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::saveToPage(): Editor is not running");\r
-\r
- var $canvas = PixasticEditor.getImageCanvas();\r
- var img = PixasticEditor.getOriginalImage();\r
- if (img.tagName.toLowerCase() == "canvas") {\r
- img.width = $canvas.attr("width");\r
- img.height = $canvas.attr("height");\r
- img.getContext("2d").drawImage($canvas.get(0), 0, 0);\r
- } else {\r
- img.src = PixasticEditor.getDataURI();\r
- }\r
- img._pixasticCanvas = PixasticEditor.getImageCanvas();\r
- },\r
- load : function(img, customBaseUrl) {\r
- if (isRunning) return false;\r
-\r
- if (!img)\r
- throw new Error("Must be called with an image or canvas as its first argument", "PixasticEditor::load")\r
-\r
- $ = PixasticEditor.jQuery;\r
-\r
- baseUrl = customBaseUrl || "http://www.pixastic.com/editor-test/";\r
-\r
- init(function() {\r
- if (img && img.tagName.toLowerCase() == "img" || img.tagName.toLowerCase() == "canvas") {\r
- loadImage(img);\r
- }\r
- });\r
- },\r
-\r
- unload : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::unload(): Editor is not running");\r
- unload();\r
- },\r
-\r
- getDocument : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::getDocument(): Editor is not running");\r
-\r
- return doc;\r
- },\r
-\r
- validSaveFormats : function() {\r
- return saveFormats;\r
- },\r
-\r
- getOriginalImage : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::getOriginalImage(): Editor is not running");\r
- return originalImageElement;\r
- },\r
-\r
- getDataURI : function(mime) {\r
- if (!isRunning) throw new Error("PixasticEditor::getDataURI(): Editor is not running");\r
-\r
- if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))\r
- throw new Error(errorDialog("$imageCanvas doesn't exist", "getImageCanvas"));\r
-\r
- return $imageCanvas.get(0).toDataURL(mime||"image/png");\r
- },\r
-\r
- getImageCanvas : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::getImageCanvas(): Editor is not running");\r
-\r
- if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))\r
- throw new Error(errorDialog("$imageCanvas doesn't exist", "getImageCanvas"));\r
-\r
- return $imageCanvas;\r
- },\r
- getOverlay : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::getOverlay(): Editor is not running");\r
-\r
- return $j("#image-overlay", doc);\r
- },\r
- getDisplayCanvas : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::getDisplayCanvas(): Editor is not running");\r
-\r
- if (!($displayCanvas && $displayCanvas.get && $displayCanvas.get(0)))\r
- throw new Error(errorDialog("$displayCanvas doesn't exist", "getDisplayCanvas"));\r
- return $displayCanvas;\r
- },\r
- getDisplayWidth : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::getDisplayWidth(): Editor is not running");\r
-\r
- return displayWidth;\r
- },\r
- getDisplayHeight : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::getDisplayHeight(): Editor is not running");\r
-\r
- return displayHeight;\r
- },\r
- getImageWidth : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::getImageWidth(): Editor is not running");\r
-\r
- return imageWidth;\r
- },\r
- getImageHeight : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::getImageHeight(): Editor is not running");\r
-\r
- return imageHeight;\r
- },\r
- errorDialog : function() {\r
- if (!isRunning) throw new Error("PixasticEditor::errorDialog(): Editor is not running");\r
-\r
- return errorDialog.apply(null, arguments);\r
- }\r
- }\r
-\r
+
+var PixasticEditor = (function () {
+
+ var $frame; // iframe container element
+ var $editor; // editor container element
+
+ // various UI structures
+ var accordionElements = {};
+ var tabElements = {};
+ var activeTabId;
+ var $activeTabContent;
+
+ var isRunning = false;
+
+ var $loadingScreen;
+
+ var $imageCanvas; // the canvas holding the current state of the image
+ var $displayCanvas; // the canvas element displayed on the screen, also the working canvas (where preview operations are performed)
+ var imageCtx;
+
+ var imageWidth = 0; // dimensions of the current image state
+ var imageHeight = 0;
+
+ var undoImages = []; // canvas elements holding previous image states
+ var undoLevels = 10;
+
+ var doc;
+
+ var $;
+
+ // test for valid file formats for toDataURL()
+ // we do that by calling it with each of the mime types in testFormats
+ // and then doing string checking on the resulting data: URI to see if it succeeded
+ var saveFormats = [];
+ var testFormats = [["image/jpeg", "JPEG"], ["image/png", "PNG"]];
+ var testCanvas = document.createElement("canvas");
+ if (testCanvas.toDataURL) {
+ testCanvas.width = testCanvas.height = 1;
+ for (var i=0;i<testFormats.length;i++) {
+ var data = testCanvas.toDataURL(testFormats[i][0]);
+ if (data.substr(0, 5 + testFormats[i][0].length) == "data:" + testFormats[i][0])
+ saveFormats.push({mime:testFormats[i][0], name:testFormats[i][1]});
+ }
+ }
+
+
+ // pops up an error dialog with the specified text (errTxt),
+ // if no context is provided, the name of the calling function is used.
+ // The final message is returned for easy throwing of actual errors
+ function errorDialog(errTxt, context) {
+ if (!($editor && $editor.get && $editor.get(0)))
+ throw new Error("errorDialog(): $editor doesn't exist");
+
+ var caller = errorDialog.caller.toString().split(" ")[1];
+ caller = caller.substring(0, caller.indexOf("("));
+ context = context || caller;
+ errTxt = context + "(): " + errTxt;
+ var dialog = $j("<div></div>", doc)
+ .addClass("error-dialog")
+ .attr("title", "Oops!")
+ .html(errTxt)
+ .dialog();
+ // the dialog is added outside the Pixastic container, so get it back in.
+ var dialogParent = $j(dialog.get(0).parentNode);
+ dialogParent.appendTo($editor);
+
+ return errTxt;
+ }
+
+ function enableTab(id, refresh) {
+ if (id == activeTabId && !refresh)
+ return;
+
+ activeTabId = id;
+
+ var activeIndex = 0;
+
+ if ($activeTabContent) {
+ if ($activeTabContent.get(0)) {
+ var $parent = $j($activeTabContent.get(0).parentNode);
+ activeIndex = $parent.data("accordionindex");
+ if ($parent.data("ondeactivate")) {
+ $parent.data("ondeactivate")();
+ }
+ if ($parent.data("previewCheckbox"))
+ $parent.data("previewCheckbox").attr("checked", false);
+ $parent.data("uidesc").previewEnabled = false;
+ if ($parent.data("uidesc").forcePreview)
+ $parent.data("uidesc").previewEnabled = true;
+ }
+ }
+
+
+ for (var a in accordionElements) {
+ if (accordionElements.hasOwnProperty(a)) {
+ accordionElements[a].accordion("option", "animated", false);
+ accordionElements[a].accordion("activate", -1);
+ accordionElements[a].hide();
+ tabElements[a].removeClass("active");
+
+ }
+ }
+
+ accordionElements[id].accordion("option", "animated", false);
+ accordionElements[id].accordion("activate", refresh ? activeIndex : 0);
+ tabElements[id].addClass("active");
+ accordionElements[id].show();
+ accordionElements[id].accordion("option", "animated", "slide");
+ resetDisplayCanvas();
+ }
+
+ // revert to a previous image state
+ function undo(idx) {
+ var undoImage = undoImages[idx];
+
+ if (!undoImage)
+ throw new Error(errorDialog("Invalid undo state"));
+ if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))
+ throw new Error(errorDialog("$imageCanvas doesn't exist"));
+
+ var canvas = $imageCanvas.get(0);
+ addUndo(canvas);
+ canvas.width = imageWidth = undoImage.width;
+ canvas.height = imageHeight = undoImage.height;
+ canvas.getContext("2d").drawImage(undoImage,0,0);
+
+ enableTab(activeTabId, true);
+ resetDisplayCanvas();
+ }
+
+ function addUndo(canvasElement) {
+ if (!canvasElement)
+ throw new Error(errorDialog("No undo image state provided"));
+
+ if (undoImages.length == undoLevels) {
+ undoImages.shift();
+ }
+ var undoCanvas = document.createElement("canvas");
+ undoCanvas.width = canvasElement.width;
+ undoCanvas.height = canvasElement.height;
+ undoCanvas.getContext("2d").drawImage(canvasElement,0,0);
+ $j(undoCanvas).addClass("undo-canvas");
+ undoImages.push(undoCanvas);
+ updateUndoList();
+ }
+
+ function updateUndoList() {
+ var $listCtr = $j("#undo-bar", doc)
+ .html("");
+
+ var ctrHeight = $listCtr.height();
+
+ var $testCanvas = $j("<canvas></canvas>", doc)
+ .addClass("undo-canvas-small")
+ .addClass("far-far-away")
+ .appendTo("body");
+
+ var canvasHeight = $testCanvas.height();
+ var canvasWidth = $testCanvas.width();
+ var canvasCSSHeight = canvasHeight + parseInt($testCanvas.css("margin-top"),10) + parseInt($testCanvas.css("margin-bottom"),10);
+
+ $testCanvas.remove();
+
+ var undoRatio = canvasWidth / canvasHeight;
+
+ for (var i=undoImages.length-1;i>=0;i--) {
+ (function(){
+ var canvas = document.createElement("canvas");
+ $j(canvas)
+ .addClass("undo-canvas-small")
+ .attr("width", canvasWidth)
+ .attr("height", canvasHeight);
+
+ var image = undoImages[i];
+ $j(image).show();
+
+ var undoWidth, undoHeight;
+ var imageRatio = image.width / image.height;
+
+ if (imageRatio > undoRatio) { // image too wide
+ undoWidth = canvasWidth;
+ undoHeight = canvasWidth / imageRatio;
+ } else {
+ undoWidth = canvasHeight * imageRatio;
+ undoHeight = canvasHeight;
+ }
+
+ var restWidth = canvasWidth - undoWidth;
+ var restHeight = canvasHeight - undoHeight;
+
+ canvas.getContext("2d").drawImage(
+ image,
+ 0,0,image.width,image.height,
+ restWidth*0.5, restHeight*0.5,
+ undoWidth, undoHeight
+ );
+
+
+ $link = $j("<a href='#'></a>", doc)
+ .addClass("undo-link")
+ .appendTo($listCtr)
+ .mouseover(function(){ $j(this).addClass("hover") })
+ .mouseout(function(){ $j(this).removeClass("hover") });
+ $j(canvas).appendTo($link);
+
+ var displayShowing;
+ var undoIndex = i;
+ $link.click(function() {
+ $j(image).hide();
+ $j(image).remove();
+ undo(undoIndex);
+ if (displayShowing)
+ $displayCanvas.show();
+ $j(".jcrop-holder", doc).show();
+ });
+
+ $link.mouseover(function() {
+ displayShowing = $displayCanvas.css("display") != "none";
+ var $imagectr = $j("#image-container", doc);
+
+ $j(".jcrop-holder", doc).hide();
+ $displayCanvas.hide();
+ $j(image).appendTo($imagectr);
+
+ var h1 = $j("#image-area", doc).height();
+ var h2 = image.height;
+ var m = Math.max(0, (h1 - h2) / 2);
+ $imagectr.css("marginTop", m);
+
+ $imagectr.height(image.height);
+ });
+
+ $link.mouseout(function() {
+ $j(image).remove();
+ if (displayShowing)
+ $displayCanvas.show();
+ $j(".jcrop-holder", doc).show();
+ updateDisplayCanvas();
+ });
+
+
+ $j(canvas).attr("title", "Click to revert to this previous image");
+
+ })();
+ }
+ }
+
+
+ function applyAction(id, options, afteraction) {
+ if (!Pixastic.Actions[id])
+ throw new Error("applyAction(): unknown action [" + id + "]");
+
+ $j("#action-bar-overlay", doc).show();
+
+ setTimeout(function() {
+ options.leaveDOM = true;
+ var canvasElement = $imageCanvas.get(0);
+ addUndo(canvasElement)
+
+ var res = Pixastic.process(
+ canvasElement, id, options,
+ function(resCanvas) {
+ canvasElement.width = imageWidth = resCanvas.width;
+ canvasElement.height = imageHeight = resCanvas.height;
+
+ var ctx = canvasElement.getContext("2d");
+ ctx.clearRect(0,0,imageWidth,imageHeight);
+ ctx.drawImage(resCanvas,0,0);
+ $imageCanvas = $j(canvasElement);
+ resetDisplayCanvas();
+
+ $j("#action-bar-overlay", doc).hide();
+
+ if (afteraction)
+ afteraction();
+ }
+ );
+ if (!res)
+ throw new Error("applyAction(): Pixastic.process() failed for action [" + id + "]");
+ },1);
+ }
+
+
+ function previewAction(id, options, afteraction) {
+ if (!Pixastic.Actions[id])
+ throw new Error("applyAction(): unknown action [" + id + "]");
+
+ $j("#action-bar-overlay", doc).show();
+
+ resetDisplayCanvas();
+
+ options.leaveDOM = true;
+ var canvasElement = $displayCanvas.get(0);
+
+ var res = Pixastic.process(
+ canvasElement, id, options,
+ function(resCanvas) {
+
+ canvasElement.width = resCanvas.width;
+ canvasElement.height = resCanvas.height;
+
+ var ctx = canvasElement.getContext("2d");
+ ctx.clearRect(0,0,canvasElement.width,canvasElement.height);
+ ctx.drawImage(resCanvas,0,0);
+ updateDisplayCanvas();
+ updateOverlay();
+
+ $j("#action-bar-overlay", doc).hide();
+
+ if (afteraction)
+ afteraction();
+ }
+ );
+ }
+
+ var onwindowresize = function() {
+ updateDisplayCanvas();
+ updateOverlay();
+ }
+
+ var baseUrl = ""
+
+ function buildEditor() {
+ var styles = [
+ "jquery-ui-1.7.1.custom.css",
+ "jquery.Jcrop.css",
+ "pixastic.css"
+ ];
+
+ for (var i=0;i<styles.length;i++) {
+ var s = doc.createElement("link");
+ s.href = baseUrl + styles[i];
+ s.type = "text/css";
+ s.rel = "stylesheet";
+ doc.getElementsByTagName("head")[0].appendChild( s );
+ }
+
+ undoImages = [];
+ accordionElements = {};
+ tabElements = {};
+ activeTabId = -1;
+ $activeTabContent = null;
+
+ // setup DOM UI skeleton
+ $editor = $j("<div />", doc)
+ .attr("id", "pixastic-editor")
+ .appendTo($j(doc.body));
+
+ $editor.append(
+ $j("<div id='background' />", doc),
+ $j("<div id='edit-ctr-1' />", doc).append(
+ $j("<div id='edit-ctr-2' />", doc).append(
+ $j("<div id='controls-bar' />", doc).append(
+ $j("<div id='action-bar' />", doc).append(
+ $j("<div id='action-bar-overlay' />", doc)
+ ),
+ $j("<div id='undo-bar' />", doc)
+ ),
+ $j("<div id='image-area' />", doc).append(
+ $j("<div id='image-area-sub' />", doc).append(
+ $j("<div id='image-container' />", doc),
+ $j("<div id='image-overlay-container' />", doc).append(
+ $j("<div id='image-overlay' />", doc)
+ )
+ )
+ )
+ )
+ ),
+ $j("<div id='main-bar' />", doc),
+ $j("<div id='powered-by-pixastic'><a href=\"http://www.pixastic.com/\" target=\"_blank\">Powered by Pixastic</a></div>", doc)
+ );
+
+ $j("#image-container", doc).append(
+ $displayCanvas = $j("<canvas />", doc)
+ .addClass("display-canvas")
+ );
+
+ // loop through all defined UI action controls
+ var tabs = PixasticEditor.UI.data.tabs;
+
+ for (var i=0;i<tabs.length;i++) {
+ (function() {
+
+ var tab = tabs[i];
+
+ var $tabElement = $j("<a href=\"#\">" + tab.title + "</a>", doc)
+ .attr("id", "main-tab-button-" + tab.id)
+ .addClass("main-tab")
+ .click(function() {
+ enableTab(tab.id);
+ })
+ .mouseover(function(){ $j(this).addClass("hover") })
+ .mouseout(function(){ $j(this).removeClass("hover") });
+
+ $j("#main-bar", doc).append($tabElement);
+
+ tabElements[tab.id] = $tabElement;
+
+ var $menu = $j("<div/>", doc);
+ accordionElements[tab.id] = $menu;
+
+ for (var j=0;j<tab.actions.length;j++) {
+ (function() {
+
+ var action = tab.actions[j];
+
+ var $actionElement = $j("<div><h3><a href=\"#\">" + action.title + "</a></h3></div>", doc)
+
+ $menu.append($actionElement);
+
+ var $content = $j("<div></div>", doc)
+ .attr("id", "pixastic-action-tab-content-" + action.id)
+ .appendTo($actionElement);
+
+ var controlOptions = [];
+
+ action.previewEnabled = false;
+ if (action.forcePreview)
+ action.previewEnabled = true;
+
+ function togglePreview(enable, doAction) {
+ if (enable && !action.previewEnabled && doAction)
+ doAction(true);
+ if (!enable && action.previewEnabled)
+ resetDisplayCanvas();
+
+ action.previewEnabled = enable;
+ }
+
+ var reset = function() {
+ for (var i in controlOptions) {
+ if (controlOptions.hasOwnProperty(i)) {
+ controlOptions[i].reset();
+ }
+ }
+ if (action.previewEnabled)
+ doAction(true);
+ }
+ var doAction = function(isPreview) {
+ var options = {};
+ for (var i in controlOptions) {
+ if (controlOptions.hasOwnProperty(i)) {
+ options[i] = controlOptions[i].valueField.val();
+ }
+ }
+
+ var afteraction = function() {
+ if (action.onafteraction)
+ action.onafteraction(action, isPreview);
+ if (!isPreview)
+ resetDisplayCanvas();
+
+ if (!isPreview && !action.forcePreview) {
+ $j("#pixastic-input-preview-" + action.id, doc).attr("checked", false);
+ togglePreview(false);
+ reset();
+ }
+ }
+
+ if (isPreview) {
+ previewAction(action.id, options, afteraction);
+ } else {
+ applyAction(action.id, options, afteraction);
+ }
+
+ }
+
+ var hadInputs = false;
+
+ if (action.controls) {
+ var onChange = function() {};
+ if (action.isAction && action.preview) {
+ onChange = function() {
+ if (action.previewEnabled)
+ doAction(true)
+ };
+ }
+
+ for (var k=0;k<action.controls.length;k++) {
+ var control = action.controls[k];
+ if (typeof control.defaultValue != "function") {
+ (function(){
+ var defVal = control.defaultValue;
+ control.defaultValue = function() {
+ return defVal;
+ }
+ })();
+ }
+ var controlId = action.id + "-" + control.option;
+
+ if (control.type != "output")
+ hadInputs = true;
+
+ switch (control.type) {
+ case "number" :
+ switch (control.ui) {
+ case "slider" :
+ var slider = PixasticEditor.UI.makeSlider(
+ control.label, controlId,
+ control.range[0], control.range[1], control.step, control.defaultValue, onChange
+ );
+
+ slider.container.appendTo($content);
+ controlOptions[control.option] = slider;
+ break;
+ case "text" :
+ var text = PixasticEditor.UI.makeNumericInput(
+ control.label, control.labelRight, controlId,
+ control.range[0], control.range[1], control.step, control.defaultValue, onChange
+ );
+ text.container.appendTo($content);
+ controlOptions[control.option] = text;
+ break;
+ }
+ break;
+ case "boolean" :
+ switch (control.ui) {
+ case "checkbox" :
+ var checkbox = PixasticEditor.UI.makeCheckbox(
+ control.label, controlId, control.defaultValue, onChange
+ );
+
+ checkbox.container.appendTo($content);
+ controlOptions[control.option] = checkbox;
+ break;
+ }
+ case "string" :
+ switch (control.ui) {
+ case "select" :
+ var select = PixasticEditor.UI.makeSelect(
+ control.label, controlId, control.values, control.defaultValue, onChange
+ );
+
+ select.container.appendTo($content);
+ controlOptions[control.option] = select;
+ break;
+ }
+ break;
+ case "output" :
+ var outputText = $j("<div></div>", doc)
+ .addClass("ui-action-output")
+ .html(control.content)
+ .appendTo($content);
+ break;
+ }
+ }
+ }
+
+ if (action.isAction) {
+
+ var $applyButton = PixasticEditor.UI.makeButton("Apply")
+ .addClass("pixastic-option-button-apply")
+ .click(function() {doAction();});
+
+ $content.append($applyButton);
+
+ if (hadInputs) {
+ var $resetButton = PixasticEditor.UI.makeButton("Reset")
+ .addClass("pixastic-option-button-reset")
+ .click(reset);
+
+ $content.append($resetButton)
+ }
+
+ if (action.preview && !action.forcePreview) {
+ var $checkctr = $j("<div></div>", doc)
+ .addClass("ui-checkbox-container")
+ .addClass("ui-preview-checkbox-container");
+
+ var $label = $j("<label></label>", doc)
+ .addClass("ui-checkbox-label")
+ .attr("for", "pixastic-input-preview-" + action.id)
+ .html("Preview:")
+ .appendTo($checkctr);
+
+ var $checkbox = $j("<input type=\"checkbox\"></input>", doc)
+ .addClass("ui-checkbox")
+ .attr("id", "pixastic-input-preview-" + action.id)
+ .appendTo($checkctr)
+ .change(function() {
+ togglePreview(this.checked, doAction)
+ });
+
+ $content.append($checkctr);
+
+ $content.data("previewCheckbox", $checkbox);
+ }
+
+ }
+
+
+ if (typeof action.content == "function") {
+ action.content($content);
+ }
+
+ // stupid hack to make it possible to get $content in change event (below)
+ $j("<span></span>", doc).appendTo($content);
+
+ $content.data("controlOptions", controlOptions);
+ $content.data("onactivate", action.onactivate);
+ $content.data("ondeactivate", action.ondeactivate);
+ $content.data("onoverlayupdate", action.onoverlayupdate);
+ $content.data("accordionindex", j);
+ $content.data("uidesc", action);
+
+ })();
+ }
+
+ $j("#action-bar", doc).append($menu);
+
+ $menu.hide().accordion({
+ header: "h3",
+ autoHeight : false,
+ collapsible : true,
+ active: -1
+ })
+ .bind("accordionchange",
+ function(event, ui) {
+ resetDisplayCanvas();
+
+ // oldContent / newContent are arrays of whatever elements are present in the content area
+ // We need the parent element (the one holding the content) but if there is no content, how do we get it?
+ // fixed above by always appending a <span> but that's ugly and needs to be done in some other way
+ if (ui.oldContent.get(0)) {
+ var $parent = $j(ui.oldContent.get(0).parentNode);
+ if ($parent.data("ondeactivate")) {
+ $parent.data("ondeactivate")();
+ }
+ }
+ $activeTabContent = ui.newContent;
+
+ if (ui.newContent.get(0)) {
+ var $parent = $j(ui.newContent.get(0).parentNode);
+ if ($parent.data("previewCheckbox"))
+ $parent.data("previewCheckbox").attr("checked", false);
+ $parent.data("uidesc").previewEnabled = false;
+ if ($parent.data("uidesc").forcePreview)
+ $parent.data("uidesc").previewEnabled = true;
+
+ var controlOptions = $parent.data("controlOptions");
+ for (var i in controlOptions) {
+ if (controlOptions.hasOwnProperty(i)) {
+ controlOptions[i].reset();
+ }
+ }
+ if ($parent.data("onactivate")) {
+ $parent.data("onactivate")();
+ }
+ }
+ updateDisplayCanvas();
+
+ }
+ );
+
+
+ })();
+ }
+
+ $j(window).bind("resize", onwindowresize);
+ }
+
+ function showLoadingScreen() {
+ if ($loadingScreen) {
+ $loadingScreen.show();
+ return;
+ }
+ $loadingScreen = $j("<div id=\"loading-screen\" />")
+ var $ctr = $j("<div id=\"loading-screen-cell\" />");
+ $j("<div />")
+ .addClass("spinner")
+ .appendTo($ctr);
+ $loadingScreen.append($ctr);
+ $loadingScreen.appendTo("body");
+ }
+
+ function hideLoadingScreen() {
+ setTimeout(function() {
+ $loadingScreen.hide();
+ }, 1);
+ }
+
+ var oldScrollLeft;
+ var oldScrollTop;
+ var oldOverflow;
+
+ // fire it up
+ function init(callback) {
+ isRunning = true;
+
+ showLoadingScreen();
+
+ oldScrollLeft = document.body.scrollLeft;
+ oldScrollTop = document.body.scrollTop;
+ oldOverflow = document.body.style.overflow;
+
+ document.body.scrollLeft = 0;
+ document.body.scrollTop = 0;
+ document.body.style.overflow = "hidden";
+
+ $frame = $j("<iframe />");
+ $frame.hide();
+ $frame.css({
+ position : "absolute",
+ left : document.body.scrollLeft + "px",
+ top : document.body.scrollTop + "px",
+ width : "100%",
+ height : "100%",
+ zIndex : "11"
+ });
+ $frame.load(function(){
+ doc = $frame.get(0).contentDocument;
+
+ buildEditor();
+ callback();
+ $frame.show();
+ hideLoadingScreen();
+ setTimeout(function(){
+ updateDisplayCanvas();
+ },10);
+ });
+ $frame.appendTo("body");
+ }
+
+ // unload the editor, remove all elements added to the page and restore whatever properties we messed with
+ function unload() {
+ $j(window).unbind("resize", onwindowresize);
+ $frame.hide();
+ $editor.hide();
+ $editor.remove();
+ $frame.remove();
+
+ document.body.scrollLeft = oldScrollLeft;
+ document.body.scrollTop = oldScrollTop;
+ document.body.style.overflow = oldOverflow;
+
+ isRunning = false;
+ }
+
+
+ // resets the display canvas (clears the canvas and repaints the current state)
+ // then updates display and overlay
+ function resetDisplayCanvas() {
+ if (!($displayCanvas && $displayCanvas.get)) throw new Error(errorDialog("$displayCanvas doesn't exist"));
+ if (!($imageCanvas && $imageCanvas.get)) throw new Error(errorDialog("$imageCanvas doesn't exist"));
+
+ var display = $displayCanvas.get(0);
+ var image = $imageCanvas.get(0);
+
+ if (!display) throw new Error(errorDialog("resetDisplayCanvas(): No elements in $displayCanvas"));
+ if (!image) throw new Error(errorDialog("resetDisplayCanvas(): No elements in $imageCanvas"));
+
+ display.width = imageWidth;
+ display.height = imageHeight;
+ display.getContext("2d").drawImage( image, 0, 0 );
+
+ updateDisplayCanvas();
+ updateOverlay();
+ }
+
+ // updates the display by resetting the height and margin of the image container
+ // this is mainly to keep vertical centering
+ function updateDisplayCanvas() {
+ var $imageCtr = $j("#image-container", doc);
+ var $editArea = $j("#image-area", doc);
+
+ if (!$imageCtr.get(0)) throw new Error(errorDialog("updateDisplayCanvas(): $imageCtr doesn't exist"));
+ if (!$displayCanvas.get(0)) throw new Error(errorDialog("updateDisplayCanvas(): $displayCanvas doesn't exist"));
+ if (!$editArea.get(0)) throw new Error(errorDialog("updateDisplayCanvas(): $editArea doesn't exist"));
+
+ var h2 = $displayCanvas.get(0).height;
+ var h1 = $j("#image-area", doc).height();
+ var m = Math.max(0, (h1 - h2) / 2);
+ $imageCtr.height(h2);
+ $imageCtr.css("marginTop", m);
+ }
+
+ // basically the same as updateDisplayCanvas but for the image overlay
+ function updateOverlay() {
+ var $overlay = $j("#image-overlay-container", doc);
+ var $imagectr = $j("#image-container", doc);
+ $overlay.height($imagectr.height());
+ $overlay.css("marginTop", $imagectr.css("marginTop"));
+
+ if ($activeTabContent && $activeTabContent.get(0)) {
+ var $tabContent = $j($activeTabContent.get(0).parentNode);
+ if (typeof $tabContent.data("onoverlayupdate") == "function")
+ $tabContent.data("onoverlayupdate")();
+ }
+ }
+
+ var imageIsLoading = false;
+ var originalImageElement;
+ var $tmpImg;
+
+ function loadImage(imgEl) {
+ if (imageIsLoading)
+ return;
+
+ imageIsLoading = true;
+
+ originalImageElement = imgEl;
+
+ $imageCanvas = $j("<canvas />", doc);
+ imageCtx = $imageCanvas.get(0).getContext("2d");
+
+ imageWidth = 0;
+ imageHeight = 0;
+ $imageCanvas.attr("width", 0);
+ $imageCanvas.attr("height", 0);
+
+ if (imgEl.tagName.toLowerCase() == "img" && !imgEl._pixasticCanvas) {
+ var onload = function(el) {
+ imageWidth = el.offsetWidth;
+ imageHeight = el.offsetHeight;
+ $imageCanvas.attr("width", imageWidth);
+ $imageCanvas.attr("height", imageHeight);
+ imageCtx.drawImage(el,0,0);
+ $tmpImg.remove();
+ imageIsLoading = false;
+ enableTab("reshape");
+ setTimeout(function() {
+ resetDisplayCanvas();
+ }, 10);
+ }
+ $tmpImg = $j("<img />", doc)
+ .css("position", "absolute")
+ .css("left", "-9999px")
+ .css("top", "-9999px")
+ .appendTo("body")
+ .load(function(){onload(this);})
+ .error(function(){
+ throw new Error("Could not load temporary copy image. Is provided image valid?");
+ unload();
+ })
+ .attr("src", imgEl.src);
+ if ($tmpImg.attr("complete")) {
+ onload($tmpImg.get(0));
+ }
+ } else {
+ var $canvas = imgEl._pixasticCanvas || imgEl;
+ imageWidth = $canvas.attr("width");
+ imageHeight = $canvas.attr("height");
+ $imageCanvas.attr("width", imageWidth);
+ $imageCanvas.attr("height", imageHeight);
+ imageCtx.drawImage($canvas.get(0), 0, 0);
+ imageIsLoading = false;
+ enableTab("reshape");
+ resetDisplayCanvas();
+ }
+ }
+
+ // return public interface
+ return {
+ /*
+ // don't call. For now we must load the image immediately via load()
+ loadImage : function(imgEl) {
+ if (!isRunning) return false;
+ loadImage(imgEl);
+ },
+ */
+ saveToPage : function() {
+ if (!isRunning) throw new Error("PixasticEditor::saveToPage(): Editor is not running");
+
+ var $canvas = PixasticEditor.getImageCanvas();
+ var img = PixasticEditor.getOriginalImage();
+ if (img.tagName.toLowerCase() == "canvas") {
+ img.width = $canvas.attr("width");
+ img.height = $canvas.attr("height");
+ img.getContext("2d").drawImage($canvas.get(0), 0, 0);
+ } else {
+ img.src = PixasticEditor.getDataURI();
+ }
+ img._pixasticCanvas = PixasticEditor.getImageCanvas();
+ },
+ load : function(img, customBaseUrl) {
+ if (isRunning) return false;
+
+ if (!img)
+ throw new Error("Must be called with an image or canvas as its first argument", "PixasticEditor::load")
+
+ $ = PixasticEditor.jQuery;
+
+ baseUrl = customBaseUrl || "http://www.pixastic.com/editor-test/";
+
+ init(function() {
+ if (img && img.tagName.toLowerCase() == "img" || img.tagName.toLowerCase() == "canvas") {
+ loadImage(img);
+ }
+ });
+ },
+
+ unload : function() {
+ if (!isRunning) throw new Error("PixasticEditor::unload(): Editor is not running");
+ unload();
+ },
+
+ getDocument : function() {
+ if (!isRunning) throw new Error("PixasticEditor::getDocument(): Editor is not running");
+
+ return doc;
+ },
+
+ validSaveFormats : function() {
+ return saveFormats;
+ },
+
+ getOriginalImage : function() {
+ if (!isRunning) throw new Error("PixasticEditor::getOriginalImage(): Editor is not running");
+ return originalImageElement;
+ },
+
+ getDataURI : function(mime) {
+ if (!isRunning) throw new Error("PixasticEditor::getDataURI(): Editor is not running");
+
+ if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))
+ throw new Error(errorDialog("$imageCanvas doesn't exist", "getImageCanvas"));
+
+ return $imageCanvas.get(0).toDataURL(mime||"image/png");
+ },
+
+ getImageCanvas : function() {
+ if (!isRunning) throw new Error("PixasticEditor::getImageCanvas(): Editor is not running");
+
+ if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))
+ throw new Error(errorDialog("$imageCanvas doesn't exist", "getImageCanvas"));
+
+ return $imageCanvas;
+ },
+ getOverlay : function() {
+ if (!isRunning) throw new Error("PixasticEditor::getOverlay(): Editor is not running");
+
+ return $j("#image-overlay", doc);
+ },
+ getDisplayCanvas : function() {
+ if (!isRunning) throw new Error("PixasticEditor::getDisplayCanvas(): Editor is not running");
+
+ if (!($displayCanvas && $displayCanvas.get && $displayCanvas.get(0)))
+ throw new Error(errorDialog("$displayCanvas doesn't exist", "getDisplayCanvas"));
+ return $displayCanvas;
+ },
+ getDisplayWidth : function() {
+ if (!isRunning) throw new Error("PixasticEditor::getDisplayWidth(): Editor is not running");
+
+ return displayWidth;
+ },
+ getDisplayHeight : function() {
+ if (!isRunning) throw new Error("PixasticEditor::getDisplayHeight(): Editor is not running");
+
+ return displayHeight;
+ },
+ getImageWidth : function() {
+ if (!isRunning) throw new Error("PixasticEditor::getImageWidth(): Editor is not running");
+
+ return imageWidth;
+ },
+ getImageHeight : function() {
+ if (!isRunning) throw new Error("PixasticEditor::getImageHeight(): Editor is not running");
+
+ return imageHeight;
+ },
+ errorDialog : function() {
+ if (!isRunning) throw new Error("PixasticEditor::errorDialog(): Editor is not running");
+
+ return errorDialog.apply(null, arguments);
+ }
+ }
+
})();
\ No newline at end of file
-/*\r
- * Pixastic Lib - Core Functions - v0.1.3\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-var Pixastic = (function() {\r
-\r
-\r
- function addEvent(el, event, handler) {\r
- if (el.addEventListener)\r
- el.addEventListener(event, handler, false); \r
- else if (el.attachEvent)\r
- el.attachEvent("on" + event, handler); \r
- }\r
-\r
- function onready(handler) {\r
- var handlerDone = false;\r
- var execHandler = function() {\r
- if (!handlerDone) {\r
- handlerDone = true;\r
- handler();\r
- }\r
- }\r
- document.write("<"+"script defer src=\"//:\" id=\"__onload_ie_sumbox__\"></"+"script>");\r
- var script = document.getElementById("__onload_ie_sumbox__");\r
- script.onreadystatechange = function() {\r
- if (script.readyState == "complete") {\r
- script.parentNode.removeChild(script);\r
- execHandler();\r
- }\r
- }\r
- if (document.addEventListener)\r
- document.addEventListener("DOMContentLoaded", execHandler, false); \r
- addEvent(window, "load", execHandler);\r
- }\r
-\r
- function init() {\r
- if (!Pixastic.parseOnLoad) return;\r
- var imgEls = getElementsByClass("pixastic", null, "img");\r
- var canvasEls = getElementsByClass("pixastic", null, "canvas");\r
- var elements = imgEls.concat(canvasEls);\r
- for (var i=0;i<elements.length;i++) {\r
- (function() {\r
-\r
- var el = elements[i];\r
- var actions = [];\r
- var classes = el.className.split(" ");\r
- for (var c=0;c<classes.length;c++) {\r
- var cls = classes[c];\r
- if (cls.substring(0,9) == "pixastic-") {\r
- var actionName = cls.substring(9);\r
- if (actionName != "")\r
- actions.push(actionName);\r
- }\r
- }\r
- if (actions.length) {\r
- if (el.tagName.toLowerCase() == "img") {\r
- var dataImg = new Image();\r
- dataImg.src = el.src;\r
- if (dataImg.complete) {\r
- for (var a=0;a<actions.length;a++) {\r
- var res = Pixastic.applyAction(el, el, actions[a], null);\r
- if (res) \r
- el = res;\r
- }\r
- } else {\r
- dataImg.onload = function() {\r
- for (var a=0;a<actions.length;a++) {\r
- var res = Pixastic.applyAction(el, el, actions[a], null)\r
- if (res) \r
- el = res;\r
- }\r
- }\r
- }\r
- } else {\r
- setTimeout(function() {\r
- for (var a=0;a<actions.length;a++) {\r
- var res = Pixastic.applyAction(\r
- el, el, actions[a], null\r
- );\r
- if (res) \r
- el = res;\r
- }\r
- },1);\r
- }\r
- }\r
-\r
- })();\r
- }\r
- }\r
-\r
-// if (typeof pixastic_no_onready == "undefined") // yuck.\r
-// onready(init);\r
-\r
- // getElementsByClass by Dustin Diaz, http://www.dustindiaz.com/getelementsbyclass/\r
- function getElementsByClass(searchClass,node,tag) {\r
- var classElements = new Array();\r
- if ( node == null )\r
- node = document;\r
- if ( tag == null )\r
- tag = '*';\r
-\r
- var els = node.getElementsByTagName(tag);\r
- var elsLen = els.length;\r
- var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");\r
- for (i = 0, j = 0; i < elsLen; i++) {\r
- if ( pattern.test(els[i].className) ) {\r
- classElements[j] = els[i];\r
- j++;\r
- }\r
- }\r
- return classElements;\r
- }\r
-\r
- var debugElement;\r
-\r
- function writeDebug(text, level) {\r
- if (!Pixastic.debug) return;\r
- try {\r
- switch (level) {\r
- case "warn" : \r
- console.warn("Pixastic:", text);\r
- break;\r
- case "error" :\r
- console.error("Pixastic:", text);\r
- break;\r
- default:\r
- console.log("Pixastic:", text);\r
- }\r
- } catch(e) {\r
- }\r
- if (!debugElement) {\r
- \r
- }\r
- }\r
-\r
-\r
- return {\r
-\r
- parseOnLoad : false,\r
-\r
- debug : false,\r
- \r
- applyAction : function(img, dataImg, actionName, options) {\r
-\r
- options = options || {};\r
-\r
- var imageIsCanvas = (img.tagName.toLowerCase() == "canvas");\r
- if (imageIsCanvas && Pixastic.Client.isIE()) {\r
- if (Pixastic.debug) writeDebug("Tried to process a canvas element but browser is IE.");\r
- return false;\r
- }\r
-\r
- var canvas, ctx;\r
- if (Pixastic.Client.hasCanvas()) {\r
- canvas = document.createElement("canvas");\r
- ctx = canvas.getContext("2d");\r
- }\r
-\r
- var w = parseInt(img.offsetWidth);\r
- var h = parseInt(img.offsetHeight);\r
-\r
- if (imageIsCanvas) {\r
- w = img.width;\r
- h = img.height;\r
- }\r
-\r
- if (actionName.indexOf("(") > -1) {\r
- var tmp = actionName;\r
- actionName = tmp.substr(0, tmp.indexOf("("));\r
- var arg = tmp.match(/\((.*?)\)/);\r
- if (arg[1]) {\r
- arg = arg[1].split(";");\r
- for (var a=0;a<arg.length;a++) {\r
- thisArg = arg[a].split("=");\r
- if (thisArg.length == 2) {\r
- if (thisArg[0] == "rect") {\r
- var rectVal = thisArg[1].split(",");\r
- options[thisArg[0]] = {\r
- left : parseInt(rectVal[0],10)||0,\r
- top : parseInt(rectVal[1],10)||0,\r
- width : parseInt(rectVal[2],10)||0,\r
- height : parseInt(rectVal[3],10)||0\r
- }\r
- } else {\r
- options[thisArg[0]] = thisArg[1];\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- if (!options.rect) {\r
- options.rect = {\r
- left : 0, top : 0, width : w, height : h\r
- };\r
- }\r
- var validAction = false;\r
- if (Pixastic.Actions[actionName] && typeof Pixastic.Actions[actionName].process == "function") {\r
- validAction = true;\r
- }\r
- if (!validAction) {\r
- if (Pixastic.debug) writeDebug("Invalid action \"" + actionName + "\". Maybe file not included?");\r
- return false;\r
- }\r
- if (!Pixastic.Actions[actionName].checkSupport()) {\r
- if (Pixastic.debug) writeDebug("Action \"" + actionName + "\" not supported by this browser.");\r
- return false;\r
- }\r
-\r
- if (Pixastic.Client.hasCanvas()) {\r
- canvas.width = w;\r
- canvas.height = h;\r
- canvas.style.width = w+"px";\r
- canvas.style.height = h+"px";\r
- ctx.drawImage(dataImg,0,0,w,h);\r
-\r
- if (!img.__pixastic_org_image) {\r
- canvas.__pixastic_org_image = img;\r
- canvas.__pixastic_org_width = w;\r
- canvas.__pixastic_org_height = h;\r
- } else {\r
- canvas.__pixastic_org_image = img.__pixastic_org_image;\r
- canvas.__pixastic_org_width = img.__pixastic_org_width;\r
- canvas.__pixastic_org_height = img.__pixastic_org_height;\r
- }\r
-\r
- } else if (Pixastic.Client.isIE() && typeof img.__pixastic_org_style == "undefined") {\r
- img.__pixastic_org_style = img.style.cssText;\r
- }\r
-\r
- var params = {\r
- image : img,\r
- canvas : canvas,\r
- width : w,\r
- height : h,\r
- useData : true,\r
- options : options\r
- }\r
-\r
- // Ok, let's do it!\r
-\r
- var res = Pixastic.Actions[actionName].process(params);\r
-\r
- if (!res) {\r
- return false;\r
- }\r
-\r
- if (Pixastic.Client.hasCanvas()) {\r
- if (params.useData) {\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- canvas.getContext("2d").putImageData(params.canvasData, options.rect.left, options.rect.top);\r
-\r
- // Opera doesn't seem to update the canvas until we draw something on it, lets draw a 0x0 rectangle.\r
- canvas.getContext("2d").fillRect(0,0,0,0);\r
- }\r
- }\r
-\r
- if (!options.leaveDOM) {\r
- // copy properties and stuff from the source image\r
- canvas.title = img.title;\r
- canvas.imgsrc = img.imgsrc;\r
- if (!imageIsCanvas) canvas.alt = img.alt;\r
- if (!imageIsCanvas) canvas.imgsrc = img.src;\r
- canvas.className = img.className;\r
- canvas.style.cssText = img.style.cssText;\r
- canvas.name = img.name;\r
- canvas.tabIndex = img.tabIndex;\r
- canvas.id = img.id;\r
- if (img.parentNode && img.parentNode.replaceChild) {\r
- img.parentNode.replaceChild(canvas, img);\r
- }\r
- }\r
-\r
- options.resultCanvas = canvas;\r
-\r
- return canvas;\r
- }\r
-\r
- return img;\r
- },\r
-\r
- prepareData : function(params, getCopy) {\r
- var ctx = params.canvas.getContext("2d");\r
- var rect = params.options.rect;\r
- var dataDesc = ctx.getImageData(rect.left, rect.top, rect.width, rect.height);\r
- var data = dataDesc.data;\r
- if (!getCopy) params.canvasData = dataDesc;\r
- return data;\r
- },\r
-\r
- // load the image file\r
- process : function(img, actionName, options, callback)\r
- {\r
- if (img.tagName.toLowerCase() == "img") {\r
- var dataImg = new Image();\r
- dataImg.src = img.src;\r
- if (dataImg.complete) {\r
- var res = Pixastic.applyAction(img, dataImg, actionName, options);\r
- if (callback) callback(res);\r
- return res;\r
- } else {\r
- dataImg.onload = function() {\r
- var res = Pixastic.applyAction(img, dataImg, actionName, options)\r
- if (callback) callback(res);\r
- }\r
- }\r
- }\r
- if (img.tagName.toLowerCase() == "canvas") {\r
- var res = Pixastic.applyAction(img, img, actionName, options);\r
- if (callback) callback(res);\r
- return res;\r
- }\r
- },\r
-\r
- revert : function(img) {\r
- if (Pixastic.Client.hasCanvas()) {\r
- if (img.tagName.toLowerCase() == "canvas" && img.__pixastic_org_image) {\r
- img.width = img.__pixastic_org_width;\r
- img.height = img.__pixastic_org_height;\r
- img.getContext("2d").drawImage(img.__pixastic_org_image, 0, 0);\r
-\r
- if (img.parentNode && img.parentNode.replaceChild) {\r
- img.parentNode.replaceChild(img.__pixastic_org_image, img);\r
- }\r
-\r
- return img;\r
- }\r
- } else if (Pixastic.Client.isIE() && typeof img.__pixastic_org_style != "undefined") {\r
- img.style.cssText = img.__pixastic_org_style;\r
- }\r
- },\r
-\r
- Client : {\r
- hasCanvas : (function() {\r
- var c = document.createElement("canvas");\r
- var val = false;\r
- try {\r
- val = !!((typeof c.getContext == "function") && c.getContext("2d"));\r
- } catch(e) {}\r
- return function() {\r
- return val;\r
- }\r
- })(),\r
-\r
- hasCanvasImageData : (function() {\r
- var c = document.createElement("canvas");\r
- var val = false;\r
- var ctx;\r
- try {\r
- if (typeof c.getContext == "function" && (ctx = c.getContext("2d"))) {\r
- val = (typeof ctx.getImageData == "function");\r
- }\r
- } catch(e) {}\r
- return function() {\r
- return val;\r
- }\r
- })(),\r
-\r
- isIE : function() {\r
- return !!document.all && !!window.attachEvent && !window.opera;\r
- }\r
- },\r
-\r
- Actions : {}\r
- }\r
-\r
-\r
-})();\r
-/*\r
- * Pixastic Lib - jQuery plugin\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-if (typeof jQuery != "undefined" && jQuery && jQuery.fn) {\r
- jQuery.fn.pixastic = function(action, options) {\r
- var newElements = [];\r
- this.each(\r
- function () {\r
- if (this.tagName.toLowerCase() == "img" && !this.complete) {\r
- return;\r
- }\r
- var res = Pixastic.process(this, action, options);\r
- if (res) {\r
- newElements.push(res);\r
- }\r
- }\r
- );\r
- if (newElements.length > 0)\r
- return jQuery(newElements);\r
- else\r
- return this;\r
- };\r
-\r
-};\r
-/*\r
- * Pixastic Lib - Blend - v0.1.1\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.blend = {\r
-\r
- process : function(params) {\r
- var amount = parseFloat(params.options.amount);\r
- var mode = (params.options.mode || "normal").toLowerCase();\r
- var image = params.options.image;\r
-\r
- amount = Math.max(0,Math.min(1,amount));\r
-\r
- if (!image) return false;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var rect = params.options.rect;\r
- var data = Pixastic.prepareData(params);\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- params.useData = false;\r
-\r
- var otherCanvas = document.createElement("canvas");\r
- otherCanvas.width = params.canvas.width;\r
- otherCanvas.height = params.canvas.height;\r
- var otherCtx = otherCanvas.getContext("2d");\r
- otherCtx.drawImage(image,0,0);\r
-\r
- var params2 = {canvas:otherCanvas,options:params.options};\r
- var data2 = Pixastic.prepareData(params2);\r
- var dataDesc2 = params2.canvasData;\r
-\r
- var p = w*h;\r
- var pix = p*4;\r
- var pix1, pix2;\r
- var r1, g1, b1;\r
- var r2, g2, b2;\r
- var r3, g3, b3;\r
- var r4, g4, b4;\r
-\r
- var dataChanged = false;\r
-\r
- switch (mode) {\r
- case "normal" : \r
- //while (p--) {\r
- // data2[pix-=4] = data2[pix];\r
- // data2[pix1=pix+1] = data2[pix1];\r
- // data2[pix2=pix+2] = data2[pix2];\r
- //}\r
- break;\r
-\r
- case "multiply" : \r
- while (p--) {\r
- data2[pix-=4] = data[pix] * data2[pix] / 255;\r
- data2[pix1=pix+1] = data[pix1] * data2[pix1] / 255;\r
- data2[pix2=pix+2] = data[pix2] * data2[pix2] / 255;\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "lighten" : \r
- while (p--) {\r
- if ((r1 = data[pix-=4]) > data2[pix])\r
- data2[pix] = r1;\r
- if ((g1 = data[pix1=pix+1]) > data2[pix1])\r
- data2[pix1] = g1;\r
- if ((b1 = data[pix2=pix+2]) > data2[pix2])\r
- data2[pix2] = b1;\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "darken" : \r
- while (p--) {\r
- if ((r1 = data[pix-=4]) < data2[pix])\r
- data2[pix] = r1;\r
- if ((g1 = data[pix1=pix+1]) < data2[pix1])\r
- data2[pix1] = g1;\r
- if ((b1 = data[pix2=pix+2]) < data2[pix2])\r
- data2[pix2] = b1;\r
-\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "darkercolor" : \r
- while (p--) {\r
- 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)) {\r
- data2[pix] = r1;\r
- data2[pix1] = g1;\r
- data2[pix2] = b1;\r
- }\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "lightercolor" : \r
- while (p--) {\r
- 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)) {\r
- data2[pix] = r1;\r
- data2[pix1] = g1;\r
- data2[pix2] = b1;\r
- }\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "lineardodge" : \r
- otherCtx.globalCompositeOperation = "source-over";\r
- otherCtx.drawImage(params.canvas, 0, 0);\r
- otherCtx.globalCompositeOperation = "lighter";\r
- otherCtx.drawImage(image, 0, 0);\r
-\r
- /*\r
- while (p--) {\r
- if ((r3 = data[pix-=4] + data2[pix]) > 255)\r
- data2[pix] = 255;\r
- else\r
- data2[pix] = r3;\r
- if ((g3 = data[pix1=pix+1] + data2[pix1]) > 255)\r
- data2[pix1] = 255;\r
- else\r
- data2[pix1] = g3;\r
- if ((b3 = data[pix2=pix+2] + data2[pix2]) > 255)\r
- data2[pix2] = 255;\r
- else\r
- data2[pix2] = b3;\r
- }\r
- dataChanged = true;\r
- */\r
-\r
- break;\r
-\r
- case "linearburn" : \r
- while (p--) {\r
- if ((r3 = data[pix-=4] + data2[pix]) < 255)\r
- data2[pix] = 0;\r
- else\r
- data2[pix] = (r3 - 255);\r
- if ((g3 = data[pix1=pix+1] + data2[pix1]) < 255)\r
- data2[pix1] = 0;\r
- else\r
- data2[pix1] = (g3 - 255);\r
- if ((b3 = data[pix2=pix+2] + data2[pix2]) < 255)\r
- data2[pix2] = 0;\r
- else\r
- data2[pix2] = (b3 - 255);\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "difference" : \r
- while (p--) {\r
- if ((r3 = data[pix-=4] - data2[pix]) < 0)\r
- data2[pix] = -r3;\r
- else\r
- data2[pix] = r3;\r
- if ((g3 = data[pix1=pix+1] - data2[pix1]) < 0)\r
- data2[pix1] = -g3;\r
- else\r
- data2[pix1] = g3;\r
- if ((b3 = data[pix2=pix+2] - data2[pix2]) < 0)\r
- data2[pix2] = -b3;\r
- else\r
- data2[pix2] = b3;\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "screen" : \r
- while (p--) {\r
- data2[pix-=4] = (255 - ( ((255-data2[pix])*(255-data[pix])) >> 8));\r
- data2[pix1=pix+1] = (255 - ( ((255-data2[pix1])*(255-data[pix1])) >> 8));\r
- data2[pix2=pix+2] = (255 - ( ((255-data2[pix2])*(255-data[pix2])) >> 8));\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "exclusion" : \r
- var div_2_255 = 2 / 255;\r
- while (p--) {\r
- data2[pix-=4] = (r1 = data[pix]) - (r1 * div_2_255 - 1) * data2[pix];\r
- data2[pix1=pix+1] = (g1 = data[pix1]) - (g1 * div_2_255 - 1) * data2[pix1];\r
- data2[pix2=pix+2] = (b1 = data[pix2]) - (b1 * div_2_255 - 1) * data2[pix2];\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "overlay" : \r
- var div_2_255 = 2 / 255;\r
- while (p--) {\r
- if ((r1 = data[pix-=4]) < 128)\r
- data2[pix] = data2[pix]*r1*div_2_255;\r
- else\r
- data2[pix] = 255 - (255-data2[pix])*(255-r1)*div_2_255;\r
-\r
- if ((g1 = data[pix1=pix+1]) < 128)\r
- data2[pix1] = data2[pix1]*g1*div_2_255;\r
- else\r
- data2[pix1] = 255 - (255-data2[pix1])*(255-g1)*div_2_255;\r
-\r
- if ((b1 = data[pix2=pix+2]) < 128)\r
- data2[pix2] = data2[pix2]*b1*div_2_255;\r
- else\r
- data2[pix2] = 255 - (255-data2[pix2])*(255-b1)*div_2_255;\r
-\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "softlight" : \r
- var div_2_255 = 2 / 255;\r
- while (p--) {\r
- if ((r1 = data[pix-=4]) < 128)\r
- data2[pix] = ((data2[pix]>>1) + 64) * r1 * div_2_255;\r
- else\r
- data2[pix] = 255 - (191 - (data2[pix]>>1)) * (255-r1) * div_2_255;\r
-\r
- if ((g1 = data[pix1=pix+1]) < 128)\r
- data2[pix1] = ((data2[pix1]>>1)+64) * g1 * div_2_255;\r
- else\r
- data2[pix1] = 255 - (191 - (data2[pix1]>>1)) * (255-g1) * div_2_255;\r
-\r
- if ((b1 = data[pix2=pix+2]) < 128)\r
- data2[pix2] = ((data2[pix2]>>1)+64) * b1 * div_2_255;\r
- else\r
- data2[pix2] = 255 - (191 - (data2[pix2]>>1)) * (255-b1) * div_2_255;\r
-\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "hardlight" : \r
- var div_2_255 = 2 / 255;\r
- while (p--) {\r
- if ((r2 = data2[pix-=4]) < 128)\r
- data2[pix] = data[pix] * r2 * div_2_255;\r
- else\r
- data2[pix] = 255 - (255-data[pix]) * (255-r2) * div_2_255;\r
-\r
- if ((g2 = data2[pix1=pix+1]) < 128)\r
- data2[pix1] = data[pix1] * g2 * div_2_255;\r
- else\r
- data2[pix1] = 255 - (255-data[pix1]) * (255-g2) * div_2_255;\r
-\r
- if ((b2 = data2[pix2=pix+2]) < 128)\r
- data2[pix2] = data[pix2] * b2 * div_2_255;\r
- else\r
- data2[pix2] = 255 - (255-data[pix2]) * (255-b2) * div_2_255;\r
-\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "colordodge" : \r
- while (p--) {\r
- if ((r3 = (data[pix-=4]<<8)/(255-(r2 = data2[pix]))) > 255 || r2 == 255)\r
- data2[pix] = 255;\r
- else\r
- data2[pix] = r3;\r
-\r
- if ((g3 = (data[pix1=pix+1]<<8)/(255-(g2 = data2[pix1]))) > 255 || g2 == 255)\r
- data2[pix1] = 255;\r
- else\r
- data2[pix1] = g3;\r
-\r
- if ((b3 = (data[pix2=pix+2]<<8)/(255-(b2 = data2[pix2]))) > 255 || b2 == 255)\r
- data2[pix2] = 255;\r
- else\r
- data2[pix2] = b3;\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "colorburn" : \r
- while (p--) {\r
- if ((r3 = 255-((255-data[pix-=4])<<8)/data2[pix]) < 0 || data2[pix] == 0)\r
- data2[pix] = 0;\r
- else\r
- data2[pix] = r3;\r
-\r
- if ((g3 = 255-((255-data[pix1=pix+1])<<8)/data2[pix1]) < 0 || data2[pix1] == 0)\r
- data2[pix1] = 0;\r
- else\r
- data2[pix1] = g3;\r
-\r
- if ((b3 = 255-((255-data[pix2=pix+2])<<8)/data2[pix2]) < 0 || data2[pix2] == 0)\r
- data2[pix2] = 0;\r
- else\r
- data2[pix2] = b3;\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "linearlight" : \r
- while (p--) {\r
- if ( ((r3 = 2*(r2=data2[pix-=4])+data[pix]-256) < 0) || (r2 < 128 && r3 < 0)) {\r
- data2[pix] = 0\r
- } else {\r
- if (r3 > 255)\r
- data2[pix] = 255;\r
- else\r
- data2[pix] = r3;\r
- }\r
- if ( ((g3 = 2*(g2=data2[pix1=pix+1])+data[pix1]-256) < 0) || (g2 < 128 && g3 < 0)) {\r
- data2[pix1] = 0\r
- } else {\r
- if (g3 > 255)\r
- data2[pix1] = 255;\r
- else\r
- data2[pix1] = g3;\r
- }\r
- if ( ((b3 = 2*(b2=data2[pix2=pix+2])+data[pix2]-256) < 0) || (b2 < 128 && b3 < 0)) {\r
- data2[pix2] = 0\r
- } else {\r
- if (b3 > 255)\r
- data2[pix2] = 255;\r
- else\r
- data2[pix2] = b3;\r
- }\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "vividlight" : \r
- while (p--) {\r
- if ((r2=data2[pix-=4]) < 128) {\r
- if (r2) {\r
- if ((r3 = 255 - ((255-data[pix])<<8) / (2*r2)) < 0) \r
- data2[pix] = 0;\r
- else\r
- data2[pix] = r3\r
- } else {\r
- data2[pix] = 0;\r
- }\r
- } else if ((r3 = (r4=2*r2-256)) < 255) {\r
- if ((r3 = (data[pix]<<8)/(255-r4)) > 255) \r
- data2[pix] = 255;\r
- else\r
- data2[pix] = r3;\r
- } else {\r
- if (r3 < 0) \r
- data2[pix] = 0;\r
- else\r
- data2[pix] = r3\r
- }\r
-\r
- if ((g2=data2[pix1=pix+1]) < 128) {\r
- if (g2) {\r
- if ((g3 = 255 - ((255-data[pix1])<<8) / (2*g2)) < 0) \r
- data2[pix1] = 0;\r
- else\r
- data2[pix1] = g3;\r
- } else {\r
- data2[pix1] = 0;\r
- }\r
- } else if ((g3 = (g4=2*g2-256)) < 255) {\r
- if ((g3 = (data[pix1]<<8)/(255-g4)) > 255)\r
- data2[pix1] = 255;\r
- else\r
- data2[pix1] = g3;\r
- } else {\r
- if (g3 < 0) \r
- data2[pix1] = 0;\r
- else\r
- data2[pix1] = g3;\r
- }\r
-\r
- if ((b2=data2[pix2=pix+2]) < 128) {\r
- if (b2) {\r
- if ((b3 = 255 - ((255-data[pix2])<<8) / (2*b2)) < 0) \r
- data2[pix2] = 0;\r
- else\r
- data2[pix2] = b3;\r
- } else {\r
- data2[pix2] = 0;\r
- }\r
- } else if ((b3 = (b4=2*b2-256)) < 255) {\r
- if ((b3 = (data[pix2]<<8)/(255-b4)) > 255) \r
- data2[pix2] = 255;\r
- else\r
- data2[pix2] = b3;\r
- } else {\r
- if (b3 < 0) \r
- data2[pix2] = 0;\r
- else\r
- data2[pix2] = b3;\r
- }\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "pinlight" : \r
- while (p--) {\r
- if ((r2=data2[pix-=4]) < 128)\r
- if ((r1=data[pix]) < (r4=2*r2))\r
- data2[pix] = r1;\r
- else\r
- data2[pix] = r4;\r
- else\r
- if ((r1=data[pix]) > (r4=2*r2-256))\r
- data2[pix] = r1;\r
- else\r
- data2[pix] = r4;\r
-\r
- if ((g2=data2[pix1=pix+1]) < 128)\r
- if ((g1=data[pix1]) < (g4=2*g2))\r
- data2[pix1] = g1;\r
- else\r
- data2[pix1] = g4;\r
- else\r
- if ((g1=data[pix1]) > (g4=2*g2-256))\r
- data2[pix1] = g1;\r
- else\r
- data2[pix1] = g4;\r
-\r
- if ((r2=data2[pix2=pix+2]) < 128)\r
- if ((r1=data[pix2]) < (r4=2*r2))\r
- data2[pix2] = r1;\r
- else\r
- data2[pix2] = r4;\r
- else\r
- if ((r1=data[pix2]) > (r4=2*r2-256))\r
- data2[pix2] = r1;\r
- else\r
- data2[pix2] = r4;\r
- }\r
- dataChanged = true;\r
- break;\r
-\r
- case "hardmix" : \r
- while (p--) {\r
- if ((r2 = data2[pix-=4]) < 128)\r
- if (255 - ((255-data[pix])<<8)/(2*r2) < 128 || r2 == 0)\r
- data2[pix] = 0;\r
- else\r
- data2[pix] = 255;\r
- else if ((r4=2*r2-256) < 255 && (data[pix]<<8)/(255-r4) < 128)\r
- data2[pix] = 0;\r
- else\r
- data2[pix] = 255;\r
-\r
- if ((g2 = data2[pix1=pix+1]) < 128)\r
- if (255 - ((255-data[pix1])<<8)/(2*g2) < 128 || g2 == 0)\r
- data2[pix1] = 0;\r
- else\r
- data2[pix1] = 255;\r
- else if ((g4=2*g2-256) < 255 && (data[pix1]<<8)/(255-g4) < 128)\r
- data2[pix1] = 0;\r
- else\r
- data2[pix1] = 255;\r
-\r
- if ((b2 = data2[pix2=pix+2]) < 128)\r
- if (255 - ((255-data[pix2])<<8)/(2*b2) < 128 || b2 == 0)\r
- data2[pix2] = 0;\r
- else\r
- data2[pix2] = 255;\r
- else if ((b4=2*b2-256) < 255 && (data[pix2]<<8)/(255-b4) < 128)\r
- data2[pix2] = 0;\r
- else\r
- data2[pix2] = 255;\r
- }\r
- dataChanged = true;\r
- break;\r
- }\r
-\r
- if (dataChanged) \r
- otherCtx.putImageData(dataDesc2,0,0);\r
-\r
- var ctx = params.canvas.getContext("2d");\r
- ctx.save();\r
- ctx.globalAlpha = amount;\r
- ctx.drawImage(\r
- otherCanvas,\r
- 0,0,rect.width,rect.height,\r
- rect.left,rect.top,rect.width,rect.height\r
- );\r
- ctx.globalAlpha = 1;\r
- ctx.restore();\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}/*\r
- * Pixastic Lib - Blur filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.blur = {\r
- process : function(params) {\r
-\r
- if (typeof params.options.fixMargin == "undefined")\r
- params.options.fixMargin = true;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var dataCopy = Pixastic.prepareData(params, true)\r
-\r
- /*\r
- var kernel = [\r
- [0.5, 1, 0.5],\r
- [1, 2, 1],\r
- [0.5, 1, 0.5]\r
- ];\r
- */\r
-\r
- var kernel = [\r
- [0, 1, 0],\r
- [1, 2, 1],\r
- [0, 1, 0]\r
- ];\r
-\r
- var weight = 0;\r
- for (var i=0;i<3;i++) {\r
- for (var j=0;j<3;j++) {\r
- weight += kernel[i][j];\r
- }\r
- }\r
-\r
- weight = 1 / (weight*2);\r
-\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
-\r
- var prevY = (y == 1) ? 0 : y-2;\r
- var nextY = (y == h) ? y - 1 : y;\r
-\r
- var offsetYPrev = prevY*w*4;\r
- var offsetYNext = nextY*w*4;\r
-\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x*4-4);\r
-\r
- var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;\r
- var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;\r
- \r
- data[offset] = (\r
- /*\r
- dataCopy[offsetPrev - 4]\r
- + dataCopy[offsetPrev+4] \r
- + dataCopy[offsetNext - 4]\r
- + dataCopy[offsetNext+4]\r
- + \r
- */\r
- (dataCopy[offsetPrev]\r
- + dataCopy[offset-4]\r
- + dataCopy[offset+4]\r
- + dataCopy[offsetNext]) * 2\r
- + dataCopy[offset] * 4\r
- ) * weight;\r
-\r
- data[offset+1] = (\r
- /*\r
- dataCopy[offsetPrev - 3]\r
- + dataCopy[offsetPrev+5] \r
- + dataCopy[offsetNext - 3] \r
- + dataCopy[offsetNext+5]\r
- + \r
- */\r
- (dataCopy[offsetPrev+1]\r
- + dataCopy[offset-3]\r
- + dataCopy[offset+5]\r
- + dataCopy[offsetNext+1]) * 2\r
- + dataCopy[offset+1] * 4\r
- ) * weight;\r
-\r
- data[offset+2] = (\r
- /*\r
- dataCopy[offsetPrev - 2] \r
- + dataCopy[offsetPrev+6] \r
- + dataCopy[offsetNext - 2] \r
- + dataCopy[offsetNext+6]\r
- + \r
- */\r
- (dataCopy[offsetPrev+2]\r
- + dataCopy[offset-2]\r
- + dataCopy[offset+6]\r
- + dataCopy[offsetNext+2]) * 2\r
- + dataCopy[offset+2] * 4\r
- ) * weight;\r
-\r
- } while (--x);\r
- } while (--y);\r
-\r
- return true;\r
-\r
- } else if (Pixastic.Client.isIE()) {\r
- params.image.style.filter += " progid:DXImageTransform.Microsoft.Blur(pixelradius=1.5)";\r
-\r
- if (params.options.fixMargin) {\r
- params.image.style.marginLeft = (parseInt(params.image.style.marginLeft,10)||0) - 2 + "px";\r
- params.image.style.marginTop = (parseInt(params.image.style.marginTop,10)||0) - 2 + "px";\r
- }\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());\r
- }\r
-}/*\r
- * Pixastic Lib - Blur Fast - v0.1.1\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.blurfast = {\r
- process : function(params) {\r
-\r
- var amount = parseFloat(params.options.amount)||0;\r
- var clear = !!(params.options.clear && params.options.clear != "false");\r
-\r
- amount = Math.max(0,Math.min(5,amount));\r
-\r
- if (Pixastic.Client.hasCanvas()) {\r
- var rect = params.options.rect;\r
-\r
- var ctx = params.canvas.getContext("2d");\r
- ctx.save();\r
- ctx.beginPath();\r
- ctx.rect(rect.left, rect.top, rect.width, rect.height);\r
- ctx.clip();\r
-\r
- var scale = 2;\r
- var smallWidth = Math.round(params.width / scale);\r
- var smallHeight = Math.round(params.height / scale);\r
-\r
- var copy = document.createElement("canvas");\r
- copy.width = smallWidth;\r
- copy.height = smallHeight;\r
-\r
- var clear = false;\r
- var steps = Math.round(amount * 20);\r
-\r
- var copyCtx = copy.getContext("2d");\r
- for (var i=0;i<steps;i++) {\r
- var scaledWidth = Math.max(1,Math.round(smallWidth - i));\r
- var scaledHeight = Math.max(1,Math.round(smallHeight - i));\r
- \r
- copyCtx.clearRect(0,0,smallWidth,smallHeight);\r
- \r
- copyCtx.drawImage(\r
- params.canvas,\r
- 0,0,params.width,params.height,\r
- 0,0,scaledWidth,scaledHeight\r
- );\r
- \r
- if (clear)\r
- ctx.clearRect(rect.left,rect.top,rect.width,rect.height);\r
- \r
- ctx.drawImage(\r
- copy,\r
- 0,0,scaledWidth,scaledHeight,\r
- 0,0,params.width,params.height\r
- );\r
- }\r
-\r
- ctx.restore();\r
-\r
- params.useData = false;\r
- return true;\r
- } else if (Pixastic.Client.isIE()) {\r
- var radius = 10 * amount;\r
- params.image.style.filter += " progid:DXImageTransform.Microsoft.Blur(pixelradius=" + radius + ")";\r
-\r
- if (params.options.fixMargin || 1) {\r
- params.image.style.marginLeft = (parseInt(params.image.style.marginLeft,10)||0) - Math.round(radius) + "px";\r
- params.image.style.marginTop = (parseInt(params.image.style.marginTop,10)||0) - Math.round(radius) + "px";\r
- }\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());\r
- }\r
-}\r
-/*\r
- * Pixastic Lib - Brightness/Contrast filter - v0.1.1\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.brightness = {\r
-\r
- process : function(params) {\r
-\r
- var brightness = parseInt(params.options.brightness,10) || 0;\r
- var contrast = parseFloat(params.options.contrast)||0;\r
- var legacy = !!(params.options.legacy && params.options.legacy != "false");\r
-\r
- if (legacy) {\r
- brightness = Math.min(150,Math.max(-150,brightness));\r
- } else {\r
- var brightMul = 1 + Math.min(150,Math.max(-150,brightness)) / 150;\r
- }\r
- contrast = Math.max(0,contrast+1);\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var p = w*h;\r
- var pix = p*4, pix1, pix2;\r
-\r
- var mul, add;\r
- if (contrast != 1) {\r
- if (legacy) {\r
- mul = contrast;\r
- add = (brightness - 128) * contrast + 128;\r
- } else {\r
- mul = brightMul * contrast;\r
- add = - contrast * 128 + 128;\r
- }\r
- } else { // this if-then is not necessary anymore, is it?\r
- if (legacy) {\r
- mul = 1;\r
- add = brightness;\r
- } else {\r
- mul = brightMul;\r
- add = 0;\r
- }\r
- }\r
- var r, g, b;\r
- while (p--) {\r
- if ((r = data[pix-=4] * mul + add) > 255 )\r
- data[pix] = 255;\r
- else if (r < 0)\r
- data[pix] = 0;\r
- else\r
- data[pix] = r;\r
-\r
- if ((g = data[pix1=pix+1] * mul + add) > 255 ) \r
- data[pix1] = 255;\r
- else if (g < 0)\r
- data[pix1] = 0;\r
- else\r
- data[pix1] = g;\r
-\r
- if ((b = data[pix2=pix+2] * mul + add) > 255 ) \r
- data[pix2] = 255;\r
- else if (b < 0)\r
- data[pix2] = 0;\r
- else\r
- data[pix2] = b;\r
- }\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}\r
-\r
-/*\r
- * Pixastic Lib - Color adjust filter - v0.1.1\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.coloradjust = {\r
-\r
- process : function(params) {\r
- var red = parseFloat(params.options.red) || 0;\r
- var green = parseFloat(params.options.green) || 0;\r
- var blue = parseFloat(params.options.blue) || 0;\r
-\r
- red = Math.round(red*255);\r
- green = Math.round(green*255);\r
- blue = Math.round(blue*255);\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var rect = params.options.rect;\r
-\r
- var p = rect.width*rect.height;\r
- var pix = p*4, pix1, pix2;\r
-\r
- var r, g, b;\r
- while (p--) {\r
- pix -= 4;\r
-\r
- if (red) {\r
- if ((r = data[pix] + red) < 0 ) \r
- data[pix] = 0;\r
- else if (r > 255 ) \r
- data[pix] = 255;\r
- else\r
- data[pix] = r;\r
- }\r
-\r
- if (green) {\r
- if ((g = data[pix1=pix+1] + green) < 0 ) \r
- data[pix1] = 0;\r
- else if (g > 255 ) \r
- data[pix1] = 255;\r
- else\r
- data[pix1] = g;\r
- }\r
-\r
- if (blue) {\r
- if ((b = data[pix2=pix+2] + blue) < 0 ) \r
- data[pix2] = 0;\r
- else if (b > 255 ) \r
- data[pix2] = 255;\r
- else\r
- data[pix2] = b;\r
- }\r
- }\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvasImageData());\r
- }\r
-}\r
-/*\r
- * Pixastic Lib - Histogram - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-\r
-Pixastic.Actions.colorhistogram = {\r
-\r
- array256 : function(default_value) {\r
- arr = [];\r
- for (var i=0; i<256; i++) { arr[i] = default_value; }\r
- return arr\r
- },\r
- \r
- process : function(params) {\r
- var values = [];\r
- if (typeof params.options.returnValue != "object") {\r
- params.options.returnValue = {rvals:[], gvals:[], bvals:[]};\r
- }\r
- var paint = !!(params.options.paint);\r
-\r
- var returnValue = params.options.returnValue;\r
- if (typeof returnValue.values != "array") {\r
- returnValue.rvals = [];\r
- returnValue.gvals = [];\r
- returnValue.bvals = [];\r
- }\r
- \r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- params.useData = false;\r
- \r
- var rvals = this.array256(0);\r
- var gvals = this.array256(0);\r
- var bvals = this.array256(0);\r
- \r
- var rect = params.options.rect;\r
-\r
- var p = rect.width*rect.height;\r
- var pix = p*4;\r
- while (p--) {\r
- rvals[data[pix-=4]]++;\r
- gvals[data[pix+1]]++;\r
- bvals[data[pix+2]]++;\r
- }\r
- \r
- returnValue.rvals = rvals;\r
- returnValue.gvals = gvals;\r
- returnValue.bvals = bvals;\r
-\r
- if (paint) {\r
- var ctx = params.canvas.getContext("2d");\r
- var vals = [rvals, gvals, bvals];\r
- for (var v=0;v<3;v++) {\r
- var yoff = (v+1) * params.height / 3;\r
- var maxValue = 0;\r
- for (var i=0;i<256;i++) {\r
- if (vals[v][i] > maxValue)\r
- maxValue = vals[v][i];\r
- }\r
- var heightScale = params.height / 3 / maxValue;\r
- var widthScale = params.width / 256;\r
- if (v==0) ctx.fillStyle = "rgba(255,0,0,0.5)";\r
- else if (v==1) ctx.fillStyle = "rgba(0,255,0,0.5)";\r
- else if (v==2) ctx.fillStyle = "rgba(0,0,255,0.5)";\r
- for (var i=0;i<256;i++) {\r
- ctx.fillRect(\r
- i * widthScale, params.height - heightScale * vals[v][i] - params.height + yoff,\r
- widthScale, vals[v][i] * heightScale\r
- );\r
- }\r
- }\r
- }\r
- return true;\r
- }\r
- },\r
-\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}/*\r
- * Pixastic Lib - Crop - v0.1.1\r
- * Copyright (c) 2008-2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.crop = {\r
- process : function(params) {\r
- if (Pixastic.Client.hasCanvas()) {\r
- var rect = params.options.rect;\r
-\r
- var width = rect.width;\r
- var height = rect.height;\r
- var top = rect.top;\r
- var left = rect.left;\r
-\r
- if (typeof params.options.left != "undefined")\r
- left = parseInt(params.options.left,10);\r
- if (typeof params.options.top != "undefined")\r
- top = parseInt(params.options.top,10);\r
- if (typeof params.options.height != "undefined")\r
- width = parseInt(params.options.width,10);\r
- if (typeof params.options.height != "undefined")\r
- height = parseInt(params.options.height,10);\r
-\r
- if (left < 0) left = 0;\r
- if (left > params.width-1) left = params.width-1;\r
-\r
- if (top < 0) top = 0;\r
- if (top > params.height-1) top = params.height-1;\r
-\r
- if (width < 1) width = 1;\r
- if (left + width > params.width)\r
- width = params.width - left;\r
-\r
- if (height < 1) height = 1;\r
- if (top + height > params.height)\r
- height = params.height - top;\r
-\r
- var copy = document.createElement("canvas");\r
- copy.width = params.width;\r
- copy.height = params.height;\r
- copy.getContext("2d").drawImage(params.canvas,0,0);\r
-\r
- params.canvas.width = width;\r
- params.canvas.height = height;\r
- params.canvas.getContext("2d").clearRect(0,0,width,height);\r
-\r
- params.canvas.getContext("2d").drawImage(copy,\r
- left,top,width,height,\r
- 0,0,width,height\r
- );\r
-\r
- params.useData = false;\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvas();\r
- }\r
-}\r
-\r
-\r
-/*\r
- * Pixastic Lib - Desaturation filter - v0.1.1\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.desaturate = {\r
-\r
- process : function(params) {\r
- var useAverage = !!(params.options.average && params.options.average != "false");\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var p = w*h;\r
- var pix = p*4, pix1, pix2;\r
-\r
- if (useAverage) {\r
- while (p--) \r
- data[pix-=4] = data[pix1=pix+1] = data[pix2=pix+2] = (data[pix]+data[pix1]+data[pix2])/3\r
- } else {\r
- while (p--)\r
- data[pix-=4] = data[pix1=pix+1] = data[pix2=pix+2] = (data[pix]*0.3 + data[pix1]*0.59 + data[pix2]*0.11);\r
- }\r
- return true;\r
- } else if (Pixastic.Client.isIE()) {\r
- params.image.style.filter += " gray";\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());\r
- }\r
-}/*\r
- * Pixastic Lib - Edge detection filter - v0.1.1\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.edges = {\r
- process : function(params) {\r
-\r
- var mono = !!(params.options.mono && params.options.mono != "false");\r
- var invert = !!(params.options.invert && params.options.invert != "false");\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var dataCopy = Pixastic.prepareData(params, true)\r
-\r
- var c = -1/8;\r
- var kernel = [\r
- [c, c, c],\r
- [c, 1, c],\r
- [c, c, c]\r
- ];\r
-\r
- weight = 1/c;\r
-\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
-\r
- var nextY = (y == h) ? y - 1 : y;\r
- var prevY = (y == 1) ? 0 : y-2;\r
-\r
- var offsetYPrev = prevY*w*4;\r
- var offsetYNext = nextY*w*4;\r
-\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x*4-4);\r
-\r
- var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;\r
- var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;\r
- \r
- var r = ((dataCopy[offsetPrev-4]\r
- + dataCopy[offsetPrev]\r
- + dataCopy[offsetPrev+4]\r
- + dataCopy[offset-4]\r
- + dataCopy[offset+4]\r
- + dataCopy[offsetNext-4]\r
- + dataCopy[offsetNext]\r
- + dataCopy[offsetNext+4]) * c\r
- + dataCopy[offset]\r
- ) \r
- * weight;\r
- \r
- var g = ((dataCopy[offsetPrev-3]\r
- + dataCopy[offsetPrev+1]\r
- + dataCopy[offsetPrev+5]\r
- + dataCopy[offset-3]\r
- + dataCopy[offset+5]\r
- + dataCopy[offsetNext-3]\r
- + dataCopy[offsetNext+1]\r
- + dataCopy[offsetNext+5]) * c\r
- + dataCopy[offset+1])\r
- * weight;\r
- \r
- var b = ((dataCopy[offsetPrev-2]\r
- + dataCopy[offsetPrev+2]\r
- + dataCopy[offsetPrev+6]\r
- + dataCopy[offset-2]\r
- + dataCopy[offset+6]\r
- + dataCopy[offsetNext-2]\r
- + dataCopy[offsetNext+2]\r
- + dataCopy[offsetNext+6]) * c\r
- + dataCopy[offset+2])\r
- * weight;\r
-\r
- if (mono) {\r
- var brightness = (r*0.3 + g*0.59 + b*0.11)||0;\r
- if (invert) brightness = 255 - brightness;\r
- if (brightness < 0 ) brightness = 0;\r
- if (brightness > 255 ) brightness = 255;\r
- r = g = b = brightness;\r
- } else {\r
- if (invert) {\r
- r = 255 - r;\r
- g = 255 - g;\r
- b = 255 - b;\r
- }\r
- if (r < 0 ) r = 0;\r
- if (g < 0 ) g = 0;\r
- if (b < 0 ) b = 0;\r
- if (r > 255 ) r = 255;\r
- if (g > 255 ) g = 255;\r
- if (b > 255 ) b = 255;\r
- }\r
-\r
- data[offset] = r;\r
- data[offset+1] = g;\r
- data[offset+2] = b;\r
-\r
- } while (--x);\r
- } while (--y);\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}/*\r
- * Pixastic Lib - Edge detection 2 - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- * \r
- * Contribution by Oliver Hunt (http://nerget.com/, http://nerget.com/canvas/edgeDetection.js). Thanks Oliver!\r
- *\r
- */\r
-\r
-Pixastic.Actions.edges2 = {\r
- process : function(params) {\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var dataCopy = Pixastic.prepareData(params, true)\r
-\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var w4 = w * 4;\r
- var pixel = w4 + 4; // Start at (1,1)\r
- var hm1 = h - 1;\r
- var wm1 = w - 1;\r
- for (var y = 1; y < hm1; ++y) {\r
- // Prepare initial cached values for current row\r
- var centerRow = pixel - 4;\r
- var priorRow = centerRow - w4;\r
- var nextRow = centerRow + w4;\r
- \r
- var r1 = - dataCopy[priorRow] - dataCopy[centerRow] - dataCopy[nextRow];\r
- var g1 = - dataCopy[++priorRow] - dataCopy[++centerRow] - dataCopy[++nextRow];\r
- var b1 = - dataCopy[++priorRow] - dataCopy[++centerRow] - dataCopy[++nextRow];\r
- \r
- var rp = dataCopy[priorRow += 2];\r
- var gp = dataCopy[++priorRow];\r
- var bp = dataCopy[++priorRow];\r
- \r
- var rc = dataCopy[centerRow += 2];\r
- var gc = dataCopy[++centerRow];\r
- var bc = dataCopy[++centerRow];\r
- \r
- var rn = dataCopy[nextRow += 2];\r
- var gn = dataCopy[++nextRow];\r
- var bn = dataCopy[++nextRow];\r
- \r
- var r2 = - rp - rc - rn;\r
- var g2 = - gp - gc - gn;\r
- var b2 = - bp - bc - bn;\r
- \r
- // Main convolution loop\r
- for (var x = 1; x < wm1; ++x) {\r
- centerRow = pixel + 4;\r
- priorRow = centerRow - w4;\r
- nextRow = centerRow + w4;\r
- \r
- var r = 127 + r1 - rp - (rc * -8) - rn;\r
- var g = 127 + g1 - gp - (gc * -8) - gn;\r
- var b = 127 + b1 - bp - (bc * -8) - bn;\r
- \r
- r1 = r2;\r
- g1 = g2;\r
- b1 = b2;\r
- \r
- rp = dataCopy[ priorRow];\r
- gp = dataCopy[++priorRow];\r
- bp = dataCopy[++priorRow];\r
- \r
- rc = dataCopy[ centerRow];\r
- gc = dataCopy[++centerRow];\r
- bc = dataCopy[++centerRow];\r
- \r
- rn = dataCopy[ nextRow];\r
- gn = dataCopy[++nextRow];\r
- bn = dataCopy[++nextRow];\r
- \r
- r += (r2 = - rp - rc - rn);\r
- g += (g2 = - gp - gc - gn);\r
- b += (b2 = - bp - bc - bn);\r
-\r
- if (r > 255) r = 255;\r
- if (g > 255) g = 255;\r
- if (b > 255) b = 255;\r
- if (r < 0) r = 0;\r
- if (g < 0) g = 0;\r
- if (b < 0) b = 0;\r
-\r
- data[pixel] = r;\r
- data[++pixel] = g;\r
- data[++pixel] = b;\r
- //data[++pixel] = 255; // alpha\r
-\r
- pixel+=2;\r
- }\r
- pixel += 8;\r
- }\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}/*\r
- * Pixastic Lib - Emboss filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.emboss = {\r
- process : function(params) {\r
-\r
- var strength = parseFloat(params.options.strength)||1;\r
- var greyLevel = typeof params.options.greyLevel != "undefined" ? parseInt(params.options.greyLevel) : 180;\r
- var direction = params.options.direction||"topleft";\r
- var blend = !!(params.options.blend && params.options.blend != "false");\r
-\r
- var dirY = 0;\r
- var dirX = 0;\r
-\r
- switch (direction) {\r
- case "topleft": // top left\r
- dirY = -1;\r
- dirX = -1;\r
- break;\r
- case "top": // top\r
- dirY = -1;\r
- dirX = 0;\r
- break;\r
- case "topright": // top right\r
- dirY = -1;\r
- dirX = 1;\r
- break;\r
- case "right": // right\r
- dirY = 0;\r
- dirX = 1;\r
- break;\r
- case "bottomright": // bottom right\r
- dirY = 1;\r
- dirX = 1;\r
- break;\r
- case "bottom": // bottom\r
- dirY = 1;\r
- dirX = 0;\r
- break;\r
- case "bottomleft": // bottom left\r
- dirY = 1;\r
- dirX = -1;\r
- break;\r
- case "left": // left\r
- dirY = 0;\r
- dirX = -1;\r
- break;\r
- }\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var dataCopy = Pixastic.prepareData(params, true)\r
-\r
- var invertAlpha = !!params.options.invertAlpha;\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
-\r
- var otherY = dirY;\r
- if (y + otherY < 1) otherY = 0;\r
- if (y + otherY > h) otherY = 0;\r
-\r
- var offsetYOther = (y-1+otherY)*w*4;\r
-\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x-1)*4;\r
-\r
- var otherX = dirX;\r
- if (x + otherX < 1) otherX = 0;\r
- if (x + otherX > w) otherX = 0;\r
-\r
- var offsetOther = offsetYOther + (x-1+otherX)*4;\r
-\r
- var dR = dataCopy[offset] - dataCopy[offsetOther];\r
- var dG = dataCopy[offset+1] - dataCopy[offsetOther+1];\r
- var dB = dataCopy[offset+2] - dataCopy[offsetOther+2];\r
-\r
- var dif = dR;\r
- var absDif = dif > 0 ? dif : -dif;\r
-\r
- var absG = dG > 0 ? dG : -dG;\r
- var absB = dB > 0 ? dB : -dB;\r
-\r
- if (absG > absDif) {\r
- dif = dG;\r
- }\r
- if (absB > absDif) {\r
- dif = dB;\r
- }\r
-\r
- dif *= strength;\r
-\r
- if (blend) {\r
- var r = data[offset] + dif;\r
- var g = data[offset+1] + dif;\r
- var b = data[offset+2] + dif;\r
-\r
- data[offset] = (r > 255) ? 255 : (r < 0 ? 0 : r);\r
- data[offset+1] = (g > 255) ? 255 : (g < 0 ? 0 : g);\r
- data[offset+2] = (b > 255) ? 255 : (b < 0 ? 0 : b);\r
- } else {\r
- var grey = greyLevel - dif;\r
- if (grey < 0) {\r
- grey = 0;\r
- } else if (grey > 255) {\r
- grey = 255;\r
- }\r
-\r
- data[offset] = data[offset+1] = data[offset+2] = grey;\r
- }\r
-\r
- } while (--x);\r
- } while (--y);\r
- return true;\r
-\r
- } else if (Pixastic.Client.isIE()) {\r
- params.image.style.filter += " progid:DXImageTransform.Microsoft.emboss()";\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());\r
- }\r
-\r
-}\r
-/*\r
- * Pixastic Lib - Flip - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.flip = {\r
- process : function(params) {\r
- var rect = params.options.rect;\r
- var copyCanvas = document.createElement("canvas");\r
- copyCanvas.width = rect.width;\r
- copyCanvas.height = rect.height;\r
- copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);\r
-\r
- var ctx = params.canvas.getContext("2d");\r
- ctx.clearRect(rect.left, rect.top, rect.width, rect.height);\r
-\r
- if (params.options.axis == "horizontal") {\r
- ctx.scale(-1,1);\r
- ctx.drawImage(copyCanvas, -rect.left-rect.width, rect.top, rect.width, rect.height)\r
- } else {\r
- ctx.scale(1,-1);\r
- ctx.drawImage(copyCanvas, rect.left, -rect.top-rect.height, rect.width, rect.height)\r
- }\r
-\r
- params.useData = false;\r
-\r
- return true; \r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvas();\r
- }\r
-}\r
-\r
-/*\r
- * Pixastic Lib - Horizontal flip - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.fliph = {\r
- process : function(params) {\r
- if (Pixastic.Client.hasCanvas()) {\r
- var rect = params.options.rect;\r
- var copyCanvas = document.createElement("canvas");\r
- copyCanvas.width = rect.width;\r
- copyCanvas.height = rect.height;\r
- copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);\r
-\r
- var ctx = params.canvas.getContext("2d");\r
- ctx.clearRect(rect.left, rect.top, rect.width, rect.height);\r
- ctx.scale(-1,1);\r
- ctx.drawImage(copyCanvas, -rect.left-rect.width, rect.top, rect.width, rect.height)\r
- params.useData = false;\r
-\r
- return true; \r
-\r
- } else if (Pixastic.Client.isIE()) {\r
- params.image.style.filter += " fliph";\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());\r
- }\r
-}\r
-\r
-/*\r
- * Pixastic Lib - Vertical flip - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.flipv = {\r
- process : function(params) {\r
- if (Pixastic.Client.hasCanvas()) {\r
- var rect = params.options.rect;\r
- var copyCanvas = document.createElement("canvas");\r
- copyCanvas.width = rect.width;\r
- copyCanvas.height = rect.height;\r
- copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);\r
-\r
- var ctx = params.canvas.getContext("2d");\r
- ctx.clearRect(rect.left, rect.top, rect.width, rect.height);\r
- ctx.scale(1,-1);\r
- ctx.drawImage(copyCanvas, rect.left, -rect.top-rect.height, rect.width, rect.height)\r
- params.useData = false;\r
-\r
- return true; \r
-\r
- } else if (Pixastic.Client.isIE()) {\r
- params.image.style.filter += " flipv";\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());\r
- }\r
-}\r
-\r
-/*\r
- * Pixastic Lib - Glow - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-\r
-Pixastic.Actions.glow = {\r
- process : function(params) {\r
-\r
- var amount = (parseFloat(params.options.amount)||0);\r
- var blurAmount = parseFloat(params.options.radius)||0;\r
-\r
- amount = Math.min(1,Math.max(0,amount));\r
- blurAmount = Math.min(5,Math.max(0,blurAmount));\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var rect = params.options.rect;\r
-\r
- var blurCanvas = document.createElement("canvas");\r
- blurCanvas.width = params.width;\r
- blurCanvas.height = params.height;\r
- var blurCtx = blurCanvas.getContext("2d");\r
- blurCtx.drawImage(params.canvas,0,0);\r
-\r
- var scale = 2;\r
- var smallWidth = Math.round(params.width / scale);\r
- var smallHeight = Math.round(params.height / scale);\r
-\r
- var copy = document.createElement("canvas");\r
- copy.width = smallWidth;\r
- copy.height = smallHeight;\r
-\r
- var clear = true;\r
- var steps = Math.round(blurAmount * 20);\r
-\r
- var copyCtx = copy.getContext("2d");\r
- for (var i=0;i<steps;i++) {\r
- var scaledWidth = Math.max(1,Math.round(smallWidth - i));\r
- var scaledHeight = Math.max(1,Math.round(smallHeight - i));\r
- \r
- copyCtx.clearRect(0,0,smallWidth,smallHeight);\r
- \r
- copyCtx.drawImage(\r
- blurCanvas,\r
- 0,0,params.width,params.height,\r
- 0,0,scaledWidth,scaledHeight\r
- );\r
- \r
- blurCtx.clearRect(0,0,params.width,params.height);\r
- \r
- blurCtx.drawImage(\r
- copy,\r
- 0,0,scaledWidth,scaledHeight,\r
- 0,0,params.width,params.height\r
- );\r
- }\r
-\r
- var data = Pixastic.prepareData(params);\r
- var blurData = Pixastic.prepareData({canvas:blurCanvas,options:params.options});\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x*4-4);\r
-\r
- var r = data[offset] + amount * blurData[offset];\r
- var g = data[offset+1] + amount * blurData[offset+1];\r
- var b = data[offset+2] + amount * blurData[offset+2];\r
- \r
- if (r > 255) r = 255;\r
- if (g > 255) g = 255;\r
- if (b > 255) b = 255;\r
- if (r < 0) r = 0;\r
- if (g < 0) g = 0;\r
- if (b < 0) b = 0;\r
-\r
- data[offset] = r;\r
- data[offset+1] = g;\r
- data[offset+2] = b;\r
-\r
- } while (--x);\r
- } while (--y);\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}\r
-\r
-\r
-\r
-/*\r
- * Pixastic Lib - Histogram - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.histogram = {\r
- process : function(params) {\r
-\r
- var average = !!(params.options.average && params.options.average != "false");\r
- var paint = !!(params.options.paint && params.options.paint != "false");\r
- var color = params.options.color || "rgba(255,255,255,0.5)";\r
- var values = [];\r
- if (typeof params.options.returnValue != "object") {\r
- params.options.returnValue = {values:[]};\r
- }\r
- var returnValue = params.options.returnValue;\r
- if (typeof returnValue.values != "array") {\r
- returnValue.values = [];\r
- }\r
- values = returnValue.values;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- params.useData = false;\r
-\r
- for (var i=0;i<256;i++) {\r
- values[i] = 0;\r
- }\r
-\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x*4-4);\r
- var brightness = average ? \r
- Math.round((data[offset]+data[offset+1]+data[offset+2])/3)\r
- : Math.round(data[offset]*0.3 + data[offset+1]*0.59 + data[offset+2]*0.11);\r
- values[brightness]++;\r
-\r
- } while (--x);\r
- } while (--y);\r
-\r
- if (paint) {\r
- var maxValue = 0;\r
- for (var i=0;i<256;i++) {\r
- if (values[i] > maxValue) {\r
- maxValue = values[i];\r
- }\r
- }\r
- var heightScale = params.height / maxValue;\r
- var widthScale = params.width / 256;\r
- var ctx = params.canvas.getContext("2d");\r
- ctx.fillStyle = color;\r
- for (var i=0;i<256;i++) {\r
- ctx.fillRect(\r
- i * widthScale, params.height - heightScale * values[i],\r
- widthScale, values[i] * heightScale\r
- );\r
- }\r
- }\r
-\r
- returnValue.values = values;\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}\r
-/*\r
- * Pixastic Lib - HSL Adjust - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.hsl = {\r
- process : function(params) {\r
-\r
- var hue = parseInt(params.options.hue,10)||0;\r
- var saturation = (parseInt(params.options.saturation,10)||0) / 100;\r
- var lightness = (parseInt(params.options.lightness,10)||0) / 100;\r
-\r
-\r
- // this seems to give the same result as Photoshop\r
- if (saturation < 0) {\r
- var satMul = 1+saturation;\r
- } else {\r
- var satMul = 1+saturation*2;\r
- }\r
-\r
- hue = (hue%360) / 360;\r
- var hue6 = hue * 6;\r
-\r
- var rgbDiv = 1 / 255;\r
-\r
- var light255 = lightness * 255;\r
- var lightp1 = 1 + lightness;\r
- var lightm1 = 1 - lightness;\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
-\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var w4 = w*4;\r
- var y = h;\r
-\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x*4-4);\r
-\r
- var r = data[offset];\r
- var g = data[offset+1];\r
- var b = data[offset+2];\r
-\r
- if (hue != 0 || saturation != 0) {\r
- // ok, here comes rgb to hsl + adjust + hsl to rgb, all in one jumbled mess. \r
- // It's not so pretty, but it's been optimized to get somewhat decent performance.\r
- // The transforms were originally adapted from the ones found in Graphics Gems, but have been heavily modified.\r
- var vs = r;\r
- if (g > vs) vs = g;\r
- if (b > vs) vs = b;\r
- var ms = r;\r
- if (g < ms) ms = g;\r
- if (b < ms) ms = b;\r
- var vm = (vs-ms);\r
- var l = (ms+vs)/255 * 0.5;\r
- if (l > 0) {\r
- if (vm > 0) {\r
- if (l <= 0.5) {\r
- var s = vm / (vs+ms) * satMul;\r
- if (s > 1) s = 1;\r
- var v = (l * (1+s));\r
- } else {\r
- var s = vm / (510-vs-ms) * satMul;\r
- if (s > 1) s = 1;\r
- var v = (l+s - l*s);\r
- }\r
- if (r == vs) {\r
- if (g == ms)\r
- var h = 5 + ((vs-b)/vm) + hue6;\r
- else\r
- var h = 1 - ((vs-g)/vm) + hue6;\r
- } else if (g == vs) {\r
- if (b == ms)\r
- var h = 1 + ((vs-r)/vm) + hue6;\r
- else\r
- var h = 3 - ((vs-b)/vm) + hue6;\r
- } else {\r
- if (r == ms)\r
- var h = 3 + ((vs-g)/vm) + hue6;\r
- else\r
- var h = 5 - ((vs-r)/vm) + hue6;\r
- }\r
- if (h < 0) h+=6;\r
- if (h >= 6) h-=6;\r
- var m = (l+l-v);\r
- var sextant = h>>0;\r
- switch (sextant) {\r
- case 0: r = v*255; g = (m+((v-m)*(h-sextant)))*255; b = m*255; break;\r
- case 1: r = (v-((v-m)*(h-sextant)))*255; g = v*255; b = m*255; break;\r
- case 2: r = m*255; g = v*255; b = (m+((v-m)*(h-sextant)))*255; break;\r
- case 3: r = m*255; g = (v-((v-m)*(h-sextant)))*255; b = v*255; break;\r
- case 4: r = (m+((v-m)*(h-sextant)))*255; g = m*255; b = v*255; break;\r
- case 5: r = v*255; g = m*255; b = (v-((v-m)*(h-sextant)))*255; break;\r
- }\r
- }\r
- }\r
- }\r
-\r
- if (lightness < 0) {\r
- r *= lightp1;\r
- g *= lightp1;\r
- b *= lightp1;\r
- } else if (lightness > 0) {\r
- r = r * lightm1 + light255;\r
- g = g * lightm1 + light255;\r
- b = b * lightm1 + light255;\r
- }\r
-\r
- if (r < 0) r = 0;\r
- if (g < 0) g = 0;\r
- if (b < 0) b = 0;\r
- if (r > 255) r = 255;\r
- if (g > 255) g = 255;\r
- if (b > 255) b = 255;\r
-\r
- data[offset] = r;\r
- data[offset+1] = g;\r
- data[offset+2] = b;\r
-\r
- } while (--x);\r
- } while (--y);\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-\r
-}\r
-/*\r
- * Pixastic Lib - Invert filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.invert = {\r
- process : function(params) {\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
-\r
- var invertAlpha = !!params.options.invertAlpha;\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x-1)*4;\r
- data[offset] = 255 - data[offset];\r
- data[offset+1] = 255 - data[offset+1];\r
- data[offset+2] = 255 - data[offset+2];\r
- if (invertAlpha) data[offset+3] = 255 - data[offset+3];\r
- } while (--x);\r
- } while (--y);\r
-\r
- return true;\r
- } else if (Pixastic.Client.isIE()) {\r
- params.image.style.filter += " invert";\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());\r
- }\r
-}\r
-/*\r
- * Pixastic Lib - Laplace filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.laplace = {\r
- process : function(params) {\r
-\r
- var strength = 1.0;\r
- var invert = !!(params.options.invert && params.options.invert != "false");\r
- var contrast = parseFloat(params.options.edgeStrength)||0;\r
-\r
- var greyLevel = parseInt(params.options.greyLevel)||0;\r
-\r
- contrast = -contrast;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var dataCopy = Pixastic.prepareData(params, true)\r
-\r
- var kernel = [\r
- [-1, -1, -1],\r
- [-1, 8, -1],\r
- [-1, -1, -1]\r
- ];\r
-\r
- var weight = 1/8;\r
-\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
-\r
- var nextY = (y == h) ? y - 1 : y;\r
- var prevY = (y == 1) ? 0 : y-2;\r
-\r
- var offsetYPrev = prevY*w*4;\r
- var offsetYNext = nextY*w*4;\r
-\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x*4-4);\r
-\r
- var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;\r
- var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;\r
- \r
- var r = ((-dataCopy[offsetPrev-4]\r
- - dataCopy[offsetPrev]\r
- - dataCopy[offsetPrev+4]\r
- - dataCopy[offset-4]\r
- - dataCopy[offset+4]\r
- - dataCopy[offsetNext-4]\r
- - dataCopy[offsetNext]\r
- - dataCopy[offsetNext+4])\r
- + dataCopy[offset] * 8) \r
- * weight;\r
- \r
- var g = ((-dataCopy[offsetPrev-3]\r
- - dataCopy[offsetPrev+1]\r
- - dataCopy[offsetPrev+5]\r
- - dataCopy[offset-3]\r
- - dataCopy[offset+5]\r
- - dataCopy[offsetNext-3]\r
- - dataCopy[offsetNext+1]\r
- - dataCopy[offsetNext+5])\r
- + dataCopy[offset+1] * 8)\r
- * weight;\r
- \r
- var b = ((-dataCopy[offsetPrev-2]\r
- - dataCopy[offsetPrev+2]\r
- - dataCopy[offsetPrev+6]\r
- - dataCopy[offset-2]\r
- - dataCopy[offset+6]\r
- - dataCopy[offsetNext-2]\r
- - dataCopy[offsetNext+2]\r
- - dataCopy[offsetNext+6])\r
- + dataCopy[offset+2] * 8)\r
- * weight;\r
-\r
- var brightness = ((r + g + b)/3) + greyLevel;\r
-\r
- if (contrast != 0) {\r
- if (brightness > 127) {\r
- brightness += ((brightness + 1) - 128) * contrast;\r
- } else if (brightness < 127) {\r
- brightness -= (brightness + 1) * contrast;\r
- }\r
- }\r
- if (invert) {\r
- brightness = 255 - brightness;\r
- }\r
- if (brightness < 0 ) brightness = 0;\r
- if (brightness > 255 ) brightness = 255;\r
-\r
- data[offset] = data[offset+1] = data[offset+2] = brightness;\r
-\r
- } while (--x);\r
- } while (--y);\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}\r
-\r
-/*\r
- * Pixastic Lib - Lighten filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.lighten = {\r
-\r
- process : function(params) {\r
- var amount = parseFloat(params.options.amount) || 0;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x-1)*4;\r
-\r
- var r = data[offset];\r
- var g = data[offset+1];\r
- var b = data[offset+2];\r
-\r
- r += r*amount;\r
- g += g*amount;\r
- b += b*amount;\r
-\r
- if (r < 0 ) r = 0;\r
- if (g < 0 ) g = 0;\r
- if (b < 0 ) b = 0;\r
- if (r > 255 ) r = 255;\r
- if (g > 255 ) g = 255;\r
- if (b > 255 ) b = 255;\r
-\r
- data[offset] = r;\r
- data[offset+1] = g;\r
- data[offset+2] = b;\r
-\r
- } while (--x);\r
- } while (--y);\r
- return true;\r
-\r
- } else if (Pixastic.Client.isIE()) {\r
- var img = params.image;\r
- if (amount < 0) {\r
- img.style.filter += " light()";\r
- img.filters[img.filters.length-1].addAmbient(\r
- 255,255,255,\r
- 100 * -amount\r
- );\r
- } else if (amount > 0) {\r
- img.style.filter += " light()";\r
- img.filters[img.filters.length-1].addAmbient(\r
- 255,255,255,\r
- 100\r
- );\r
- img.filters[img.filters.length-1].addAmbient(\r
- 255,255,255,\r
- 100 * amount\r
- );\r
- }\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());\r
- }\r
-}\r
-/*\r
- * Pixastic Lib - Mosaic filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.mosaic = {\r
-\r
- process : function(params) {\r
- var blockSize = Math.max(1,parseInt(params.options.blockSize,10));\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
-\r
- var ctx = params.canvas.getContext("2d");\r
-\r
- var pixel = document.createElement("canvas");\r
- pixel.width = pixel.height = 1;\r
- var pixelCtx = pixel.getContext("2d");\r
-\r
- var copy = document.createElement("canvas");\r
- copy.width = w;\r
- copy.height = h;\r
- var copyCtx = copy.getContext("2d");\r
- copyCtx.drawImage(params.canvas,rect.left,rect.top,w,h, 0,0,w,h);\r
-\r
- for (var y=0;y<h;y+=blockSize) {\r
- for (var x=0;x<w;x+=blockSize) {\r
- var blockSizeX = blockSize;\r
- var blockSizeY = blockSize;\r
- \r
- if (blockSizeX + x > w)\r
- blockSizeX = w - x;\r
- if (blockSizeY + y > h)\r
- blockSizeY = h - y;\r
-\r
- pixelCtx.drawImage(copy, x, y, blockSizeX, blockSizeY, 0, 0, 1, 1);\r
- var data = pixelCtx.getImageData(0,0,1,1).data;\r
- ctx.fillStyle = "rgb(" + data[0] + "," + data[1] + "," + data[2] + ")";\r
- ctx.fillRect(rect.left + x, rect.top + y, blockSize, blockSize);\r
- }\r
- }\r
- params.useData = false;\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvasImageData());\r
- }\r
-}/*\r
- * Pixastic Lib - Noise filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.noise = {\r
-\r
- process : function(params) {\r
- var amount = 0;\r
- var strength = 0;\r
- var mono = false;\r
-\r
- if (typeof params.options.amount != "undefined")\r
- amount = parseFloat(params.options.amount)||0;\r
- if (typeof params.options.strength != "undefined")\r
- strength = parseFloat(params.options.strength)||0;\r
- if (typeof params.options.mono != "undefined")\r
- mono = !!(params.options.mono && params.options.mono != "false");\r
-\r
- amount = Math.max(0,Math.min(1,amount));\r
- strength = Math.max(0,Math.min(1,strength));\r
-\r
- var noise = 128 * strength;\r
- var noise2 = noise / 2;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
- var random = Math.random;\r
-\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x-1)*4;\r
- if (random() < amount) {\r
- if (mono) {\r
- var pixelNoise = - noise2 + random() * noise;\r
- var r = data[offset] + pixelNoise;\r
- var g = data[offset+1] + pixelNoise;\r
- var b = data[offset+2] + pixelNoise;\r
- } else {\r
- var r = data[offset] - noise2 + (random() * noise);\r
- var g = data[offset+1] - noise2 + (random() * noise);\r
- var b = data[offset+2] - noise2 + (random() * noise);\r
- }\r
-\r
- if (r < 0 ) r = 0;\r
- if (g < 0 ) g = 0;\r
- if (b < 0 ) b = 0;\r
- if (r > 255 ) r = 255;\r
- if (g > 255 ) g = 255;\r
- if (b > 255 ) b = 255;\r
-\r
- data[offset] = r;\r
- data[offset+1] = g;\r
- data[offset+2] = b;\r
- }\r
- } while (--x);\r
- } while (--y);\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}\r
-\r
-/*\r
- * Pixastic Lib - Posterize effect - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.posterize = {\r
-\r
- process : function(params) {\r
-\r
- \r
- var numLevels = 256;\r
- if (typeof params.options.levels != "undefined")\r
- numLevels = parseInt(params.options.levels,10)||1;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
-\r
- numLevels = Math.max(2,Math.min(256,numLevels));\r
- \r
- var numAreas = 256 / numLevels;\r
- var numValues = 256 / (numLevels-1);\r
-\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x-1)*4;\r
-\r
- var r = numValues * ((data[offset] / numAreas)>>0);\r
- var g = numValues * ((data[offset+1] / numAreas)>>0);\r
- var b = numValues * ((data[offset+2] / numAreas)>>0);\r
-\r
- if (r > 255) r = 255;\r
- if (g > 255) g = 255;\r
- if (b > 255) b = 255;\r
-\r
- data[offset] = r;\r
- data[offset+1] = g;\r
- data[offset+2] = b;\r
-\r
- } while (--x);\r
- } while (--y);\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}\r
-\r
-\r
-/*\r
- * Pixastic Lib - Pointillize filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.pointillize = {\r
-\r
- process : function(params) {\r
- var radius = Math.max(1,parseInt(params.options.radius,10));\r
- var density = Math.min(5,Math.max(0,parseFloat(params.options.density)||0));\r
- var noise = Math.max(0,parseFloat(params.options.noise)||0);\r
- var transparent = !!(params.options.transparent && params.options.transparent != "false");\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
-\r
- var ctx = params.canvas.getContext("2d");\r
- var canvasWidth = params.canvas.width;\r
- var canvasHeight = params.canvas.height;\r
-\r
- var pixel = document.createElement("canvas");\r
- pixel.width = pixel.height = 1;\r
- var pixelCtx = pixel.getContext("2d");\r
-\r
- var copy = document.createElement("canvas");\r
- copy.width = w;\r
- copy.height = h;\r
- var copyCtx = copy.getContext("2d");\r
- copyCtx.drawImage(params.canvas,rect.left,rect.top,w,h, 0,0,w,h);\r
-\r
- var diameter = radius * 2;\r
-\r
- if (transparent)\r
- ctx.clearRect(rect.left, rect.top, rect.width, rect.height);\r
-\r
- var noiseRadius = radius * noise;\r
-\r
- var dist = 1 / density;\r
-\r
- for (var y=0;y<h+radius;y+=diameter*dist) {\r
- for (var x=0;x<w+radius;x+=diameter*dist) {\r
- rndX = noise ? (x+((Math.random()*2-1) * noiseRadius))>>0 : x;\r
- rndY = noise ? (y+((Math.random()*2-1) * noiseRadius))>>0 : y;\r
-\r
- var pixX = rndX - radius;\r
- var pixY = rndY - radius;\r
- if (pixX < 0) pixX = 0;\r
- if (pixY < 0) pixY = 0;\r
-\r
- var cx = rndX + rect.left;\r
- var cy = rndY + rect.top;\r
- if (cx < 0) cx = 0;\r
- if (cx > canvasWidth) cx = canvasWidth;\r
- if (cy < 0) cy = 0;\r
- if (cy > canvasHeight) cy = canvasHeight;\r
-\r
- var diameterX = diameter;\r
- var diameterY = diameter;\r
-\r
- if (diameterX + pixX > w)\r
- diameterX = w - pixX;\r
- if (diameterY + pixY > h)\r
- diameterY = h - pixY;\r
- if (diameterX < 1) diameterX = 1;\r
- if (diameterY < 1) diameterY = 1;\r
-\r
- pixelCtx.drawImage(copy, pixX, pixY, diameterX, diameterY, 0, 0, 1, 1);\r
- var data = pixelCtx.getImageData(0,0,1,1).data;\r
-\r
- ctx.fillStyle = "rgb(" + data[0] + "," + data[1] + "," + data[2] + ")";\r
- ctx.beginPath();\r
- ctx.arc(cx, cy, radius, 0, Math.PI*2, true);\r
- ctx.closePath();\r
- ctx.fill();\r
- }\r
- }\r
-\r
- params.useData = false;\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvasImageData());\r
- }\r
-}/*\r
- * Pixastic Lib - Resize - v0.1.0\r
- * Copyright (c) 2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.resize = {\r
- process : function(params) {\r
- if (Pixastic.Client.hasCanvas()) {\r
- var width = parseInt(params.options.width,10);\r
- var height = parseInt(params.options.height,10);\r
- var canvas = params.canvas;\r
-\r
- if (width < 1) width = 1;\r
- if (width < 2) width = 2;\r
-\r
- var copy = document.createElement("canvas");\r
- copy.width = width;\r
- copy.height = height;\r
-\r
- copy.getContext("2d").drawImage(canvas,0,0,width,height);\r
- canvas.width = width;\r
- canvas.height = height;\r
-\r
- canvas.getContext("2d").drawImage(copy,0,0);\r
-\r
- params.useData = false;\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvas();\r
- }\r
-}\r
-\r
-\r
-/*\r
- * Pixastic Lib - Remove noise - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.removenoise = {\r
- process : function(params) {\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
-\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
-\r
- var nextY = (y == h) ? y - 1 : y;\r
- var prevY = (y == 1) ? 0 : y-2;\r
-\r
- var offsetYPrev = prevY*w*4;\r
- var offsetYNext = nextY*w*4;\r
-\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x*4-4);\r
-\r
- var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;\r
- var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;\r
-\r
- var minR, maxR, minG, maxG, minB, maxB;\r
-\r
- minR = maxR = data[offsetPrev];\r
- var r1 = data[offset-4], r2 = data[offset+4], r3 = data[offsetNext];\r
- if (r1 < minR) minR = r1;\r
- if (r2 < minR) minR = r2;\r
- if (r3 < minR) minR = r3;\r
- if (r1 > maxR) maxR = r1;\r
- if (r2 > maxR) maxR = r2;\r
- if (r3 > maxR) maxR = r3;\r
-\r
- minG = maxG = data[offsetPrev+1];\r
- var g1 = data[offset-3], g2 = data[offset+5], g3 = data[offsetNext+1];\r
- if (g1 < minG) minG = g1;\r
- if (g2 < minG) minG = g2;\r
- if (g3 < minG) minG = g3;\r
- if (g1 > maxG) maxG = g1;\r
- if (g2 > maxG) maxG = g2;\r
- if (g3 > maxG) maxG = g3;\r
-\r
- minB = maxB = data[offsetPrev+2];\r
- var b1 = data[offset-2], b2 = data[offset+6], b3 = data[offsetNext+2];\r
- if (b1 < minB) minB = b1;\r
- if (b2 < minB) minB = b2;\r
- if (b3 < minB) minB = b3;\r
- if (b1 > maxB) maxB = b1;\r
- if (b2 > maxB) maxB = b2;\r
- if (b3 > maxB) maxB = b3;\r
-\r
- if (data[offset] > maxR) {\r
- data[offset] = maxR;\r
- } else if (data[offset] < minR) {\r
- data[offset] = minR;\r
- }\r
- if (data[offset+1] > maxG) {\r
- data[offset+1] = maxG;\r
- } else if (data[offset+1] < minG) {\r
- data[offset+1] = minG;\r
- }\r
- if (data[offset+2] > maxB) {\r
- data[offset+2] = maxB;\r
- } else if (data[offset+2] < minB) {\r
- data[offset+2] = minB;\r
- }\r
-\r
- } while (--x);\r
- } while (--y);\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}/*\r
- * Pixastic Lib - Rotate - v0.1.0\r
- * Copyright (c) 2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.rotate = {\r
- process : function(params) {\r
- if (Pixastic.Client.hasCanvas()) {\r
- var canvas = params.canvas;\r
-\r
- var width = params.width;\r
- var height = params.height;\r
-\r
- var copy = document.createElement("canvas");\r
- copy.width = width;\r
- copy.height = height;\r
- copy.getContext("2d").drawImage(canvas,0,0,width,height);\r
-\r
- var angle = -parseFloat(params.options.angle) * Math.PI / 180;\r
-\r
- var dimAngle = angle;\r
- if (dimAngle > Math.PI*0.5)\r
- dimAngle = Math.PI - dimAngle;\r
- if (dimAngle < -Math.PI*0.5)\r
- dimAngle = -Math.PI - dimAngle;\r
-\r
- var diag = Math.sqrt(width*width + height*height);\r
-\r
- var diagAngle1 = Math.abs(dimAngle) - Math.abs(Math.atan2(height, width));\r
- var diagAngle2 = Math.abs(dimAngle) + Math.abs(Math.atan2(height, width));\r
-\r
- var newWidth = Math.abs(Math.cos(diagAngle1) * diag);\r
- var newHeight = Math.abs(Math.sin(diagAngle2) * diag);\r
-\r
- canvas.width = newWidth;\r
- canvas.height = newHeight;\r
-\r
- var ctx = canvas.getContext("2d");\r
- ctx.translate(newWidth/2, newHeight/2);\r
- ctx.rotate(angle);\r
- ctx.drawImage(copy,-width/2,-height/2);\r
-\r
- params.useData = false;\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvas();\r
- }\r
-}\r
-\r
-\r
-/*\r
- * Pixastic Lib - Sepia filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.sepia = {\r
-\r
- process : function(params) {\r
- var mode = (parseInt(params.options.mode,10)||0);\r
- if (mode < 0) mode = 0;\r
- if (mode > 1) mode = 1;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x-1)*4;\r
-\r
- if (mode) {\r
- // a bit faster, but not as good\r
- var d = data[offset] * 0.299 + data[offset+1] * 0.587 + data[offset+2] * 0.114;\r
- var r = (d + 39);\r
- var g = (d + 14);\r
- var b = (d - 36);\r
- } else {\r
- // Microsoft\r
- var or = data[offset];\r
- var og = data[offset+1];\r
- var ob = data[offset+2];\r
- \r
- var r = (or * 0.393 + og * 0.769 + ob * 0.189);\r
- var g = (or * 0.349 + og * 0.686 + ob * 0.168);\r
- var b = (or * 0.272 + og * 0.534 + ob * 0.131);\r
- }\r
-\r
- if (r < 0) r = 0; if (r > 255) r = 255;\r
- if (g < 0) g = 0; if (g > 255) g = 255;\r
- if (b < 0) b = 0; if (b > 255) b = 255;\r
-\r
- data[offset] = r;\r
- data[offset+1] = g;\r
- data[offset+2] = b;\r
-\r
- } while (--x);\r
- } while (--y);\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}/*\r
- * Pixastic Lib - Sharpen filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.sharpen = {\r
- process : function(params) {\r
-\r
- var strength = 0;\r
- if (typeof params.options.amount != "undefined")\r
- strength = parseFloat(params.options.amount)||0;\r
-\r
- if (strength < 0) strength = 0;\r
- if (strength > 1) strength = 1;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var dataCopy = Pixastic.prepareData(params, true)\r
-\r
- var mul = 15;\r
- var mulOther = 1 + 3*strength;\r
-\r
- var kernel = [\r
- [0, -mulOther, 0],\r
- [-mulOther, mul, -mulOther],\r
- [0, -mulOther, 0]\r
- ];\r
-\r
- var weight = 0;\r
- for (var i=0;i<3;i++) {\r
- for (var j=0;j<3;j++) {\r
- weight += kernel[i][j];\r
- }\r
- }\r
-\r
- weight = 1 / weight;\r
-\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
-\r
- mul *= weight;\r
- mulOther *= weight;\r
-\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
-\r
- var nextY = (y == h) ? y - 1 : y;\r
- var prevY = (y == 1) ? 0 : y-2;\r
-\r
- var offsetYPrev = prevY*w4;\r
- var offsetYNext = nextY*w4;\r
-\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x*4-4);\r
-\r
- var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;\r
- var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;\r
-\r
- var r = ((\r
- - dataCopy[offsetPrev]\r
- - dataCopy[offset-4]\r
- - dataCopy[offset+4]\r
- - dataCopy[offsetNext]) * mulOther\r
- + dataCopy[offset] * mul\r
- );\r
-\r
- var g = ((\r
- - dataCopy[offsetPrev+1]\r
- - dataCopy[offset-3]\r
- - dataCopy[offset+5]\r
- - dataCopy[offsetNext+1]) * mulOther\r
- + dataCopy[offset+1] * mul\r
- );\r
-\r
- var b = ((\r
- - dataCopy[offsetPrev+2]\r
- - dataCopy[offset-2]\r
- - dataCopy[offset+6]\r
- - dataCopy[offsetNext+2]) * mulOther\r
- + dataCopy[offset+2] * mul\r
- );\r
-\r
-\r
- if (r < 0 ) r = 0;\r
- if (g < 0 ) g = 0;\r
- if (b < 0 ) b = 0;\r
- if (r > 255 ) r = 255;\r
- if (g > 255 ) g = 255;\r
- if (b > 255 ) b = 255;\r
-\r
- data[offset] = r;\r
- data[offset+1] = g;\r
- data[offset+2] = b;\r
-\r
- } while (--x);\r
- } while (--y);\r
-\r
- return true;\r
-\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}\r
-/*\r
- * Pixastic Lib - Solarize filter - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-Pixastic.Actions.solarize = {\r
-\r
- process : function(params) {\r
- var useAverage = !!(params.options.average && params.options.average != "false");\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var data = Pixastic.prepareData(params);\r
- var rect = params.options.rect;\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x-1)*4;\r
-\r
- var r = data[offset];\r
- var g = data[offset+1];\r
- var b = data[offset+2];\r
-\r
- if (r > 127) r = 255 - r;\r
- if (g > 127) g = 255 - g;\r
- if (b > 127) b = 255 - b;\r
-\r
- data[offset] = r;\r
- data[offset+1] = g;\r
- data[offset+2] = b;\r
-\r
- } while (--x);\r
- } while (--y);\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return (Pixastic.Client.hasCanvasImageData());\r
- }\r
-}/*\r
- * Pixastic Lib - USM - v0.1.0\r
- * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/\r
- * License: [http://www.pixastic.com/lib/license.txt]\r
- */\r
-\r
-\r
-Pixastic.Actions.unsharpmask = {\r
- process : function(params) {\r
-\r
- var amount = (parseFloat(params.options.amount)||0);\r
- var blurAmount = parseFloat(params.options.radius)||0;\r
- var threshold = parseFloat(params.options.threshold)||0;\r
-\r
- amount = Math.min(500,Math.max(0,amount)) / 2;\r
- blurAmount = Math.min(5,Math.max(0,blurAmount)) / 10;\r
- threshold = Math.min(255,Math.max(0,threshold));\r
-\r
- threshold--;\r
- var thresholdNeg = -threshold;\r
-\r
- amount *= 0.016;\r
- amount++;\r
-\r
- if (Pixastic.Client.hasCanvasImageData()) {\r
- var rect = params.options.rect;\r
-\r
- var blurCanvas = document.createElement("canvas");\r
- blurCanvas.width = params.width;\r
- blurCanvas.height = params.height;\r
- var blurCtx = blurCanvas.getContext("2d");\r
- blurCtx.drawImage(params.canvas,0,0);\r
-\r
- var scale = 2;\r
- var smallWidth = Math.round(params.width / scale);\r
- var smallHeight = Math.round(params.height / scale);\r
-\r
- var copy = document.createElement("canvas");\r
- copy.width = smallWidth;\r
- copy.height = smallHeight;\r
-\r
- var steps = Math.round(blurAmount * 20);\r
-\r
- var copyCtx = copy.getContext("2d");\r
- for (var i=0;i<steps;i++) {\r
- var scaledWidth = Math.max(1,Math.round(smallWidth - i));\r
- var scaledHeight = Math.max(1,Math.round(smallHeight - i));\r
-\r
- copyCtx.clearRect(0,0,smallWidth,smallHeight);\r
-\r
- copyCtx.drawImage(\r
- blurCanvas,\r
- 0,0,params.width,params.height,\r
- 0,0,scaledWidth,scaledHeight\r
- );\r
- \r
- blurCtx.clearRect(0,0,params.width,params.height);\r
- \r
- blurCtx.drawImage(\r
- copy,\r
- 0,0,scaledWidth,scaledHeight,\r
- 0,0,params.width,params.height\r
- );\r
- }\r
-\r
- var data = Pixastic.prepareData(params);\r
- var blurData = Pixastic.prepareData({canvas:blurCanvas,options:params.options});\r
- var w = rect.width;\r
- var h = rect.height;\r
- var w4 = w*4;\r
- var y = h;\r
- do {\r
- var offsetY = (y-1)*w4;\r
- var x = w;\r
- do {\r
- var offset = offsetY + (x*4-4);\r
-\r
- var difR = data[offset] - blurData[offset];\r
- if (difR > threshold || difR < thresholdNeg) {\r
- var blurR = blurData[offset];\r
- blurR = amount * difR + blurR;\r
- data[offset] = blurR > 255 ? 255 : (blurR < 0 ? 0 : blurR);\r
- }\r
-\r
- var difG = data[offset+1] - blurData[offset+1];\r
- if (difG > threshold || difG < thresholdNeg) {\r
- var blurG = blurData[offset+1];\r
- blurG = amount * difG + blurG;\r
- data[offset+1] = blurG > 255 ? 255 : (blurG < 0 ? 0 : blurG);\r
- }\r
-\r
- var difB = data[offset+2] - blurData[offset+2];\r
- if (difB > threshold || difB < thresholdNeg) {\r
- var blurB = blurData[offset+2];\r
- blurB = amount * difB + blurB;\r
- data[offset+2] = blurB > 255 ? 255 : (blurB < 0 ? 0 : blurB);\r
- }\r
-\r
- } while (--x);\r
- } while (--y);\r
-\r
- return true;\r
- }\r
- },\r
- checkSupport : function() {\r
- return Pixastic.Client.hasCanvasImageData();\r
- }\r
-}\r
-\r
-\r
-\r
-\r
+/*
+ * Pixastic Lib - Core Functions - v0.1.3
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+var Pixastic = (function() {
+
+
+ function addEvent(el, event, handler) {
+ if (el.addEventListener)
+ el.addEventListener(event, handler, false);
+ else if (el.attachEvent)
+ el.attachEvent("on" + event, handler);
+ }
+
+ function onready(handler) {
+ var handlerDone = false;
+ var execHandler = function() {
+ if (!handlerDone) {
+ handlerDone = true;
+ handler();
+ }
+ }
+ document.write("<"+"script defer src=\"//:\" id=\"__onload_ie_sumbox__\"></"+"script>");
+ var script = document.getElementById("__onload_ie_sumbox__");
+ script.onreadystatechange = function() {
+ if (script.readyState == "complete") {
+ script.parentNode.removeChild(script);
+ execHandler();
+ }
+ }
+ if (document.addEventListener)
+ document.addEventListener("DOMContentLoaded", execHandler, false);
+ addEvent(window, "load", execHandler);
+ }
+
+ function init() {
+ if (!Pixastic.parseOnLoad) return;
+ var imgEls = getElementsByClass("pixastic", null, "img");
+ var canvasEls = getElementsByClass("pixastic", null, "canvas");
+ var elements = imgEls.concat(canvasEls);
+ for (var i=0;i<elements.length;i++) {
+ (function() {
+
+ var el = elements[i];
+ var actions = [];
+ var classes = el.className.split(" ");
+ for (var c=0;c<classes.length;c++) {
+ var cls = classes[c];
+ if (cls.substring(0,9) == "pixastic-") {
+ var actionName = cls.substring(9);
+ if (actionName != "")
+ actions.push(actionName);
+ }
+ }
+ if (actions.length) {
+ if (el.tagName.toLowerCase() == "img") {
+ var dataImg = new Image();
+ dataImg.src = el.src;
+ if (dataImg.complete) {
+ for (var a=0;a<actions.length;a++) {
+ var res = Pixastic.applyAction(el, el, actions[a], null);
+ if (res)
+ el = res;
+ }
+ } else {
+ dataImg.onload = function() {
+ for (var a=0;a<actions.length;a++) {
+ var res = Pixastic.applyAction(el, el, actions[a], null)
+ if (res)
+ el = res;
+ }
+ }
+ }
+ } else {
+ setTimeout(function() {
+ for (var a=0;a<actions.length;a++) {
+ var res = Pixastic.applyAction(
+ el, el, actions[a], null
+ );
+ if (res)
+ el = res;
+ }
+ },1);
+ }
+ }
+
+ })();
+ }
+ }
+
+// if (typeof pixastic_no_onready == "undefined") // yuck.
+// onready(init);
+
+ // getElementsByClass by Dustin Diaz, http://www.dustindiaz.com/getelementsbyclass/
+ function getElementsByClass(searchClass,node,tag) {
+ var classElements = new Array();
+ if ( node == null )
+ node = document;
+ if ( tag == null )
+ tag = '*';
+
+ var els = node.getElementsByTagName(tag);
+ var elsLen = els.length;
+ var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
+ for (i = 0, j = 0; i < elsLen; i++) {
+ if ( pattern.test(els[i].className) ) {
+ classElements[j] = els[i];
+ j++;
+ }
+ }
+ return classElements;
+ }
+
+ var debugElement;
+
+ function writeDebug(text, level) {
+ if (!Pixastic.debug) return;
+ try {
+ switch (level) {
+ case "warn" :
+ console.warn("Pixastic:", text);
+ break;
+ case "error" :
+ console.error("Pixastic:", text);
+ break;
+ default:
+ console.log("Pixastic:", text);
+ }
+ } catch(e) {
+ }
+ if (!debugElement) {
+
+ }
+ }
+
+
+ return {
+
+ parseOnLoad : false,
+
+ debug : false,
+
+ applyAction : function(img, dataImg, actionName, options) {
+
+ options = options || {};
+
+ var imageIsCanvas = (img.tagName.toLowerCase() == "canvas");
+ if (imageIsCanvas && Pixastic.Client.isIE()) {
+ if (Pixastic.debug) writeDebug("Tried to process a canvas element but browser is IE.");
+ return false;
+ }
+
+ var canvas, ctx;
+ if (Pixastic.Client.hasCanvas()) {
+ canvas = document.createElement("canvas");
+ ctx = canvas.getContext("2d");
+ }
+
+ var w = parseInt(img.offsetWidth);
+ var h = parseInt(img.offsetHeight);
+
+ if (imageIsCanvas) {
+ w = img.width;
+ h = img.height;
+ }
+
+ if (actionName.indexOf("(") > -1) {
+ var tmp = actionName;
+ actionName = tmp.substr(0, tmp.indexOf("("));
+ var arg = tmp.match(/\((.*?)\)/);
+ if (arg[1]) {
+ arg = arg[1].split(";");
+ for (var a=0;a<arg.length;a++) {
+ thisArg = arg[a].split("=");
+ if (thisArg.length == 2) {
+ if (thisArg[0] == "rect") {
+ var rectVal = thisArg[1].split(",");
+ options[thisArg[0]] = {
+ left : parseInt(rectVal[0],10)||0,
+ top : parseInt(rectVal[1],10)||0,
+ width : parseInt(rectVal[2],10)||0,
+ height : parseInt(rectVal[3],10)||0
+ }
+ } else {
+ options[thisArg[0]] = thisArg[1];
+ }
+ }
+ }
+ }
+ }
+
+ if (!options.rect) {
+ options.rect = {
+ left : 0, top : 0, width : w, height : h
+ };
+ }
+ var validAction = false;
+ if (Pixastic.Actions[actionName] && typeof Pixastic.Actions[actionName].process == "function") {
+ validAction = true;
+ }
+ if (!validAction) {
+ if (Pixastic.debug) writeDebug("Invalid action \"" + actionName + "\". Maybe file not included?");
+ return false;
+ }
+ if (!Pixastic.Actions[actionName].checkSupport()) {
+ if (Pixastic.debug) writeDebug("Action \"" + actionName + "\" not supported by this browser.");
+ return false;
+ }
+
+ if (Pixastic.Client.hasCanvas()) {
+ canvas.width = w;
+ canvas.height = h;
+ canvas.style.width = w+"px";
+ canvas.style.height = h+"px";
+ ctx.drawImage(dataImg,0,0,w,h);
+
+ if (!img.__pixastic_org_image) {
+ canvas.__pixastic_org_image = img;
+ canvas.__pixastic_org_width = w;
+ canvas.__pixastic_org_height = h;
+ } else {
+ canvas.__pixastic_org_image = img.__pixastic_org_image;
+ canvas.__pixastic_org_width = img.__pixastic_org_width;
+ canvas.__pixastic_org_height = img.__pixastic_org_height;
+ }
+
+ } else if (Pixastic.Client.isIE() && typeof img.__pixastic_org_style == "undefined") {
+ img.__pixastic_org_style = img.style.cssText;
+ }
+
+ var params = {
+ image : img,
+ canvas : canvas,
+ width : w,
+ height : h,
+ useData : true,
+ options : options
+ }
+
+ // Ok, let's do it!
+
+ var res = Pixastic.Actions[actionName].process(params);
+
+ if (!res) {
+ return false;
+ }
+
+ if (Pixastic.Client.hasCanvas()) {
+ if (params.useData) {
+ if (Pixastic.Client.hasCanvasImageData()) {
+ canvas.getContext("2d").putImageData(params.canvasData, options.rect.left, options.rect.top);
+
+ // Opera doesn't seem to update the canvas until we draw something on it, lets draw a 0x0 rectangle.
+ canvas.getContext("2d").fillRect(0,0,0,0);
+ }
+ }
+
+ if (!options.leaveDOM) {
+ // copy properties and stuff from the source image
+ canvas.title = img.title;
+ canvas.imgsrc = img.imgsrc;
+ if (!imageIsCanvas) canvas.alt = img.alt;
+ if (!imageIsCanvas) canvas.imgsrc = img.src;
+ canvas.className = img.className;
+ canvas.style.cssText = img.style.cssText;
+ canvas.name = img.name;
+ canvas.tabIndex = img.tabIndex;
+ canvas.id = img.id;
+ if (img.parentNode && img.parentNode.replaceChild) {
+ img.parentNode.replaceChild(canvas, img);
+ }
+ }
+
+ options.resultCanvas = canvas;
+
+ return canvas;
+ }
+
+ return img;
+ },
+
+ prepareData : function(params, getCopy) {
+ var ctx = params.canvas.getContext("2d");
+ var rect = params.options.rect;
+ var dataDesc = ctx.getImageData(rect.left, rect.top, rect.width, rect.height);
+ var data = dataDesc.data;
+ if (!getCopy) params.canvasData = dataDesc;
+ return data;
+ },
+
+ // load the image file
+ process : function(img, actionName, options, callback)
+ {
+ if (img.tagName.toLowerCase() == "img") {
+ var dataImg = new Image();
+ dataImg.src = img.src;
+ if (dataImg.complete) {
+ var res = Pixastic.applyAction(img, dataImg, actionName, options);
+ if (callback) callback(res);
+ return res;
+ } else {
+ dataImg.onload = function() {
+ var res = Pixastic.applyAction(img, dataImg, actionName, options)
+ if (callback) callback(res);
+ }
+ }
+ }
+ if (img.tagName.toLowerCase() == "canvas") {
+ var res = Pixastic.applyAction(img, img, actionName, options);
+ if (callback) callback(res);
+ return res;
+ }
+ },
+
+ revert : function(img) {
+ if (Pixastic.Client.hasCanvas()) {
+ if (img.tagName.toLowerCase() == "canvas" && img.__pixastic_org_image) {
+ img.width = img.__pixastic_org_width;
+ img.height = img.__pixastic_org_height;
+ img.getContext("2d").drawImage(img.__pixastic_org_image, 0, 0);
+
+ if (img.parentNode && img.parentNode.replaceChild) {
+ img.parentNode.replaceChild(img.__pixastic_org_image, img);
+ }
+
+ return img;
+ }
+ } else if (Pixastic.Client.isIE() && typeof img.__pixastic_org_style != "undefined") {
+ img.style.cssText = img.__pixastic_org_style;
+ }
+ },
+
+ Client : {
+ hasCanvas : (function() {
+ var c = document.createElement("canvas");
+ var val = false;
+ try {
+ val = !!((typeof c.getContext == "function") && c.getContext("2d"));
+ } catch(e) {}
+ return function() {
+ return val;
+ }
+ })(),
+
+ hasCanvasImageData : (function() {
+ var c = document.createElement("canvas");
+ var val = false;
+ var ctx;
+ try {
+ if (typeof c.getContext == "function" && (ctx = c.getContext("2d"))) {
+ val = (typeof ctx.getImageData == "function");
+ }
+ } catch(e) {}
+ return function() {
+ return val;
+ }
+ })(),
+
+ isIE : function() {
+ return !!document.all && !!window.attachEvent && !window.opera;
+ }
+ },
+
+ Actions : {}
+ }
+
+
+})();
+/*
+ * Pixastic Lib - jQuery plugin
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+if (typeof jQuery != "undefined" && jQuery && jQuery.fn) {
+ jQuery.fn.pixastic = function(action, options) {
+ var newElements = [];
+ this.each(
+ function () {
+ if (this.tagName.toLowerCase() == "img" && !this.complete) {
+ return;
+ }
+ var res = Pixastic.process(this, action, options);
+ if (res) {
+ newElements.push(res);
+ }
+ }
+ );
+ if (newElements.length > 0)
+ return jQuery(newElements);
+ else
+ return this;
+ };
+
+};
+/*
+ * Pixastic Lib - Blend - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.blend = {
+
+ process : function(params) {
+ var amount = parseFloat(params.options.amount);
+ var mode = (params.options.mode || "normal").toLowerCase();
+ var image = params.options.image;
+
+ amount = Math.max(0,Math.min(1,amount));
+
+ if (!image) return false;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var rect = params.options.rect;
+ var data = Pixastic.prepareData(params);
+ var w = rect.width;
+ var h = rect.height;
+
+ params.useData = false;
+
+ var otherCanvas = document.createElement("canvas");
+ otherCanvas.width = params.canvas.width;
+ otherCanvas.height = params.canvas.height;
+ var otherCtx = otherCanvas.getContext("2d");
+ otherCtx.drawImage(image,0,0);
+
+ var params2 = {canvas:otherCanvas,options:params.options};
+ var data2 = Pixastic.prepareData(params2);
+ var dataDesc2 = params2.canvasData;
+
+ var p = w*h;
+ var pix = p*4;
+ var pix1, pix2;
+ var r1, g1, b1;
+ var r2, g2, b2;
+ var r3, g3, b3;
+ var r4, g4, b4;
+
+ var dataChanged = false;
+
+ switch (mode) {
+ case "normal" :
+ //while (p--) {
+ // data2[pix-=4] = data2[pix];
+ // data2[pix1=pix+1] = data2[pix1];
+ // data2[pix2=pix+2] = data2[pix2];
+ //}
+ break;
+
+ case "multiply" :
+ while (p--) {
+ data2[pix-=4] = data[pix] * data2[pix] / 255;
+ data2[pix1=pix+1] = data[pix1] * data2[pix1] / 255;
+ data2[pix2=pix+2] = data[pix2] * data2[pix2] / 255;
+ }
+ dataChanged = true;
+ break;
+
+ case "lighten" :
+ while (p--) {
+ if ((r1 = data[pix-=4]) > data2[pix])
+ data2[pix] = r1;
+ if ((g1 = data[pix1=pix+1]) > data2[pix1])
+ data2[pix1] = g1;
+ if ((b1 = data[pix2=pix+2]) > data2[pix2])
+ data2[pix2] = b1;
+ }
+ dataChanged = true;
+ break;
+
+ case "darken" :
+ while (p--) {
+ if ((r1 = data[pix-=4]) < data2[pix])
+ data2[pix] = r1;
+ if ((g1 = data[pix1=pix+1]) < data2[pix1])
+ data2[pix1] = g1;
+ if ((b1 = data[pix2=pix+2]) < data2[pix2])
+ data2[pix2] = b1;
+
+ }
+ dataChanged = true;
+ break;
+
+ case "darkercolor" :
+ while (p--) {
+ 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)) {
+ data2[pix] = r1;
+ data2[pix1] = g1;
+ data2[pix2] = b1;
+ }
+ }
+ dataChanged = true;
+ break;
+
+ case "lightercolor" :
+ while (p--) {
+ 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)) {
+ data2[pix] = r1;
+ data2[pix1] = g1;
+ data2[pix2] = b1;
+ }
+ }
+ dataChanged = true;
+ break;
+
+ case "lineardodge" :
+ otherCtx.globalCompositeOperation = "source-over";
+ otherCtx.drawImage(params.canvas, 0, 0);
+ otherCtx.globalCompositeOperation = "lighter";
+ otherCtx.drawImage(image, 0, 0);
+
+ /*
+ while (p--) {
+ if ((r3 = data[pix-=4] + data2[pix]) > 255)
+ data2[pix] = 255;
+ else
+ data2[pix] = r3;
+ if ((g3 = data[pix1=pix+1] + data2[pix1]) > 255)
+ data2[pix1] = 255;
+ else
+ data2[pix1] = g3;
+ if ((b3 = data[pix2=pix+2] + data2[pix2]) > 255)
+ data2[pix2] = 255;
+ else
+ data2[pix2] = b3;
+ }
+ dataChanged = true;
+ */
+
+ break;
+
+ case "linearburn" :
+ while (p--) {
+ if ((r3 = data[pix-=4] + data2[pix]) < 255)
+ data2[pix] = 0;
+ else
+ data2[pix] = (r3 - 255);
+ if ((g3 = data[pix1=pix+1] + data2[pix1]) < 255)
+ data2[pix1] = 0;
+ else
+ data2[pix1] = (g3 - 255);
+ if ((b3 = data[pix2=pix+2] + data2[pix2]) < 255)
+ data2[pix2] = 0;
+ else
+ data2[pix2] = (b3 - 255);
+ }
+ dataChanged = true;
+ break;
+
+ case "difference" :
+ while (p--) {
+ if ((r3 = data[pix-=4] - data2[pix]) < 0)
+ data2[pix] = -r3;
+ else
+ data2[pix] = r3;
+ if ((g3 = data[pix1=pix+1] - data2[pix1]) < 0)
+ data2[pix1] = -g3;
+ else
+ data2[pix1] = g3;
+ if ((b3 = data[pix2=pix+2] - data2[pix2]) < 0)
+ data2[pix2] = -b3;
+ else
+ data2[pix2] = b3;
+ }
+ dataChanged = true;
+ break;
+
+ case "screen" :
+ while (p--) {
+ data2[pix-=4] = (255 - ( ((255-data2[pix])*(255-data[pix])) >> 8));
+ data2[pix1=pix+1] = (255 - ( ((255-data2[pix1])*(255-data[pix1])) >> 8));
+ data2[pix2=pix+2] = (255 - ( ((255-data2[pix2])*(255-data[pix2])) >> 8));
+ }
+ dataChanged = true;
+ break;
+
+ case "exclusion" :
+ var div_2_255 = 2 / 255;
+ while (p--) {
+ data2[pix-=4] = (r1 = data[pix]) - (r1 * div_2_255 - 1) * data2[pix];
+ data2[pix1=pix+1] = (g1 = data[pix1]) - (g1 * div_2_255 - 1) * data2[pix1];
+ data2[pix2=pix+2] = (b1 = data[pix2]) - (b1 * div_2_255 - 1) * data2[pix2];
+ }
+ dataChanged = true;
+ break;
+
+ case "overlay" :
+ var div_2_255 = 2 / 255;
+ while (p--) {
+ if ((r1 = data[pix-=4]) < 128)
+ data2[pix] = data2[pix]*r1*div_2_255;
+ else
+ data2[pix] = 255 - (255-data2[pix])*(255-r1)*div_2_255;
+
+ if ((g1 = data[pix1=pix+1]) < 128)
+ data2[pix1] = data2[pix1]*g1*div_2_255;
+ else
+ data2[pix1] = 255 - (255-data2[pix1])*(255-g1)*div_2_255;
+
+ if ((b1 = data[pix2=pix+2]) < 128)
+ data2[pix2] = data2[pix2]*b1*div_2_255;
+ else
+ data2[pix2] = 255 - (255-data2[pix2])*(255-b1)*div_2_255;
+
+ }
+ dataChanged = true;
+ break;
+
+ case "softlight" :
+ var div_2_255 = 2 / 255;
+ while (p--) {
+ if ((r1 = data[pix-=4]) < 128)
+ data2[pix] = ((data2[pix]>>1) + 64) * r1 * div_2_255;
+ else
+ data2[pix] = 255 - (191 - (data2[pix]>>1)) * (255-r1) * div_2_255;
+
+ if ((g1 = data[pix1=pix+1]) < 128)
+ data2[pix1] = ((data2[pix1]>>1)+64) * g1 * div_2_255;
+ else
+ data2[pix1] = 255 - (191 - (data2[pix1]>>1)) * (255-g1) * div_2_255;
+
+ if ((b1 = data[pix2=pix+2]) < 128)
+ data2[pix2] = ((data2[pix2]>>1)+64) * b1 * div_2_255;
+ else
+ data2[pix2] = 255 - (191 - (data2[pix2]>>1)) * (255-b1) * div_2_255;
+
+ }
+ dataChanged = true;
+ break;
+
+ case "hardlight" :
+ var div_2_255 = 2 / 255;
+ while (p--) {
+ if ((r2 = data2[pix-=4]) < 128)
+ data2[pix] = data[pix] * r2 * div_2_255;
+ else
+ data2[pix] = 255 - (255-data[pix]) * (255-r2) * div_2_255;
+
+ if ((g2 = data2[pix1=pix+1]) < 128)
+ data2[pix1] = data[pix1] * g2 * div_2_255;
+ else
+ data2[pix1] = 255 - (255-data[pix1]) * (255-g2) * div_2_255;
+
+ if ((b2 = data2[pix2=pix+2]) < 128)
+ data2[pix2] = data[pix2] * b2 * div_2_255;
+ else
+ data2[pix2] = 255 - (255-data[pix2]) * (255-b2) * div_2_255;
+
+ }
+ dataChanged = true;
+ break;
+
+ case "colordodge" :
+ while (p--) {
+ if ((r3 = (data[pix-=4]<<8)/(255-(r2 = data2[pix]))) > 255 || r2 == 255)
+ data2[pix] = 255;
+ else
+ data2[pix] = r3;
+
+ if ((g3 = (data[pix1=pix+1]<<8)/(255-(g2 = data2[pix1]))) > 255 || g2 == 255)
+ data2[pix1] = 255;
+ else
+ data2[pix1] = g3;
+
+ if ((b3 = (data[pix2=pix+2]<<8)/(255-(b2 = data2[pix2]))) > 255 || b2 == 255)
+ data2[pix2] = 255;
+ else
+ data2[pix2] = b3;
+ }
+ dataChanged = true;
+ break;
+
+ case "colorburn" :
+ while (p--) {
+ if ((r3 = 255-((255-data[pix-=4])<<8)/data2[pix]) < 0 || data2[pix] == 0)
+ data2[pix] = 0;
+ else
+ data2[pix] = r3;
+
+ if ((g3 = 255-((255-data[pix1=pix+1])<<8)/data2[pix1]) < 0 || data2[pix1] == 0)
+ data2[pix1] = 0;
+ else
+ data2[pix1] = g3;
+
+ if ((b3 = 255-((255-data[pix2=pix+2])<<8)/data2[pix2]) < 0 || data2[pix2] == 0)
+ data2[pix2] = 0;
+ else
+ data2[pix2] = b3;
+ }
+ dataChanged = true;
+ break;
+
+ case "linearlight" :
+ while (p--) {
+ if ( ((r3 = 2*(r2=data2[pix-=4])+data[pix]-256) < 0) || (r2 < 128 && r3 < 0)) {
+ data2[pix] = 0
+ } else {
+ if (r3 > 255)
+ data2[pix] = 255;
+ else
+ data2[pix] = r3;
+ }
+ if ( ((g3 = 2*(g2=data2[pix1=pix+1])+data[pix1]-256) < 0) || (g2 < 128 && g3 < 0)) {
+ data2[pix1] = 0
+ } else {
+ if (g3 > 255)
+ data2[pix1] = 255;
+ else
+ data2[pix1] = g3;
+ }
+ if ( ((b3 = 2*(b2=data2[pix2=pix+2])+data[pix2]-256) < 0) || (b2 < 128 && b3 < 0)) {
+ data2[pix2] = 0
+ } else {
+ if (b3 > 255)
+ data2[pix2] = 255;
+ else
+ data2[pix2] = b3;
+ }
+ }
+ dataChanged = true;
+ break;
+
+ case "vividlight" :
+ while (p--) {
+ if ((r2=data2[pix-=4]) < 128) {
+ if (r2) {
+ if ((r3 = 255 - ((255-data[pix])<<8) / (2*r2)) < 0)
+ data2[pix] = 0;
+ else
+ data2[pix] = r3
+ } else {
+ data2[pix] = 0;
+ }
+ } else if ((r3 = (r4=2*r2-256)) < 255) {
+ if ((r3 = (data[pix]<<8)/(255-r4)) > 255)
+ data2[pix] = 255;
+ else
+ data2[pix] = r3;
+ } else {
+ if (r3 < 0)
+ data2[pix] = 0;
+ else
+ data2[pix] = r3
+ }
+
+ if ((g2=data2[pix1=pix+1]) < 128) {
+ if (g2) {
+ if ((g3 = 255 - ((255-data[pix1])<<8) / (2*g2)) < 0)
+ data2[pix1] = 0;
+ else
+ data2[pix1] = g3;
+ } else {
+ data2[pix1] = 0;
+ }
+ } else if ((g3 = (g4=2*g2-256)) < 255) {
+ if ((g3 = (data[pix1]<<8)/(255-g4)) > 255)
+ data2[pix1] = 255;
+ else
+ data2[pix1] = g3;
+ } else {
+ if (g3 < 0)
+ data2[pix1] = 0;
+ else
+ data2[pix1] = g3;
+ }
+
+ if ((b2=data2[pix2=pix+2]) < 128) {
+ if (b2) {
+ if ((b3 = 255 - ((255-data[pix2])<<8) / (2*b2)) < 0)
+ data2[pix2] = 0;
+ else
+ data2[pix2] = b3;
+ } else {
+ data2[pix2] = 0;
+ }
+ } else if ((b3 = (b4=2*b2-256)) < 255) {
+ if ((b3 = (data[pix2]<<8)/(255-b4)) > 255)
+ data2[pix2] = 255;
+ else
+ data2[pix2] = b3;
+ } else {
+ if (b3 < 0)
+ data2[pix2] = 0;
+ else
+ data2[pix2] = b3;
+ }
+ }
+ dataChanged = true;
+ break;
+
+ case "pinlight" :
+ while (p--) {
+ if ((r2=data2[pix-=4]) < 128)
+ if ((r1=data[pix]) < (r4=2*r2))
+ data2[pix] = r1;
+ else
+ data2[pix] = r4;
+ else
+ if ((r1=data[pix]) > (r4=2*r2-256))
+ data2[pix] = r1;
+ else
+ data2[pix] = r4;
+
+ if ((g2=data2[pix1=pix+1]) < 128)
+ if ((g1=data[pix1]) < (g4=2*g2))
+ data2[pix1] = g1;
+ else
+ data2[pix1] = g4;
+ else
+ if ((g1=data[pix1]) > (g4=2*g2-256))
+ data2[pix1] = g1;
+ else
+ data2[pix1] = g4;
+
+ if ((r2=data2[pix2=pix+2]) < 128)
+ if ((r1=data[pix2]) < (r4=2*r2))
+ data2[pix2] = r1;
+ else
+ data2[pix2] = r4;
+ else
+ if ((r1=data[pix2]) > (r4=2*r2-256))
+ data2[pix2] = r1;
+ else
+ data2[pix2] = r4;
+ }
+ dataChanged = true;
+ break;
+
+ case "hardmix" :
+ while (p--) {
+ if ((r2 = data2[pix-=4]) < 128)
+ if (255 - ((255-data[pix])<<8)/(2*r2) < 128 || r2 == 0)
+ data2[pix] = 0;
+ else
+ data2[pix] = 255;
+ else if ((r4=2*r2-256) < 255 && (data[pix]<<8)/(255-r4) < 128)
+ data2[pix] = 0;
+ else
+ data2[pix] = 255;
+
+ if ((g2 = data2[pix1=pix+1]) < 128)
+ if (255 - ((255-data[pix1])<<8)/(2*g2) < 128 || g2 == 0)
+ data2[pix1] = 0;
+ else
+ data2[pix1] = 255;
+ else if ((g4=2*g2-256) < 255 && (data[pix1]<<8)/(255-g4) < 128)
+ data2[pix1] = 0;
+ else
+ data2[pix1] = 255;
+
+ if ((b2 = data2[pix2=pix+2]) < 128)
+ if (255 - ((255-data[pix2])<<8)/(2*b2) < 128 || b2 == 0)
+ data2[pix2] = 0;
+ else
+ data2[pix2] = 255;
+ else if ((b4=2*b2-256) < 255 && (data[pix2]<<8)/(255-b4) < 128)
+ data2[pix2] = 0;
+ else
+ data2[pix2] = 255;
+ }
+ dataChanged = true;
+ break;
+ }
+
+ if (dataChanged)
+ otherCtx.putImageData(dataDesc2,0,0);
+
+ var ctx = params.canvas.getContext("2d");
+ ctx.save();
+ ctx.globalAlpha = amount;
+ ctx.drawImage(
+ otherCanvas,
+ 0,0,rect.width,rect.height,
+ rect.left,rect.top,rect.width,rect.height
+ );
+ ctx.globalAlpha = 1;
+ ctx.restore();
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}/*
+ * Pixastic Lib - Blur filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.blur = {
+ process : function(params) {
+
+ if (typeof params.options.fixMargin == "undefined")
+ params.options.fixMargin = true;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var dataCopy = Pixastic.prepareData(params, true)
+
+ /*
+ var kernel = [
+ [0.5, 1, 0.5],
+ [1, 2, 1],
+ [0.5, 1, 0.5]
+ ];
+ */
+
+ var kernel = [
+ [0, 1, 0],
+ [1, 2, 1],
+ [0, 1, 0]
+ ];
+
+ var weight = 0;
+ for (var i=0;i<3;i++) {
+ for (var j=0;j<3;j++) {
+ weight += kernel[i][j];
+ }
+ }
+
+ weight = 1 / (weight*2);
+
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+
+ var prevY = (y == 1) ? 0 : y-2;
+ var nextY = (y == h) ? y - 1 : y;
+
+ var offsetYPrev = prevY*w*4;
+ var offsetYNext = nextY*w*4;
+
+ var x = w;
+ do {
+ var offset = offsetY + (x*4-4);
+
+ var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+ var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+
+ data[offset] = (
+ /*
+ dataCopy[offsetPrev - 4]
+ + dataCopy[offsetPrev+4]
+ + dataCopy[offsetNext - 4]
+ + dataCopy[offsetNext+4]
+ +
+ */
+ (dataCopy[offsetPrev]
+ + dataCopy[offset-4]
+ + dataCopy[offset+4]
+ + dataCopy[offsetNext]) * 2
+ + dataCopy[offset] * 4
+ ) * weight;
+
+ data[offset+1] = (
+ /*
+ dataCopy[offsetPrev - 3]
+ + dataCopy[offsetPrev+5]
+ + dataCopy[offsetNext - 3]
+ + dataCopy[offsetNext+5]
+ +
+ */
+ (dataCopy[offsetPrev+1]
+ + dataCopy[offset-3]
+ + dataCopy[offset+5]
+ + dataCopy[offsetNext+1]) * 2
+ + dataCopy[offset+1] * 4
+ ) * weight;
+
+ data[offset+2] = (
+ /*
+ dataCopy[offsetPrev - 2]
+ + dataCopy[offsetPrev+6]
+ + dataCopy[offsetNext - 2]
+ + dataCopy[offsetNext+6]
+ +
+ */
+ (dataCopy[offsetPrev+2]
+ + dataCopy[offset-2]
+ + dataCopy[offset+6]
+ + dataCopy[offsetNext+2]) * 2
+ + dataCopy[offset+2] * 4
+ ) * weight;
+
+ } while (--x);
+ } while (--y);
+
+ return true;
+
+ } else if (Pixastic.Client.isIE()) {
+ params.image.style.filter += " progid:DXImageTransform.Microsoft.Blur(pixelradius=1.5)";
+
+ if (params.options.fixMargin) {
+ params.image.style.marginLeft = (parseInt(params.image.style.marginLeft,10)||0) - 2 + "px";
+ params.image.style.marginTop = (parseInt(params.image.style.marginTop,10)||0) - 2 + "px";
+ }
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+ }
+}/*
+ * Pixastic Lib - Blur Fast - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.blurfast = {
+ process : function(params) {
+
+ var amount = parseFloat(params.options.amount)||0;
+ var clear = !!(params.options.clear && params.options.clear != "false");
+
+ amount = Math.max(0,Math.min(5,amount));
+
+ if (Pixastic.Client.hasCanvas()) {
+ var rect = params.options.rect;
+
+ var ctx = params.canvas.getContext("2d");
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(rect.left, rect.top, rect.width, rect.height);
+ ctx.clip();
+
+ var scale = 2;
+ var smallWidth = Math.round(params.width / scale);
+ var smallHeight = Math.round(params.height / scale);
+
+ var copy = document.createElement("canvas");
+ copy.width = smallWidth;
+ copy.height = smallHeight;
+
+ var clear = false;
+ var steps = Math.round(amount * 20);
+
+ var copyCtx = copy.getContext("2d");
+ for (var i=0;i<steps;i++) {
+ var scaledWidth = Math.max(1,Math.round(smallWidth - i));
+ var scaledHeight = Math.max(1,Math.round(smallHeight - i));
+
+ copyCtx.clearRect(0,0,smallWidth,smallHeight);
+
+ copyCtx.drawImage(
+ params.canvas,
+ 0,0,params.width,params.height,
+ 0,0,scaledWidth,scaledHeight
+ );
+
+ if (clear)
+ ctx.clearRect(rect.left,rect.top,rect.width,rect.height);
+
+ ctx.drawImage(
+ copy,
+ 0,0,scaledWidth,scaledHeight,
+ 0,0,params.width,params.height
+ );
+ }
+
+ ctx.restore();
+
+ params.useData = false;
+ return true;
+ } else if (Pixastic.Client.isIE()) {
+ var radius = 10 * amount;
+ params.image.style.filter += " progid:DXImageTransform.Microsoft.Blur(pixelradius=" + radius + ")";
+
+ if (params.options.fixMargin || 1) {
+ params.image.style.marginLeft = (parseInt(params.image.style.marginLeft,10)||0) - Math.round(radius) + "px";
+ params.image.style.marginTop = (parseInt(params.image.style.marginTop,10)||0) - Math.round(radius) + "px";
+ }
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
+ }
+}
+/*
+ * Pixastic Lib - Brightness/Contrast filter - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.brightness = {
+
+ process : function(params) {
+
+ var brightness = parseInt(params.options.brightness,10) || 0;
+ var contrast = parseFloat(params.options.contrast)||0;
+ var legacy = !!(params.options.legacy && params.options.legacy != "false");
+
+ if (legacy) {
+ brightness = Math.min(150,Math.max(-150,brightness));
+ } else {
+ var brightMul = 1 + Math.min(150,Math.max(-150,brightness)) / 150;
+ }
+ contrast = Math.max(0,contrast+1);
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var p = w*h;
+ var pix = p*4, pix1, pix2;
+
+ var mul, add;
+ if (contrast != 1) {
+ if (legacy) {
+ mul = contrast;
+ add = (brightness - 128) * contrast + 128;
+ } else {
+ mul = brightMul * contrast;
+ add = - contrast * 128 + 128;
+ }
+ } else { // this if-then is not necessary anymore, is it?
+ if (legacy) {
+ mul = 1;
+ add = brightness;
+ } else {
+ mul = brightMul;
+ add = 0;
+ }
+ }
+ var r, g, b;
+ while (p--) {
+ if ((r = data[pix-=4] * mul + add) > 255 )
+ data[pix] = 255;
+ else if (r < 0)
+ data[pix] = 0;
+ else
+ data[pix] = r;
+
+ if ((g = data[pix1=pix+1] * mul + add) > 255 )
+ data[pix1] = 255;
+ else if (g < 0)
+ data[pix1] = 0;
+ else
+ data[pix1] = g;
+
+ if ((b = data[pix2=pix+2] * mul + add) > 255 )
+ data[pix2] = 255;
+ else if (b < 0)
+ data[pix2] = 0;
+ else
+ data[pix2] = b;
+ }
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}
+
+/*
+ * Pixastic Lib - Color adjust filter - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.coloradjust = {
+
+ process : function(params) {
+ var red = parseFloat(params.options.red) || 0;
+ var green = parseFloat(params.options.green) || 0;
+ var blue = parseFloat(params.options.blue) || 0;
+
+ red = Math.round(red*255);
+ green = Math.round(green*255);
+ blue = Math.round(blue*255);
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var rect = params.options.rect;
+
+ var p = rect.width*rect.height;
+ var pix = p*4, pix1, pix2;
+
+ var r, g, b;
+ while (p--) {
+ pix -= 4;
+
+ if (red) {
+ if ((r = data[pix] + red) < 0 )
+ data[pix] = 0;
+ else if (r > 255 )
+ data[pix] = 255;
+ else
+ data[pix] = r;
+ }
+
+ if (green) {
+ if ((g = data[pix1=pix+1] + green) < 0 )
+ data[pix1] = 0;
+ else if (g > 255 )
+ data[pix1] = 255;
+ else
+ data[pix1] = g;
+ }
+
+ if (blue) {
+ if ((b = data[pix2=pix+2] + blue) < 0 )
+ data[pix2] = 0;
+ else if (b > 255 )
+ data[pix2] = 255;
+ else
+ data[pix2] = b;
+ }
+ }
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvasImageData());
+ }
+}
+/*
+ * Pixastic Lib - Histogram - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+
+Pixastic.Actions.colorhistogram = {
+
+ array256 : function(default_value) {
+ arr = [];
+ for (var i=0; i<256; i++) { arr[i] = default_value; }
+ return arr
+ },
+
+ process : function(params) {
+ var values = [];
+ if (typeof params.options.returnValue != "object") {
+ params.options.returnValue = {rvals:[], gvals:[], bvals:[]};
+ }
+ var paint = !!(params.options.paint);
+
+ var returnValue = params.options.returnValue;
+ if (typeof returnValue.values != "array") {
+ returnValue.rvals = [];
+ returnValue.gvals = [];
+ returnValue.bvals = [];
+ }
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ params.useData = false;
+
+ var rvals = this.array256(0);
+ var gvals = this.array256(0);
+ var bvals = this.array256(0);
+
+ var rect = params.options.rect;
+
+ var p = rect.width*rect.height;
+ var pix = p*4;
+ while (p--) {
+ rvals[data[pix-=4]]++;
+ gvals[data[pix+1]]++;
+ bvals[data[pix+2]]++;
+ }
+
+ returnValue.rvals = rvals;
+ returnValue.gvals = gvals;
+ returnValue.bvals = bvals;
+
+ if (paint) {
+ var ctx = params.canvas.getContext("2d");
+ var vals = [rvals, gvals, bvals];
+ for (var v=0;v<3;v++) {
+ var yoff = (v+1) * params.height / 3;
+ var maxValue = 0;
+ for (var i=0;i<256;i++) {
+ if (vals[v][i] > maxValue)
+ maxValue = vals[v][i];
+ }
+ var heightScale = params.height / 3 / maxValue;
+ var widthScale = params.width / 256;
+ if (v==0) ctx.fillStyle = "rgba(255,0,0,0.5)";
+ else if (v==1) ctx.fillStyle = "rgba(0,255,0,0.5)";
+ else if (v==2) ctx.fillStyle = "rgba(0,0,255,0.5)";
+ for (var i=0;i<256;i++) {
+ ctx.fillRect(
+ i * widthScale, params.height - heightScale * vals[v][i] - params.height + yoff,
+ widthScale, vals[v][i] * heightScale
+ );
+ }
+ }
+ }
+ return true;
+ }
+ },
+
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}/*
+ * Pixastic Lib - Crop - v0.1.1
+ * Copyright (c) 2008-2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.crop = {
+ process : function(params) {
+ if (Pixastic.Client.hasCanvas()) {
+ var rect = params.options.rect;
+
+ var width = rect.width;
+ var height = rect.height;
+ var top = rect.top;
+ var left = rect.left;
+
+ if (typeof params.options.left != "undefined")
+ left = parseInt(params.options.left,10);
+ if (typeof params.options.top != "undefined")
+ top = parseInt(params.options.top,10);
+ if (typeof params.options.height != "undefined")
+ width = parseInt(params.options.width,10);
+ if (typeof params.options.height != "undefined")
+ height = parseInt(params.options.height,10);
+
+ if (left < 0) left = 0;
+ if (left > params.width-1) left = params.width-1;
+
+ if (top < 0) top = 0;
+ if (top > params.height-1) top = params.height-1;
+
+ if (width < 1) width = 1;
+ if (left + width > params.width)
+ width = params.width - left;
+
+ if (height < 1) height = 1;
+ if (top + height > params.height)
+ height = params.height - top;
+
+ var copy = document.createElement("canvas");
+ copy.width = params.width;
+ copy.height = params.height;
+ copy.getContext("2d").drawImage(params.canvas,0,0);
+
+ params.canvas.width = width;
+ params.canvas.height = height;
+ params.canvas.getContext("2d").clearRect(0,0,width,height);
+
+ params.canvas.getContext("2d").drawImage(copy,
+ left,top,width,height,
+ 0,0,width,height
+ );
+
+ params.useData = false;
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvas();
+ }
+}
+
+
+/*
+ * Pixastic Lib - Desaturation filter - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.desaturate = {
+
+ process : function(params) {
+ var useAverage = !!(params.options.average && params.options.average != "false");
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var p = w*h;
+ var pix = p*4, pix1, pix2;
+
+ if (useAverage) {
+ while (p--)
+ data[pix-=4] = data[pix1=pix+1] = data[pix2=pix+2] = (data[pix]+data[pix1]+data[pix2])/3
+ } else {
+ while (p--)
+ data[pix-=4] = data[pix1=pix+1] = data[pix2=pix+2] = (data[pix]*0.3 + data[pix1]*0.59 + data[pix2]*0.11);
+ }
+ return true;
+ } else if (Pixastic.Client.isIE()) {
+ params.image.style.filter += " gray";
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+ }
+}/*
+ * Pixastic Lib - Edge detection filter - v0.1.1
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.edges = {
+ process : function(params) {
+
+ var mono = !!(params.options.mono && params.options.mono != "false");
+ var invert = !!(params.options.invert && params.options.invert != "false");
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var dataCopy = Pixastic.prepareData(params, true)
+
+ var c = -1/8;
+ var kernel = [
+ [c, c, c],
+ [c, 1, c],
+ [c, c, c]
+ ];
+
+ weight = 1/c;
+
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+
+ var nextY = (y == h) ? y - 1 : y;
+ var prevY = (y == 1) ? 0 : y-2;
+
+ var offsetYPrev = prevY*w*4;
+ var offsetYNext = nextY*w*4;
+
+ var x = w;
+ do {
+ var offset = offsetY + (x*4-4);
+
+ var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+ var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+
+ var r = ((dataCopy[offsetPrev-4]
+ + dataCopy[offsetPrev]
+ + dataCopy[offsetPrev+4]
+ + dataCopy[offset-4]
+ + dataCopy[offset+4]
+ + dataCopy[offsetNext-4]
+ + dataCopy[offsetNext]
+ + dataCopy[offsetNext+4]) * c
+ + dataCopy[offset]
+ )
+ * weight;
+
+ var g = ((dataCopy[offsetPrev-3]
+ + dataCopy[offsetPrev+1]
+ + dataCopy[offsetPrev+5]
+ + dataCopy[offset-3]
+ + dataCopy[offset+5]
+ + dataCopy[offsetNext-3]
+ + dataCopy[offsetNext+1]
+ + dataCopy[offsetNext+5]) * c
+ + dataCopy[offset+1])
+ * weight;
+
+ var b = ((dataCopy[offsetPrev-2]
+ + dataCopy[offsetPrev+2]
+ + dataCopy[offsetPrev+6]
+ + dataCopy[offset-2]
+ + dataCopy[offset+6]
+ + dataCopy[offsetNext-2]
+ + dataCopy[offsetNext+2]
+ + dataCopy[offsetNext+6]) * c
+ + dataCopy[offset+2])
+ * weight;
+
+ if (mono) {
+ var brightness = (r*0.3 + g*0.59 + b*0.11)||0;
+ if (invert) brightness = 255 - brightness;
+ if (brightness < 0 ) brightness = 0;
+ if (brightness > 255 ) brightness = 255;
+ r = g = b = brightness;
+ } else {
+ if (invert) {
+ r = 255 - r;
+ g = 255 - g;
+ b = 255 - b;
+ }
+ if (r < 0 ) r = 0;
+ if (g < 0 ) g = 0;
+ if (b < 0 ) b = 0;
+ if (r > 255 ) r = 255;
+ if (g > 255 ) g = 255;
+ if (b > 255 ) b = 255;
+ }
+
+ data[offset] = r;
+ data[offset+1] = g;
+ data[offset+2] = b;
+
+ } while (--x);
+ } while (--y);
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}/*
+ * Pixastic Lib - Edge detection 2 - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ *
+ * Contribution by Oliver Hunt (http://nerget.com/, http://nerget.com/canvas/edgeDetection.js). Thanks Oliver!
+ *
+ */
+
+Pixastic.Actions.edges2 = {
+ process : function(params) {
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var dataCopy = Pixastic.prepareData(params, true)
+
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var w4 = w * 4;
+ var pixel = w4 + 4; // Start at (1,1)
+ var hm1 = h - 1;
+ var wm1 = w - 1;
+ for (var y = 1; y < hm1; ++y) {
+ // Prepare initial cached values for current row
+ var centerRow = pixel - 4;
+ var priorRow = centerRow - w4;
+ var nextRow = centerRow + w4;
+
+ var r1 = - dataCopy[priorRow] - dataCopy[centerRow] - dataCopy[nextRow];
+ var g1 = - dataCopy[++priorRow] - dataCopy[++centerRow] - dataCopy[++nextRow];
+ var b1 = - dataCopy[++priorRow] - dataCopy[++centerRow] - dataCopy[++nextRow];
+
+ var rp = dataCopy[priorRow += 2];
+ var gp = dataCopy[++priorRow];
+ var bp = dataCopy[++priorRow];
+
+ var rc = dataCopy[centerRow += 2];
+ var gc = dataCopy[++centerRow];
+ var bc = dataCopy[++centerRow];
+
+ var rn = dataCopy[nextRow += 2];
+ var gn = dataCopy[++nextRow];
+ var bn = dataCopy[++nextRow];
+
+ var r2 = - rp - rc - rn;
+ var g2 = - gp - gc - gn;
+ var b2 = - bp - bc - bn;
+
+ // Main convolution loop
+ for (var x = 1; x < wm1; ++x) {
+ centerRow = pixel + 4;
+ priorRow = centerRow - w4;
+ nextRow = centerRow + w4;
+
+ var r = 127 + r1 - rp - (rc * -8) - rn;
+ var g = 127 + g1 - gp - (gc * -8) - gn;
+ var b = 127 + b1 - bp - (bc * -8) - bn;
+
+ r1 = r2;
+ g1 = g2;
+ b1 = b2;
+
+ rp = dataCopy[ priorRow];
+ gp = dataCopy[++priorRow];
+ bp = dataCopy[++priorRow];
+
+ rc = dataCopy[ centerRow];
+ gc = dataCopy[++centerRow];
+ bc = dataCopy[++centerRow];
+
+ rn = dataCopy[ nextRow];
+ gn = dataCopy[++nextRow];
+ bn = dataCopy[++nextRow];
+
+ r += (r2 = - rp - rc - rn);
+ g += (g2 = - gp - gc - gn);
+ b += (b2 = - bp - bc - bn);
+
+ if (r > 255) r = 255;
+ if (g > 255) g = 255;
+ if (b > 255) b = 255;
+ if (r < 0) r = 0;
+ if (g < 0) g = 0;
+ if (b < 0) b = 0;
+
+ data[pixel] = r;
+ data[++pixel] = g;
+ data[++pixel] = b;
+ //data[++pixel] = 255; // alpha
+
+ pixel+=2;
+ }
+ pixel += 8;
+ }
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}/*
+ * Pixastic Lib - Emboss filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.emboss = {
+ process : function(params) {
+
+ var strength = parseFloat(params.options.strength)||1;
+ var greyLevel = typeof params.options.greyLevel != "undefined" ? parseInt(params.options.greyLevel) : 180;
+ var direction = params.options.direction||"topleft";
+ var blend = !!(params.options.blend && params.options.blend != "false");
+
+ var dirY = 0;
+ var dirX = 0;
+
+ switch (direction) {
+ case "topleft": // top left
+ dirY = -1;
+ dirX = -1;
+ break;
+ case "top": // top
+ dirY = -1;
+ dirX = 0;
+ break;
+ case "topright": // top right
+ dirY = -1;
+ dirX = 1;
+ break;
+ case "right": // right
+ dirY = 0;
+ dirX = 1;
+ break;
+ case "bottomright": // bottom right
+ dirY = 1;
+ dirX = 1;
+ break;
+ case "bottom": // bottom
+ dirY = 1;
+ dirX = 0;
+ break;
+ case "bottomleft": // bottom left
+ dirY = 1;
+ dirX = -1;
+ break;
+ case "left": // left
+ dirY = 0;
+ dirX = -1;
+ break;
+ }
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var dataCopy = Pixastic.prepareData(params, true)
+
+ var invertAlpha = !!params.options.invertAlpha;
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+
+ var otherY = dirY;
+ if (y + otherY < 1) otherY = 0;
+ if (y + otherY > h) otherY = 0;
+
+ var offsetYOther = (y-1+otherY)*w*4;
+
+ var x = w;
+ do {
+ var offset = offsetY + (x-1)*4;
+
+ var otherX = dirX;
+ if (x + otherX < 1) otherX = 0;
+ if (x + otherX > w) otherX = 0;
+
+ var offsetOther = offsetYOther + (x-1+otherX)*4;
+
+ var dR = dataCopy[offset] - dataCopy[offsetOther];
+ var dG = dataCopy[offset+1] - dataCopy[offsetOther+1];
+ var dB = dataCopy[offset+2] - dataCopy[offsetOther+2];
+
+ var dif = dR;
+ var absDif = dif > 0 ? dif : -dif;
+
+ var absG = dG > 0 ? dG : -dG;
+ var absB = dB > 0 ? dB : -dB;
+
+ if (absG > absDif) {
+ dif = dG;
+ }
+ if (absB > absDif) {
+ dif = dB;
+ }
+
+ dif *= strength;
+
+ if (blend) {
+ var r = data[offset] + dif;
+ var g = data[offset+1] + dif;
+ var b = data[offset+2] + dif;
+
+ data[offset] = (r > 255) ? 255 : (r < 0 ? 0 : r);
+ data[offset+1] = (g > 255) ? 255 : (g < 0 ? 0 : g);
+ data[offset+2] = (b > 255) ? 255 : (b < 0 ? 0 : b);
+ } else {
+ var grey = greyLevel - dif;
+ if (grey < 0) {
+ grey = 0;
+ } else if (grey > 255) {
+ grey = 255;
+ }
+
+ data[offset] = data[offset+1] = data[offset+2] = grey;
+ }
+
+ } while (--x);
+ } while (--y);
+ return true;
+
+ } else if (Pixastic.Client.isIE()) {
+ params.image.style.filter += " progid:DXImageTransform.Microsoft.emboss()";
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+ }
+
+}
+/*
+ * Pixastic Lib - Flip - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.flip = {
+ process : function(params) {
+ var rect = params.options.rect;
+ var copyCanvas = document.createElement("canvas");
+ copyCanvas.width = rect.width;
+ copyCanvas.height = rect.height;
+ copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);
+
+ var ctx = params.canvas.getContext("2d");
+ ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
+
+ if (params.options.axis == "horizontal") {
+ ctx.scale(-1,1);
+ ctx.drawImage(copyCanvas, -rect.left-rect.width, rect.top, rect.width, rect.height)
+ } else {
+ ctx.scale(1,-1);
+ ctx.drawImage(copyCanvas, rect.left, -rect.top-rect.height, rect.width, rect.height)
+ }
+
+ params.useData = false;
+
+ return true;
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvas();
+ }
+}
+
+/*
+ * Pixastic Lib - Horizontal flip - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.fliph = {
+ process : function(params) {
+ if (Pixastic.Client.hasCanvas()) {
+ var rect = params.options.rect;
+ var copyCanvas = document.createElement("canvas");
+ copyCanvas.width = rect.width;
+ copyCanvas.height = rect.height;
+ copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);
+
+ var ctx = params.canvas.getContext("2d");
+ ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
+ ctx.scale(-1,1);
+ ctx.drawImage(copyCanvas, -rect.left-rect.width, rect.top, rect.width, rect.height)
+ params.useData = false;
+
+ return true;
+
+ } else if (Pixastic.Client.isIE()) {
+ params.image.style.filter += " fliph";
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
+ }
+}
+
+/*
+ * Pixastic Lib - Vertical flip - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.flipv = {
+ process : function(params) {
+ if (Pixastic.Client.hasCanvas()) {
+ var rect = params.options.rect;
+ var copyCanvas = document.createElement("canvas");
+ copyCanvas.width = rect.width;
+ copyCanvas.height = rect.height;
+ copyCanvas.getContext("2d").drawImage(params.image, rect.left, rect.top, rect.width, rect.height, 0, 0, rect.width, rect.height);
+
+ var ctx = params.canvas.getContext("2d");
+ ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
+ ctx.scale(1,-1);
+ ctx.drawImage(copyCanvas, rect.left, -rect.top-rect.height, rect.width, rect.height)
+ params.useData = false;
+
+ return true;
+
+ } else if (Pixastic.Client.isIE()) {
+ params.image.style.filter += " flipv";
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvas() || Pixastic.Client.isIE());
+ }
+}
+
+/*
+ * Pixastic Lib - Glow - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+
+Pixastic.Actions.glow = {
+ process : function(params) {
+
+ var amount = (parseFloat(params.options.amount)||0);
+ var blurAmount = parseFloat(params.options.radius)||0;
+
+ amount = Math.min(1,Math.max(0,amount));
+ blurAmount = Math.min(5,Math.max(0,blurAmount));
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var rect = params.options.rect;
+
+ var blurCanvas = document.createElement("canvas");
+ blurCanvas.width = params.width;
+ blurCanvas.height = params.height;
+ var blurCtx = blurCanvas.getContext("2d");
+ blurCtx.drawImage(params.canvas,0,0);
+
+ var scale = 2;
+ var smallWidth = Math.round(params.width / scale);
+ var smallHeight = Math.round(params.height / scale);
+
+ var copy = document.createElement("canvas");
+ copy.width = smallWidth;
+ copy.height = smallHeight;
+
+ var clear = true;
+ var steps = Math.round(blurAmount * 20);
+
+ var copyCtx = copy.getContext("2d");
+ for (var i=0;i<steps;i++) {
+ var scaledWidth = Math.max(1,Math.round(smallWidth - i));
+ var scaledHeight = Math.max(1,Math.round(smallHeight - i));
+
+ copyCtx.clearRect(0,0,smallWidth,smallHeight);
+
+ copyCtx.drawImage(
+ blurCanvas,
+ 0,0,params.width,params.height,
+ 0,0,scaledWidth,scaledHeight
+ );
+
+ blurCtx.clearRect(0,0,params.width,params.height);
+
+ blurCtx.drawImage(
+ copy,
+ 0,0,scaledWidth,scaledHeight,
+ 0,0,params.width,params.height
+ );
+ }
+
+ var data = Pixastic.prepareData(params);
+ var blurData = Pixastic.prepareData({canvas:blurCanvas,options:params.options});
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x*4-4);
+
+ var r = data[offset] + amount * blurData[offset];
+ var g = data[offset+1] + amount * blurData[offset+1];
+ var b = data[offset+2] + amount * blurData[offset+2];
+
+ if (r > 255) r = 255;
+ if (g > 255) g = 255;
+ if (b > 255) b = 255;
+ if (r < 0) r = 0;
+ if (g < 0) g = 0;
+ if (b < 0) b = 0;
+
+ data[offset] = r;
+ data[offset+1] = g;
+ data[offset+2] = b;
+
+ } while (--x);
+ } while (--y);
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}
+
+
+
+/*
+ * Pixastic Lib - Histogram - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.histogram = {
+ process : function(params) {
+
+ var average = !!(params.options.average && params.options.average != "false");
+ var paint = !!(params.options.paint && params.options.paint != "false");
+ var color = params.options.color || "rgba(255,255,255,0.5)";
+ var values = [];
+ if (typeof params.options.returnValue != "object") {
+ params.options.returnValue = {values:[]};
+ }
+ var returnValue = params.options.returnValue;
+ if (typeof returnValue.values != "array") {
+ returnValue.values = [];
+ }
+ values = returnValue.values;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ params.useData = false;
+
+ for (var i=0;i<256;i++) {
+ values[i] = 0;
+ }
+
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x*4-4);
+ var brightness = average ?
+ Math.round((data[offset]+data[offset+1]+data[offset+2])/3)
+ : Math.round(data[offset]*0.3 + data[offset+1]*0.59 + data[offset+2]*0.11);
+ values[brightness]++;
+
+ } while (--x);
+ } while (--y);
+
+ if (paint) {
+ var maxValue = 0;
+ for (var i=0;i<256;i++) {
+ if (values[i] > maxValue) {
+ maxValue = values[i];
+ }
+ }
+ var heightScale = params.height / maxValue;
+ var widthScale = params.width / 256;
+ var ctx = params.canvas.getContext("2d");
+ ctx.fillStyle = color;
+ for (var i=0;i<256;i++) {
+ ctx.fillRect(
+ i * widthScale, params.height - heightScale * values[i],
+ widthScale, values[i] * heightScale
+ );
+ }
+ }
+
+ returnValue.values = values;
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}
+/*
+ * Pixastic Lib - HSL Adjust - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.hsl = {
+ process : function(params) {
+
+ var hue = parseInt(params.options.hue,10)||0;
+ var saturation = (parseInt(params.options.saturation,10)||0) / 100;
+ var lightness = (parseInt(params.options.lightness,10)||0) / 100;
+
+
+ // this seems to give the same result as Photoshop
+ if (saturation < 0) {
+ var satMul = 1+saturation;
+ } else {
+ var satMul = 1+saturation*2;
+ }
+
+ hue = (hue%360) / 360;
+ var hue6 = hue * 6;
+
+ var rgbDiv = 1 / 255;
+
+ var light255 = lightness * 255;
+ var lightp1 = 1 + lightness;
+ var lightm1 = 1 - lightness;
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var w4 = w*4;
+ var y = h;
+
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x*4-4);
+
+ var r = data[offset];
+ var g = data[offset+1];
+ var b = data[offset+2];
+
+ if (hue != 0 || saturation != 0) {
+ // ok, here comes rgb to hsl + adjust + hsl to rgb, all in one jumbled mess.
+ // It's not so pretty, but it's been optimized to get somewhat decent performance.
+ // The transforms were originally adapted from the ones found in Graphics Gems, but have been heavily modified.
+ var vs = r;
+ if (g > vs) vs = g;
+ if (b > vs) vs = b;
+ var ms = r;
+ if (g < ms) ms = g;
+ if (b < ms) ms = b;
+ var vm = (vs-ms);
+ var l = (ms+vs)/255 * 0.5;
+ if (l > 0) {
+ if (vm > 0) {
+ if (l <= 0.5) {
+ var s = vm / (vs+ms) * satMul;
+ if (s > 1) s = 1;
+ var v = (l * (1+s));
+ } else {
+ var s = vm / (510-vs-ms) * satMul;
+ if (s > 1) s = 1;
+ var v = (l+s - l*s);
+ }
+ if (r == vs) {
+ if (g == ms)
+ var h = 5 + ((vs-b)/vm) + hue6;
+ else
+ var h = 1 - ((vs-g)/vm) + hue6;
+ } else if (g == vs) {
+ if (b == ms)
+ var h = 1 + ((vs-r)/vm) + hue6;
+ else
+ var h = 3 - ((vs-b)/vm) + hue6;
+ } else {
+ if (r == ms)
+ var h = 3 + ((vs-g)/vm) + hue6;
+ else
+ var h = 5 - ((vs-r)/vm) + hue6;
+ }
+ if (h < 0) h+=6;
+ if (h >= 6) h-=6;
+ var m = (l+l-v);
+ var sextant = h>>0;
+ switch (sextant) {
+ case 0: r = v*255; g = (m+((v-m)*(h-sextant)))*255; b = m*255; break;
+ case 1: r = (v-((v-m)*(h-sextant)))*255; g = v*255; b = m*255; break;
+ case 2: r = m*255; g = v*255; b = (m+((v-m)*(h-sextant)))*255; break;
+ case 3: r = m*255; g = (v-((v-m)*(h-sextant)))*255; b = v*255; break;
+ case 4: r = (m+((v-m)*(h-sextant)))*255; g = m*255; b = v*255; break;
+ case 5: r = v*255; g = m*255; b = (v-((v-m)*(h-sextant)))*255; break;
+ }
+ }
+ }
+ }
+
+ if (lightness < 0) {
+ r *= lightp1;
+ g *= lightp1;
+ b *= lightp1;
+ } else if (lightness > 0) {
+ r = r * lightm1 + light255;
+ g = g * lightm1 + light255;
+ b = b * lightm1 + light255;
+ }
+
+ if (r < 0) r = 0;
+ if (g < 0) g = 0;
+ if (b < 0) b = 0;
+ if (r > 255) r = 255;
+ if (g > 255) g = 255;
+ if (b > 255) b = 255;
+
+ data[offset] = r;
+ data[offset+1] = g;
+ data[offset+2] = b;
+
+ } while (--x);
+ } while (--y);
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+
+}
+/*
+ * Pixastic Lib - Invert filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.invert = {
+ process : function(params) {
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+
+ var invertAlpha = !!params.options.invertAlpha;
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x-1)*4;
+ data[offset] = 255 - data[offset];
+ data[offset+1] = 255 - data[offset+1];
+ data[offset+2] = 255 - data[offset+2];
+ if (invertAlpha) data[offset+3] = 255 - data[offset+3];
+ } while (--x);
+ } while (--y);
+
+ return true;
+ } else if (Pixastic.Client.isIE()) {
+ params.image.style.filter += " invert";
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+ }
+}
+/*
+ * Pixastic Lib - Laplace filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.laplace = {
+ process : function(params) {
+
+ var strength = 1.0;
+ var invert = !!(params.options.invert && params.options.invert != "false");
+ var contrast = parseFloat(params.options.edgeStrength)||0;
+
+ var greyLevel = parseInt(params.options.greyLevel)||0;
+
+ contrast = -contrast;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var dataCopy = Pixastic.prepareData(params, true)
+
+ var kernel = [
+ [-1, -1, -1],
+ [-1, 8, -1],
+ [-1, -1, -1]
+ ];
+
+ var weight = 1/8;
+
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+
+ var nextY = (y == h) ? y - 1 : y;
+ var prevY = (y == 1) ? 0 : y-2;
+
+ var offsetYPrev = prevY*w*4;
+ var offsetYNext = nextY*w*4;
+
+ var x = w;
+ do {
+ var offset = offsetY + (x*4-4);
+
+ var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+ var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+
+ var r = ((-dataCopy[offsetPrev-4]
+ - dataCopy[offsetPrev]
+ - dataCopy[offsetPrev+4]
+ - dataCopy[offset-4]
+ - dataCopy[offset+4]
+ - dataCopy[offsetNext-4]
+ - dataCopy[offsetNext]
+ - dataCopy[offsetNext+4])
+ + dataCopy[offset] * 8)
+ * weight;
+
+ var g = ((-dataCopy[offsetPrev-3]
+ - dataCopy[offsetPrev+1]
+ - dataCopy[offsetPrev+5]
+ - dataCopy[offset-3]
+ - dataCopy[offset+5]
+ - dataCopy[offsetNext-3]
+ - dataCopy[offsetNext+1]
+ - dataCopy[offsetNext+5])
+ + dataCopy[offset+1] * 8)
+ * weight;
+
+ var b = ((-dataCopy[offsetPrev-2]
+ - dataCopy[offsetPrev+2]
+ - dataCopy[offsetPrev+6]
+ - dataCopy[offset-2]
+ - dataCopy[offset+6]
+ - dataCopy[offsetNext-2]
+ - dataCopy[offsetNext+2]
+ - dataCopy[offsetNext+6])
+ + dataCopy[offset+2] * 8)
+ * weight;
+
+ var brightness = ((r + g + b)/3) + greyLevel;
+
+ if (contrast != 0) {
+ if (brightness > 127) {
+ brightness += ((brightness + 1) - 128) * contrast;
+ } else if (brightness < 127) {
+ brightness -= (brightness + 1) * contrast;
+ }
+ }
+ if (invert) {
+ brightness = 255 - brightness;
+ }
+ if (brightness < 0 ) brightness = 0;
+ if (brightness > 255 ) brightness = 255;
+
+ data[offset] = data[offset+1] = data[offset+2] = brightness;
+
+ } while (--x);
+ } while (--y);
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}
+
+/*
+ * Pixastic Lib - Lighten filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.lighten = {
+
+ process : function(params) {
+ var amount = parseFloat(params.options.amount) || 0;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x-1)*4;
+
+ var r = data[offset];
+ var g = data[offset+1];
+ var b = data[offset+2];
+
+ r += r*amount;
+ g += g*amount;
+ b += b*amount;
+
+ if (r < 0 ) r = 0;
+ if (g < 0 ) g = 0;
+ if (b < 0 ) b = 0;
+ if (r > 255 ) r = 255;
+ if (g > 255 ) g = 255;
+ if (b > 255 ) b = 255;
+
+ data[offset] = r;
+ data[offset+1] = g;
+ data[offset+2] = b;
+
+ } while (--x);
+ } while (--y);
+ return true;
+
+ } else if (Pixastic.Client.isIE()) {
+ var img = params.image;
+ if (amount < 0) {
+ img.style.filter += " light()";
+ img.filters[img.filters.length-1].addAmbient(
+ 255,255,255,
+ 100 * -amount
+ );
+ } else if (amount > 0) {
+ img.style.filter += " light()";
+ img.filters[img.filters.length-1].addAmbient(
+ 255,255,255,
+ 100
+ );
+ img.filters[img.filters.length-1].addAmbient(
+ 255,255,255,
+ 100 * amount
+ );
+ }
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvasImageData() || Pixastic.Client.isIE());
+ }
+}
+/*
+ * Pixastic Lib - Mosaic filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.mosaic = {
+
+ process : function(params) {
+ var blockSize = Math.max(1,parseInt(params.options.blockSize,10));
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+
+ var ctx = params.canvas.getContext("2d");
+
+ var pixel = document.createElement("canvas");
+ pixel.width = pixel.height = 1;
+ var pixelCtx = pixel.getContext("2d");
+
+ var copy = document.createElement("canvas");
+ copy.width = w;
+ copy.height = h;
+ var copyCtx = copy.getContext("2d");
+ copyCtx.drawImage(params.canvas,rect.left,rect.top,w,h, 0,0,w,h);
+
+ for (var y=0;y<h;y+=blockSize) {
+ for (var x=0;x<w;x+=blockSize) {
+ var blockSizeX = blockSize;
+ var blockSizeY = blockSize;
+
+ if (blockSizeX + x > w)
+ blockSizeX = w - x;
+ if (blockSizeY + y > h)
+ blockSizeY = h - y;
+
+ pixelCtx.drawImage(copy, x, y, blockSizeX, blockSizeY, 0, 0, 1, 1);
+ var data = pixelCtx.getImageData(0,0,1,1).data;
+ ctx.fillStyle = "rgb(" + data[0] + "," + data[1] + "," + data[2] + ")";
+ ctx.fillRect(rect.left + x, rect.top + y, blockSize, blockSize);
+ }
+ }
+ params.useData = false;
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvasImageData());
+ }
+}/*
+ * Pixastic Lib - Noise filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.noise = {
+
+ process : function(params) {
+ var amount = 0;
+ var strength = 0;
+ var mono = false;
+
+ if (typeof params.options.amount != "undefined")
+ amount = parseFloat(params.options.amount)||0;
+ if (typeof params.options.strength != "undefined")
+ strength = parseFloat(params.options.strength)||0;
+ if (typeof params.options.mono != "undefined")
+ mono = !!(params.options.mono && params.options.mono != "false");
+
+ amount = Math.max(0,Math.min(1,amount));
+ strength = Math.max(0,Math.min(1,strength));
+
+ var noise = 128 * strength;
+ var noise2 = noise / 2;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+ var random = Math.random;
+
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x-1)*4;
+ if (random() < amount) {
+ if (mono) {
+ var pixelNoise = - noise2 + random() * noise;
+ var r = data[offset] + pixelNoise;
+ var g = data[offset+1] + pixelNoise;
+ var b = data[offset+2] + pixelNoise;
+ } else {
+ var r = data[offset] - noise2 + (random() * noise);
+ var g = data[offset+1] - noise2 + (random() * noise);
+ var b = data[offset+2] - noise2 + (random() * noise);
+ }
+
+ if (r < 0 ) r = 0;
+ if (g < 0 ) g = 0;
+ if (b < 0 ) b = 0;
+ if (r > 255 ) r = 255;
+ if (g > 255 ) g = 255;
+ if (b > 255 ) b = 255;
+
+ data[offset] = r;
+ data[offset+1] = g;
+ data[offset+2] = b;
+ }
+ } while (--x);
+ } while (--y);
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}
+
+/*
+ * Pixastic Lib - Posterize effect - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.posterize = {
+
+ process : function(params) {
+
+
+ var numLevels = 256;
+ if (typeof params.options.levels != "undefined")
+ numLevels = parseInt(params.options.levels,10)||1;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+
+ numLevels = Math.max(2,Math.min(256,numLevels));
+
+ var numAreas = 256 / numLevels;
+ var numValues = 256 / (numLevels-1);
+
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x-1)*4;
+
+ var r = numValues * ((data[offset] / numAreas)>>0);
+ var g = numValues * ((data[offset+1] / numAreas)>>0);
+ var b = numValues * ((data[offset+2] / numAreas)>>0);
+
+ if (r > 255) r = 255;
+ if (g > 255) g = 255;
+ if (b > 255) b = 255;
+
+ data[offset] = r;
+ data[offset+1] = g;
+ data[offset+2] = b;
+
+ } while (--x);
+ } while (--y);
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}
+
+
+/*
+ * Pixastic Lib - Pointillize filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.pointillize = {
+
+ process : function(params) {
+ var radius = Math.max(1,parseInt(params.options.radius,10));
+ var density = Math.min(5,Math.max(0,parseFloat(params.options.density)||0));
+ var noise = Math.max(0,parseFloat(params.options.noise)||0);
+ var transparent = !!(params.options.transparent && params.options.transparent != "false");
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+
+ var ctx = params.canvas.getContext("2d");
+ var canvasWidth = params.canvas.width;
+ var canvasHeight = params.canvas.height;
+
+ var pixel = document.createElement("canvas");
+ pixel.width = pixel.height = 1;
+ var pixelCtx = pixel.getContext("2d");
+
+ var copy = document.createElement("canvas");
+ copy.width = w;
+ copy.height = h;
+ var copyCtx = copy.getContext("2d");
+ copyCtx.drawImage(params.canvas,rect.left,rect.top,w,h, 0,0,w,h);
+
+ var diameter = radius * 2;
+
+ if (transparent)
+ ctx.clearRect(rect.left, rect.top, rect.width, rect.height);
+
+ var noiseRadius = radius * noise;
+
+ var dist = 1 / density;
+
+ for (var y=0;y<h+radius;y+=diameter*dist) {
+ for (var x=0;x<w+radius;x+=diameter*dist) {
+ rndX = noise ? (x+((Math.random()*2-1) * noiseRadius))>>0 : x;
+ rndY = noise ? (y+((Math.random()*2-1) * noiseRadius))>>0 : y;
+
+ var pixX = rndX - radius;
+ var pixY = rndY - radius;
+ if (pixX < 0) pixX = 0;
+ if (pixY < 0) pixY = 0;
+
+ var cx = rndX + rect.left;
+ var cy = rndY + rect.top;
+ if (cx < 0) cx = 0;
+ if (cx > canvasWidth) cx = canvasWidth;
+ if (cy < 0) cy = 0;
+ if (cy > canvasHeight) cy = canvasHeight;
+
+ var diameterX = diameter;
+ var diameterY = diameter;
+
+ if (diameterX + pixX > w)
+ diameterX = w - pixX;
+ if (diameterY + pixY > h)
+ diameterY = h - pixY;
+ if (diameterX < 1) diameterX = 1;
+ if (diameterY < 1) diameterY = 1;
+
+ pixelCtx.drawImage(copy, pixX, pixY, diameterX, diameterY, 0, 0, 1, 1);
+ var data = pixelCtx.getImageData(0,0,1,1).data;
+
+ ctx.fillStyle = "rgb(" + data[0] + "," + data[1] + "," + data[2] + ")";
+ ctx.beginPath();
+ ctx.arc(cx, cy, radius, 0, Math.PI*2, true);
+ ctx.closePath();
+ ctx.fill();
+ }
+ }
+
+ params.useData = false;
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvasImageData());
+ }
+}/*
+ * Pixastic Lib - Resize - v0.1.0
+ * Copyright (c) 2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.resize = {
+ process : function(params) {
+ if (Pixastic.Client.hasCanvas()) {
+ var width = parseInt(params.options.width,10);
+ var height = parseInt(params.options.height,10);
+ var canvas = params.canvas;
+
+ if (width < 1) width = 1;
+ if (width < 2) width = 2;
+
+ var copy = document.createElement("canvas");
+ copy.width = width;
+ copy.height = height;
+
+ copy.getContext("2d").drawImage(canvas,0,0,width,height);
+ canvas.width = width;
+ canvas.height = height;
+
+ canvas.getContext("2d").drawImage(copy,0,0);
+
+ params.useData = false;
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvas();
+ }
+}
+
+
+/*
+ * Pixastic Lib - Remove noise - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.removenoise = {
+ process : function(params) {
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+
+ var nextY = (y == h) ? y - 1 : y;
+ var prevY = (y == 1) ? 0 : y-2;
+
+ var offsetYPrev = prevY*w*4;
+ var offsetYNext = nextY*w*4;
+
+ var x = w;
+ do {
+ var offset = offsetY + (x*4-4);
+
+ var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+ var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+
+ var minR, maxR, minG, maxG, minB, maxB;
+
+ minR = maxR = data[offsetPrev];
+ var r1 = data[offset-4], r2 = data[offset+4], r3 = data[offsetNext];
+ if (r1 < minR) minR = r1;
+ if (r2 < minR) minR = r2;
+ if (r3 < minR) minR = r3;
+ if (r1 > maxR) maxR = r1;
+ if (r2 > maxR) maxR = r2;
+ if (r3 > maxR) maxR = r3;
+
+ minG = maxG = data[offsetPrev+1];
+ var g1 = data[offset-3], g2 = data[offset+5], g3 = data[offsetNext+1];
+ if (g1 < minG) minG = g1;
+ if (g2 < minG) minG = g2;
+ if (g3 < minG) minG = g3;
+ if (g1 > maxG) maxG = g1;
+ if (g2 > maxG) maxG = g2;
+ if (g3 > maxG) maxG = g3;
+
+ minB = maxB = data[offsetPrev+2];
+ var b1 = data[offset-2], b2 = data[offset+6], b3 = data[offsetNext+2];
+ if (b1 < minB) minB = b1;
+ if (b2 < minB) minB = b2;
+ if (b3 < minB) minB = b3;
+ if (b1 > maxB) maxB = b1;
+ if (b2 > maxB) maxB = b2;
+ if (b3 > maxB) maxB = b3;
+
+ if (data[offset] > maxR) {
+ data[offset] = maxR;
+ } else if (data[offset] < minR) {
+ data[offset] = minR;
+ }
+ if (data[offset+1] > maxG) {
+ data[offset+1] = maxG;
+ } else if (data[offset+1] < minG) {
+ data[offset+1] = minG;
+ }
+ if (data[offset+2] > maxB) {
+ data[offset+2] = maxB;
+ } else if (data[offset+2] < minB) {
+ data[offset+2] = minB;
+ }
+
+ } while (--x);
+ } while (--y);
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}/*
+ * Pixastic Lib - Rotate - v0.1.0
+ * Copyright (c) 2009 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.rotate = {
+ process : function(params) {
+ if (Pixastic.Client.hasCanvas()) {
+ var canvas = params.canvas;
+
+ var width = params.width;
+ var height = params.height;
+
+ var copy = document.createElement("canvas");
+ copy.width = width;
+ copy.height = height;
+ copy.getContext("2d").drawImage(canvas,0,0,width,height);
+
+ var angle = -parseFloat(params.options.angle) * Math.PI / 180;
+
+ var dimAngle = angle;
+ if (dimAngle > Math.PI*0.5)
+ dimAngle = Math.PI - dimAngle;
+ if (dimAngle < -Math.PI*0.5)
+ dimAngle = -Math.PI - dimAngle;
+
+ var diag = Math.sqrt(width*width + height*height);
+
+ var diagAngle1 = Math.abs(dimAngle) - Math.abs(Math.atan2(height, width));
+ var diagAngle2 = Math.abs(dimAngle) + Math.abs(Math.atan2(height, width));
+
+ var newWidth = Math.abs(Math.cos(diagAngle1) * diag);
+ var newHeight = Math.abs(Math.sin(diagAngle2) * diag);
+
+ canvas.width = newWidth;
+ canvas.height = newHeight;
+
+ var ctx = canvas.getContext("2d");
+ ctx.translate(newWidth/2, newHeight/2);
+ ctx.rotate(angle);
+ ctx.drawImage(copy,-width/2,-height/2);
+
+ params.useData = false;
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvas();
+ }
+}
+
+
+/*
+ * Pixastic Lib - Sepia filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.sepia = {
+
+ process : function(params) {
+ var mode = (parseInt(params.options.mode,10)||0);
+ if (mode < 0) mode = 0;
+ if (mode > 1) mode = 1;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x-1)*4;
+
+ if (mode) {
+ // a bit faster, but not as good
+ var d = data[offset] * 0.299 + data[offset+1] * 0.587 + data[offset+2] * 0.114;
+ var r = (d + 39);
+ var g = (d + 14);
+ var b = (d - 36);
+ } else {
+ // Microsoft
+ var or = data[offset];
+ var og = data[offset+1];
+ var ob = data[offset+2];
+
+ var r = (or * 0.393 + og * 0.769 + ob * 0.189);
+ var g = (or * 0.349 + og * 0.686 + ob * 0.168);
+ var b = (or * 0.272 + og * 0.534 + ob * 0.131);
+ }
+
+ if (r < 0) r = 0; if (r > 255) r = 255;
+ if (g < 0) g = 0; if (g > 255) g = 255;
+ if (b < 0) b = 0; if (b > 255) b = 255;
+
+ data[offset] = r;
+ data[offset+1] = g;
+ data[offset+2] = b;
+
+ } while (--x);
+ } while (--y);
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}/*
+ * Pixastic Lib - Sharpen filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.sharpen = {
+ process : function(params) {
+
+ var strength = 0;
+ if (typeof params.options.amount != "undefined")
+ strength = parseFloat(params.options.amount)||0;
+
+ if (strength < 0) strength = 0;
+ if (strength > 1) strength = 1;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var dataCopy = Pixastic.prepareData(params, true)
+
+ var mul = 15;
+ var mulOther = 1 + 3*strength;
+
+ var kernel = [
+ [0, -mulOther, 0],
+ [-mulOther, mul, -mulOther],
+ [0, -mulOther, 0]
+ ];
+
+ var weight = 0;
+ for (var i=0;i<3;i++) {
+ for (var j=0;j<3;j++) {
+ weight += kernel[i][j];
+ }
+ }
+
+ weight = 1 / weight;
+
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+
+ mul *= weight;
+ mulOther *= weight;
+
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+
+ var nextY = (y == h) ? y - 1 : y;
+ var prevY = (y == 1) ? 0 : y-2;
+
+ var offsetYPrev = prevY*w4;
+ var offsetYNext = nextY*w4;
+
+ var x = w;
+ do {
+ var offset = offsetY + (x*4-4);
+
+ var offsetPrev = offsetYPrev + ((x == 1) ? 0 : x-2) * 4;
+ var offsetNext = offsetYNext + ((x == w) ? x-1 : x) * 4;
+
+ var r = ((
+ - dataCopy[offsetPrev]
+ - dataCopy[offset-4]
+ - dataCopy[offset+4]
+ - dataCopy[offsetNext]) * mulOther
+ + dataCopy[offset] * mul
+ );
+
+ var g = ((
+ - dataCopy[offsetPrev+1]
+ - dataCopy[offset-3]
+ - dataCopy[offset+5]
+ - dataCopy[offsetNext+1]) * mulOther
+ + dataCopy[offset+1] * mul
+ );
+
+ var b = ((
+ - dataCopy[offsetPrev+2]
+ - dataCopy[offset-2]
+ - dataCopy[offset+6]
+ - dataCopy[offsetNext+2]) * mulOther
+ + dataCopy[offset+2] * mul
+ );
+
+
+ if (r < 0 ) r = 0;
+ if (g < 0 ) g = 0;
+ if (b < 0 ) b = 0;
+ if (r > 255 ) r = 255;
+ if (g > 255 ) g = 255;
+ if (b > 255 ) b = 255;
+
+ data[offset] = r;
+ data[offset+1] = g;
+ data[offset+2] = b;
+
+ } while (--x);
+ } while (--y);
+
+ return true;
+
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}
+/*
+ * Pixastic Lib - Solarize filter - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+Pixastic.Actions.solarize = {
+
+ process : function(params) {
+ var useAverage = !!(params.options.average && params.options.average != "false");
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var data = Pixastic.prepareData(params);
+ var rect = params.options.rect;
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x-1)*4;
+
+ var r = data[offset];
+ var g = data[offset+1];
+ var b = data[offset+2];
+
+ if (r > 127) r = 255 - r;
+ if (g > 127) g = 255 - g;
+ if (b > 127) b = 255 - b;
+
+ data[offset] = r;
+ data[offset+1] = g;
+ data[offset+2] = b;
+
+ } while (--x);
+ } while (--y);
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return (Pixastic.Client.hasCanvasImageData());
+ }
+}/*
+ * Pixastic Lib - USM - v0.1.0
+ * Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk, http://blog.nihilogic.dk/
+ * License: [http://www.pixastic.com/lib/license.txt]
+ */
+
+
+Pixastic.Actions.unsharpmask = {
+ process : function(params) {
+
+ var amount = (parseFloat(params.options.amount)||0);
+ var blurAmount = parseFloat(params.options.radius)||0;
+ var threshold = parseFloat(params.options.threshold)||0;
+
+ amount = Math.min(500,Math.max(0,amount)) / 2;
+ blurAmount = Math.min(5,Math.max(0,blurAmount)) / 10;
+ threshold = Math.min(255,Math.max(0,threshold));
+
+ threshold--;
+ var thresholdNeg = -threshold;
+
+ amount *= 0.016;
+ amount++;
+
+ if (Pixastic.Client.hasCanvasImageData()) {
+ var rect = params.options.rect;
+
+ var blurCanvas = document.createElement("canvas");
+ blurCanvas.width = params.width;
+ blurCanvas.height = params.height;
+ var blurCtx = blurCanvas.getContext("2d");
+ blurCtx.drawImage(params.canvas,0,0);
+
+ var scale = 2;
+ var smallWidth = Math.round(params.width / scale);
+ var smallHeight = Math.round(params.height / scale);
+
+ var copy = document.createElement("canvas");
+ copy.width = smallWidth;
+ copy.height = smallHeight;
+
+ var steps = Math.round(blurAmount * 20);
+
+ var copyCtx = copy.getContext("2d");
+ for (var i=0;i<steps;i++) {
+ var scaledWidth = Math.max(1,Math.round(smallWidth - i));
+ var scaledHeight = Math.max(1,Math.round(smallHeight - i));
+
+ copyCtx.clearRect(0,0,smallWidth,smallHeight);
+
+ copyCtx.drawImage(
+ blurCanvas,
+ 0,0,params.width,params.height,
+ 0,0,scaledWidth,scaledHeight
+ );
+
+ blurCtx.clearRect(0,0,params.width,params.height);
+
+ blurCtx.drawImage(
+ copy,
+ 0,0,scaledWidth,scaledHeight,
+ 0,0,params.width,params.height
+ );
+ }
+
+ var data = Pixastic.prepareData(params);
+ var blurData = Pixastic.prepareData({canvas:blurCanvas,options:params.options});
+ var w = rect.width;
+ var h = rect.height;
+ var w4 = w*4;
+ var y = h;
+ do {
+ var offsetY = (y-1)*w4;
+ var x = w;
+ do {
+ var offset = offsetY + (x*4-4);
+
+ var difR = data[offset] - blurData[offset];
+ if (difR > threshold || difR < thresholdNeg) {
+ var blurR = blurData[offset];
+ blurR = amount * difR + blurR;
+ data[offset] = blurR > 255 ? 255 : (blurR < 0 ? 0 : blurR);
+ }
+
+ var difG = data[offset+1] - blurData[offset+1];
+ if (difG > threshold || difG < thresholdNeg) {
+ var blurG = blurData[offset+1];
+ blurG = amount * difG + blurG;
+ data[offset+1] = blurG > 255 ? 255 : (blurG < 0 ? 0 : blurG);
+ }
+
+ var difB = data[offset+2] - blurData[offset+2];
+ if (difB > threshold || difB < thresholdNeg) {
+ var blurB = blurData[offset+2];
+ blurB = amount * difB + blurB;
+ data[offset+2] = blurB > 255 ? 255 : (blurB < 0 ? 0 : blurB);
+ }
+
+ } while (--x);
+ } while (--y);
+
+ return true;
+ }
+ },
+ checkSupport : function() {
+ return Pixastic.Client.hasCanvasImageData();
+ }
+}
+
+
+
+
-/* http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/ */\r
-\r
-html, body, div, span, applet, object, iframe,\r
-h1, h2, h3, h4, h5, h6, p, blockquote, pre,\r
-a, abbr, acronym, address, big, cite, code,\r
-del, dfn, em, font, img, ins, kbd, q, s, samp,\r
-small, strike, strong, sub, sup, tt, var,\r
-dl, dt, dd, ol, ul, li,\r
-fieldset, form, label, legend,\r
-table, caption, tbody, tfoot, thead, tr, th, td {\r
- margin: 0;\r
- padding: 0;\r
- border: 0;\r
- outline: 0;\r
- font-weight: inherit;\r
- font-style: inherit;\r
- font-size: 100%;\r
- font-family: inherit;\r
- vertical-align: baseline;\r
-}\r
-/* remember to define focus styles! */\r
-:focus {\r
- outline: 0;\r
-}\r
-body {\r
- line-height: 1;\r
- color: black;\r
- background: white;\r
-}\r
-ol, ul {\r
- list-style: none;\r
-}\r
-/* tables still need 'cellspacing="0"' in the markup */\r
-table {\r
- border-collapse: separate;\r
- border-spacing: 0;\r
-}\r
-caption, th, td {\r
- text-align: left;\r
- font-weight: normal;\r
-}\r
-blockquote:before, blockquote:after,\r
-q:before, q:after {\r
- content: "";\r
-}\r
-blockquote, q {\r
- quotes: "" "";\r
-}\r
-/* end reset */\r
-\r
-/* -----------------------\r
- * Base\r
- * -----------------------\r
- */\r
-\r
-/* main container element for editor app */\r
-#pixastic-editor {\r
- margin : 0;\r
- position : absolute;\r
- left : 0;\r
- top : 0;\r
- padding: 0px;\r
- width: 100%;\r
- height: 100%;\r
- font-family : Helvetica,Arial,sans-serif;\r
- overflow : hidden;\r
- z-index : 10000000;\r
-} \r
-\r
-\r
-/* -----------------------\r
- * Loading screen\r
- * -----------------------\r
- */\r
-\r
-/* container for loading screen */\r
-#loading-screen {\r
- margin : 0;\r
- position : absolute;\r
- left : 0;\r
- top : 0;\r
- padding: 0px;\r
- width: 100%;\r
- height: 100%;\r
- font-family : Helvetica,Arial,sans-serif;\r
- overflow : hidden;\r
- z-index : 10000000;\r
- background-color : #111;\r
- opacity : 0.9;\r
- display : table;\r
- text-align : center;\r
-} \r
-\r
-/* container for spinner in loading screen */\r
-#loading-screen-cell {\r
- display : table-cell;\r
- vertical-align : middle;\r
- text-align : center;\r
-}\r
-\r
-\r
-/* -----------------------\r
- * Misc\r
- * -----------------------\r
- */\r
-\r
-\r
-// UI error dialog\r
-.ui-dialog .error-dialog {\r
- background-color : #544;\r
-}\r
-\r
-/* loading spinner */\r
-.spinner {\r
- width : 31px;\r
- height : 31px;\r
- display : inline-block;\r
- background: url(spinner.gif);\r
- overflow : hidden;\r
-}\r
-\r
-canvas.display-canvas,\r
-canvas.undo-canvas {\r
- /*\r
- background : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC1JREFUeNpiPHPmDAM2YGxsjFWciYFEMKqBGMD4//9/rBJnz54dDSX6aQAIMABCtQiAsDRF+wAAAABJRU5ErkJggg==');\r
- */\r
- background : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC5JREFUeNpiPHPmTAMDHmBsbIxPmoGJgUIwasBgMICFUDyfPXt2NBCHvwEAAQYAICIGn294LYEAAAAASUVORK5CYII=');\r
-\r
-}\r
-\r
-.far-far-away {\r
- position : absolute;\r
- left : -9999px;\r
- top : -9999px;\r
-}\r
-\r
-#powered-by-pixastic {\r
- position : absolute;\r
- bottom : 0px;\r
- margin-bottom : 23px;\r
- margin-left : 42px;\r
-}\r
-#powered-by-pixastic a {\r
- font-size : 12px;\r
- font-family : Helvetica,Arial,sans-serif;\r
- letter-spacing : 0.1em;\r
- color : rgb(100,100,100);\r
- color : rgba(255,255,255,0.2);\r
- text-decoration : none;\r
-}\r
-\r
-#powered-by-pixastic a:hover {\r
- color : rgb(200,200,200);\r
- color : rgba(255,255,255,0.7);\r
- text-decoration : underline;\r
-}\r
-\r
-\r
-/* -----------------------\r
- * Skeleton structure\r
- * -----------------------\r
- */\r
-\r
-/* editor background underlay */\r
-#background {\r
- background-color : #111;\r
- opacity : 0.9;\r
- width : 100%;\r
- height : 100%;\r
- position : absolute;\r
- z-index : -1;\r
-}\r
-\r
-#image-area {\r
- position : relative;\r
- background-color : #222;\r
- border : 1px solid #444;\r
- width : 100%;\r
- height : 100%;\r
- -moz-box-sizing:border-box;\r
- overflow : auto;\r
- text-align : center;\r
-}\r
-\r
-#image-area-sub {\r
-}\r
-\r
-#image-container {\r
-}\r
-\r
-#image-overlay-container {\r
- -moz-box-sizing:border-box;\r
- width:100%;\r
- height:100%;\r
- position:absolute;\r
- top:0;\r
- left:0;\r
-}\r
-\r
-#image-overlay {\r
-}\r
-\r
-\r
-/* structure elements */\r
-#edit-ctr-1 {\r
- position : absolute;\r
- top : 0;\r
- left : 0;\r
- width : 100%;\r
- height : 100%;\r
-}\r
-\r
-#edit-ctr-2 {\r
- -moz-box-sizing : border-box;\r
- box-sizing : border-box;\r
- padding-left:40px;\r
- padding-right:420px;\r
- padding-top:70px;\r
- padding-bottom : 40px;\r
- height : 100%;\r
- width : 100%;\r
-}\r
-\r
-\r
-/* main menu bar */\r
-#main-bar {\r
- position : absolute;\r
- width : 100%;\r
- text-align : right;\r
- margin-top : 20px;\r
- margin-right : 30px;\r
-}\r
-\r
-/* area on the right with accordion widgets and undo bar */\r
-#controls-bar {\r
- margin-right : -385px;\r
- width : 372px;\r
- float : right;\r
- height : 100%;\r
-}\r
-\r
-/* accordion area */\r
-#action-bar {\r
- padding : 10px;\r
- width : 290px;\r
- background-color : #222;\r
- border : 1px solid #444;\r
- -moz-box-sizing : border-box;\r
- box-sizing : border-box;\r
- height : 100%;\r
- overflow-x : hidden;\r
- overflow-y : auto;\r
- float: right; \r
- position : relative;\r
-}\r
-\r
-#action-bar-overlay {\r
- position : absolute;\r
- z-index : 1000000;\r
- width : 100%;\r
- height : 100%;\r
- left : 0;\r
- top : 0;\r
- background-color : #444;\r
- opacity : 0.2;\r
- display : none;\r
-}\r
-\r
-\r
-/* vertical bar with undo image states */\r
-#undo-bar {\r
- -moz-box-sizing : border-box;\r
- box-sizing : border-box;\r
- background-color : #222;\r
- border : 1px solid #444;\r
- width: 70px; \r
- height: 100%;\r
- overflow: hidden;\r
- padding-top : 3px;\r
-}\r
-\r
-\r
-\r
-/* -----------------------\r
- * Main menu styles\r
- * -----------------------\r
- */\r
-\r
-.main-tab {\r
- color : #999;\r
- display : inline-block;\r
- width : 150px;\r
- text-transform : lowercase;\r
- font-size : 22px;\r
- cursor : pointer;\r
- text-align : center;\r
- text-decoration : none;\r
- padding-top : 4px;\r
- padding-bottom : 5px;\r
- outline : 0;\r
-}\r
-\r
-.main-tab.hover {\r
- color : white !important;\r
-}\r
-\r
-.main-tab.active {\r
- color : white;\r
-}\r
-\r
-\r
-\r
-/* -----------------------\r
- * Undo list\r
- * -----------------------\r
- */\r
-\r
-\r
-.undo-canvas-small {\r
- width : 60px;\r
- height : 40px;\r
- cursor : pointer;\r
-}\r
-\r
-.undo-link {\r
- width : 60px;\r
- height : 40px;\r
- display : block;\r
- margin : 4px;\r
- cursor : pointer;\r
- opacity : 0.8;\r
-}\r
-\r
-.undo-link.hover {\r
- opacity : 1;\r
-}\r
-\r
-\r
-\r
-/* -----------------------\r
- * Action UI controls\r
- * -----------------------\r
- */\r
-\r
-\r
-.ui-slider-label, \r
-.ui-checkbox-label, \r
-.ui-textinput-label, \r
-.ui-select-label {\r
- width : 70px;\r
- text-align : right;\r
- margin-right : 5px;\r
- display : inline-block;\r
-}\r
-\r
-.ui-textinput-label-right {\r
- margin-left : 5px;\r
-}\r
-\r
-.ui-textinput {\r
-}\r
-\r
-.ui-numericinput {\r
- width : 35px;\r
-}\r
-\r
-.ui-slider {\r
- width : 125px;\r
- display : inline-block;\r
- margin-left : 3px;\r
- background-color : #222;\r
-}\r
-\r
-.ui-slider-value {\r
- font-size : 11px;\r
- width : 25px;\r
- display : inline-block;\r
- margin-left : 10px;\r
-}\r
-\r
-.ui-action-output {\r
- margin-bottom : 10px;\r
-}\r
-\r
-.ui-accordion .ui-accordion-content-active {\r
- font-size : 11px;\r
- overflow : hidden;\r
-}\r
-\r
-.ui-slider-horizontal {\r
-}\r
-\r
-.ui-slider-container, \r
-.ui-checkbox-container, \r
-.ui-textinput-container, \r
-.ui-select-container {\r
- margin-top : 0px;\r
- margin-bottom : 10px;\r
- white-space : nowrap;\r
-}\r
-\r
-.ui-preview-checkbox-container {\r
- display : inline-block;\r
-}\r
-\r
-.ui-checkbox {\r
- margin-bottom:3px;\r
- margin-left:5px;\r
- margin-right:5px;\r
- margin-top:0px;\r
- vertical-align:middle;\r
-}\r
-\r
-input::-moz-focus-inner { border: 0; }\r
-\r
-.action-output-text {\r
- margin-bottom : 5px;\r
-}\r
-\r
-button {\r
- margin-right : 5px;\r
-}\r
-\r
+/* http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/ */
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, font, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ outline: 0;
+ font-weight: inherit;
+ font-style: inherit;
+ font-size: 100%;
+ font-family: inherit;
+ vertical-align: baseline;
+}
+/* remember to define focus styles! */
+:focus {
+ outline: 0;
+}
+body {
+ line-height: 1;
+ color: black;
+ background: white;
+}
+ol, ul {
+ list-style: none;
+}
+/* tables still need 'cellspacing="0"' in the markup */
+table {
+ border-collapse: separate;
+ border-spacing: 0;
+}
+caption, th, td {
+ text-align: left;
+ font-weight: normal;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+ content: "";
+}
+blockquote, q {
+ quotes: "" "";
+}
+/* end reset */
+
+/* -----------------------
+ * Base
+ * -----------------------
+ */
+
+/* main container element for editor app */
+#pixastic-editor {
+ margin : 0;
+ position : absolute;
+ left : 0;
+ top : 0;
+ padding: 0px;
+ width: 100%;
+ height: 100%;
+ font-family : Helvetica,Arial,sans-serif;
+ overflow : hidden;
+ z-index : 10000000;
+}
+
+
+/* -----------------------
+ * Loading screen
+ * -----------------------
+ */
+
+/* container for loading screen */
+#loading-screen {
+ margin : 0;
+ position : absolute;
+ left : 0;
+ top : 0;
+ padding: 0px;
+ width: 100%;
+ height: 100%;
+ font-family : Helvetica,Arial,sans-serif;
+ overflow : hidden;
+ z-index : 10000000;
+ background-color : #111;
+ opacity : 0.9;
+ display : table;
+ text-align : center;
+}
+
+/* container for spinner in loading screen */
+#loading-screen-cell {
+ display : table-cell;
+ vertical-align : middle;
+ text-align : center;
+}
+
+
+/* -----------------------
+ * Misc
+ * -----------------------
+ */
+
+
+// UI error dialog
+.ui-dialog .error-dialog {
+ background-color : #544;
+}
+
+/* loading spinner */
+.spinner {
+ width : 31px;
+ height : 31px;
+ display : inline-block;
+ background: url(spinner.gif);
+ overflow : hidden;
+}
+
+canvas.display-canvas,
+canvas.undo-canvas {
+ /*
+ background : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC1JREFUeNpiPHPmDAM2YGxsjFWciYFEMKqBGMD4//9/rBJnz54dDSX6aQAIMABCtQiAsDRF+wAAAABJRU5ErkJggg==');
+ */
+ background : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC5JREFUeNpiPHPmTAMDHmBsbIxPmoGJgUIwasBgMICFUDyfPXt2NBCHvwEAAQYAICIGn294LYEAAAAASUVORK5CYII=');
+
+}
+
+.far-far-away {
+ position : absolute;
+ left : -9999px;
+ top : -9999px;
+}
+
+#powered-by-pixastic {
+ position : absolute;
+ bottom : 0px;
+ margin-bottom : 23px;
+ margin-left : 42px;
+}
+#powered-by-pixastic a {
+ font-size : 12px;
+ font-family : Helvetica,Arial,sans-serif;
+ letter-spacing : 0.1em;
+ color : rgb(100,100,100);
+ color : rgba(255,255,255,0.2);
+ text-decoration : none;
+}
+
+#powered-by-pixastic a:hover {
+ color : rgb(200,200,200);
+ color : rgba(255,255,255,0.7);
+ text-decoration : underline;
+}
+
+
+/* -----------------------
+ * Skeleton structure
+ * -----------------------
+ */
+
+/* editor background underlay */
+#background {
+ background-color : #111;
+ opacity : 0.9;
+ width : 100%;
+ height : 100%;
+ position : absolute;
+ z-index : -1;
+}
+
+#image-area {
+ position : relative;
+ background-color : #222;
+ border : 1px solid #444;
+ width : 100%;
+ height : 100%;
+ -moz-box-sizing:border-box;
+ overflow : auto;
+ text-align : center;
+}
+
+#image-area-sub {
+}
+
+#image-container {
+}
+
+#image-overlay-container {
+ -moz-box-sizing:border-box;
+ width:100%;
+ height:100%;
+ position:absolute;
+ top:0;
+ left:0;
+}
+
+#image-overlay {
+}
+
+
+/* structure elements */
+#edit-ctr-1 {
+ position : absolute;
+ top : 0;
+ left : 0;
+ width : 100%;
+ height : 100%;
+}
+
+#edit-ctr-2 {
+ -moz-box-sizing : border-box;
+ box-sizing : border-box;
+ padding-left:40px;
+ padding-right:420px;
+ padding-top:70px;
+ padding-bottom : 40px;
+ height : 100%;
+ width : 100%;
+}
+
+
+/* main menu bar */
+#main-bar {
+ position : absolute;
+ width : 100%;
+ text-align : right;
+ margin-top : 20px;
+ margin-right : 30px;
+}
+
+/* area on the right with accordion widgets and undo bar */
+#controls-bar {
+ margin-right : -385px;
+ width : 372px;
+ float : right;
+ height : 100%;
+}
+
+/* accordion area */
+#action-bar {
+ padding : 10px;
+ width : 290px;
+ background-color : #222;
+ border : 1px solid #444;
+ -moz-box-sizing : border-box;
+ box-sizing : border-box;
+ height : 100%;
+ overflow-x : hidden;
+ overflow-y : auto;
+ float: right;
+ position : relative;
+}
+
+#action-bar-overlay {
+ position : absolute;
+ z-index : 1000000;
+ width : 100%;
+ height : 100%;
+ left : 0;
+ top : 0;
+ background-color : #444;
+ opacity : 0.2;
+ display : none;
+}
+
+
+/* vertical bar with undo image states */
+#undo-bar {
+ -moz-box-sizing : border-box;
+ box-sizing : border-box;
+ background-color : #222;
+ border : 1px solid #444;
+ width: 70px;
+ height: 100%;
+ overflow: hidden;
+ padding-top : 3px;
+}
+
+
+
+/* -----------------------
+ * Main menu styles
+ * -----------------------
+ */
+
+.main-tab {
+ color : #999;
+ display : inline-block;
+ width : 150px;
+ text-transform : lowercase;
+ font-size : 22px;
+ cursor : pointer;
+ text-align : center;
+ text-decoration : none;
+ padding-top : 4px;
+ padding-bottom : 5px;
+ outline : 0;
+}
+
+.main-tab.hover {
+ color : white !important;
+}
+
+.main-tab.active {
+ color : white;
+}
+
+
+
+/* -----------------------
+ * Undo list
+ * -----------------------
+ */
+
+
+.undo-canvas-small {
+ width : 60px;
+ height : 40px;
+ cursor : pointer;
+}
+
+.undo-link {
+ width : 60px;
+ height : 40px;
+ display : block;
+ margin : 4px;
+ cursor : pointer;
+ opacity : 0.8;
+}
+
+.undo-link.hover {
+ opacity : 1;
+}
+
+
+
+/* -----------------------
+ * Action UI controls
+ * -----------------------
+ */
+
+
+.ui-slider-label,
+.ui-checkbox-label,
+.ui-textinput-label,
+.ui-select-label {
+ width : 70px;
+ text-align : right;
+ margin-right : 5px;
+ display : inline-block;
+}
+
+.ui-textinput-label-right {
+ margin-left : 5px;
+}
+
+.ui-textinput {
+}
+
+.ui-numericinput {
+ width : 35px;
+}
+
+.ui-slider {
+ width : 125px;
+ display : inline-block;
+ margin-left : 3px;
+ background-color : #222;
+}
+
+.ui-slider-value {
+ font-size : 11px;
+ width : 25px;
+ display : inline-block;
+ margin-left : 10px;
+}
+
+.ui-action-output {
+ margin-bottom : 10px;
+}
+
+.ui-accordion .ui-accordion-content-active {
+ font-size : 11px;
+ overflow : hidden;
+}
+
+.ui-slider-horizontal {
+}
+
+.ui-slider-container,
+.ui-checkbox-container,
+.ui-textinput-container,
+.ui-select-container {
+ margin-top : 0px;
+ margin-bottom : 10px;
+ white-space : nowrap;
+}
+
+.ui-preview-checkbox-container {
+ display : inline-block;
+}
+
+.ui-checkbox {
+ margin-bottom:3px;
+ margin-left:5px;
+ margin-right:5px;
+ margin-top:0px;
+ vertical-align:middle;
+}
+
+input::-moz-focus-inner { border: 0; }
+
+.action-output-text {
+ margin-bottom : 5px;
+}
+
+button {
+ margin-right : 5px;
+}
+
-(function($) {\r
-\r
- var PE = PixasticEditor;\r
-\r
- function makeSlider(label, id, min, max, step, defaultVal, onChange) {\r
- var $ctr = $j("<div></div>", PE.getDocument())\r
- .addClass("ui-slider-container");\r
-\r
- var $label = $j("<label></label>", PE.getDocument())\r
- .addClass("ui-slider-label")\r
- .attr("for", "input-slider-" + id)\r
- .html(label + ":")\r
- .appendTo($ctr);\r
-\r
- var $value = $j("<div></div>", PE.getDocument())\r
- .addClass("ui-slider-value")\r
- .html(defaultVal());\r
-\r
- var $valueField = $j("<input type='hidden'>", PE.getDocument())\r
- .attr("id", "input-hidden-" + id)\r
- .val(defaultVal())\r
- .appendTo($ctr);\r
-\r
- var performOnChange = true;\r
-\r
- var $slider = $j("<div class='ui-slider'><div class='ui-slider-handle'></div><div class='ui-slider-range'></div></div>", PE.getDocument())\r
- .appendTo($ctr)\r
- .attr("id", "input-slider-" + id)\r
- .slider({\r
- slide: function() {\r
- $value.html($j(this).slider("value"));\r
- $valueField.val($j(this).slider("value"));\r
- },\r
- change : function() {\r
- $value.html($j(this).slider("value"));\r
- $valueField.val($j(this).slider("value"));\r
- if (onChange && performOnChange)\r
- onChange();\r
- },\r
- min : min,\r
- max : max,\r
- step : step,\r
- value : defaultVal()\r
- });\r
-\r
- $value.appendTo($ctr);\r
-\r
- return {\r
- container : $ctr,\r
- label : $label,\r
- slider : $slider,\r
- valueText : $value,\r
- valueField : $valueField,\r
- reset : function() {\r
- performOnChange = false;\r
- $value.html(defaultVal());\r
- $valueField.val(defaultVal());\r
- $slider.slider("value", defaultVal());\r
- performOnChange = true;\r
- }\r
- };\r
- }\r
-\r
- function makeCheckbox(label, id, defaultVal, onChange) {\r
- var $ctr = $j("<div></div>", PE.getDocument())\r
- .addClass("ui-checkbox-container");\r
-\r
- var $label = $j("<label></label>", PE.getDocument())\r
- .addClass("ui-checkbox-label")\r
- .attr("for", "input-checkbox-" + id)\r
- .html(label + ":")\r
- .appendTo($ctr);\r
-\r
- var $valueField = $j("<input type='hidden'>", PE.getDocument())\r
- .attr("id", "input-hidden-" + id)\r
- .val(defaultVal())\r
- .appendTo($ctr);\r
-\r
- var performOnChange = true;\r
-\r
- var $checkbox = $j("<input type=\"checkbox\"></input>", PE.getDocument())\r
- .addClass("ui-checkbox")\r
- .attr("id", "input-checkbox-" + id)\r
- .attr("checked", defaultVal())\r
- .appendTo($ctr)\r
- .change(function() {\r
- $valueField.val(this.checked);\r
- if (onChange && performOnChange)\r
- onChange();\r
- });\r
-\r
- return {\r
- container : $ctr,\r
- label : $label,\r
- checkbox : $checkbox,\r
- valueField : $valueField,\r
- reset : function() {\r
- performOnChange = false;\r
- $checkbox.attr("checked", defaultVal());\r
- $valueField.val(defaultVal());\r
- performOnChange = true;\r
- }\r
- };\r
- }\r
-\r
- function makeSelect(label, id, values, defaultVal, onChange) {\r
- var $ctr = $j("<div></div>", PE.getDocument())\r
- .addClass("ui-select-container");\r
-\r
- var $label = $j("<label></label>", PE.getDocument())\r
- .addClass("ui-checkbox-label")\r
- .attr("for", "input-checkbox-" + id)\r
- .html(label + ":")\r
- .appendTo($ctr);\r
-\r
- var $valueField = $j("<input type='hidden'>", PE.getDocument())\r
- .attr("id", "input-hidden-" + id)\r
- .val(defaultVal())\r
- .appendTo($ctr);\r
-\r
- var selectHtml = "<select>";\r
- for (var i=0;i<values.length;i++) {\r
- selectHtml += "<option value='" + values[i].value + "' " \r
- + (defaultVal() == values[i].value ? "selected" : "") \r
- + ">" + values[i].name + "</option>";\r
- }\r
- selectHtml += "</select>";\r
-\r
- var $select = $j(selectHtml).appendTo($ctr);\r
-\r
- var performOnChange = true;\r
-\r
- $select.change(\r
- function() {\r
- $valueField.val(this.options[this.selectedIndex].value);\r
- if (onChange && performOnChange)\r
- onChange();\r
- }\r
- );\r
-\r
- return {\r
- container : $ctr,\r
- label : $label,\r
- select : $select,\r
- valueField : $valueField,\r
- reset : function() {\r
- performOnChange = false;\r
- var defVal = defaultVal();\r
- $select.val(defVal);\r
- $valueField.val(defVal);\r
- performOnChange = true;\r
- }\r
- };\r
- }\r
-\r
- function makeNumericInput(label, labelRight, id, min, max, step, defaultVal, onChange) {\r
- var $ctr = $j("<div></div>", PE.getDocument())\r
- .addClass("ui-textinput-container");\r
-\r
- var $label = $j("<label></label>", PE.getDocument())\r
- .addClass("ui-textinput-label")\r
- .attr("for", "input-numeric-" + id)\r
- .html(label + ":")\r
- .appendTo($ctr);\r
-\r
- var $valueField = $j("<input type='hidden'>", PE.getDocument())\r
- .attr("id", "input-hidden-" + id)\r
- .val(defaultVal())\r
- .appendTo($ctr);\r
-\r
- var performOnChange = true;\r
-\r
- function setVal(val) {\r
- val = Math.min(max, val);\r
- val = Math.max(min, val);\r
- $textInput.val(val);\r
- $valueField.val(val);\r
- }\r
-\r
- var $textInput = $j("<input type=\"text\"></input>", PE.getDocument())\r
- .addClass("ui-textinput")\r
- .addClass("ui-numericinput")\r
- .appendTo($ctr)\r
- .val(defaultVal())\r
- .attr("id", "input-numeric-" + id)\r
- .change(function() {\r
- var val = parseFloat(this.value);\r
- setVal(val);\r
- if (onChange && performOnChange)\r
- onChange();\r
- })\r
- .keydown(function(e) {\r
- var val = parseFloat($j(this).val());\r
- if (e.keyCode == 38) { // up\r
- setVal(val + step);\r
- }\r
- if (e.keyCode == 40) { // down\r
- setVal(val - step);\r
- }\r
- });\r
-\r
- if (labelRight) {\r
- var $labelRight = $j("<label></label>", PE.getDocument())\r
- .addClass("ui-textinput-label-right")\r
- .html(labelRight)\r
- .appendTo($ctr);\r
- }\r
-\r
- return {\r
- container : $ctr,\r
- label : $label,\r
- textinput : $textInput,\r
- valueField : $valueField,\r
- reset : function() {\r
- performOnChange = false;\r
- setVal(defaultVal());\r
- performOnChange = true;\r
- }\r
- };\r
- }\r
-\r
- function makeButton(text) {\r
- var $button = $j("<button></button>", PE.getDocument()).html(text);\r
- return $button;\r
- }\r
-\r
-\r
- PE.UI = {\r
- makeSlider : makeSlider,\r
- makeCheckbox : makeCheckbox,\r
- makeNumericInput : makeNumericInput,\r
- makeSelect : makeSelect,\r
- makeButton : makeButton\r
- }\r
-\r
-})(PixasticEditor.jQuery);\r
-\r
+(function($) {
+
+ var PE = PixasticEditor;
+
+ function makeSlider(label, id, min, max, step, defaultVal, onChange) {
+ var $ctr = $j("<div></div>", PE.getDocument())
+ .addClass("ui-slider-container");
+
+ var $label = $j("<label></label>", PE.getDocument())
+ .addClass("ui-slider-label")
+ .attr("for", "input-slider-" + id)
+ .html(label + ":")
+ .appendTo($ctr);
+
+ var $value = $j("<div></div>", PE.getDocument())
+ .addClass("ui-slider-value")
+ .html(defaultVal());
+
+ var $valueField = $j("<input type='hidden'>", PE.getDocument())
+ .attr("id", "input-hidden-" + id)
+ .val(defaultVal())
+ .appendTo($ctr);
+
+ var performOnChange = true;
+
+ var $slider = $j("<div class='ui-slider'><div class='ui-slider-handle'></div><div class='ui-slider-range'></div></div>", PE.getDocument())
+ .appendTo($ctr)
+ .attr("id", "input-slider-" + id)
+ .slider({
+ slide: function() {
+ $value.html($j(this).slider("value"));
+ $valueField.val($j(this).slider("value"));
+ },
+ change : function() {
+ $value.html($j(this).slider("value"));
+ $valueField.val($j(this).slider("value"));
+ if (onChange && performOnChange)
+ onChange();
+ },
+ min : min,
+ max : max,
+ step : step,
+ value : defaultVal()
+ });
+
+ $value.appendTo($ctr);
+
+ return {
+ container : $ctr,
+ label : $label,
+ slider : $slider,
+ valueText : $value,
+ valueField : $valueField,
+ reset : function() {
+ performOnChange = false;
+ $value.html(defaultVal());
+ $valueField.val(defaultVal());
+ $slider.slider("value", defaultVal());
+ performOnChange = true;
+ }
+ };
+ }
+
+ function makeCheckbox(label, id, defaultVal, onChange) {
+ var $ctr = $j("<div></div>", PE.getDocument())
+ .addClass("ui-checkbox-container");
+
+ var $label = $j("<label></label>", PE.getDocument())
+ .addClass("ui-checkbox-label")
+ .attr("for", "input-checkbox-" + id)
+ .html(label + ":")
+ .appendTo($ctr);
+
+ var $valueField = $j("<input type='hidden'>", PE.getDocument())
+ .attr("id", "input-hidden-" + id)
+ .val(defaultVal())
+ .appendTo($ctr);
+
+ var performOnChange = true;
+
+ var $checkbox = $j("<input type=\"checkbox\"></input>", PE.getDocument())
+ .addClass("ui-checkbox")
+ .attr("id", "input-checkbox-" + id)
+ .attr("checked", defaultVal())
+ .appendTo($ctr)
+ .change(function() {
+ $valueField.val(this.checked);
+ if (onChange && performOnChange)
+ onChange();
+ });
+
+ return {
+ container : $ctr,
+ label : $label,
+ checkbox : $checkbox,
+ valueField : $valueField,
+ reset : function() {
+ performOnChange = false;
+ $checkbox.attr("checked", defaultVal());
+ $valueField.val(defaultVal());
+ performOnChange = true;
+ }
+ };
+ }
+
+ function makeSelect(label, id, values, defaultVal, onChange) {
+ var $ctr = $j("<div></div>", PE.getDocument())
+ .addClass("ui-select-container");
+
+ var $label = $j("<label></label>", PE.getDocument())
+ .addClass("ui-checkbox-label")
+ .attr("for", "input-checkbox-" + id)
+ .html(label + ":")
+ .appendTo($ctr);
+
+ var $valueField = $j("<input type='hidden'>", PE.getDocument())
+ .attr("id", "input-hidden-" + id)
+ .val(defaultVal())
+ .appendTo($ctr);
+
+ var selectHtml = "<select>";
+ for (var i=0;i<values.length;i++) {
+ selectHtml += "<option value='" + values[i].value + "' "
+ + (defaultVal() == values[i].value ? "selected" : "")
+ + ">" + values[i].name + "</option>";
+ }
+ selectHtml += "</select>";
+
+ var $select = $j(selectHtml).appendTo($ctr);
+
+ var performOnChange = true;
+
+ $select.change(
+ function() {
+ $valueField.val(this.options[this.selectedIndex].value);
+ if (onChange && performOnChange)
+ onChange();
+ }
+ );
+
+ return {
+ container : $ctr,
+ label : $label,
+ select : $select,
+ valueField : $valueField,
+ reset : function() {
+ performOnChange = false;
+ var defVal = defaultVal();
+ $select.val(defVal);
+ $valueField.val(defVal);
+ performOnChange = true;
+ }
+ };
+ }
+
+ function makeNumericInput(label, labelRight, id, min, max, step, defaultVal, onChange) {
+ var $ctr = $j("<div></div>", PE.getDocument())
+ .addClass("ui-textinput-container");
+
+ var $label = $j("<label></label>", PE.getDocument())
+ .addClass("ui-textinput-label")
+ .attr("for", "input-numeric-" + id)
+ .html(label + ":")
+ .appendTo($ctr);
+
+ var $valueField = $j("<input type='hidden'>", PE.getDocument())
+ .attr("id", "input-hidden-" + id)
+ .val(defaultVal())
+ .appendTo($ctr);
+
+ var performOnChange = true;
+
+ function setVal(val) {
+ val = Math.min(max, val);
+ val = Math.max(min, val);
+ $textInput.val(val);
+ $valueField.val(val);
+ }
+
+ var $textInput = $j("<input type=\"text\"></input>", PE.getDocument())
+ .addClass("ui-textinput")
+ .addClass("ui-numericinput")
+ .appendTo($ctr)
+ .val(defaultVal())
+ .attr("id", "input-numeric-" + id)
+ .change(function() {
+ var val = parseFloat(this.value);
+ setVal(val);
+ if (onChange && performOnChange)
+ onChange();
+ })
+ .keydown(function(e) {
+ var val = parseFloat($j(this).val());
+ if (e.keyCode == 38) { // up
+ setVal(val + step);
+ }
+ if (e.keyCode == 40) { // down
+ setVal(val - step);
+ }
+ });
+
+ if (labelRight) {
+ var $labelRight = $j("<label></label>", PE.getDocument())
+ .addClass("ui-textinput-label-right")
+ .html(labelRight)
+ .appendTo($ctr);
+ }
+
+ return {
+ container : $ctr,
+ label : $label,
+ textinput : $textInput,
+ valueField : $valueField,
+ reset : function() {
+ performOnChange = false;
+ setVal(defaultVal());
+ performOnChange = true;
+ }
+ };
+ }
+
+ function makeButton(text) {
+ var $button = $j("<button></button>", PE.getDocument()).html(text);
+ return $button;
+ }
+
+
+ PE.UI = {
+ makeSlider : makeSlider,
+ makeCheckbox : makeCheckbox,
+ makeNumericInput : makeNumericInput,
+ makeSelect : makeSelect,
+ makeButton : makeButton
+ }
+
+})(PixasticEditor.jQuery);
+
-(function($) {\r
-\r
-var PE = PixasticEditor;\r
-\r
-PE.UI.data = {\r
- tabs : [\r
- {\r
- title : "Reshape",\r
- id : "reshape",\r
- actions : [\r
- {\r
- title : "Resize",\r
- id : "resize",\r
- isAction : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Enter new dimensions below."\r
- },\r
- {\r
- label : "Width",\r
- labelRight : "px",\r
- option : "width",\r
- type : "number", \r
- range : [1,10000], \r
- step : 1,\r
- defaultValue : function() { return PE.getImageWidth(); },\r
- ui : "text"\r
- },\r
- {\r
- label : "Height",\r
- labelRight : "px",\r
- option : "height",\r
- type : "number", \r
- range : [1,10000], \r
- step : 1,\r
- defaultValue : function() { return PE.getImageHeight(); },\r
- ui : "text"\r
- }\r
- ]\r
- },\r
- {\r
- title : "Crop",\r
- id : "crop",\r
- isAction : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Enter new crop values below or use mouse to select crop area."\r
- },\r
- {\r
- label : "X",\r
- labelRight : "px",\r
- option : "left",\r
- type : "number", \r
- range : [0,10000], \r
- step : 1,\r
- defaultValue : 0,\r
- ui : "text"\r
- },\r
- {\r
- label : "Y",\r
- labelRight : "px",\r
- option : "top",\r
- type : "number", \r
- range : [0,10000], \r
- step : 1,\r
- defaultValue : 0,\r
- ui : "text"\r
- },\r
- {\r
- label : "Width",\r
- labelRight : "px",\r
- option : "width",\r
- type : "number", \r
- range : [1,10000], \r
- step : 1,\r
- defaultValue : function() { return PE.getImageWidth(); },\r
- ui : "text"\r
- },\r
- {\r
- label : "Height",\r
- labelRight : "px",\r
- option : "height",\r
- type : "number", \r
- range : [1,10000], \r
- step : 1,\r
- defaultValue : function() { return PE.getImageHeight(); },\r
- ui : "text"\r
- }\r
- ],\r
- onactivate : function() {\r
- var $canvas = PE.getDisplayCanvas();\r
- var onchange = function(c) {\r
- var doc = PE.getDocument();\r
- $j("#input-numeric-crop-left", doc).val(c.x).change();\r
- $j("#input-numeric-crop-top", doc).val(c.y).change();\r
- $j("#input-numeric-crop-width", doc).val(c.w).change();\r
- $j("#input-numeric-crop-height", doc).val(c.h).change();\r
- $j("#input-hidden-crop-left", doc).val(c.x).change();\r
- $j("#input-hidden-crop-top", doc).val(c.y).change();\r
- $j("#input-hidden-crop-width", doc).val(c.w).change();\r
- $j("#input-hidden-crop-height", doc).val(c.h).change();\r
- }\r
- $canvas.data("Jcrop-onchange", onchange);\r
- $canvas.Jcrop({onChange:onchange}, PE.getDocument());\r
- },\r
- ondeactivate : function() {\r
- var $canvas = PE.getDisplayCanvas();\r
- if ($canvas.data("Jcrop") && $canvas.data("Jcrop").destroy)\r
- $canvas.data("Jcrop").destroy();\r
- },\r
- onafteraction : function(action, isPreview) {\r
- action.ondeactivate();\r
- action.onactivate();\r
- /*\r
- var $canvas = PE.getDisplayCanvas();\r
- if ($canvas.data("Jcrop") && $canvas.data("Jcrop").destroy)\r
- $canvas.data("Jcrop").destroy();\r
- var onchange = $canvas.data("Jcrop-onchange");\r
- $canvas.Jcrop({onChange:onchange});\r
- */\r
- }\r
- },\r
- {\r
- title : "Rotate",\r
- id : "rotate",\r
- isAction : true,\r
- preview : true,\r
- forcePreview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Enter the angle (-180° to 180°) you want to rotate the picture. Use negative values for clockwise rotation, positive for counterclockwise."\r
- },\r
- {\r
- label : "Angle",\r
- labelRight : "°",\r
- option : "angle",\r
- type : "number", \r
- range : [-180,180], \r
- step : 1,\r
- defaultValue : 0,\r
- ui : "text"\r
- }\r
- ],\r
- onactivate : function() {\r
- var doc = PE.getDocument();\r
- var $displayCanvas = PE.getDisplayCanvas();\r
- var dim = Math.min($displayCanvas.attr("height"), 200);\r
- var $canvas = $j("<canvas></canvas>", doc);\r
- PE.getOverlay().append($canvas);\r
-\r
- $canvas.attr("width", dim);\r
- $canvas.attr("height", dim);\r
- $canvas.width(dim);\r
- $canvas.height(dim);\r
-\r
- $canvas.css("marginTop", (($displayCanvas.attr("height") - dim) * 0.5) + "px");\r
-\r
- var lineWidth = 20;\r
- var radius = dim/2 - lineWidth;\r
- if (radius < 1) radius = 1;\r
-\r
- var ctx = $canvas.get(0).getContext("2d");\r
- ctx.beginPath()\r
- ctx.arc(dim/2, dim/2, radius, 0, Math.PI*2, true);\r
- ctx.closePath();\r
- ctx.fillStyle = "rgba(200,200,200,0.2)";\r
- ctx.fill();\r
- ctx.strokeStyle = "rgba(200,200,200,0.5)";\r
- ctx.lineWidth = 20;\r
- ctx.stroke();\r
-\r
- $j("#image-area", doc).css("cursor", "move");\r
-\r
- $overlay = PE.getOverlay();\r
-\r
- $canvas.get(0).ondragstart = function() {return false;}\r
- $canvas.get(0).onselectstart = function() {return false;}\r
-\r
- var mx = 0, my = 0;\r
- var startMouseAngle = 0;\r
- var startAngle = 0;\r
- var deltaAngle = 0;\r
- var angle = 0;\r
-\r
- var mouseIsDown = false;\r
- var onmousedown = function(e) {\r
- mouseIsDown = true;\r
- var offset = $displayCanvas.offset();\r
- mx = (e.pageX - offset.left) - $displayCanvas.attr("width")*0.5;\r
- my = (e.pageY - offset.top) - $displayCanvas.attr("height")*0.5;\r
- startMouseAngle = Math.atan2(my, mx);\r
- startAngle = parseInt($j("#input-numeric-rotate-angle", doc).val(), 10) * Math.PI / 180;\r
- }\r
- var onmousemove = function(e) {\r
- if (!mouseIsDown) return;\r
-\r
- var offset = $displayCanvas.offset();\r
- mx = (e.pageX - offset.left) - $displayCanvas.attr("width")*0.5;\r
- my = (e.pageY - offset.top) - $displayCanvas.attr("height")*0.5;\r
- deltaAngle = Math.atan2(my, mx) - startMouseAngle;\r
- angle = startAngle - deltaAngle;\r
- if (angle < -Math.PI) angle += 2*Math.PI;\r
- if (angle > Math.PI) angle -= 2*Math.PI;\r
- $j("#input-numeric-rotate-angle", doc).val(Math.round(angle * 180 / Math.PI));\r
- $j("#input-numeric-rotate-angle", doc).change();\r
- }\r
- var onmouseup = function() {\r
- mouseIsDown = false;\r
- }\r
-\r
- $j("#image-area", doc).bind("mousedown", onmousedown);\r
- $j("#image-area", doc).bind("mousemove", onmousemove);\r
- $j("#image-area", doc).bind("mouseup", onmouseup);\r
- $canvas.data("onmousedown", onmousedown);\r
- $canvas.data("onmousemove", onmousemove);\r
- $canvas.data("onmouseup", onmouseup);\r
- $displayCanvas.data("rotateCanvas", $canvas);\r
- },\r
- ondeactivate : function() {\r
- var doc = PE.getDocument();\r
- var $displayCanvas = PE.getDisplayCanvas();\r
- $overlay = PE.getOverlay();\r
- $j("#image-area", doc).css("cursor", "default");\r
-\r
- var $canvas = $displayCanvas.data("rotateCanvas");\r
-\r
- $j("#image-area", doc).unbind("mousedown", $canvas.data("onmousedown"));\r
- $j("#image-area", doc).unbind("mousemove", $canvas.data("onmousemove"));\r
- $j("#image-area", doc).unbind("mouseup", $canvas.data("onmouseup"));\r
- $displayCanvas.removeData("rotateCanvas");\r
- $canvas.remove();\r
- },\r
- onafteraction : function(action, isPreview) {\r
- if (!isPreview) { // rebuild the rotate widget\r
- action.ondeactivate();\r
- action.onactivate();\r
- }\r
- },\r
- onoverlayupdate : function() {\r
- var $canvas = PE.getDisplayCanvas().data("rotateCanvas");\r
- if ($canvas) {\r
- $canvas.css("marginTop", ((PE.getDisplayCanvas().get(0).height - $canvas.get(0).height) * 0.5) + "px");\r
- }\r
- }\r
- },\r
- {\r
- title : "Flip",\r
- id : "flip",\r
- isAction : true,\r
- controls : [\r
- {\r
- label : "Axis",\r
- option : "axis",\r
- type : "string", \r
- values : [\r
- {name:"Horizontal", value:"horizontal"},\r
- {name:"Vertical", value:"vertical"}\r
- ],\r
- defaultValue : "vertical",\r
- ui : "select"\r
- }\r
- ]\r
- }\r
- ]\r
- },\r
- {\r
- title : "Develop",\r
- id : "develop",\r
- actions : [\r
- {\r
- title : "Brightness & Contrast",\r
- id : "brightness",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Use the sliders below to adjust the brightness and/or contrast of the image."\r
- },\r
- {\r
- label : "Brightness",\r
- option : "brightness",\r
- type : "number", \r
- range : [-100,100], \r
- defaultValue : 0,\r
- ui : "slider",\r
- step : 1\r
- },\r
- {\r
- label : "Contrast",\r
- option : "contrast",\r
- type : "number", \r
- range : [-1,1], \r
- defaultValue : 0,\r
- ui : "slider",\r
- step : 0.01\r
- },\r
- {\r
- label : "Legacy mode",\r
- option : "legacy",\r
- type : "boolean", \r
- defaultValue : false,\r
- ui : "checkbox"\r
- }\r
- ]\r
- },\r
- {\r
- title : "Hue/Saturation/Lightness",\r
- id : "hsl",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Use the sliders below to adjust the hue, saturation and/or lightness of the image."\r
- },\r
- {\r
- label : "Hue",\r
- option : "hue",\r
- type : "number", \r
- range : [-180,180], \r
- defaultValue : 0,\r
- ui : "slider",\r
- step : 1\r
- },\r
- {\r
- label : "Saturation",\r
- option : "saturation",\r
- type : "number", \r
- range : [-100,100], \r
- defaultValue : 0,\r
- ui : "slider",\r
- step : 1\r
- },\r
- {\r
- label : "Lightness",\r
- option : "lightness",\r
- type : "number", \r
- range : [-100,100], \r
- defaultValue : 0,\r
- ui : "slider",\r
- step : 1\r
- }\r
- ]\r
- },\r
- {\r
- title : "Adjust colors",\r
- id : "coloradjust",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Use the sliders below to shift the R, G and B channels of the image."\r
- },\r
- {\r
- label : "Red",\r
- option : "red",\r
- type : "number", \r
- range : [-1,1], \r
- defaultValue : 0,\r
- ui : "slider",\r
- step : 0.01\r
- },\r
- {\r
- label : "Green",\r
- option : "green",\r
- type : "number", \r
- range : [-1,1], \r
- defaultValue : 0,\r
- ui : "slider",\r
- step : 0.01\r
- },\r
- {\r
- label : "Blue",\r
- option : "blue",\r
- type : "number", \r
- range : [-1,1], \r
- defaultValue : 0,\r
- ui : "slider",\r
- step : 0.01\r
- }\r
- ]\r
- },\r
- {\r
- title : "Desaturate",\r
- id : "desaturate",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- 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."\r
- },\r
- {\r
- label : "Use average",\r
- option : "average",\r
- type : "boolean", \r
- defaultValue : false,\r
- ui : "checkbox"\r
- }\r
- ]\r
- },\r
- {\r
- title : "Sepia toning",\r
- id : "sepia",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Applies a sepia toning effect to the image."\r
- }\r
- ]\r
- },\r
- {\r
- title : "Invert",\r
- id : "invert",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "This will invert the colors of the image."\r
- }\r
- ]\r
- },\r
- {\r
- title : "Lighten",\r
- id : "lighten",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Use the slider below to lighten or darken the image."\r
- },\r
- {\r
- label : "Amount",\r
- option : "amount",\r
- type : "number", \r
- range : [-1,1], \r
- defaultValue : 0,\r
- ui : "slider",\r
- step : 0.01\r
- }\r
- ]\r
- },\r
- {\r
- title : "Unsharp mask",\r
- id : "unsharpmask",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Use the sliders below to adjust the unsharp mask parameters."\r
- },\r
- {\r
- label : "Amount",\r
- option : "amount",\r
- type : "number", \r
- range : [0,500], \r
- defaultValue : 200,\r
- ui : "slider",\r
- step : 2\r
- },\r
- {\r
- label : "Radius",\r
- option : "radius",\r
- type : "number", \r
- range : [0,5], \r
- defaultValue : 2,\r
- ui : "slider",\r
- step : 0.1\r
- },\r
- {\r
- label : "Threshold",\r
- option : "amount",\r
- type : "number", \r
- range : [0,255], \r
- defaultValue : 25,\r
- ui : "slider",\r
- step : 1\r
- }\r
- ]\r
- }\r
-\r
- ]\r
- },\r
- {\r
- title : "Effects",\r
- id : "effects",\r
- actions : [\r
- {\r
- title : "Blur",\r
- id : "blurfast",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Use the slider to set the blur amount."\r
- },\r
- {\r
- label : "Amount",\r
- option : "amount",\r
- type : "number", \r
- range : [0,1], \r
- defaultValue : 0.5,\r
- ui : "slider",\r
- step : 0.01\r
- }\r
- ]\r
-\r
- },\r
- {\r
- title : "Edge detection",\r
- id : "edges",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Performs edge detection on the image."\r
- },\r
- {\r
- label : "Greyscale",\r
- option : "mono",\r
- type : "boolean", \r
- defaultValue : false,\r
- ui : "checkbox"\r
- },\r
- {\r
- label : "Invert",\r
- option : "invert",\r
- type : "boolean", \r
- defaultValue : false,\r
- ui : "checkbox"\r
- }\r
- ]\r
- },\r
- {\r
- title : "Emboss",\r
- id : "emboss",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- 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."\r
- },\r
- {\r
- label : "Strength",\r
- option : "strength",\r
- type : "number", \r
- range : [0,10], \r
- defaultValue : 1,\r
- ui : "slider",\r
- step : 0.1\r
- },\r
- {\r
- label : "Grey level",\r
- option : "greyLevel",\r
- type : "number", \r
- range : [0,255], \r
- defaultValue : 180,\r
- ui : "slider",\r
- step : 1\r
- },\r
- {\r
- label : "Direction",\r
- option : "direction",\r
- type : "string", \r
- values : [\r
- {name:"Top left", value:"topleft"},\r
- {name:"Top", value:"top"},\r
- {name:"Top right", value:"topright"},\r
- {name:"Right", value:"right"},\r
- {name:"Bottom right", value:"bottomright"},\r
- {name:"Bottom", value:"bottom"},\r
- {name:"Bottom left", value:"bottomleft"},\r
- {name:"Left", value:"left"}\r
- ],\r
- defaultValue : "topleft",\r
- ui : "select"\r
- },\r
- {\r
- label : "Blend",\r
- option : "blend",\r
- type : "boolean", \r
- defaultValue : false,\r
- ui : "checkbox"\r
- }\r
- ]\r
-\r
- },\r
- {\r
- title : "Glow",\r
- id : "glow",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Creates a glowing effect on the image."\r
- },\r
- {\r
- label : "Amount",\r
- option : "amount",\r
- type : "number", \r
- range : [0,1], \r
- defaultValue : 0.5,\r
- ui : "slider",\r
- step : 0.01\r
- },\r
- {\r
- label : "Radius",\r
- option : "radius",\r
- type : "number", \r
- range : [0,1], \r
- defaultValue : 0.5,\r
- ui : "slider",\r
- step : 0.01\r
- }\r
- ]\r
- },\r
- {\r
- title : "Add noise",\r
- id : "noise",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Add random noise to the image."\r
- },\r
- {\r
- label : "Amount",\r
- option : "amount",\r
- type : "number", \r
- range : [0,1], \r
- defaultValue : 0.5,\r
- ui : "slider",\r
- step : 0.01\r
- },\r
- {\r
- label : "Strength",\r
- option : "strength",\r
- type : "number", \r
- range : [0,1], \r
- defaultValue : 0.5,\r
- ui : "slider",\r
- step : 0.01\r
- },\r
- {\r
- label : "Greyscale",\r
- option : "mono",\r
- type : "boolean", \r
- defaultValue : false,\r
- ui : "checkbox"\r
- }\r
- ]\r
- },\r
- {\r
- title : "Remove noise",\r
- id : "removenoise",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Attempts to remove noise from the image. Works best for getting rid of single pixels that stand out."\r
- }\r
- ]\r
- },\r
- {\r
- title : "Pointillize",\r
- id : "pointillize",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Paints the picture with circular points."\r
- },\r
- {\r
- label : "Point radius",\r
- option : "radius",\r
- type : "number", \r
- range : [1,50], \r
- defaultValue : 5,\r
- ui : "slider",\r
- step : 1\r
- },\r
- {\r
- label : "Density",\r
- option : "density",\r
- type : "number", \r
- range : [0,5], \r
- defaultValue : 1,\r
- ui : "slider",\r
- step : 0.01\r
- },\r
- {\r
- label : "Noise",\r
- option : "noise",\r
- type : "number", \r
- range : [0,2], \r
- defaultValue : 1,\r
- ui : "slider",\r
- step : 0.01\r
- },\r
- {\r
- label : "Transparent",\r
- option : "transparent",\r
- type : "boolean", \r
- defaultValue : false,\r
- ui : "checkbox"\r
- }\r
- ]\r
- },\r
- {\r
- title : "Posterize",\r
- id : "posterize",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Reduces the number of colours to a specified number of levels."\r
- },\r
- {\r
- label : "Levels",\r
- option : "levels",\r
- type : "number", \r
- range : [1,32], \r
- defaultValue : 5,\r
- ui : "slider",\r
- step : 1\r
- }\r
- ]\r
- },\r
- {\r
- title : "Solarize",\r
- id : "solarize",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Applies a solarize effect to the image."\r
- }\r
- ]\r
- },\r
- {\r
- title : "Mosaic",\r
- id : "mosaic",\r
- isAction : true,\r
- preview : true,\r
- controls : [\r
- {\r
- type : "output",\r
- content : "Creates a pixelated look."\r
- },\r
- {\r
- label : "Block size",\r
- option : "blockSize",\r
- type : "number", \r
- range : [1,100], \r
- defaultValue : 5,\r
- ui : "slider",\r
- step : 1\r
- }\r
- ]\r
- }\r
-\r
-\r
- ]\r
- },\r
- {\r
- title : "Done",\r
- id : "done",\r
- actions : [\r
- {\r
- title : "Save to page",\r
- id : "savepage",\r
- content : function($ctr) {\r
- var doc = PE.getDocument();\r
- $j("<div></div>", doc)\r
- .addClass("action-output-text")\r
- .html("This will save the image to the page.")\r
- .appendTo($ctr);\r
-\r
- var $buttonCtr = $j("<div></div>", doc).appendTo($ctr);\r
- var $saveButton = $j("<button></button>", doc)\r
- .html("Save image")\r
- .appendTo($buttonCtr)\r
- .click(function() {\r
- PE.saveToPage();\r
- });\r
-\r
- }\r
- },\r
- {\r
- title : "Save to file",\r
- id : "savefile",\r
- content : function(ctr) {\r
- var doc = PE.getDocument();\r
- $j("<div></div>", doc)\r
- .addClass("action-output-text")\r
- .html("This will save the image to your local computer.")\r
- .appendTo(ctr);\r
-\r
- var formats = PE.validSaveFormats();\r
-\r
- var selectHtml = "<select>";\r
- for (var i=0;i<formats.length;i++) {\r
- selectHtml += "<option value='" + formats[i].mime + "'>" + formats[i].name + "</option>";\r
- }\r
- selectHtml += "</select>";\r
-\r
- var selectCtr = $j("<div></div>", doc)\r
- .addClass("ui-select-container");\r
-\r
-\r
- var label = $j("<div></div>", doc)\r
- .addClass("ui-select-label")\r
- .html("Format:")\r
- .appendTo(selectCtr);\r
-\r
- var formatSelect = $j(selectHtml, doc).appendTo(selectCtr);\r
-\r
-\r
- selectCtr.appendTo(ctr);\r
-\r
- var buttonCtr = $j("<div></div>", doc).appendTo(ctr);\r
- var saveButton = $j("<button></button>", doc)\r
- .html("Save file")\r
- .appendTo(buttonCtr)\r
-\r
- saveButton.click(function() {\r
- var selectElement = formatSelect.get(0);\r
- var formatMime = selectElement.options[selectElement.selectedIndex].value;\r
- var dataString = PE.getDataURI(formatMime);\r
-\r
- var dialog = $j("<div></div>", doc)\r
- .attr("id", "save-dialog")\r
- .attr("title", "Download file")\r
- .html(\r
- "Right click the link below and select \"Save as...\" to save your file.<br/>"\r
- + "<br/>"\r
- + "<a href=\"" + dataString + "\">Image Link</a>"\r
- )\r
- .dialog();\r
-\r
- // the dialog is added outside the Pixastic container, so get it back in.\r
- var dialogParent = $j(dialog.get(0).parentNode);\r
- $j("#pixastic-editor", doc).append(dialogParent);\r
- });\r
- }\r
- },\r
- /*\r
- {\r
- title : "Upload to Flickr",\r
- id : "flickrupload",\r
- content : function($ctr) {\r
- var doc = PE.getDocument();\r
-\r
- function flickrAuthed() {\r
- var $text = $j("<div />", doc)\r
- .addClass("action-output-text")\r
- .html("Authorized as: " + PE.Flickr.getAuthName());\r
-\r
- var $buttonCtr = $j("<div></div>", doc);\r
- var $uploadButton = $j("<button></button>", doc)\r
- .html("Upload image")\r
- .appendTo($buttonCtr)\r
-\r
- $uploadButton.click(function() {\r
- PE.Flickr.uploadImage(PE.getDataURI());\r
- });\r
-\r
- $ctr.append($text, $buttonCtr);\r
- }\r
-\r
- var $authCtr = $j("<div />", doc).appendTo($ctr);\r
-\r
- $j("<div />", doc)\r
- .addClass("action-output-text")\r
- .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.")\r
- .appendTo($authCtr);\r
-\r
- var $buttonCtr = $j("<div></div>", doc).appendTo($authCtr);\r
- var $authButton = $j("<button></button>", doc)\r
- .html("Authenticate")\r
- .appendTo($buttonCtr)\r
-\r
- var checkButtonAdded = false;\r
- $authButton.click(function() {\r
- PE.Flickr.auth();\r
- if (!checkButtonAdded) {\r
- checkButtonAdded = true;\r
-\r
- var $text = $j("<div />", doc)\r
- .addClass("action-output-text")\r
- .html("Now click the button below when you have authorized access to your Flickr account.");\r
- \r
- var $buttonCtr = $j("<div></div>", doc);\r
- \r
- $authCtr.append($text, $buttonCtr);\r
- \r
- var $checkButton = $j("<button></button>", doc)\r
- .html("I have authenticated!")\r
- .appendTo($buttonCtr);\r
- \r
- $checkButton.click(function() {\r
- PE.Flickr.checkAuth(function(res) {\r
- if (res.stat == "ok") {\r
- $authCtr.remove();\r
- flickrAuthed();\r
- }\r
- });\r
- });\r
- }\r
-\r
- });\r
- }\r
- },\r
- */\r
- {\r
- title : "Quit",\r
- id : "quit", \r
- content : function(ctr) {\r
- var doc = PE.getDocument();\r
-\r
- $j("<div>Are you sure you want to quit?</div>", doc)\r
- .addClass("action-output-text")\r
- .appendTo(ctr);\r
- var $buttonCtr = $j("<div></div>", doc).appendTo(ctr);\r
-\r
- var $quitButton = PE.UI.makeButton("Yes, quit now!")\r
- .appendTo($buttonCtr)\r
-\r
- $quitButton.click(function() {\r
- PE.unload();\r
- });\r
-\r
- var $saveButton = PE.UI.makeButton("Save to page and quit")\r
- .appendTo($buttonCtr)\r
- .click(function() {\r
- PE.saveToPage();\r
- PE.unload();\r
- });\r
- }\r
- }\r
- ]\r
- }\r
- ]\r
-};\r
-\r
-\r
+(function($) {
+
+var PE = PixasticEditor;
+
+PE.UI.data = {
+ tabs : [
+ {
+ title : "Reshape",
+ id : "reshape",
+ actions : [
+ {
+ title : "Resize",
+ id : "resize",
+ isAction : true,
+ controls : [
+ {
+ type : "output",
+ content : "Enter new dimensions below."
+ },
+ {
+ label : "Width",
+ labelRight : "px",
+ option : "width",
+ type : "number",
+ range : [1,10000],
+ step : 1,
+ defaultValue : function() { return PE.getImageWidth(); },
+ ui : "text"
+ },
+ {
+ label : "Height",
+ labelRight : "px",
+ option : "height",
+ type : "number",
+ range : [1,10000],
+ step : 1,
+ defaultValue : function() { return PE.getImageHeight(); },
+ ui : "text"
+ }
+ ]
+ },
+ {
+ title : "Crop",
+ id : "crop",
+ isAction : true,
+ controls : [
+ {
+ type : "output",
+ content : "Enter new crop values below or use mouse to select crop area."
+ },
+ {
+ label : "X",
+ labelRight : "px",
+ option : "left",
+ type : "number",
+ range : [0,10000],
+ step : 1,
+ defaultValue : 0,
+ ui : "text"
+ },
+ {
+ label : "Y",
+ labelRight : "px",
+ option : "top",
+ type : "number",
+ range : [0,10000],
+ step : 1,
+ defaultValue : 0,
+ ui : "text"
+ },
+ {
+ label : "Width",
+ labelRight : "px",
+ option : "width",
+ type : "number",
+ range : [1,10000],
+ step : 1,
+ defaultValue : function() { return PE.getImageWidth(); },
+ ui : "text"
+ },
+ {
+ label : "Height",
+ labelRight : "px",
+ option : "height",
+ type : "number",
+ range : [1,10000],
+ step : 1,
+ defaultValue : function() { return PE.getImageHeight(); },
+ ui : "text"
+ }
+ ],
+ onactivate : function() {
+ var $canvas = PE.getDisplayCanvas();
+ var onchange = function(c) {
+ var doc = PE.getDocument();
+ $j("#input-numeric-crop-left", doc).val(c.x).change();
+ $j("#input-numeric-crop-top", doc).val(c.y).change();
+ $j("#input-numeric-crop-width", doc).val(c.w).change();
+ $j("#input-numeric-crop-height", doc).val(c.h).change();
+ $j("#input-hidden-crop-left", doc).val(c.x).change();
+ $j("#input-hidden-crop-top", doc).val(c.y).change();
+ $j("#input-hidden-crop-width", doc).val(c.w).change();
+ $j("#input-hidden-crop-height", doc).val(c.h).change();
+ }
+ $canvas.data("Jcrop-onchange", onchange);
+ $canvas.Jcrop({onChange:onchange}, PE.getDocument());
+ },
+ ondeactivate : function() {
+ var $canvas = PE.getDisplayCanvas();
+ if ($canvas.data("Jcrop") && $canvas.data("Jcrop").destroy)
+ $canvas.data("Jcrop").destroy();
+ },
+ onafteraction : function(action, isPreview) {
+ action.ondeactivate();
+ action.onactivate();
+ /*
+ var $canvas = PE.getDisplayCanvas();
+ if ($canvas.data("Jcrop") && $canvas.data("Jcrop").destroy)
+ $canvas.data("Jcrop").destroy();
+ var onchange = $canvas.data("Jcrop-onchange");
+ $canvas.Jcrop({onChange:onchange});
+ */
+ }
+ },
+ {
+ title : "Rotate",
+ id : "rotate",
+ isAction : true,
+ preview : true,
+ forcePreview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Enter the angle (-180° to 180°) you want to rotate the picture. Use negative values for clockwise rotation, positive for counterclockwise."
+ },
+ {
+ label : "Angle",
+ labelRight : "°",
+ option : "angle",
+ type : "number",
+ range : [-180,180],
+ step : 1,
+ defaultValue : 0,
+ ui : "text"
+ }
+ ],
+ onactivate : function() {
+ var doc = PE.getDocument();
+ var $displayCanvas = PE.getDisplayCanvas();
+ var dim = Math.min($displayCanvas.attr("height"), 200);
+ var $canvas = $j("<canvas></canvas>", doc);
+ PE.getOverlay().append($canvas);
+
+ $canvas.attr("width", dim);
+ $canvas.attr("height", dim);
+ $canvas.width(dim);
+ $canvas.height(dim);
+
+ $canvas.css("marginTop", (($displayCanvas.attr("height") - dim) * 0.5) + "px");
+
+ var lineWidth = 20;
+ var radius = dim/2 - lineWidth;
+ if (radius < 1) radius = 1;
+
+ var ctx = $canvas.get(0).getContext("2d");
+ ctx.beginPath()
+ ctx.arc(dim/2, dim/2, radius, 0, Math.PI*2, true);
+ ctx.closePath();
+ ctx.fillStyle = "rgba(200,200,200,0.2)";
+ ctx.fill();
+ ctx.strokeStyle = "rgba(200,200,200,0.5)";
+ ctx.lineWidth = 20;
+ ctx.stroke();
+
+ $j("#image-area", doc).css("cursor", "move");
+
+ $overlay = PE.getOverlay();
+
+ $canvas.get(0).ondragstart = function() {return false;}
+ $canvas.get(0).onselectstart = function() {return false;}
+
+ var mx = 0, my = 0;
+ var startMouseAngle = 0;
+ var startAngle = 0;
+ var deltaAngle = 0;
+ var angle = 0;
+
+ var mouseIsDown = false;
+ var onmousedown = function(e) {
+ mouseIsDown = true;
+ var offset = $displayCanvas.offset();
+ mx = (e.pageX - offset.left) - $displayCanvas.attr("width")*0.5;
+ my = (e.pageY - offset.top) - $displayCanvas.attr("height")*0.5;
+ startMouseAngle = Math.atan2(my, mx);
+ startAngle = parseInt($j("#input-numeric-rotate-angle", doc).val(), 10) * Math.PI / 180;
+ }
+ var onmousemove = function(e) {
+ if (!mouseIsDown) return;
+
+ var offset = $displayCanvas.offset();
+ mx = (e.pageX - offset.left) - $displayCanvas.attr("width")*0.5;
+ my = (e.pageY - offset.top) - $displayCanvas.attr("height")*0.5;
+ deltaAngle = Math.atan2(my, mx) - startMouseAngle;
+ angle = startAngle - deltaAngle;
+ if (angle < -Math.PI) angle += 2*Math.PI;
+ if (angle > Math.PI) angle -= 2*Math.PI;
+ $j("#input-numeric-rotate-angle", doc).val(Math.round(angle * 180 / Math.PI));
+ $j("#input-numeric-rotate-angle", doc).change();
+ }
+ var onmouseup = function() {
+ mouseIsDown = false;
+ }
+
+ $j("#image-area", doc).bind("mousedown", onmousedown);
+ $j("#image-area", doc).bind("mousemove", onmousemove);
+ $j("#image-area", doc).bind("mouseup", onmouseup);
+ $canvas.data("onmousedown", onmousedown);
+ $canvas.data("onmousemove", onmousemove);
+ $canvas.data("onmouseup", onmouseup);
+ $displayCanvas.data("rotateCanvas", $canvas);
+ },
+ ondeactivate : function() {
+ var doc = PE.getDocument();
+ var $displayCanvas = PE.getDisplayCanvas();
+ $overlay = PE.getOverlay();
+ $j("#image-area", doc).css("cursor", "default");
+
+ var $canvas = $displayCanvas.data("rotateCanvas");
+
+ $j("#image-area", doc).unbind("mousedown", $canvas.data("onmousedown"));
+ $j("#image-area", doc).unbind("mousemove", $canvas.data("onmousemove"));
+ $j("#image-area", doc).unbind("mouseup", $canvas.data("onmouseup"));
+ $displayCanvas.removeData("rotateCanvas");
+ $canvas.remove();
+ },
+ onafteraction : function(action, isPreview) {
+ if (!isPreview) { // rebuild the rotate widget
+ action.ondeactivate();
+ action.onactivate();
+ }
+ },
+ onoverlayupdate : function() {
+ var $canvas = PE.getDisplayCanvas().data("rotateCanvas");
+ if ($canvas) {
+ $canvas.css("marginTop", ((PE.getDisplayCanvas().get(0).height - $canvas.get(0).height) * 0.5) + "px");
+ }
+ }
+ },
+ {
+ title : "Flip",
+ id : "flip",
+ isAction : true,
+ controls : [
+ {
+ label : "Axis",
+ option : "axis",
+ type : "string",
+ values : [
+ {name:"Horizontal", value:"horizontal"},
+ {name:"Vertical", value:"vertical"}
+ ],
+ defaultValue : "vertical",
+ ui : "select"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ title : "Develop",
+ id : "develop",
+ actions : [
+ {
+ title : "Brightness & Contrast",
+ id : "brightness",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Use the sliders below to adjust the brightness and/or contrast of the image."
+ },
+ {
+ label : "Brightness",
+ option : "brightness",
+ type : "number",
+ range : [-100,100],
+ defaultValue : 0,
+ ui : "slider",
+ step : 1
+ },
+ {
+ label : "Contrast",
+ option : "contrast",
+ type : "number",
+ range : [-1,1],
+ defaultValue : 0,
+ ui : "slider",
+ step : 0.01
+ },
+ {
+ label : "Legacy mode",
+ option : "legacy",
+ type : "boolean",
+ defaultValue : false,
+ ui : "checkbox"
+ }
+ ]
+ },
+ {
+ title : "Hue/Saturation/Lightness",
+ id : "hsl",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Use the sliders below to adjust the hue, saturation and/or lightness of the image."
+ },
+ {
+ label : "Hue",
+ option : "hue",
+ type : "number",
+ range : [-180,180],
+ defaultValue : 0,
+ ui : "slider",
+ step : 1
+ },
+ {
+ label : "Saturation",
+ option : "saturation",
+ type : "number",
+ range : [-100,100],
+ defaultValue : 0,
+ ui : "slider",
+ step : 1
+ },
+ {
+ label : "Lightness",
+ option : "lightness",
+ type : "number",
+ range : [-100,100],
+ defaultValue : 0,
+ ui : "slider",
+ step : 1
+ }
+ ]
+ },
+ {
+ title : "Adjust colors",
+ id : "coloradjust",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Use the sliders below to shift the R, G and B channels of the image."
+ },
+ {
+ label : "Red",
+ option : "red",
+ type : "number",
+ range : [-1,1],
+ defaultValue : 0,
+ ui : "slider",
+ step : 0.01
+ },
+ {
+ label : "Green",
+ option : "green",
+ type : "number",
+ range : [-1,1],
+ defaultValue : 0,
+ ui : "slider",
+ step : 0.01
+ },
+ {
+ label : "Blue",
+ option : "blue",
+ type : "number",
+ range : [-1,1],
+ defaultValue : 0,
+ ui : "slider",
+ step : 0.01
+ }
+ ]
+ },
+ {
+ title : "Desaturate",
+ id : "desaturate",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ 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."
+ },
+ {
+ label : "Use average",
+ option : "average",
+ type : "boolean",
+ defaultValue : false,
+ ui : "checkbox"
+ }
+ ]
+ },
+ {
+ title : "Sepia toning",
+ id : "sepia",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Applies a sepia toning effect to the image."
+ }
+ ]
+ },
+ {
+ title : "Invert",
+ id : "invert",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "This will invert the colors of the image."
+ }
+ ]
+ },
+ {
+ title : "Lighten",
+ id : "lighten",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Use the slider below to lighten or darken the image."
+ },
+ {
+ label : "Amount",
+ option : "amount",
+ type : "number",
+ range : [-1,1],
+ defaultValue : 0,
+ ui : "slider",
+ step : 0.01
+ }
+ ]
+ },
+ {
+ title : "Unsharp mask",
+ id : "unsharpmask",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Use the sliders below to adjust the unsharp mask parameters."
+ },
+ {
+ label : "Amount",
+ option : "amount",
+ type : "number",
+ range : [0,500],
+ defaultValue : 200,
+ ui : "slider",
+ step : 2
+ },
+ {
+ label : "Radius",
+ option : "radius",
+ type : "number",
+ range : [0,5],
+ defaultValue : 2,
+ ui : "slider",
+ step : 0.1
+ },
+ {
+ label : "Threshold",
+ option : "amount",
+ type : "number",
+ range : [0,255],
+ defaultValue : 25,
+ ui : "slider",
+ step : 1
+ }
+ ]
+ }
+
+ ]
+ },
+ {
+ title : "Effects",
+ id : "effects",
+ actions : [
+ {
+ title : "Blur",
+ id : "blurfast",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Use the slider to set the blur amount."
+ },
+ {
+ label : "Amount",
+ option : "amount",
+ type : "number",
+ range : [0,1],
+ defaultValue : 0.5,
+ ui : "slider",
+ step : 0.01
+ }
+ ]
+
+ },
+ {
+ title : "Edge detection",
+ id : "edges",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Performs edge detection on the image."
+ },
+ {
+ label : "Greyscale",
+ option : "mono",
+ type : "boolean",
+ defaultValue : false,
+ ui : "checkbox"
+ },
+ {
+ label : "Invert",
+ option : "invert",
+ type : "boolean",
+ defaultValue : false,
+ ui : "checkbox"
+ }
+ ]
+ },
+ {
+ title : "Emboss",
+ id : "emboss",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ 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."
+ },
+ {
+ label : "Strength",
+ option : "strength",
+ type : "number",
+ range : [0,10],
+ defaultValue : 1,
+ ui : "slider",
+ step : 0.1
+ },
+ {
+ label : "Grey level",
+ option : "greyLevel",
+ type : "number",
+ range : [0,255],
+ defaultValue : 180,
+ ui : "slider",
+ step : 1
+ },
+ {
+ label : "Direction",
+ option : "direction",
+ type : "string",
+ values : [
+ {name:"Top left", value:"topleft"},
+ {name:"Top", value:"top"},
+ {name:"Top right", value:"topright"},
+ {name:"Right", value:"right"},
+ {name:"Bottom right", value:"bottomright"},
+ {name:"Bottom", value:"bottom"},
+ {name:"Bottom left", value:"bottomleft"},
+ {name:"Left", value:"left"}
+ ],
+ defaultValue : "topleft",
+ ui : "select"
+ },
+ {
+ label : "Blend",
+ option : "blend",
+ type : "boolean",
+ defaultValue : false,
+ ui : "checkbox"
+ }
+ ]
+
+ },
+ {
+ title : "Glow",
+ id : "glow",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Creates a glowing effect on the image."
+ },
+ {
+ label : "Amount",
+ option : "amount",
+ type : "number",
+ range : [0,1],
+ defaultValue : 0.5,
+ ui : "slider",
+ step : 0.01
+ },
+ {
+ label : "Radius",
+ option : "radius",
+ type : "number",
+ range : [0,1],
+ defaultValue : 0.5,
+ ui : "slider",
+ step : 0.01
+ }
+ ]
+ },
+ {
+ title : "Add noise",
+ id : "noise",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Add random noise to the image."
+ },
+ {
+ label : "Amount",
+ option : "amount",
+ type : "number",
+ range : [0,1],
+ defaultValue : 0.5,
+ ui : "slider",
+ step : 0.01
+ },
+ {
+ label : "Strength",
+ option : "strength",
+ type : "number",
+ range : [0,1],
+ defaultValue : 0.5,
+ ui : "slider",
+ step : 0.01
+ },
+ {
+ label : "Greyscale",
+ option : "mono",
+ type : "boolean",
+ defaultValue : false,
+ ui : "checkbox"
+ }
+ ]
+ },
+ {
+ title : "Remove noise",
+ id : "removenoise",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Attempts to remove noise from the image. Works best for getting rid of single pixels that stand out."
+ }
+ ]
+ },
+ {
+ title : "Pointillize",
+ id : "pointillize",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Paints the picture with circular points."
+ },
+ {
+ label : "Point radius",
+ option : "radius",
+ type : "number",
+ range : [1,50],
+ defaultValue : 5,
+ ui : "slider",
+ step : 1
+ },
+ {
+ label : "Density",
+ option : "density",
+ type : "number",
+ range : [0,5],
+ defaultValue : 1,
+ ui : "slider",
+ step : 0.01
+ },
+ {
+ label : "Noise",
+ option : "noise",
+ type : "number",
+ range : [0,2],
+ defaultValue : 1,
+ ui : "slider",
+ step : 0.01
+ },
+ {
+ label : "Transparent",
+ option : "transparent",
+ type : "boolean",
+ defaultValue : false,
+ ui : "checkbox"
+ }
+ ]
+ },
+ {
+ title : "Posterize",
+ id : "posterize",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Reduces the number of colours to a specified number of levels."
+ },
+ {
+ label : "Levels",
+ option : "levels",
+ type : "number",
+ range : [1,32],
+ defaultValue : 5,
+ ui : "slider",
+ step : 1
+ }
+ ]
+ },
+ {
+ title : "Solarize",
+ id : "solarize",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Applies a solarize effect to the image."
+ }
+ ]
+ },
+ {
+ title : "Mosaic",
+ id : "mosaic",
+ isAction : true,
+ preview : true,
+ controls : [
+ {
+ type : "output",
+ content : "Creates a pixelated look."
+ },
+ {
+ label : "Block size",
+ option : "blockSize",
+ type : "number",
+ range : [1,100],
+ defaultValue : 5,
+ ui : "slider",
+ step : 1
+ }
+ ]
+ }
+
+
+ ]
+ },
+ {
+ title : "Done",
+ id : "done",
+ actions : [
+ {
+ title : "Save to page",
+ id : "savepage",
+ content : function($ctr) {
+ var doc = PE.getDocument();
+ $j("<div></div>", doc)
+ .addClass("action-output-text")
+ .html("This will save the image to the page.")
+ .appendTo($ctr);
+
+ var $buttonCtr = $j("<div></div>", doc).appendTo($ctr);
+ var $saveButton = $j("<button></button>", doc)
+ .html("Save image")
+ .appendTo($buttonCtr)
+ .click(function() {
+ PE.saveToPage();
+ });
+
+ }
+ },
+ {
+ title : "Save to file",
+ id : "savefile",
+ content : function(ctr) {
+ var doc = PE.getDocument();
+ $j("<div></div>", doc)
+ .addClass("action-output-text")
+ .html("This will save the image to your local computer.")
+ .appendTo(ctr);
+
+ var formats = PE.validSaveFormats();
+
+ var selectHtml = "<select>";
+ for (var i=0;i<formats.length;i++) {
+ selectHtml += "<option value='" + formats[i].mime + "'>" + formats[i].name + "</option>";
+ }
+ selectHtml += "</select>";
+
+ var selectCtr = $j("<div></div>", doc)
+ .addClass("ui-select-container");
+
+
+ var label = $j("<div></div>", doc)
+ .addClass("ui-select-label")
+ .html("Format:")
+ .appendTo(selectCtr);
+
+ var formatSelect = $j(selectHtml, doc).appendTo(selectCtr);
+
+
+ selectCtr.appendTo(ctr);
+
+ var buttonCtr = $j("<div></div>", doc).appendTo(ctr);
+ var saveButton = $j("<button></button>", doc)
+ .html("Save file")
+ .appendTo(buttonCtr)
+
+ saveButton.click(function() {
+ var selectElement = formatSelect.get(0);
+ var formatMime = selectElement.options[selectElement.selectedIndex].value;
+ var dataString = PE.getDataURI(formatMime);
+
+ var dialog = $j("<div></div>", doc)
+ .attr("id", "save-dialog")
+ .attr("title", "Download file")
+ .html(
+ "Right click the link below and select \"Save as...\" to save your file.<br/>"
+ + "<br/>"
+ + "<a href=\"" + dataString + "\">Image Link</a>"
+ )
+ .dialog();
+
+ // the dialog is added outside the Pixastic container, so get it back in.
+ var dialogParent = $j(dialog.get(0).parentNode);
+ $j("#pixastic-editor", doc).append(dialogParent);
+ });
+ }
+ },
+ /*
+ {
+ title : "Upload to Flickr",
+ id : "flickrupload",
+ content : function($ctr) {
+ var doc = PE.getDocument();
+
+ function flickrAuthed() {
+ var $text = $j("<div />", doc)
+ .addClass("action-output-text")
+ .html("Authorized as: " + PE.Flickr.getAuthName());
+
+ var $buttonCtr = $j("<div></div>", doc);
+ var $uploadButton = $j("<button></button>", doc)
+ .html("Upload image")
+ .appendTo($buttonCtr)
+
+ $uploadButton.click(function() {
+ PE.Flickr.uploadImage(PE.getDataURI());
+ });
+
+ $ctr.append($text, $buttonCtr);
+ }
+
+ var $authCtr = $j("<div />", doc).appendTo($ctr);
+
+ $j("<div />", doc)
+ .addClass("action-output-text")
+ .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.")
+ .appendTo($authCtr);
+
+ var $buttonCtr = $j("<div></div>", doc).appendTo($authCtr);
+ var $authButton = $j("<button></button>", doc)
+ .html("Authenticate")
+ .appendTo($buttonCtr)
+
+ var checkButtonAdded = false;
+ $authButton.click(function() {
+ PE.Flickr.auth();
+ if (!checkButtonAdded) {
+ checkButtonAdded = true;
+
+ var $text = $j("<div />", doc)
+ .addClass("action-output-text")
+ .html("Now click the button below when you have authorized access to your Flickr account.");
+
+ var $buttonCtr = $j("<div></div>", doc);
+
+ $authCtr.append($text, $buttonCtr);
+
+ var $checkButton = $j("<button></button>", doc)
+ .html("I have authenticated!")
+ .appendTo($buttonCtr);
+
+ $checkButton.click(function() {
+ PE.Flickr.checkAuth(function(res) {
+ if (res.stat == "ok") {
+ $authCtr.remove();
+ flickrAuthed();
+ }
+ });
+ });
+ }
+
+ });
+ }
+ },
+ */
+ {
+ title : "Quit",
+ id : "quit",
+ content : function(ctr) {
+ var doc = PE.getDocument();
+
+ $j("<div>Are you sure you want to quit?</div>", doc)
+ .addClass("action-output-text")
+ .appendTo(ctr);
+ var $buttonCtr = $j("<div></div>", doc).appendTo(ctr);
+
+ var $quitButton = PE.UI.makeButton("Yes, quit now!")
+ .appendTo($buttonCtr)
+
+ $quitButton.click(function() {
+ PE.unload();
+ });
+
+ var $saveButton = PE.UI.makeButton("Save to page and quit")
+ .appendTo($buttonCtr)
+ .click(function() {
+ PE.saveToPage();
+ PE.unload();
+ });
+ }
+ }
+ ]
+ }
+ ]
+};
+
+
})(PixasticEditor.jQuery);
\ No newline at end of file