├── AUTHORS
├── res
└── img
│ ├── 1.jpg
│ ├── 2.jpg
│ ├── 3.jpg
│ ├── 4.jpg
│ ├── 5.jpg
│ ├── 7.jpg
│ ├── 8.jpg
│ ├── y.jpg
│ ├── 10.jpg
│ ├── 11.jpg
│ ├── 12.jpg
│ ├── Yuv3.jpg
│ ├── yuv2.jpg
│ └── yuv4.jpg
├── doc
└── AI规范.md
├── test
├── test.html
├── testRect.html
├── testTransform.html
├── denoise.html
├── testWidth.html
├── testDefine.html
├── save.html
├── test2.html
├── testnew.html
├── testSeletiveColor.html
├── testTools.html
└── testView.html
├── nsrc
├── alloyimage.info.js
├── alloyimage.util.js
├── alloyimage.define.js
├── alloyimage.fix.js
├── alloyimage.config.js
├── alloyimage.process.js
├── alloyimage.layer.js
└── alloyimage.base.js
├── src
├── module
│ ├── filter
│ │ ├── toReverse.js
│ │ ├── toGray.js
│ │ ├── toThresh.js
│ │ ├── lapOfGauss.js
│ │ ├── ImageEnhance.js
│ │ ├── sepia.js
│ │ ├── noise.js
│ │ ├── sharp.js
│ │ ├── corrode.js
│ │ ├── oilPainting.js
│ │ ├── posterize.js
│ │ ├── embossment.js
│ │ ├── mosaic.js
│ │ ├── darkCorner.js
│ │ ├── dotted.js
│ │ └── gaussBlur.js
│ ├── alteration
│ │ ├── brightness.js
│ │ ├── gamma.js
│ │ ├── setHSI.js
│ │ ├── curve.js
│ │ └── seletiveColor.js
│ ├── fix.js
│ ├── applyMatrix.js
│ ├── config.js
│ ├── easy.js
│ ├── dorsyWorker.js
│ ├── tools.js
│ ├── addLayer.js
│ └── dorsyMath.js
└── other
│ ├── LICENSE.md
│ └── binaryajax.js
├── .gitignore
├── demo
├── demo3.html
├── demo4.html
├── demo2.html
├── demo5.html
├── demo1.html
└── index.html
├── LICENSE
├── README.md
└── release
└── alloyimage-1.1.js
/AUTHORS:
--------------------------------------------------------------------------------
1 | --AUTHORS--
2 |
3 |
--------------------------------------------------------------------------------
/res/img/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlloyTeam/AlloyImage/HEAD/res/img/1.jpg
--------------------------------------------------------------------------------
/res/img/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlloyTeam/AlloyImage/HEAD/res/img/2.jpg
--------------------------------------------------------------------------------
/res/img/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlloyTeam/AlloyImage/HEAD/res/img/3.jpg
--------------------------------------------------------------------------------
/res/img/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlloyTeam/AlloyImage/HEAD/res/img/4.jpg
--------------------------------------------------------------------------------
/res/img/5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlloyTeam/AlloyImage/HEAD/res/img/5.jpg
--------------------------------------------------------------------------------
/res/img/7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlloyTeam/AlloyImage/HEAD/res/img/7.jpg
--------------------------------------------------------------------------------
/res/img/8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlloyTeam/AlloyImage/HEAD/res/img/8.jpg
--------------------------------------------------------------------------------
/res/img/y.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlloyTeam/AlloyImage/HEAD/res/img/y.jpg
--------------------------------------------------------------------------------
/res/img/10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlloyTeam/AlloyImage/HEAD/res/img/10.jpg
--------------------------------------------------------------------------------
/res/img/11.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlloyTeam/AlloyImage/HEAD/res/img/11.jpg
--------------------------------------------------------------------------------
/res/img/12.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlloyTeam/AlloyImage/HEAD/res/img/12.jpg
--------------------------------------------------------------------------------
/res/img/Yuv3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlloyTeam/AlloyImage/HEAD/res/img/Yuv3.jpg
--------------------------------------------------------------------------------
/res/img/yuv2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlloyTeam/AlloyImage/HEAD/res/img/yuv2.jpg
--------------------------------------------------------------------------------
/res/img/yuv4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AlloyTeam/AlloyImage/HEAD/res/img/yuv4.jpg
--------------------------------------------------------------------------------
/doc/AI规范.md:
--------------------------------------------------------------------------------
1 | # 代码编写的一些原则
2 | ### 主处理对象保持单例、私有的,且不能与DOM交互
3 | ### 内部保持清晰逻辑体系,可以更复杂架构以达到清晰分类,外部接口始终保持单一、简单
4 | ### 滤镜Filter模块相互之间不能调用
5 |
--------------------------------------------------------------------------------
/test/test.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/test/testRect.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/test/testTransform.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/nsrc/alloyimage.info.js:
--------------------------------------------------------------------------------
1 | /**
2 | * AlloyImage info module
3 | * something about AlloyImage
4 | * @author dorsywang From Tencent AlloyTeam
5 | */
6 |
7 | AIDefine('info', [], function(){
8 | var Info = {
9 | VERSION: "1.0.0",
10 | AUTHOR: "dorsywang",
11 | EMAIL: "314416946@qq.com",
12 | BLOG: "http://www.dorsywang.com",
13 | TEAM: "Tencent.AlloyTeam",
14 | TEAM_BLOG: "http://www.alloyteam.com"
15 | };
16 |
17 | AIExport.put('info', Info);
18 |
19 | return Info;
20 | });
21 |
--------------------------------------------------------------------------------
/test/denoise.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/test/testWidth.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/test/testDefine.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/test/save.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/module/filter/toReverse.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: 反色
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("Filter.toReverse",function(P){
9 |
10 | var M = {
11 | process: function(imgData){
12 | var data = imgData.data;
13 |
14 | for(var i = 0,n = data.length;i < n;i += 4){
15 | data[i] = 255 - data[i];
16 | data[i + 1] = 255 - data[i + 1];
17 | data[i + 2] = 255 - data[i + 2];
18 | }
19 |
20 | imgData.data = data;
21 |
22 | return imgData;
23 | }
24 | };
25 |
26 | return M;
27 |
28 | });
29 |
30 | })("psLib");
31 |
--------------------------------------------------------------------------------
/src/module/filter/toGray.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: 灰度处理
4 | * @modify: 灰度算法改成加权平均值 (0.299, 0.578, 0.114)
5 | *
6 | */
7 | ;(function(Ps){
8 |
9 | window[Ps].module("Filter.toGray",function(P){
10 |
11 | var M = {
12 | process: function(imgData){
13 | var data = imgData.data;
14 |
15 | for(var i = 0,n = data.length;i < n;i += 4){
16 | var gray = parseInt((0.299 * data[i] + 0.578 * data[i + 1] + 0.114 * data[i + 2]));
17 | data[i + 2] = data[i + 1] = data[i] = gray;
18 | }
19 |
20 | imgData.data = data;
21 |
22 | return imgData;
23 | }
24 | };
25 |
26 | return M;
27 |
28 | });
29 |
30 | })("psLib");
31 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Include your project-specific ignores in this file
2 | # Read about how to use .gitignore: https://help.github.com/articles/ignoring-files
3 |
4 | # Numerous always-ignore extensions
5 | *.diff
6 | *.err
7 | *.orig
8 | *.log
9 | *.rej
10 | *.swo
11 | *.swp
12 | *.vi
13 | *~
14 | *.sass-cache
15 |
16 | # OS or Editor folders
17 | .DS_Store
18 | ._*
19 | Thumbs.db
20 | .cache
21 | .project
22 | .settings
23 | .tmproj
24 | nbproject
25 | *.sublime-project
26 | *.sublime-workspace
27 |
28 | # Dreamweaver added files
29 | _notes
30 | dwsync.xml
31 |
32 | # Komodo
33 | *.komodoproject
34 | .komodotools
35 |
36 | # Espresso
37 | *.esproj
38 | *.espressostorage
39 |
40 | # Rubinius
41 | *.rbc
42 |
43 | # Folders to ignore
44 | .hg
45 | .svn
46 | .CVS
47 | intermediate
48 | publish
49 | .idea
50 |
51 |
--------------------------------------------------------------------------------
/src/module/filter/toThresh.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description:灰度阈值 做只有2级灰度图像处理
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("Filter.toThresh",function(P){
9 |
10 | var M = {
11 | process: function(imgData,arg){
12 | imgData = P.reflect("toGray", imgData);
13 | var data = imgData.data;
14 |
15 | var arg = arg[0] || 128;
16 | for(var i = 0,n = data.length;i < n;i ++){
17 | if((i + 1) % 4){
18 | data[i] = data[i] > arg ? 255 : 0;
19 | }
20 | }
21 |
22 | imgData.data = data;
23 |
24 | return imgData;
25 | }
26 | };
27 |
28 | return M;
29 |
30 | });
31 |
32 | })("psLib");
33 |
--------------------------------------------------------------------------------
/test/test2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/demo/demo3.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AlloyPhoto Demo1
6 |
10 |
11 |
12 |
13 |
14 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/nsrc/alloyimage.util.js:
--------------------------------------------------------------------------------
1 | /**
2 | * AlloyImage util module
3 | * @author dorsywang From Tencent AlloyTeam
4 | */
5 |
6 | AIDefine('util', [], function(){
7 | var Util = {
8 | getDevice: function(){
9 | var device;
10 |
11 | if(window.navigator){
12 | var ua = window.navigator.userAgent;
13 |
14 | if(/Android|android/.test(ua)){
15 | device = 'android';
16 | }else if(/iPhone|iPad|iPod/.test(ua)){
17 | device = 'ios';
18 | }else{
19 | device = 'other';
20 | }
21 | }else{
22 | device = "sandBox";
23 | }
24 |
25 | return function(){
26 | return device;
27 | };
28 | }()
29 | };
30 |
31 | return Util;
32 | });
33 |
--------------------------------------------------------------------------------
/test/testnew.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/demo/demo4.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AlloyPhoto Demo1
6 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/module/filter/lapOfGauss.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: 查找边缘
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("Filter.borderline",function(P){
9 |
10 | var M = {
11 | process: function(imgData,arg){
12 | var template1 = [
13 | -2,-4,-4,-4,-2,
14 | -4,0,8,0,-4,
15 | -4,8,24,8,-4,
16 | -4,0,8,0,-4,
17 | -2,-4,-4,-4,-2
18 | ];
19 | var template2 = [
20 | 0, 1, 0,
21 | 1, -4, 1,
22 | 0, 1, 0
23 | ];
24 | var template3 = [
25 | ];
26 | return P.lib.dorsyMath.applyMatrix(imgData,template2,250);
27 | }
28 | };
29 |
30 | return M;
31 |
32 | });
33 |
34 | })("psLib");
35 |
--------------------------------------------------------------------------------
/src/module/filter/ImageEnhance.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description:灰度扩展
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("Filter.ImageEnhance",function(P){
9 |
10 | var M = {
11 | process: function(imgData,arg1,arg2){
12 | var lamta = arg || 0.5;
13 | var data = imgData.data;
14 | var width = imgData.width;
15 | var height = imgData.height;
16 | var p1 = arg1 || {x: 10,y: 10};
17 | var p2 = arg2 || {x: 50,y: 40};
18 |
19 | function transfer(d){
20 | }
21 |
22 | for(var i = 0,n = data.length;i < n;i += 4){
23 |
24 | }
25 |
26 | imgData.data = data;
27 |
28 | return imgData;
29 | }
30 | };
31 |
32 | return M;
33 |
34 | });
35 |
36 | })("psLib");
37 |
--------------------------------------------------------------------------------
/src/module/alteration/brightness.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: 调整亮度对比度
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("Alteration.brightness",function(P){
9 |
10 | var M = {
11 | //调节亮度对比度
12 | process: function(imgData, args){
13 | var data = imgData.data;
14 | var brightness = args[0] / 50;// -1,1
15 | var arg2 = args[1] || 0;
16 | var c = arg2 / 50;// -1,1
17 | var k = Math.tan((45 + 44 * c) * Math.PI / 180);
18 |
19 | for(var i = 0,n = data.length;i < n;i += 4){
20 | for(var j = 0;j < 3;j ++){
21 | data[i + j] = (data[i + j] - 127.5 * (1 - brightness)) * k + 127.5 * (1 + brightness);
22 | }
23 | }
24 |
25 | return imgData;
26 | }
27 | };
28 |
29 | return M;
30 |
31 | });
32 |
33 | })("psLib");
34 |
--------------------------------------------------------------------------------
/demo/demo2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AlloyPhoto Demo1
6 |
10 |
11 |
12 |
13 |
14 |
15 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/demo/demo5.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AlloyPhoto Demo1 亮白
6 |
10 |
11 |
12 |
13 |
14 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/test/testSeletiveColor.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/module/filter/sepia.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: 棕褐色
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("Filter.sepia",function(P){
9 |
10 | var M = {
11 | process: function(imgData){
12 | var dM = P.lib.dorsyMath;
13 | var data = imgData.data;
14 | var width = imgData.width;
15 | var height = imgData.height;
16 |
17 | for(var x = 0; x < width; x ++){
18 | for(var y = 0; y < height; y ++){
19 | dM.xyCal(imgData, x, y, function(r, g, b){
20 | return [
21 | r * 0.393 + g * 0.769 + b * 0.189,
22 | r * 0.349 + g * 0.686 + b * 0.168,
23 | r * 0.272 + g * 0.534 + b * 0.131
24 | ];
25 | });
26 | }
27 | }
28 | return imgData;
29 | }
30 | };
31 |
32 | return M;
33 |
34 | });
35 |
36 | })("psLib");
37 |
--------------------------------------------------------------------------------
/src/module/filter/noise.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: 添加杂色
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("Filter.noise",function(P){
9 |
10 | var M = {
11 | process: function(imgData,arg){
12 | var R = parseInt(arg[0]) || 100;
13 | var data = imgData.data;
14 | var width = imgData.width;
15 | var height = imgData.height;
16 | var xLength = R * 2 + 1;
17 |
18 | //区块
19 | for(var x = 0;x < width;x ++){
20 |
21 | for(var y = 0;y < height;y ++){
22 |
23 | var realI = y * width + x;
24 | for(var j = 0;j < 3;j ++){
25 | var rand = parseInt(Math.random() * R * 2) - R;
26 | data[realI * 4 + j] += rand;
27 | }
28 |
29 | }
30 |
31 | }
32 |
33 |
34 | return imgData;
35 | }
36 | };
37 |
38 | return M;
39 |
40 | });
41 |
42 | })("psLib");
43 |
--------------------------------------------------------------------------------
/src/other/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2008 Jacob Seidelin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/demo/demo1.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AlloyPhoto Demo1
6 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 腾讯 AlloyTeam
4 | http://www.alloyteam.com
5 | http://alloyteam.github.io/
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining
8 | a copy of this software and associated documentation files (the
9 | "Software"), to deal in the Software without restriction, including
10 | without limitation the rights to use, copy, modify, merge, publish,
11 | distribute, sublicense, and/or sell copies of the Software, and to
12 | permit persons to whom the Software is furnished to do so, subject to
13 | the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be
16 | included in all copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 |
--------------------------------------------------------------------------------
/test/testTools.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/src/module/filter/sharp.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description:锐化
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("Filter.sharp",function(P){
9 |
10 | var M = {
11 | process: function(imgData,arg){
12 | var lamta = arg[0] || 0.6;
13 | var data = imgData.data;
14 | var width = imgData.width;
15 | var height = imgData.height;
16 |
17 | for(var i = 0,n = data.length;i < n;i += 4){
18 | var ii = i / 4;
19 | var row = parseInt(ii / width);
20 | var col = ii % width;
21 | if(row == 0 || col == 0) continue;
22 |
23 | var A = ((row - 1) * width + (col - 1)) * 4;
24 | var B = ((row - 1) * width + col) * 4;
25 | var E = (ii - 1) * 4;
26 |
27 | for(var j = 0;j < 3;j ++){
28 | var delta = data[i + j] - (data[B + j] + data[E + j] + data[A + j]) / 3;
29 | data[i + j] += delta * lamta;
30 | }
31 | }
32 |
33 | return imgData;
34 | }
35 | };
36 |
37 | return M;
38 |
39 | });
40 |
41 | })("psLib");
42 |
--------------------------------------------------------------------------------
/src/module/filter/corrode.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: 腐蚀
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("Filter.corrode", function(P){
9 |
10 | var M = {
11 | process: function(imgData, arg){
12 | var R = parseInt(arg[0]) || 3;
13 | var data = imgData.data;
14 | var width = imgData.width;
15 | var height = imgData.height;
16 | var xLength = R * 2 + 1;
17 |
18 | //区块
19 | for(var x = 0; x < width; x ++){
20 |
21 | for(var y = 0; y < height; y ++){
22 |
23 | var randomI = parseInt(Math.random() * R * 2) - R ;//区块随机代表
24 | var randomJ = parseInt(Math.random() * R * 2) - R;//区块随机代表
25 | var realI = y * width + x;
26 | var realJ = (y + randomI) * width + x + randomJ;
27 |
28 | for(var j = 0; j < 3; j ++){
29 | data[realI * 4 + j] = data[realJ * 4 + j];
30 | }
31 |
32 | }
33 |
34 | }
35 |
36 | return imgData;
37 | }
38 | };
39 |
40 | return M;
41 |
42 | });
43 |
44 | })("psLib");
45 |
--------------------------------------------------------------------------------
/src/module/filter/oilPainting.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: 油画
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("Filter.oilPainting",function(P){
9 |
10 | var M = {
11 | process: function(imgData,arg){
12 | var R = parseInt(arg[0]) || 16;
13 | var data = imgData.data;
14 | var width = imgData.width;
15 | var height = imgData.height;
16 | var xLength = R * 2 + 1;
17 |
18 | //区块
19 | for(var x = 0;x < width;x ++){
20 |
21 | for(var y = 0;y < height;y ++){
22 |
23 | var realI = y * width + x;
24 | var gray = 0;
25 | for(var j = 0;j < 3;j ++){
26 | gray += data[realI * 4 + j];
27 | }
28 | gray = gray / 3;
29 | var every = parseInt(gray / R) * R;
30 | for(var j = 0;j < 3;j ++){
31 | data[realI * 4 + j] = every;
32 | }
33 | }
34 |
35 | }
36 |
37 |
38 | return imgData;
39 | }
40 | };
41 |
42 | return M;
43 |
44 | });
45 |
46 | })("psLib");
47 |
--------------------------------------------------------------------------------
/src/module/alteration/gamma.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: gamma调节
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("Alteration.gamma",function(P){
9 |
10 | var M = {
11 | process: function(imgData, args){
12 | var dM = P.lib.dorsyMath;
13 | var data = imgData.data;
14 | var width = imgData.width;
15 | var height = imgData.height;
16 |
17 | //gamma阶-100, 100
18 | var gamma;
19 |
20 | if(args[0] == undefined) gamma = 10;
21 | else gamma = args[0];
22 |
23 | var normalizedArg = ((gamma + 100) / 200) * 2;
24 |
25 | for(var x = 0; x < width; x ++){
26 | for(var y = 0; y < height; y ++){
27 | dM.xyCal(imgData, x, y, function(r, g, b){
28 | return [
29 | Math.pow(r, normalizedArg),
30 | Math.pow(g, normalizedArg),
31 | Math.pow(b, normalizedArg)
32 | ];
33 | });
34 | }
35 | }
36 | return imgData;
37 | }
38 | };
39 |
40 | return M;
41 |
42 | });
43 |
44 | })("psLib");
45 |
--------------------------------------------------------------------------------
/src/module/filter/posterize.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: 色调分离
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("Filter.posterize",function(P){
9 |
10 | var M = {
11 | process: function(imgData, args){
12 | var dM = P.lib.dorsyMath;
13 | var data = imgData.data;
14 | var width = imgData.width;
15 | var height = imgData.height;
16 |
17 | //灰度阶数
18 | //由原来的255阶映射为现在的阶数
19 | var step = args[0] || 20;
20 |
21 | step = step < 1 ? 1 : (step > 255 ? 255 : step);
22 | var level = Math.floor(255 / step);
23 |
24 | for(var x = 0; x < width; x ++){
25 | for(var y = 0; y < height; y ++){
26 | dM.xyCal(imgData, x, y, function(r, g, b){
27 | return [
28 | Math.floor(r / level) * level,
29 | Math.floor(g / level) * level,
30 | Math.floor(b / level) * level
31 | ];
32 | });
33 | }
34 | }
35 | return imgData;
36 | }
37 | };
38 |
39 | return M;
40 |
41 | });
42 |
43 | })("psLib");
44 |
--------------------------------------------------------------------------------
/src/module/filter/embossment.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: 浮雕效果
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("Filter.embossment",function(P){
9 |
10 | var M = {
11 | process: function(imgData,arg){//调节亮度对比度
12 | var data = imgData.data;
13 | var width = imgData.width;
14 | var height = imgData.height;
15 |
16 | var outData = [];
17 | for(var i = 0,n = data.length;i < n;i += 4){
18 |
19 | var ii = i / 4;
20 | var row = parseInt(ii / width);
21 | var col = ii % width;
22 | var A = ((row - 1) * width + (col - 1)) * 4;
23 | var G = (row + 1) * width * 4 + (col + 1) * 4;
24 |
25 | if(row == 0 || col == 0) continue;
26 | for(var j = 0;j < 3;j ++){
27 | outData[i + j] = data[A + j] - data[G + j] + 127.5;
28 | }
29 | outData[i + 4] = data[i + 4];
30 | }
31 |
32 | for(var i = 0,n = data.length;i < n;i ++){
33 | data[i] = outData[i] || data[i];
34 | }
35 |
36 |
37 | return imgData;
38 | }
39 | };
40 |
41 | return M;
42 |
43 | });
44 |
45 | })("psLib");
46 |
--------------------------------------------------------------------------------
/test/testView.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/src/module/alteration/setHSI.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: 调整RGB 饱和和度
4 | * H (-2*Math.PI , 2 * Math.PI) S (-100,100) I (-100,100)
5 | * 着色原理 勾选着色后,所有的像素不管之前是什么色相,都变成当前设置的色相,
6 | * 然后饱和度变成现在设置的饱和度,但保持明度为原来的基础上加上设置的明度
7 | *
8 | */
9 | ;(function(Ps){
10 |
11 | window[Ps].module("Alteration.setHSI",function(P){
12 |
13 | var M = {
14 | process: function(imgData,arg){//调节亮度对比度
15 | arg[0] = arg[0] / 180 * Math.PI;
16 | arg[1] = arg[1] / 100 || 0;
17 | arg[2] = arg[2] / 100 * 255 || 0;
18 | arg[3] = arg[3] || false;//着色
19 |
20 | //调节通道
21 | var channel = arg[4];
22 | if(!(/[RGBCMY]+/.test(channel))){
23 | channel = "RGBCMY";
24 | }
25 |
26 | var letters = channel.split("");
27 | var indexOf = {};
28 |
29 | for(var i = 0; i < letters.length; i ++){
30 | indexOf[letters[i]] = 1;
31 | }
32 |
33 | P.lib.dorsyMath.applyInHSI(imgData,function(i, color){
34 | if(! indexOf[color]) return;
35 |
36 | if(arg[3]){
37 | i.H = arg[0];
38 | i.S = arg[1];
39 | i.I += arg[2];
40 | }else{
41 | i.H += arg[0];
42 | i.S += arg[1];
43 | i.I += arg[2];
44 | }
45 |
46 | });
47 |
48 | return imgData;
49 | }
50 | };
51 |
52 | return M;
53 |
54 | });
55 |
56 | })("psLib");
57 |
--------------------------------------------------------------------------------
/src/module/alteration/curve.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: 曲线
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("Alteration.curve", function(P){
9 |
10 | var M = {
11 | process: function(imgData, arg){
12 | /*
13 | * arg arg[0] = [3,3] ,arg[1] = [2,2]
14 | * */
15 |
16 | //获得插值函数
17 | var f = P.lib.dorsyMath.lagrange(arg[0], arg[1]);
18 | var data = imgData.data;
19 | var width = imgData.width;
20 | var height = imgData.height;
21 |
22 | //调节通道
23 | var channel = arg[2];
24 | if(!(/[RGB]+/.test(channel))){
25 | channel = "RGB";
26 | }
27 |
28 | var channelString = channel.replace("R","0").replace("G","1").replace("B","2");
29 |
30 | var indexOfArr = [
31 | channelString.indexOf("0") > -1,
32 | channelString.indexOf("1") > -1,
33 | channelString.indexOf("2") > -1
34 | ];
35 |
36 | //区块
37 | for(var x = 0; x < width; x ++){
38 |
39 | for(var y = 0; y < height; y ++){
40 |
41 | var realI = y * width + x;
42 |
43 | for(var j = 0; j < 3; j ++){
44 | if(! indexOfArr[j]) continue;
45 | data[realI * 4 + j] = f(data[realI * 4 + j]);
46 | }
47 |
48 | }
49 |
50 | }
51 |
52 | return imgData;
53 | }
54 | };
55 |
56 | return M;
57 |
58 | });
59 |
60 | })("psLib");
61 |
--------------------------------------------------------------------------------
/nsrc/alloyimage.define.js:
--------------------------------------------------------------------------------
1 | /**
2 | * AlloyImage Define Module
3 | * Just Like requireJS, but for js library
4 | * @author dorsywang
5 | */
6 | ;(function(){
7 | //define modules
8 | var mainPort = 'AlloyImage';
9 | var __definePools__ = {};
10 |
11 | //checking if modules ready;
12 | var checkReady = function(name){
13 | if(__definePools__[name]){
14 | var modules = __definePools__[name].modules;
15 |
16 | var readyModule = [];
17 | modules.map(function(item, index){
18 | var itemObject = checkReady(item);
19 | if(itemObject){
20 | readyModule.push(itemObject);
21 | }else{
22 | }
23 | });
24 |
25 | if(readyModule.length == modules.length){
26 | return __definePools__[name].func.apply(null, readyModule);
27 | }
28 | }else{
29 | }
30 |
31 | };
32 |
33 | //AI define method, just like common define method;
34 | var AIDefine = function(name, modules, func){
35 | __definePools__[name] = {
36 | func: func,
37 | modules: modules
38 | };
39 |
40 | checkReady(mainPort);
41 | };
42 |
43 | //Global Object: AlloyImage Or $AI;
44 | window.$AI = window.AlloyImage = AlloyImage = $AI = function(){};
45 |
46 | //AI export method, just like common export method;
47 | var AIExport = {
48 | put: function(name, obj){
49 | if(name === ""){
50 | for(var i in obj){
51 | $AI[i] = obj[i];
52 | }
53 | }else{
54 | $AI[name] = obj;
55 | }
56 | },
57 |
58 | external: function(name, obj){
59 | window[name] = obj;
60 | }
61 | };
62 |
63 | AIExport.external('AIExport', AIExport);
64 | AIExport.external('AIDefine', AIDefine);
65 |
66 | })();
67 |
--------------------------------------------------------------------------------
/src/module/filter/mosaic.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: 马赛克
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("Filter.mosaic",function(P){
9 |
10 | var M = {
11 | process: function(imgData,arg){//调节亮度对比度
12 | var R = parseInt(arg[0]) || 3;
13 | var data = imgData.data;
14 | var width = imgData.width;
15 | var height = imgData.height;
16 | var xLength = R * 2 + 1;
17 |
18 | for(var x = 0,n = parseInt(width / xLength);x < n;x ++){
19 |
20 | for(var y = 0,m = parseInt(height / xLength);y < m;y ++){
21 |
22 | var average = [],sum = [0,0,0];
23 | for(var i = 0;i < xLength;i ++){
24 |
25 | for(var j = 0;j < xLength;j ++){
26 | var realI = (y * xLength + i) * width + x * xLength + j;
27 | sum[0] += data[realI * 4];
28 | sum[1] += data[realI * 4 + 1];
29 | sum[2] += data[realI * 4 + 2];
30 | }
31 | }
32 | average[0] = sum[0] / (xLength * xLength);
33 | average[1] = sum[1] / (xLength * xLength);
34 | average[2] = sum[2] / (xLength * xLength);
35 |
36 | for(var i = 0;i < xLength;i ++){
37 |
38 | for(var j = 0;j < xLength;j ++){
39 | var realI = (y * xLength + i) * width + x * xLength + j;
40 | data[realI * 4] = average[0];
41 | data[realI * 4 + 1] = average[1];
42 | data[realI * 4 + 2] = average[2];
43 |
44 | }
45 | }
46 |
47 | }
48 |
49 | }
50 |
51 |
52 | return imgData;
53 | }
54 | };
55 |
56 | return M;
57 |
58 | });
59 |
60 | })("psLib");
61 |
--------------------------------------------------------------------------------
/nsrc/alloyimage.fix.js:
--------------------------------------------------------------------------------
1 | /**
2 | * AlloyImage fix module
3 | * @author dorsywang From Tencent AlloyTeam
4 | */
5 |
6 | AIDefine('fix', [], function(){
7 | function detectVerticalSquash(img) {
8 | var iw = img.naturalWidth, ih = img.naturalHeight;
9 | var canvas = document.createElement('canvas');
10 | canvas.width = 1;
11 | canvas.height = ih;
12 | var ctx = canvas.getContext('2d');
13 | ctx.drawImage(img, 0, 0);
14 | var data = ctx.getImageData(0, 0, 1, ih).data;
15 | // search image edge pixel position in case it is squashed vertically.
16 | var sy = 0;
17 | var ey = ih;
18 | var py = ih;
19 | while (py > sy) {
20 | var alpha = data[(py - 1) * 4 + 3];
21 | if (alpha === 0) {
22 | ey = py;
23 | } else {
24 | sy = py;
25 | }
26 | py = (ey + sy) >> 1;
27 | }
28 | var ratio = (py / ih);
29 | return (ratio===0)?1:ratio;
30 | }
31 |
32 | /**
33 | * A replacement for context.drawImage
34 | * (args are for source and destination).
35 | */
36 | function drawImageIOSFix(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) {
37 | var vertSquashRatio = detectVerticalSquash(img);
38 | // Works only if whole image is displayed:
39 | // ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio);
40 | // The following works correct also when only a part of the image is displayed:
41 | ctx.drawImage(img, sx * vertSquashRatio, sy * vertSquashRatio,
42 | sw * vertSquashRatio, sh * vertSquashRatio,
43 | dx, dy, dw, dh );
44 | }
45 |
46 | function drawImageIOS(ctx, img, dw, dh){
47 | var sx = 0,
48 | sy = 0,
49 | sw = img.width,
50 | sh = img.height,
51 | dx = 0,
52 | dy = 0;
53 | drawImageIOSFix(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh);
54 | }
55 |
56 |
57 | var Fix = {
58 | drawImageIOS: drawImageIOS,
59 | drawImageIOSFix: drawImageIOSFix
60 | };
61 |
62 | return Fix;
63 | });
64 |
--------------------------------------------------------------------------------
/src/module/fix.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @description: fix bugs
3 | *
4 | */
5 | ;(function(Ps){
6 |
7 | window[Ps].module("Fix",function(P){
8 | function detectVerticalSquash(img) {
9 | var iw = img.naturalWidth, ih = img.naturalHeight;
10 | var canvas = document.createElement('canvas');
11 | canvas.width = 1;
12 | canvas.height = ih;
13 | var ctx = canvas.getContext('2d');
14 | ctx.drawImage(img, 0, 0);
15 | var data = ctx.getImageData(0, 0, 1, ih).data;
16 | // search image edge pixel position in case it is squashed vertically.
17 | var sy = 0;
18 | var ey = ih;
19 | var py = ih;
20 | while (py > sy) {
21 | var alpha = data[(py - 1) * 4 + 3];
22 | if (alpha === 0) {
23 | ey = py;
24 | } else {
25 | sy = py;
26 | }
27 | py = (ey + sy) >> 1;
28 | }
29 | var ratio = (py / ih);
30 | return (ratio===0)?1:ratio;
31 | }
32 |
33 | /**
34 | * A replacement for context.drawImage
35 | * (args are for source and destination).
36 | */
37 | function drawImageIOSFix(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) {
38 | var vertSquashRatio = detectVerticalSquash(img);
39 | // Works only if whole image is displayed:
40 | // ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio);
41 | // The following works correct also when only a part of the image is displayed:
42 | ctx.drawImage(img, sx * vertSquashRatio, sy * vertSquashRatio,
43 | sw * vertSquashRatio, sh * vertSquashRatio,
44 | dx, dy, dw, dh );
45 | }
46 |
47 | function drawImageIOS(ctx, img, dw, dh){
48 | var sx = 0,
49 | sy = 0,
50 | sw = img.width,
51 | sh = img.height,
52 | dx = 0,
53 | dy = 0;
54 | drawImageIOSFix(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh);
55 | }
56 |
57 |
58 | var M = {
59 | drawImageIOS: drawImageIOS,
60 | drawImageIOSFix: drawImageIOSFix
61 | };
62 |
63 | return M;
64 |
65 | });
66 |
67 | })("psLib");
68 |
69 |
--------------------------------------------------------------------------------
/src/module/applyMatrix.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: 查找边缘
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("applyMatrix",function(P){
9 |
10 | var M = {
11 | process: function(imgData, arg){
12 | var lamta = arg || 0.6;
13 | var data = imgData.data;
14 | var width = imgData.width;
15 | var height = imgData.height;
16 | var template = new P.lib.dorsyMath.Matrix([
17 | -2,-4,-4,-4,-2,
18 | -4,0,8,0,-4,
19 | -4,8,24,8,-4,
20 | -4,0,8,0,-4,
21 | -2,-4,-4,-4,-2
22 | ],25,1);
23 | var tempData = [];
24 |
25 | for(var i = 0, n = data.length; i < n; i += 4){
26 | var ii = i / 4;
27 | var row = parseInt(ii / width);
28 | var col = ii % width;
29 | if(row == 0 || col == 0) continue;
30 |
31 | var pixelArr = [[],[],[]];
32 |
33 | for(var k = -2; k < 3; k ++){
34 | var currRow = row + k;
35 |
36 | for(var kk = -2; kk < 3; kk ++){
37 |
38 | var currCol = col + kk;
39 | var currI = (currRow * width + currCol) * 4;
40 |
41 | for(var j = 0; j < 3; j ++){
42 | var tempI = currI + j;
43 | pixelArr[j].push(data[tempI]);
44 | }
45 |
46 | }
47 |
48 | }
49 |
50 | var pixelMatrix = new P.lib.dorsyMath.Matrix(pixelArr, 3, matrixSize);
51 | var resultMatrix = pixelMatrix.mutiply(template);
52 |
53 | for(var j = 0; j < 3; j ++){
54 | tempData[i + j] = resultMatrix.data[j];
55 | }
56 |
57 | tempData[i + 4] = data[i + 4];
58 | }
59 |
60 | for(var i = 0, n = data.length; i < n; i ++){
61 | data[i] = tempData[i] || data[i];
62 | }
63 |
64 | return imgData;
65 | }
66 | };
67 |
68 | return M;
69 |
70 | });
71 |
72 | })("psLib");
73 |
--------------------------------------------------------------------------------
/src/module/filter/darkCorner.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: 暗角
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("Filter.darkCorner", function(P){
9 |
10 | var M = {
11 | process: function(imgData,arg){
12 | //暗角级别 分1-10级吧
13 | var R = parseInt(arg[0]) || 3;
14 |
15 | //暗角的形状
16 | var type = arg[2] || "round";
17 |
18 | //暗角最终的级别 0 - 255
19 | var lastLevel = arg[1] || 30;
20 |
21 | var data = imgData.data;
22 | var width = imgData.width;
23 | var height = imgData.height;
24 | var xLength = R * 2 + 1;
25 |
26 | //计算中心点
27 | var middleX = width * 2 / 3;
28 | var middleY = height * 1/ 2;
29 |
30 | //计算距中心点最长距离
31 | var maxDistance = P.lib.dorsyMath.distance([middleX ,middleY]);
32 | //开始产生暗角的距离
33 | var startDistance = maxDistance * (1 - R / 10);
34 |
35 | var f = function(x, p0, p1, p2, p3){
36 |
37 | //基于三次贝塞尔曲线
38 | return p0 * Math.pow((1 - x), 3) + 3 * p1 * x * Math.pow((1 - x), 2) + 3 * p2 * x * x * (1 - x) + p3 * Math.pow(x, 3);
39 | }
40 |
41 | //计算当前点应增加的暗度
42 | function calDark(x, y, p){
43 | //计算距中心点距离
44 | var distance = P.lib.dorsyMath.distance([x, y], [middleX, middleY]);
45 | var currBilv = (distance - startDistance) / (maxDistance - startDistance);
46 | if(currBilv < 0) currBilv = 0;
47 |
48 | //应该增加暗度
49 | return f(currBilv, 0, 0.02, 0.3, 1) * p * lastLevel / 255;
50 | }
51 |
52 | //区块
53 | for(var x = 0; x < width; x ++){
54 |
55 | for(var y = 0; y < height; y ++){
56 |
57 | var realI = y * width + x;
58 | for(var j = 0;j < 3;j ++){
59 | var dDarkness = calDark(x, y, data[realI * 4 + j]);
60 | data[realI * 4 + j] -= dDarkness;
61 | }
62 |
63 | }
64 |
65 | }
66 |
67 |
68 | return imgData;
69 | }
70 | };
71 |
72 | return M;
73 |
74 | });
75 |
76 | })("psLib");
77 |
--------------------------------------------------------------------------------
/src/module/filter/dotted.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: 马赛克
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("Filter.dotted",function(P){
9 |
10 | var M = {
11 | process: function(imgData,arg){//调节亮度对比度
12 | //矩形半径
13 | var R = parseInt(arg[0]) || 1;
14 |
15 | //内小圆半径
16 | var r = parseInt(arg[1]) || 1;
17 |
18 | var data = imgData.data;
19 | var width = imgData.width;
20 | var height = imgData.height;
21 | var xLength = R * 2 + 1;
22 |
23 | //构造距离模板
24 | var disTmlMatrix = [
25 | ];
26 |
27 | var r2 = r * r;
28 | for(var x = -R; x < R; x ++){
29 |
30 | for(var y = -R; y < R; y ++){
31 | if((x * x + y * y) > r2){
32 | disTmlMatrix.push([x, y]);
33 | }
34 | }
35 |
36 | }
37 |
38 | var xyToIFun = P.lib.dorsyMath.xyToIFun(width);
39 |
40 | //将大于距离外面的透明度置为0
41 | for(var x = 0, n = parseInt(width / xLength); x < n; x ++){
42 |
43 | for(var y = 0, m = parseInt(height / xLength); y < m;y ++){
44 | var middleX = parseInt((x + 0.5) * xLength);
45 | var middleY = parseInt((y + 0.5) * xLength);
46 |
47 | for(var i = 0; i < disTmlMatrix.length; i ++){
48 | var dotX = middleX + disTmlMatrix[i][0];
49 | var dotY = middleY + disTmlMatrix[i][1];
50 |
51 | //data[(dotY * width + dotX) * 4 + 3] = 0;
52 | data[xyToIFun(dotX, dotY, 3)] = 225;
53 | data[xyToIFun(dotX, dotY, 2)] = 225;
54 | data[xyToIFun(dotX, dotY, 0)] = 225;
55 | data[xyToIFun(dotX, dotY, 1)] = 225;
56 | }
57 | }
58 |
59 | }
60 |
61 | /*
62 | for(var x = 0; x < width; x ++){
63 | for(var y = 0; y < height; y ++){
64 | data[(y * width + x) * 4 + 3] = 0;
65 | }
66 | }
67 | */
68 |
69 |
70 | return imgData;
71 | }
72 | };
73 |
74 | return M;
75 |
76 | });
77 |
78 | })("psLib");
79 |
--------------------------------------------------------------------------------
/nsrc/alloyimage.config.js:
--------------------------------------------------------------------------------
1 | AIDefine('config', [], function(){
2 | //记录映射关系
3 | var Reflection = {
4 | //调整
5 | Alteration: {
6 | "亮度": "brightness",
7 | "色相/饱和度调节": "setHSI",
8 | "曲线" : "curve",
9 | "gamma调节" : "gamma",
10 | "可选颜色": "selectiveColor"
11 | },
12 |
13 | //滤镜
14 | Filter: {
15 | "灰度处理": "toGray",
16 | "反色": "toReverse",
17 | "灰度阈值": "toThresh",
18 | "高斯模糊": "gaussBlur",
19 | "浮雕效果": "embossment",
20 | "查找边缘": "borderline",
21 | "马赛克": "mosaic",
22 | "油画": "oilPainting",
23 | "腐蚀": "corrode",
24 | "锐化" : "sharp",
25 | "添加杂色" : "noise",
26 | "暗角" : "darkCorner",
27 | "喷点" : "dotted",
28 | "降噪" : "denoise",
29 | "棕褐色" : "sepia",
30 | "色调分离" : "posterize"
31 | },
32 |
33 | ComEffect: {
34 | "美肤" : "softenFace",
35 | "素描" : "sketch",
36 | "自然增强" : "softEnhancement",
37 | "紫调" : "purpleStyle",
38 | "柔焦" : "soften",
39 | "复古" : "vintage",
40 | "黑白" : "gray",
41 | "仿lomo" : "lomo",
42 | "亮白增强" : "strongEnhancement",
43 | "灰白" : "strongGray",
44 | "灰色" : "lightGray",
45 | "暖秋" : "warmAutumn",
46 | "木雕" : "carveStyle",
47 | "粗糙" : "rough"
48 | }
49 | };
50 |
51 | //转换映射关系 便于查找
52 | var revertReflection = function(){
53 | var result = {};
54 |
55 | for(var i in Reflection){
56 | //comEffect 组合效果不遍历
57 | if(i == "ComEffect") continue;
58 |
59 | for(var j in Reflection[i]){
60 | result[j] = i;
61 | result[Reflection[i][j]] = i;
62 | }
63 | }
64 |
65 | return result;
66 | }();
67 |
68 | var Config = {
69 |
70 | getModuleName: function(method){
71 | var spaceName;
72 |
73 | if(spaceName = revertReflection[method]){
74 | var actName = Reflection[spaceName][method] || method;
75 | return {
76 | spaceName: spaceName,
77 | actName: actName
78 | };
79 |
80 | }else{
81 | P.destroySelf("AI_ERROR:调用AI不存在的方法" + method);
82 | }
83 | },
84 |
85 | //组合效果
86 | getEasyFun: function(effect){
87 | return {
88 | spaceName: "ComEffect",
89 | actName: Reflection.ComEffect[effect] || effect
90 | };
91 | },
92 |
93 | getConfig: function(){
94 | return Reflection;
95 | }
96 | };
97 |
98 | return Config;
99 |
100 | });
101 |
--------------------------------------------------------------------------------
/src/module/config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: Main config
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("config",function(P){
9 |
10 | //记录映射关系
11 | var Reflection = {
12 | //调整
13 | Alteration: {
14 | "亮度": "brightness",
15 | "色相/饱和度调节": "setHSI",
16 | "曲线" : "curve",
17 | "gamma调节" : "gamma",
18 | "可选颜色": "selectiveColor"
19 | },
20 |
21 | //滤镜
22 | Filter: {
23 | "灰度处理": "toGray",
24 | "反色": "toReverse",
25 | "灰度阈值": "toThresh",
26 | "高斯模糊": "gaussBlur",
27 | "浮雕效果": "embossment",
28 | "查找边缘": "borderline",
29 | "马赛克": "mosaic",
30 | "油画": "oilPainting",
31 | "腐蚀": "corrode",
32 | "锐化" : "sharp",
33 | "添加杂色" : "noise",
34 | "暗角" : "darkCorner",
35 | "喷点" : "dotted",
36 | "降噪" : "denoise",
37 | "棕褐色" : "sepia",
38 | "色调分离" : "posterize"
39 | },
40 |
41 | ComEffect: {
42 | "美肤" : "softenFace",
43 | "素描" : "sketch",
44 | "自然增强" : "softEnhancement",
45 | "紫调" : "purpleStyle",
46 | "柔焦" : "soften",
47 | "复古" : "vintage",
48 | "黑白" : "gray",
49 | "仿lomo" : "lomo",
50 | "亮白增强" : "strongEnhancement",
51 | "灰白" : "strongGray",
52 | "灰色" : "lightGray",
53 | "暖秋" : "warmAutumn",
54 | "木雕" : "carveStyle",
55 | "粗糙" : "rough"
56 | }
57 | };
58 |
59 | //转换映射关系 便于查找
60 | var revertReflection = function(){
61 | var result = {};
62 |
63 | for(var i in Reflection){
64 | //comEffect 组合效果不遍历
65 | if(i == "ComEffect") continue;
66 |
67 | for(var j in Reflection[i]){
68 | result[j] = i;
69 | result[Reflection[i][j]] = i;
70 | }
71 | }
72 |
73 | return result;
74 | }();
75 |
76 | var Config = {
77 |
78 | getModuleName: function(method){
79 | var spaceName;
80 |
81 | if(spaceName = revertReflection[method]){
82 | var actName = Reflection[spaceName][method] || method;
83 | return {
84 | spaceName: spaceName,
85 | actName: actName
86 | };
87 |
88 | }else{
89 | throw new Error("AI_ERROR:调用AI不存在的方法" + method);
90 | }
91 | },
92 |
93 | //组合效果
94 | getEasyFun: function(effect){
95 | return {
96 | spaceName: "ComEffect",
97 | actName: Reflection.ComEffect[effect] || effect
98 | };
99 | },
100 |
101 | getConfig: function(){
102 | return Reflection;
103 | }
104 | };
105 |
106 | return Config;
107 |
108 | });
109 |
110 | })("psLib");
111 |
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
137 |
138 |
139 |
--------------------------------------------------------------------------------
/nsrc/alloyimage.process.js:
--------------------------------------------------------------------------------
1 | /**
2 | * AlloyImage process module
3 | * The main Process module For AlloyImage, It's private;
4 | * @author dorsywang From Tencent AlloyTeam
5 | */
6 |
7 | AIDefine('process', ['config', 'layer'], function(Config, Layer){
8 | var Process = {
9 |
10 | //模块池
11 | lib: [],
12 |
13 | //外部定义的ps效果
14 | definedPs: {},
15 |
16 | //初始化准备
17 | init: function(){
18 | this.require("config");
19 | },
20 |
21 | //模块注册方法
22 | module: function(name, func){
23 | var moduleArr = [name];
24 | if(/\./g.test(name)){
25 | moduleArr = name.split(".");
26 | }
27 |
28 | var count = -1, _this = this;
29 | function addModule(obj){
30 | count ++;
31 |
32 | var attr = moduleArr[count];
33 |
34 | //递归出口
35 | if(count == moduleArr.length - 1){
36 | obj[attr] = func.call(null, _this);
37 |
38 | return;
39 | }
40 |
41 | obj[attr] ? addModule(obj[attr]) : addModule(obj[attr] = {});
42 | }
43 |
44 | addModule(this.lib);
45 |
46 | },
47 |
48 | //加载文件
49 | require: function(name){
50 | var _this = this;
51 | var scriptLoader = document.createElement("script");
52 |
53 | document.body.appendChild(scriptLoader);
54 | scriptLoader.src = "./js/module/" + name + ".js";
55 | scriptLoader.onload = scriptLoader.onerror = function(e){
56 | _this.handlerror(e);
57 | }
58 | },
59 |
60 | //错误处理部分
61 | handlerror: function(e){
62 | //this.destroySelf("程序因未知原因中断");
63 | },
64 |
65 | //程序被迫自杀,杀前请留下遗嘱
66 | destroySelf: function(msg){
67 | delete window[Ps];
68 | var e = new Error(msg);
69 | throw(e);
70 | },
71 |
72 | //映射器,将中文方法或...映射为实际方法
73 | reflect: function(method, imgData, args){
74 |
75 | //得到实际的模块名称
76 | var moduleName = Config.getModuleName(method);
77 |
78 | var spaceName = moduleName.spaceName;
79 | var actName = moduleName.actName;
80 |
81 | switch(spaceName){
82 | case "Filter":
83 | return Filter[actName].process(imgData, args);
84 |
85 | case "Alteration":
86 |
87 | return Alteration[actName].process(imgData, args);
88 | //break;
89 |
90 | case "ComEffect":
91 | return ComEffect[actName].process(imgData, args);
92 | //break;
93 |
94 | default:
95 | //逻辑几乎不会到这里 出于好的习惯,加上default
96 | this.destroySelf("AI_ERROR: ");
97 | }
98 | },
99 |
100 | //组合效果映射器
101 | reflectEasy: function(effect){
102 | var fun = Config.getEasyFun(effect).actName;
103 | return this.definedPs[effect] || ComEffect.getFun(fun);
104 | },
105 |
106 | //合并一个图层到对象
107 | add: function(lowerData, upperData, method, alpha, dx, dy, isFast, channel){
108 | return Layer.add(lowerData, upperData, method, alpha, dx, dy, isFast, channel);
109 | },
110 |
111 | //用worker进行异步处理
112 | worker: function(func, callback){
113 |
114 | },
115 |
116 | //对图像进行掩模算子变换
117 | applyMatrix: function(imgData, matrixArr){
118 | },
119 |
120 | //args[0]代表处理方法,args[1...]代表参数
121 | tools: function(imgData, args){
122 | var actMethod = Array.prototype.shift.call(args);
123 |
124 | if(this.lib.Tools[actMethod]){
125 | return this.lib.Tools[actMethod].process(imgData, args);
126 | }else{
127 | throw new Error("AI_ERROR: 不存在的工具方法_" + actMethod);
128 | }
129 | },
130 |
131 | definePs: function(name, func){
132 | this.definedPs[name] = func;
133 | }
134 | };
135 |
136 | return Process;
137 | });
138 |
--------------------------------------------------------------------------------
/src/module/easy.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: 腐蚀
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("easy",function(P){
9 |
10 | var M = {
11 | getFun: function(fun){
12 | var Effects = {
13 | softenFace: function(){//美肤
14 | var _this = this.clone();
15 | return _this.add(
16 | this.act("高斯模糊",10),"滤色"
17 | ).act("亮度",-10,5);
18 | },
19 | sketch: function(){//素描
20 | var _this = this.clone();
21 | return this.add(
22 | _this.act("反色").act("高斯模糊",8), "颜色减淡"
23 | ).act("toGray").act("锐化",1);
24 | },
25 | softEnhancement: function(){//自然增强
26 | return this.act("曲线",[0,190,255],[0,229,255]);
27 | },
28 | purpleStyle: function(){
29 | var _this = this.clone();
30 | return this.add(
31 | _this.act("高斯模糊",3), "正片叠底" ,"RG"
32 | );
33 |
34 | },
35 | soften: function(){
36 | var _this = this.clone();
37 | return this.add(
38 | _this.act("高斯模糊",6), "变暗"
39 | );
40 | },
41 | vintage: function(){//复古
42 | var _this = this.clone();
43 | return this.act("灰度处理").add(
44 | window[Ps](this.canvas.width,this.canvas.height,"#808080").act("添加杂色").act("高斯模糊",4).act("色相/饱和度调节",32,19,0,true),"叠加"
45 | );
46 | },
47 | gray: function(){//黑白
48 | return this.act("灰度处理");
49 | },
50 | lomo: function(){//仿lomo
51 | var m = this.clone().add(
52 | this.clone() , "滤色"
53 | ).add(
54 | this.clone() , "柔光"
55 | );
56 |
57 | return m.add(
58 | this.clone().act("反色") , "正常","20%","B"
59 | ).act("暗角", 6, 200);
60 |
61 | },
62 | strongEnhancement: function(){
63 | return this.clone().add(
64 | this.clone().act("曲线",[0,50,255],[0,234,255]), "柔光"
65 | );
66 | },
67 | strongGray: function(){//高对比 灰白
68 | return this.act("灰度处理").act("曲线",[0,61,69,212,255],[0,111,176,237,255]);
69 | },
70 | lightGray: function(){
71 | return this.act("灰度处理").act("曲线",[0,60,142,194,255],[0,194,240,247,255])
72 | },
73 | warmAutumn: function(){
74 | var m = this.clone().act("色相/饱和度调节",36,47,8,true).act("暗角", 6, 150);
75 | return this.add(
76 | m, "叠加"
77 | );
78 | },
79 |
80 | //木雕的效果
81 | carveStyle: function(){
82 | var layerClone = this.clone().act("马赛克").act("查找边缘").act("浮雕效果");
83 | return this.add(
84 | layerClone, "线性光"
85 | );
86 | },
87 |
88 | //粗糙
89 | rough: function(){
90 | return this.add(
91 |
92 | window[Ps](this.canvas.width, this.canvas.height, "#000").act("喷点").act("反色").act("浮雕效果")
93 | ,"叠加"
94 | );
95 | }
96 | };
97 |
98 | return Effects[fun];
99 | }
100 | };
101 |
102 | return M;
103 |
104 | });
105 |
106 | })("psLib");
107 |
--------------------------------------------------------------------------------
/src/module/dorsyWorker.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: Main worker
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("dorsyWorker",function(P){
9 | //等待时间
10 | var WAITING_SECONDS = 200;
11 |
12 | var M = function(aiObj){
13 | //static private single
14 | var worker = new Worker(P.path);// + "?" + (+ new Date()));
15 | if(! worker){
16 | throw new Error("使用worker时,alloyimage文件目录指定出错");
17 | }
18 |
19 | var workerObj = {
20 | //等待处理的队列
21 | queue: [],
22 | //开始进入多线程
23 | startWorker: function(){
24 | //console.log("startWorker");
25 | this.shiftAction();
26 | },
27 |
28 | //从队列中取出一个动作来处理
29 | shiftAction: function(){
30 | var action = this.queue.shift(), _this = this;
31 |
32 | //如果没有了,等待100ms再次检查, 如果还没有,表明队列中无新增处理动作, readyOK
33 | if(! action){
34 | setTimeout(function(){
35 | action = _this.queue.shift();
36 |
37 | if(! action){
38 | aiObj.notify("readyStateOK");
39 | //console.log("readyStateOK");
40 | }
41 |
42 | }, WAITING_SECONDS);
43 |
44 | return;
45 | }
46 |
47 | //调用方法
48 | var actionMethod = action[0];
49 |
50 | //此处理为动作
51 | if(actionMethod == "act"){
52 |
53 | //向worker发消息
54 | worker.postMessage(["act", action[1], aiObj.imgData, action[2]]);
55 |
56 | //为添加要检查添加的图层是否处理完成
57 | }else if(actionMethod == "add"){
58 | //console.log("add");
59 |
60 |
61 | function checkReadyState(){
62 |
63 | //完成
64 | if(action[1].readyState){
65 |
66 | //构造参数
67 | var params = [
68 | aiObj.imgData,
69 | action[1].imgData
70 | ].concat(
71 | action.slice(2)
72 | );
73 |
74 | worker.postMessage(["add", params]);
75 |
76 | //如果没有完成则不断检查是否完成,期间可以做其他的动作,但处理暂时中止
77 | }else{
78 | setTimeout(function(){
79 | checkReadyState();
80 | }, WAITING_SECONDS);
81 | }
82 | }
83 |
84 | checkReadyState();
85 | }else if(actionMethod == "show"){
86 | aiObj.show(action[1], action[2], 1);
87 | this.shiftAction();
88 |
89 | //遇到回调出现
90 | }else if(actionMethod == "complete"){
91 | //console.log("complete trigger");
92 | action[1] && action[1]();
93 | this.shiftAction();
94 |
95 | //如果是复制图层
96 | }else if(actionMethod == "clone"){
97 | aiObj.clone(1);
98 | this.shiftAction();
99 | }else if(actionMethod == "save"){
100 | aiObj.save(0, 1);
101 | this.shiftAction();
102 | }else if(actionMethod == "replace"){
103 | aiObj.replace(action[1], 1);
104 | this.shiftAction();
105 | }
106 | },
107 |
108 | //worker回调监听
109 | callback: function(data){
110 | //console.log("callback");
111 | aiObj.imgData = data;
112 | this.shiftAction();
113 | }
114 | };
115 |
116 | //收到消息后再从队列中检查然后进行处理
117 | worker.onmessage = function(e){
118 | //console.log("onmessage");
119 | workerObj.callback(e.data);
120 | };
121 |
122 | return workerObj;
123 | };
124 |
125 | return M;
126 |
127 | });
128 |
129 | })("psLib");
130 |
131 |
--------------------------------------------------------------------------------
/src/module/filter/gaussBlur.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: az@alloyTeam Bin Wang
3 | * @description: 高斯模糊
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("Filter.gaussBlur",function(P){
9 |
10 | var M = {
11 |
12 | /**
13 | * 高斯模糊
14 | * @param {Array} pixes pix array
15 | * @param {Number} width 图片的宽度
16 | * @param {Number} height 图片的高度
17 | * @param {Number} radius 取样区域半径, 正数, 可选, 默认为 3.0
18 | * @param {Number} sigma 标准方差, 可选, 默认取值为 radius / 3
19 | * @return {Array}
20 | */
21 | process: function(imgData, args) {
22 | var pixes = imgData.data;
23 | var width = imgData.width;
24 | var height = imgData.height;
25 | var gaussMatrix = [],
26 | gaussSum = 0,
27 | x, y,
28 | r, g, b, a,
29 | i, j, k, len;
30 |
31 | var radius = args[0];
32 | var sigma = args[1];
33 |
34 |
35 | radius = Math.floor(radius) || 3;
36 | sigma = sigma || radius / 3;
37 |
38 | a = 1 / (Math.sqrt(2 * Math.PI) * sigma);
39 | b = -1 / (2 * sigma * sigma);
40 | //生成高斯矩阵
41 | for (i = 0, x = -radius; x <= radius; x++, i++){
42 | g = a * Math.exp(b * x * x);
43 | gaussMatrix[i] = g;
44 | gaussSum += g;
45 |
46 | }
47 | //归一化, 保证高斯矩阵的值在[0,1]之间
48 | for (i = 0, len = gaussMatrix.length; i < len; i++) {
49 | gaussMatrix[i] /= gaussSum;
50 | }
51 | //x 方向一维高斯运算
52 | for (y = 0; y < height; y++) {
53 | for (x = 0; x < width; x++) {
54 | r = g = b = a = 0;
55 | gaussSum = 0;
56 | for(j = -radius; j <= radius; j++){
57 | k = x + j;
58 | if(k >= 0 && k < width){//确保 k 没超出 x 的范围
59 | //r,g,b,a 四个一组
60 | i = (y * width + k) * 4;
61 | r += pixes[i] * gaussMatrix[j + radius];
62 | g += pixes[i + 1] * gaussMatrix[j + radius];
63 | b += pixes[i + 2] * gaussMatrix[j + radius];
64 | // a += pixes[i + 3] * gaussMatrix[j];
65 | gaussSum += gaussMatrix[j + radius];
66 | }
67 | }
68 | i = (y * width + x) * 4;
69 | // 除以 gaussSum 是为了消除处于边缘的像素, 高斯运算不足的问题
70 | // console.log(gaussSum)
71 | pixes[i] = r / gaussSum;
72 | pixes[i + 1] = g / gaussSum;
73 | pixes[i + 2] = b / gaussSum;
74 | // pixes[i + 3] = a ;
75 | }
76 | }
77 | //y 方向一维高斯运算
78 | for (x = 0; x < width; x++) {
79 | for (y = 0; y < height; y++) {
80 | r = g = b = a = 0;
81 | gaussSum = 0;
82 | for(j = -radius; j <= radius; j++){
83 | k = y + j;
84 | if(k >= 0 && k < height){//确保 k 没超出 y 的范围
85 | i = (k * width + x) * 4;
86 | r += pixes[i] * gaussMatrix[j + radius];
87 | g += pixes[i + 1] * gaussMatrix[j + radius];
88 | b += pixes[i + 2] * gaussMatrix[j + radius];
89 | // a += pixes[i + 3] * gaussMatrix[j];
90 | gaussSum += gaussMatrix[j + radius];
91 | }
92 | }
93 | i = (y * width + x) * 4;
94 | pixes[i] = r / gaussSum;
95 | pixes[i + 1] = g / gaussSum;
96 | pixes[i + 2] = b / gaussSum;
97 | // pixes[i] = r ;
98 | // pixes[i + 1] = g ;
99 | // pixes[i + 2] = b ;
100 | // pixes[i + 3] = a ;
101 | }
102 | }
103 | //end
104 | imgData.data = pixes;
105 | return imgData;
106 | }
107 | };
108 |
109 | return M;
110 |
111 | });
112 |
113 | })("psLib");
114 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [AlloyImage](http://alloyteam.github.com/AlloyPhoto/) - 基于HTML5技术的专业图像处理库
2 | ===========================
3 |
4 | ### 功能特性
5 |
6 | #### 强大功能
7 | 1. 基于多图层操作 -- 一个图层的处理不影响其他图层
8 | 2. 与PS对应的17种图层混合模式 -- 便于PS处理教程的无缝迁移
9 | 3. 多种基本滤镜处理效果 -- 基本滤镜不断丰富、可扩展
10 | 4. 基本的图像调节功能 -- 色相、饱和度、对比度、亮度、曲线等
11 |
12 |
13 | #### 便捷开发
14 | 1. 简单快捷的API -- 链式处理、API简洁易用、传参灵活
15 | 2. 多种组合效果封装 -- 一句代码轻松实现一种风格
16 | 3. 友好参数支持 -- 中、英文参数双向支持,降低专业词汇记忆门槛
17 | 4. 接口一致的单、多线程支持 -- 单、多线程切换无需更改一行代码,多线程保持快捷API特性
18 | 5. 可预见的错误友好提醒 -- 对一些可能出现错误的地方提醒,方便开发与调试
19 |
20 |
21 | #### 丰富扩展
22 | 1. 方便的添加功能扩展 -- 轻松添加滤镜插件
23 | 2. 为扩展提供数学封装 -- 封装了一些数学模块供扩展调用
24 |
25 | ### 建议使用场景
26 | 1.桌面软件客户端内嵌网页运行方式
27 | >>>打包webkit内核: 用户较大头像上传风格处理、用户相册风格处理(处理时间平均<1s)
28 |
29 | 2.Win8 Metro应用
30 | >>>用户上传头像,比较小的图片风格处理后上传(Win8下IE10支持多线程)
31 |
32 | 3.Mobile APP
33 | >>>Andriod平台、IOS平台小图风格web处理的需求,如phoneGap应用, 在线头像上传时的风格处理、mobile web端分享图片时风格处理等
34 |
35 | ### 如何构建源码?
36 |
37 | 首先使用git clone复制一份AlloyPhoto的代码到本地:
38 | ```sh
39 | git clone git://github.com/AlloyTeam/AlloyPhoto.git
40 | ```
41 | 然后使用npm安装[modjs](https://github.com/modulejs/modjs):
42 | ```sh
43 | npm install -g modjs
44 | ```
45 | 安装成功后:
46 | ```sh
47 | cd AlloyPhoto && mod dist
48 | ```
49 | 构建成功后会在 `./js/combined`目录下生成`alloyimage.js`文件
50 |
51 | ### 变更历史
52 | #### AlloyImage 1.2开发版代码 获取
53 | > 在release目录下获取开发版
54 |
55 | #### AlloyImage 1.2 开发中
56 | 1. 更改代码架构,分离Filter
57 | 2. 添加工具方法支持:色系提取
58 | 3. 添加下载文件方法
59 | 4. 添加 棕褐色 滤镜
60 | 5. 添加 色调分离 滤镜
61 | 6. 添加 Gamma 调节
62 | 7. 更改代码,分离Alteration
63 | 8. 添加仿射变换(缩放、平移、旋转)、裁切
64 | 9. 增加可选颜色调节
65 | 10. 曲线命令支持通道调节
66 | 11. 优化IOS下性能,修复变形的bug
67 |
68 |
69 | ##### 新增API 1.2以上
70 |
71 | >###$AI 或 AlloyImage
72 | 初始化一个AlloyImage对象
73 | 增加新的参数适配 AIObj $AI(HTMLImageObj img[, Number width, Number height]);
74 | {img} 图片元素
75 | {width} 缩放的宽度 可选
76 | {height} 缩放的高度 可选
77 | 如果width 或height一个为null,则使用等比缩放,如果都没有,使用img宽度
78 | tips: 在IOS下请使用width参数来缩放相册中的图片,IOS下不使用缩放,图片太大可能无法绘制到Canvas上
79 |
80 | 示例
81 | ```javascript
82 | var ps = $AI(img, 600).save('jpg', 0.6);
83 | ```
84 |
85 | >###save
86 | 将合成图片保存成base64格式字符串
87 | base64String save(String filetype [, Number comRatio]);
88 | {filetype} 图片格式类型,支持png,jpg,gif等
89 | {comRatio} 对于jpg格式的图片,图片压缩比率或者图片质量,0 - 1的小数
90 | 返回 base64的字符串
91 |
92 | 示例
93 | ```javascript
94 | var string = AlloyImage(img).save('jpg', 0.8);
95 | ```
96 | >###saveFile
97 | 将合成图片下载到本地
98 | void saveFile(String fileName[, Number comRatio]);
99 | {fileName} 图片文件名,如果不带后缀,默认为png格式
100 | {comRatio} 对于jpg格式的图片,图片压缩比率或者图片质量,0 - 1的小数
101 | 返回 空
102 |
103 | 示例
104 | ```javascript
105 | img.onclick = function(){
106 | AlloyImage(this).saveFile('处理后图像.jpg', 0.8);
107 | }
108 | ```
109 |
110 | >###download
111 | 功能与使用同saveFile
112 |
113 |
114 |
115 | >###transform
116 | 进行仿射变换
117 | AIObj transform(Array Matrix);
118 | {Matrix} 变换矩阵 数组 [a1, a2, b1, b2, dx, dy]
119 | 如水平翻转 [-1, 0, 0, 1, 0, 0]
120 | 示例
121 | ```javascript
122 | //将图层垂直翻转
123 | AlloyImage(img).transform([1, 0, 0, -1, 0, 0]).show();
124 | ```
125 |
126 |
127 | >###scaleTo
128 | 将图层或合成图像缩放到指定宽高
129 | AIObj scaleTo(Number width, Nubmer height);
130 | {width} 宽度
131 | {height} 高度
132 | 如果不指定某一参数,则使用等比缩放
133 |
134 | 返回 AIObj
135 |
136 | 示例
137 | ```javascript
138 | //将图层缩放放到100px * 100px
139 | AlloyImage(img).scaleTo(100, 100).show();
140 |
141 | //将图层等比缩放到高50px
142 | AlloyImage(img).scaleTo(null, 100).show();
143 | ```
144 | >###scale
145 | 将图层或合成图像缩放指定倍数
146 | AIObj scale(Number xRatio, Nubmer yRatio);
147 | {xRatio} 横向缩放倍数
148 | {yRatio} 纵向缩放倍数
149 | 如果不指定某一参数,则使用等比缩放
150 |
151 | 返回 AIObj
152 |
153 | 示例
154 | ```javascript
155 | //将图层缩放放2 * 2倍
156 | AlloyImage(img).scale(2, 2).show();
157 |
158 | //将图层等比缩放3倍
159 | AlloyImage(img).scale(3).show();
160 | ```
161 | >###rotate
162 | 将图层或合成图像旋转一定的角度
163 | AIObj rotate(Numbe degree);
164 | {degree} 顺时旋转角度,以度为单位
165 |
166 | 返回 AIObj
167 |
168 | 示例
169 | ```javascript
170 | //将图层旋转30度
171 | AlloyImage(img).rotate(30).show();
172 |
173 | ```
174 |
175 | >###clip
176 | 将图层或合成图像裁剪
177 | AIObj rotate(Numbe x0, Number y0, Number width, Number height);
178 | {x0} 起始横坐标
179 | {y0} 起始纵坐标
180 | {width} 裁剪图像宽度
181 | {height} 裁剪图像高度
182 |
183 | 返回 AIObj
184 |
185 | 示例
186 | ```javascript
187 | //将图层从(30, 30)开始裁剪宽100px高100px的图像,并获取图像base64代码
188 | var imgString = AlloyImage(img).clip(30, 30, 100, 100).save('jpg', 0.8);
189 |
190 | ```
191 |
192 | >###drawRect
193 | 画出合成像的直方图
194 | void drawRect(String seletor, String channel);
195 | {seletor} 直方图绘制的wrapper
196 | {channel} 要绘制的通道, 比如 'RG', 'GB', 默认为'RGB'
197 |
198 | 返回 空
199 |
200 | 示例
201 | ```javascript
202 | var imgString = AlloyImage(img).drawRect('#p');
203 |
204 | ```
205 |
206 | ## 预览、撤销、重做
207 | >###doView
208 | 保存view的中间结果,下次使用view将会根据上次doView之前的结果进行处理,与undoView结合,可进行撤销操作
209 | AIObj doView();
210 | 返回 AIObj
211 | 示例参照undoView方法
212 |
213 |
214 |
215 | >###undoView
216 | 撤销上次view的执行结果
217 | AIObj undoView();
218 | 返回 AIObj
219 |
220 | 示例
221 | ```javascript
222 | var layer = $AI(img);
223 | layer.view("setHSI", 10, 0, 0).show();
224 |
225 | // 再次调节 这次还是基于原图调节
226 | layer.view("setHSI", -10, 0, 0).show();
227 |
228 | //调节好了 保存这次结果
229 | layer.doView();
230 |
231 | // 基于上次的调节结果进行计算
232 | layer.view("brightness", 10, 0, 0).show();
233 |
234 | // 不满意 撤销亮度调节操作
235 | layer.undoView().show();
236 |
237 | // 回到最原始的图像
238 | layer.undoView().show();
239 |
240 | ```
241 |
242 |
243 |
244 |
245 |
246 | #### AlloyImage 1.1
247 | 1. 优化代码,组合效果处理性能提升80%
248 | 2. 添加木雕组合效果
249 |
250 | #### AlloyImage 1.0
251 |
252 | ### 目录结构
253 | >--build 构建目录 一些项目的构建工具
254 |
255 | >--combined 中间构建合成的项目代码,用于测试和发布
256 |
257 | >--demo demo文件
258 |
259 | >--doc 目录文档
260 |
261 | >--release 已发布的文件版本
262 |
263 | >--res 一些测试用的静态资源
264 |
265 | >--src 项目JS源码
266 |
267 | >> alloyimage.base.js core文件 base文件
268 |
269 | >> --module 模块文件
270 |
271 | >> --alteration 调节模块
272 |
273 | >> --filter 滤镜插件
274 | >--test 测试文件
275 |
276 | ### 这些产品使用了AlloyImage
277 |
278 | [AlloyDesigner](http://alloyteam.github.io/AlloyDesigner/)
279 |
280 | [AlloyClip](https://github.com/AlloyTeam/AlloyClip)
281 |
282 | [AlloyPhoto](https://github.com/AlloyTeam/AlloyPhoto)
283 |
--------------------------------------------------------------------------------
/src/module/tools.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: 图像工具方法 不会返回AI本身,会得到图像的一些特征
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("Tools",function(P){
9 |
10 | var M = {
11 | //获得到图像的色系特征
12 | getColor: {
13 | process: function(imgData, args){
14 |
15 | var dM = P.lib.dorsyMath;
16 | var xyToIFun = dM.xyToIFun(imgData.width), i;
17 |
18 | var sum = [0, 0, 0];
19 |
20 |
21 | var level = 50;
22 | var every = Math.PI * 2 / level, n;
23 |
24 | var result = [];
25 |
26 | //在HSI空间应用
27 | dM.applyInHSI(imgData, function(obj, rColor, alpha){
28 | if(alpha > 128){
29 | n = parseInt(obj.H / every);
30 |
31 | if(result[n]){
32 | }else{
33 | result[n] = [];
34 | }
35 |
36 | result[n].push([obj.S, obj.I]);
37 | }
38 |
39 | });
40 |
41 | var t = 3;
42 |
43 | //计算出最大的level分区
44 | var max = 0, maxI = 0;;
45 | for(var i = 0; i < level; i ++){
46 | if(result[i] && result[i].length > max){
47 | max = result[i].length;
48 | maxI = i;
49 | }
50 | }
51 |
52 | //计算平均饱和度与灰度
53 | var sumS = 0, avS, sumI = 0, avI;
54 | for(var i = 0; i < result[maxI].length; i ++){
55 | sumS += result[maxI][i][0];
56 | sumI += result[maxI][i][1];
57 | }
58 |
59 | avS = sumS / result[maxI].length;
60 | avI = sumI / result[maxI].length;
61 |
62 | /*
63 | var dResult = [], ddResult = [0];
64 | //计算微分
65 | for(var i = 1; i < level; i ++){
66 | dResult[i] = result[i] - result[i - 1];
67 | }
68 |
69 | //计算2次微分
70 | for(var i = 2; i < level; i ++){
71 | ddResult[i] = dResult[i] - dResult[i - 1];
72 | }
73 |
74 | var rect2 = $AI(400, 400);
75 | rect2.ctx(function(){
76 | this.fillStyle = "#000";
77 | this.moveTo(0, 200);
78 | this.lineTo(400, 200);
79 | this.stroke();
80 |
81 | this.moveTo(0, 200);
82 | for(var i = 0; i < result.length; i ++){
83 | var x = i / result.length * 400;
84 | var y = 400 - (result[i] / 100 + 200);
85 |
86 | this.lineTo(x, y);
87 | this.fillRect(x - 2, y - 2, 4, 4);
88 | }
89 |
90 | this.stroke();
91 | }).show();
92 |
93 | $AI(400, 100).show();
94 |
95 | rect2.ctx(function(){
96 | this.moveTo(0, 200);
97 | this.lineTo(400, 200);
98 | this.stroke();
99 |
100 | this.fillStyle = "red";
101 |
102 | this.moveTo(0, 200);
103 | for(var i = 1; i < dResult.length; i ++){
104 | var x = i / dResult.length * 400;
105 | var y = 400 - (dResult[i] / 100 + 200);
106 |
107 | this.lineTo(x, y);
108 | this.fillRect(x - 2, y - 2, 4, 4);
109 | }
110 |
111 | this.stroke();
112 | }).show();
113 |
114 | /*
115 | var rect3 = $AI(400, 400);
116 | rect3.ctx(function(){
117 | this.moveTo(0, 200);
118 | this.lineTo(400, 200);
119 | this.stroke();
120 |
121 | this.moveTo(0, 200);
122 | for(var i = 1; i < ddResult.length; i ++){
123 | var x = i / ddResult.length * 400;
124 | var y = 400 - (ddResult[i] / 1 + 200);
125 |
126 | this.lineTo(x, y);
127 | }
128 |
129 | this.stroke();
130 | }).show();
131 | */
132 |
133 | //计算出现频率最大的色相
134 | var maxH = maxI * every;
135 |
136 | var rgb = dM.HSIToRGB(maxH, avS, avI);
137 |
138 | /*
139 | var all = this.width * this.height * 3;
140 | var r = parseInt(sum[0] / all);
141 | var g = parseInt(sum[1] / all);
142 | var b = parseInt(sum[2] / all);
143 | */
144 |
145 | var color = "rgb(" + parseInt(rgb.R) + "," + parseInt(rgb.G) + "," + parseInt(rgb.B) + ")";
146 | return color;
147 | }
148 | },
149 |
150 | toText: {
151 | process: function(imgData, args){
152 | var data = imgData.data,
153 | width = imgData.width,
154 | height = imgData.height,
155 | averageG,
156 |
157 | //灰度串
158 | str = args[0] || ".:;!#@",
159 |
160 | //记录位置信息Arr
161 | positionArr = [],
162 |
163 | //结果字符
164 | resultStr = "";
165 |
166 | console.log(str);
167 |
168 | var dM = P.lib.dorsyMath;
169 | var xyToIFun = dM.xyToIFun(imgData.width);
170 |
171 | //创建div串
172 | var i, everyLevel = 255 / str.length, j;
173 | for(var x = 0; x < width; x += 1){
174 | for(var y = 0; y < height; y += 1){
175 | i = xyToIFun(x, y, 0);
176 | averageG = (data[i] + data[i + 1] + data[i + 2]) / 3;
177 |
178 | j = parseInt(averageG / everyLevel);
179 |
180 | resultStr += str[j];
181 | }
182 |
183 | resultStr += "
";
184 | }
185 |
186 | return resultStr;
187 | }
188 | }
189 | };
190 |
191 | return M;
192 |
193 | });
194 |
195 | })("psLib");
196 |
--------------------------------------------------------------------------------
/src/module/alteration/seletiveColor.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: 可选颜色
4 | * @参考:http://wenku.baidu.com/view/e32d41ea856a561252d36f0b.html
5 | *
6 | */
7 | ;(function(Ps){
8 |
9 | window[Ps].module("Alteration.selectiveColor",function(P){
10 |
11 | var M = {
12 | process: function(imgData, arg){//调节亮度对比度
13 | //选择的颜色
14 | var color = arg[0];
15 |
16 | //百分数
17 | var C = arg[1];
18 | var M = arg[2];
19 | var Y = arg[3];
20 | var K = arg[4];
21 |
22 | //是否相对
23 | var isRelative = arg[5] || 0;
24 |
25 | var maxColorMap = {
26 | red: "R",
27 | green: "G",
28 | blue: "B",
29 | "红色": "R",
30 | "绿色": "G",
31 | "蓝色": "B"
32 | };
33 |
34 | var minColorMap = {
35 | cyan: "R",
36 | magenta: "G",
37 | yellow: "B",
38 | "青色": "R",
39 | "洋红": "G",
40 | "黄色": "B"
41 | };
42 |
43 | //检查是否是被选中的颜色
44 | var checkSelectedColor = function(colorObj){
45 | if(maxColorMap[color]){
46 | return Math.max(colorObj.R, colorObj.G, colorObj.B) == colorObj[maxColorMap[color]];
47 | }else if(minColorMap[color]){
48 | return Math.min(colorObj.R, colorObj.G, colorObj.B) == colorObj[minColorMap[color]];
49 | }else if(color == "black" || color == "黑色"){
50 | return Math.min(colorObj.R, colorObj.G, colorObj.B) < 128;
51 | }else if(color == "white" || color == "白色"){
52 | return Math.max(colorObj.R, colorObj.G, colorObj.B) > 128;
53 | }else if(color == "中性色"){
54 | return ! ((Math.max(colorObj.R, colorObj.G, colorObj.B) < 1) || (Math.min(colorObj.R, colorObj.G, colorObj.B) > 224));
55 | }
56 | };
57 |
58 | var upLimit = 0;
59 | var lowLimit = 0;
60 | var limit = 0;
61 |
62 | var alterNum = [C, M, Y, K];
63 | for(var x = 0, w = imgData.width; x < w; x ++){
64 | for(var y = 0, h = imgData.height; y < h; y ++){
65 | P.lib.dorsyMath.xyCal(imgData, x, y, function(R, G, B){
66 | var colorObj = {
67 | R: R,
68 | G: G,
69 | B: B
70 | };
71 |
72 | var colorArr = [R, G, B];
73 | var resultArr =[];
74 |
75 | if(checkSelectedColor(colorObj)){
76 | if(maxColorMap[color]){
77 | var maxColor = maxColorMap[color];
78 |
79 | var middleValue = R + G + B - Math.max(R, G, B) - Math.min(R, G, B);
80 | limit = colorObj[maxColor] - middleValue;
81 | }else if(minColorMap[color]){
82 | var minColor = minColorMap[color];
83 |
84 | var middleValue = R + G + B - Math.max(R, G, B) - Math.min(R, G, B);
85 | limit = middleValue - colorObj[minColor] ;
86 | }else if(color == "black" || color == "黑色"){
87 | limit = parseInt(127.5 - Math.max(R, G, B)) * 2;
88 | }else if(color == "white" || color == "白色"){
89 | limit = parseInt(Math.min(R, G, B) - 127.5) * 2;
90 | }else if(color == "中性色"){
91 | limit = 255 - (Math.abs(Math.max(R, G, B) - 127.5) + Math.abs(Math.min(R, G, B) - 127.5));
92 | }else{
93 | return;
94 | }
95 |
96 | for(var i = 0; i < 3; i ++){
97 | //可减少到的量
98 | var lowLimitDelta = parseInt(limit * (colorArr[i] / 255));
99 | var lowLimit = colorArr[i] - lowLimitDelta;
100 |
101 | //可增加到的量
102 | var upLimitDelta = parseInt(limit * (1 - colorArr[i] / 255));
103 | var upLimit = colorArr[i] + upLimitDelta;
104 |
105 | //将黑色算进去 得到影响百分比因子
106 | var factor = (alterNum[i] + K + alterNum[i] * K);
107 |
108 | //相对调节
109 | if(isRelative){
110 | //如果分量大于128 减少量=增加量
111 | if(colorArr[i] > 128){
112 | lowLimitDelta = upLimitDelta;
113 | }
114 |
115 | //先算出黑色导致的原始增量
116 | if(K > 0){
117 | var realUpLimit = colorArr[i] - K * lowLimitDelta;
118 | }else{
119 | var realUpLimit = colorArr[i] - K * upLimitDelta;
120 | }
121 |
122 | //标准化
123 | if(realUpLimit > upLimit) realUpLimit = upLimit;
124 | if(realUpLimit < lowLimit) realUpLimit = lowLimit;
125 |
126 | upLimitDelta = upLimit - realUpLimit;
127 | lowLimitDelta = realUpLimit - lowLimit;
128 |
129 | if(K < 0){
130 | lowLimitDelta = upLimitDelta;
131 | }else{
132 | }
133 |
134 | //> 0表明在减少
135 | if(alterNum[i] > 0){
136 | realUpLimit -= alterNum[i] * lowLimitDelta;
137 | }else{
138 | realUpLimit -= alterNum[i] * upLimitDelta;
139 | }
140 |
141 |
142 | }else{
143 |
144 | //现在量
145 | var realUpLimit = limit * - factor + colorArr[i];
146 |
147 | }
148 |
149 | if(realUpLimit > upLimit) realUpLimit = upLimit;
150 | if(realUpLimit < lowLimit) realUpLimit = lowLimit;
151 |
152 | resultArr[i] = realUpLimit;
153 | }
154 |
155 | return resultArr;
156 | }
157 | });//end xyCal
158 | }//end forY
159 | }//end forX
160 |
161 | return imgData;
162 |
163 | }//end process Method
164 | };//end M defination
165 |
166 | return M;
167 | });
168 |
169 | })("psLib");
170 |
--------------------------------------------------------------------------------
/src/other/binaryajax.js:
--------------------------------------------------------------------------------
1 |
2 | var BinaryFile = function(strData, iDataOffset, iDataLength) {
3 | var data = strData;
4 | var dataOffset = iDataOffset || 0;
5 | var dataLength = 0;
6 |
7 | this.getRawData = function() {
8 | return data;
9 | }
10 |
11 | if (typeof strData == "string") {
12 | dataLength = iDataLength || data.length;
13 |
14 | this.getByteAt = function(iOffset) {
15 | return data.charCodeAt(iOffset + dataOffset) & 0xFF;
16 | }
17 |
18 | this.getBytesAt = function(iOffset, iLength) {
19 | var aBytes = [];
20 |
21 | for (var i = 0; i < iLength; i++) {
22 | aBytes[i] = data.charCodeAt((iOffset + i) + dataOffset) & 0xFF
23 | };
24 |
25 | return aBytes;
26 | }
27 | } else if (typeof strData == "unknown") {
28 | dataLength = iDataLength || IEBinary_getLength(data);
29 |
30 | this.getByteAt = function(iOffset) {
31 | return IEBinary_getByteAt(data, iOffset + dataOffset);
32 | }
33 |
34 | this.getBytesAt = function(iOffset, iLength) {
35 | return new VBArray(IEBinary_getBytesAt(data, iOffset + dataOffset, iLength)).toArray();
36 | }
37 | }
38 |
39 | this.getLength = function() {
40 | return dataLength;
41 | }
42 |
43 | this.getSByteAt = function(iOffset) {
44 | var iByte = this.getByteAt(iOffset);
45 | if (iByte > 127)
46 | return iByte - 256;
47 | else
48 | return iByte;
49 | }
50 |
51 | this.getShortAt = function(iOffset, bBigEndian) {
52 | var iShort = bBigEndian ?
53 | (this.getByteAt(iOffset) << 8) + this.getByteAt(iOffset + 1)
54 | : (this.getByteAt(iOffset + 1) << 8) + this.getByteAt(iOffset)
55 | if (iShort < 0) iShort += 65536;
56 | return iShort;
57 | }
58 | this.getSShortAt = function(iOffset, bBigEndian) {
59 | var iUShort = this.getShortAt(iOffset, bBigEndian);
60 | if (iUShort > 32767)
61 | return iUShort - 65536;
62 | else
63 | return iUShort;
64 | }
65 | this.getLongAt = function(iOffset, bBigEndian) {
66 | var iByte1 = this.getByteAt(iOffset),
67 | iByte2 = this.getByteAt(iOffset + 1),
68 | iByte3 = this.getByteAt(iOffset + 2),
69 | iByte4 = this.getByteAt(iOffset + 3);
70 |
71 | var iLong = bBigEndian ?
72 | (((((iByte1 << 8) + iByte2) << 8) + iByte3) << 8) + iByte4
73 | : (((((iByte4 << 8) + iByte3) << 8) + iByte2) << 8) + iByte1;
74 | if (iLong < 0) iLong += 4294967296;
75 | return iLong;
76 | }
77 | this.getSLongAt = function(iOffset, bBigEndian) {
78 | var iULong = this.getLongAt(iOffset, bBigEndian);
79 | if (iULong > 2147483647)
80 | return iULong - 4294967296;
81 | else
82 | return iULong;
83 | }
84 |
85 | this.getStringAt = function(iOffset, iLength) {
86 | var aStr = [];
87 |
88 | var aBytes = this.getBytesAt(iOffset, iLength);
89 | for (var j=0; j < iLength; j++) {
90 | aStr[j] = String.fromCharCode(aBytes[j]);
91 | }
92 | return aStr.join("");
93 | }
94 |
95 | this.getCharAt = function(iOffset) {
96 | return String.fromCharCode(this.getByteAt(iOffset));
97 | }
98 | this.toBase64 = function() {
99 | return window.btoa(data);
100 | }
101 | this.fromBase64 = function(strBase64) {
102 | data = window.atob(strBase64);
103 | }
104 | }
105 |
106 |
107 | var BinaryAjax = (function() {
108 |
109 | function createRequest() {
110 | var oHTTP = null;
111 | if (window.ActiveXObject) {
112 | oHTTP = new ActiveXObject("Microsoft.XMLHTTP");
113 | } else if (window.XMLHttpRequest) {
114 | oHTTP = new XMLHttpRequest();
115 | }
116 | return oHTTP;
117 | }
118 |
119 | function getHead(strURL, fncCallback, fncError) {
120 | var oHTTP = createRequest();
121 | if (oHTTP) {
122 | if (fncCallback) {
123 | if (typeof(oHTTP.onload) != "undefined") {
124 | oHTTP.onload = function() {
125 | if (oHTTP.status == "200") {
126 | fncCallback(this);
127 | } else {
128 | if (fncError) fncError();
129 | }
130 | oHTTP = null;
131 | };
132 | } else {
133 | oHTTP.onreadystatechange = function() {
134 | if (oHTTP.readyState == 4) {
135 | if (oHTTP.status == "200") {
136 | fncCallback(this);
137 | } else {
138 | if (fncError) fncError();
139 | }
140 | oHTTP = null;
141 | }
142 | };
143 | }
144 | }
145 | oHTTP.open("HEAD", strURL, true);
146 | oHTTP.send(null);
147 | } else {
148 | if (fncError) fncError();
149 | }
150 | }
151 |
152 | function sendRequest(strURL, fncCallback, fncError, aRange, bAcceptRanges, iFileSize) {
153 | var oHTTP = createRequest();
154 | if (oHTTP) {
155 |
156 | var iDataOffset = 0;
157 | if (aRange && !bAcceptRanges) {
158 | iDataOffset = aRange[0];
159 | }
160 | var iDataLen = 0;
161 | if (aRange) {
162 | iDataLen = aRange[1]-aRange[0]+1;
163 | }
164 |
165 | if (fncCallback) {
166 | if (typeof(oHTTP.onload) != "undefined") {
167 | oHTTP.onload = function() {
168 | if (oHTTP.status == "200" || oHTTP.status == "206" || oHTTP.status == "0") {
169 | oHTTP.binaryResponse = new BinaryFile(oHTTP.responseText, iDataOffset, iDataLen);
170 | oHTTP.fileSize = iFileSize || oHTTP.getResponseHeader("Content-Length");
171 | fncCallback(oHTTP);
172 | } else {
173 | if (fncError) fncError();
174 | }
175 | oHTTP = null;
176 | };
177 | } else {
178 | oHTTP.onreadystatechange = function() {
179 | if (oHTTP.readyState == 4) {
180 | if (oHTTP.status == "200" || oHTTP.status == "206" || oHTTP.status == "0") {
181 | // IE6 craps if we try to extend the XHR object
182 | var oRes = {
183 | status : oHTTP.status,
184 | // IE needs responseBody, Chrome/Safari needs responseText
185 | binaryResponse : new BinaryFile(
186 | typeof oHTTP.responseBody == "unknown" ? oHTTP.responseBody : oHTTP.responseText, iDataOffset, iDataLen
187 | ),
188 | fileSize : iFileSize || oHTTP.getResponseHeader("Content-Length")
189 | };
190 | fncCallback(oRes);
191 | } else {
192 | if (fncError) fncError();
193 | }
194 | oHTTP = null;
195 | }
196 | };
197 | }
198 | }
199 | oHTTP.open("GET", strURL, true);
200 |
201 | if (oHTTP.overrideMimeType) oHTTP.overrideMimeType('text/plain; charset=x-user-defined');
202 |
203 | if (aRange && bAcceptRanges) {
204 | oHTTP.setRequestHeader("Range", "bytes=" + aRange[0] + "-" + aRange[1]);
205 | }
206 |
207 | oHTTP.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 1970 00:00:00 GMT");
208 |
209 | oHTTP.send(null);
210 | } else {
211 | if (fncError) fncError();
212 | }
213 | }
214 |
215 | return function(strURL, fncCallback, fncError, aRange) {
216 |
217 | if (aRange) {
218 | getHead(
219 | strURL,
220 | function(oHTTP) {
221 | var iLength = parseInt(oHTTP.getResponseHeader("Content-Length"),10);
222 | var strAcceptRanges = oHTTP.getResponseHeader("Accept-Ranges");
223 |
224 | var iStart, iEnd;
225 | iStart = aRange[0];
226 | if (aRange[0] < 0)
227 | iStart += iLength;
228 | iEnd = iStart + aRange[1] - 1;
229 |
230 | sendRequest(strURL, fncCallback, fncError, [iStart, iEnd], (strAcceptRanges == "bytes"), iLength);
231 | }
232 | );
233 |
234 | } else {
235 | sendRequest(strURL, fncCallback, fncError);
236 | }
237 | }
238 |
239 | }());
240 |
241 | /*
242 | document.write(
243 | "\r\n"
251 | );
252 | */
253 |
254 | document.write(
255 | "\r\n"
271 | );
--------------------------------------------------------------------------------
/nsrc/alloyimage.layer.js:
--------------------------------------------------------------------------------
1 | AIDefine('layer', [], function(){
2 | var Add = {
3 |
4 | //isFast用于快速,适用于中间处理
5 | add: function(lowerData, upperData, method, alpha, dx, dy, isFast, channel){
6 | var l = lowerData.data,
7 | u = upperData.data,
8 |
9 | dx = dx || 0,
10 | dy = dy || 0,
11 | alpha = alpha || 1,//alpha 范围为0 - 100
12 | isFast = isFast || false,
13 | channel = channel || "RGB";
14 |
15 | if(!(/[RGB]+/.test(channel))){
16 | channel = "RGB";
17 | }
18 |
19 | var channelString = channel.replace("R","0").replace("G","1").replace("B","2"),
20 | jump = 1,
21 | result,
22 | width = lowerData.width,
23 | height = lowerData.height,
24 | upperLength = u.length,
25 | upperWidth = upperData.width,
26 | upperHeight = upperData.height,
27 |
28 | indexOfArr = [
29 | channelString.indexOf("0") > -1,
30 | channelString.indexOf("1") > -1,
31 | channelString.indexOf("2") > -1
32 | ],
33 | everyJump = 4 * jump;
34 |
35 | /*
36 | if(isFast){
37 | jump = 1;
38 | }
39 | */
40 |
41 | var ii, row, col, uRow, uCol, uIi, uI;
42 |
43 | //计算重叠部分x ,y范围
44 | var xMin, yMin, xMax, yMax;
45 |
46 | var uXMin = dx;
47 | var uXMax = dx + upperWidth;
48 | var uYMin = dy;
49 | var uYMax = dy + upperHeight;
50 |
51 | if(uXMin > width){
52 | return;
53 | }else if(uXMin < 0){
54 | uXMin = 0;
55 | }
56 |
57 | if(uXMax < 0){
58 | return;
59 | }else if(uXMax > width){
60 | uXMax = width;
61 | }
62 |
63 | if(uYMin > height){
64 | return;
65 | }else if(uYMin < 0){
66 | uYMin = 0;
67 | }
68 |
69 | if(uYMax < 0){
70 | return;
71 | }else if(uYMax > height){
72 | uYMax = height;
73 | }
74 |
75 |
76 | var currRow, upperY, upperRow;
77 | for(var y = uYMin; y < uYMax; y ++){
78 | currRow = y * width;
79 | upperY = y - dy;
80 | upperRow = upperY * upperWidth;
81 |
82 | for(var x = uXMin; x < uXMax; x ++){
83 | //计算此时对应的upperX,Y
84 | var upperX = x - dx;
85 |
86 | //计算此时的i
87 | var i = (currRow + x) * 4;
88 |
89 | //计算此时的upperI
90 | var uI = (upperRow + upperX) * 4;
91 |
92 | //for(var i = 0, n = l.length; i < n; i += everyJump){
93 |
94 | //ii = i / 4;
95 |
96 | //得到当前点的坐标 y分量
97 | //row = ~~(ii / width);
98 | //col = ii % width;
99 |
100 | //uRow = row - dy;
101 | //uCol = col - dx;
102 |
103 | //uIi = uRow * upperWidth + uCol;
104 | //uI = uIi * 4;
105 |
106 | //if(uI >= 0 && uI < (upperLength - 4) && uCol < upperWidth && uCol >= 0){
107 |
108 | //l[i + 3] = u[uI + 3];//透明度
109 | for(var j = 0; j < 3; j ++){
110 |
111 | //若此点透明则不计算
112 | if(u[uI + 3] == 0) break;
113 | else l[i + 3] = u[uI + 3];
114 |
115 | switch(method){
116 | case "颜色减淡" :
117 | if(indexOfArr[j]){
118 | result = l[i + j] + (l[i + j] * u[uI + j]) / (255 - u[uI + j]);
119 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
120 | }
121 | break;
122 |
123 | case "变暗":
124 | if(indexOfArr[j]){
125 | result = l[i + j] < u[uI + j] ? l[i + j] : u[uI + j];
126 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
127 | }
128 | break;
129 |
130 | case "变亮":
131 | if(indexOfArr[j]){
132 | result = l[i + j] > u[uI + j] ? l[i + j] : u[uI + j];
133 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
134 | }
135 | break;
136 |
137 | case "正片叠底":
138 | if(indexOfArr[j]){
139 | result = ~~((l[i + j] * u[uI + j]) / 255);
140 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
141 | }
142 | break;
143 |
144 | case "滤色" :
145 | if(indexOfArr[j]){
146 | result = ~~(255 - (255 - l[i + j]) * (255 - u[uI + j]) / 255);
147 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
148 | }
149 | break;
150 |
151 | case "叠加":
152 | if(indexOfArr[j]){
153 | if(l[i + j] <= 127.5){
154 | result = l[i + j] * u[uI + j] / 127.5;
155 | }else{
156 | result = 255 - (255 - l[i + j]) * (255 - u[uI + j]) / 127.5;
157 | }
158 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
159 | }
160 | break;
161 |
162 | case "强光":
163 | if(indexOfArr[j]){
164 | if(u[uI + j] <= 127.5){
165 | result = l[i + j] * u[uI + j] / 127.5;
166 | }else{
167 | result = l[i + j] + (255 - l[i + j]) * (u[uI + j] - 127.5) / 127.5;
168 | }
169 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
170 | }
171 | break;
172 |
173 | case "差值":
174 | if(indexOfArr[j]){
175 | result = l[i + j] > u[uI + j] ? l[i + j] - u[uI + j] : u[uI + j] - l[i + j];
176 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
177 | }
178 | break;
179 |
180 | case "排除":
181 | if(indexOfArr[j]){
182 | result = l[i + j] + u[uI + j] - (l[i + j] * u[uI + j]) / 127.5;
183 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
184 | }
185 | break;
186 |
187 | case "点光":
188 | if(indexOfArr[j]){
189 | if(l[i + j] < (2 * u[uI + j] - 255)){
190 | result = 2 * u[uI + j] - 255;
191 | }else if(l[i + j] < 2 * u[uI + j]){
192 | result = l[i + j];
193 | }else{
194 | result = 2 * u[uI + j];
195 | }
196 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
197 | }
198 | break;
199 |
200 | case "颜色加深":
201 | if(indexOfArr[j]){
202 | result = 255 - 255 * (255 - l[i + j]) / u[uI + j];
203 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
204 | }
205 | break;
206 |
207 | case "线性加深":
208 | if(indexOfArr[j]){
209 | var tempR = l[i + j] + u[uI + j];
210 | result = tempR > 255 ? tempR - 255 : 0;
211 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
212 | }
213 | break;
214 |
215 | case "线性减淡":
216 | if(indexOfArr[j]){
217 | var tempR = l[i + j] + u[uI + j];
218 | result = tempR > 255 ? 255 : tempR;
219 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
220 | }
221 | break;
222 |
223 | case "柔光":
224 | if(indexOfArr[j]){
225 | if(u[uI + j] < 127.5){
226 | result = ((2 * u[uI + j] - 255) * (255 - l[i + j]) / (255 * 255) + 1) * l[i + j];
227 | }else{
228 | result = (2 * u[uI + j] - 255) * (Math.sqrt(l[i + j] / 255) - l[i + j] / 255) + l[i + j];
229 | }
230 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
231 | }
232 | break;
233 |
234 | case "亮光":
235 | if(indexOfArr[j]){
236 | if(u[uI + j] < 127.5){
237 | result = (1 - (255 - l[i + j]) / (2 * u[uI + j])) * 255;
238 | }else{
239 | result = l[i + j] / (2 * (1 - u[uI + j] / 255));
240 | }
241 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
242 | }
243 | break;
244 |
245 | case "线性光":
246 | if(indexOfArr[j]){
247 | var tempR = l[i + j] + 2 * u[uI + j] - 255;
248 | result = tempR > 255 ? 255 : tempR;
249 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
250 | }
251 | break;
252 |
253 | case "实色混合":
254 | if(indexOfArr[j]){
255 | if(u[uI + j] < (255 - l[i + j])){
256 | result = 0;
257 | }else{
258 | result = 255;
259 | }
260 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
261 | }
262 | break;
263 |
264 | default:
265 | if(indexOfArr[j]){
266 | result = u[uI + j];
267 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
268 | }
269 | }//end switch
270 | }//end for
271 | }//end y
272 |
273 | }//end x
274 |
275 | return lowerData;
276 | }
277 | };
278 |
279 | return Add;
280 | });
281 |
--------------------------------------------------------------------------------
/src/module/addLayer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description: Main add
4 | *
5 | */
6 | ;(function(Ps){
7 |
8 | window[Ps].module("addLayer",function(P){
9 |
10 | var Add = {
11 |
12 | //isFast用于快速,适用于中间处理
13 | add: function(lowerData, upperData, method, alpha, dx, dy, isFast, channel){
14 | var l = lowerData.data,
15 | u = upperData.data,
16 |
17 | dx = dx || 0,
18 | dy = dy || 0,
19 | alpha = alpha || 1,//alpha 范围为0 - 100
20 | isFast = isFast || false,
21 | channel = channel || "RGB";
22 |
23 | if(!(/[RGB]+/.test(channel))){
24 | channel = "RGB";
25 | }
26 |
27 | var channelString = channel.replace("R","0").replace("G","1").replace("B","2"),
28 | jump = 1,
29 | result,
30 | width = lowerData.width,
31 | height = lowerData.height,
32 | upperLength = u.length,
33 | upperWidth = upperData.width,
34 | upperHeight = upperData.height,
35 |
36 | indexOfArr = [
37 | channelString.indexOf("0") > -1,
38 | channelString.indexOf("1") > -1,
39 | channelString.indexOf("2") > -1
40 | ],
41 | everyJump = 4 * jump;
42 |
43 | /*
44 | if(isFast){
45 | jump = 1;
46 | }
47 | */
48 |
49 | var ii, row, col, uRow, uCol, uIi, uI;
50 |
51 | //计算重叠部分x ,y范围
52 | var xMin, yMin, xMax, yMax;
53 |
54 | var uXMin = dx;
55 | var uXMax = dx + upperWidth;
56 | var uYMin = dy;
57 | var uYMax = dy + upperHeight;
58 |
59 | if(uXMin > width){
60 | return;
61 | }else if(uXMin < 0){
62 | uXMin = 0;
63 | }
64 |
65 | if(uXMax < 0){
66 | return;
67 | }else if(uXMax > width){
68 | uXMax = width;
69 | }
70 |
71 | if(uYMin > height){
72 | return;
73 | }else if(uYMin < 0){
74 | uYMin = 0;
75 | }
76 |
77 | if(uYMax < 0){
78 | return;
79 | }else if(uYMax > height){
80 | uYMax = height;
81 | }
82 |
83 |
84 | var currRow, upperY, upperRow;
85 | for(var y = uYMin; y < uYMax; y ++){
86 | currRow = y * width;
87 | upperY = y - dy;
88 | upperRow = upperY * upperWidth;
89 |
90 | for(var x = uXMin; x < uXMax; x ++){
91 | //计算此时对应的upperX,Y
92 | var upperX = x - dx;
93 |
94 | //计算此时的i
95 | var i = (currRow + x) * 4;
96 |
97 | //计算此时的upperI
98 | var uI = (upperRow + upperX) * 4;
99 |
100 | //for(var i = 0, n = l.length; i < n; i += everyJump){
101 |
102 | //ii = i / 4;
103 |
104 | //得到当前点的坐标 y分量
105 | //row = ~~(ii / width);
106 | //col = ii % width;
107 |
108 | //uRow = row - dy;
109 | //uCol = col - dx;
110 |
111 | //uIi = uRow * upperWidth + uCol;
112 | //uI = uIi * 4;
113 |
114 | //if(uI >= 0 && uI < (upperLength - 4) && uCol < upperWidth && uCol >= 0){
115 |
116 | //l[i + 3] = u[uI + 3];//透明度
117 | for(var j = 0; j < 3; j ++){
118 |
119 | //若此点透明则不计算
120 | if(u[uI + 3] == 0) break;
121 | else l[i + 3] = u[uI + 3];
122 |
123 | switch(method){
124 | case "颜色减淡" :
125 | if(indexOfArr[j]){
126 | result = l[i + j] + (l[i + j] * u[uI + j]) / (255 - u[uI + j]);
127 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
128 | }
129 | break;
130 |
131 | case "变暗":
132 | if(indexOfArr[j]){
133 | result = l[i + j] < u[uI + j] ? l[i + j] : u[uI + j];
134 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
135 | }
136 | break;
137 |
138 | case "变亮":
139 | if(indexOfArr[j]){
140 | result = l[i + j] > u[uI + j] ? l[i + j] : u[uI + j];
141 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
142 | }
143 | break;
144 |
145 | case "正片叠底":
146 | if(indexOfArr[j]){
147 | result = ~~((l[i + j] * u[uI + j]) / 255);
148 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
149 | }
150 | break;
151 |
152 | case "滤色" :
153 | if(indexOfArr[j]){
154 | result = ~~(255 - (255 - l[i + j]) * (255 - u[uI + j]) / 255);
155 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
156 | }
157 | break;
158 |
159 | case "叠加":
160 | if(indexOfArr[j]){
161 | if(l[i + j] <= 127.5){
162 | result = l[i + j] * u[uI + j] / 127.5;
163 | }else{
164 | result = 255 - (255 - l[i + j]) * (255 - u[uI + j]) / 127.5;
165 | }
166 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
167 | }
168 | break;
169 |
170 | case "强光":
171 | if(indexOfArr[j]){
172 | if(u[uI + j] <= 127.5){
173 | result = l[i + j] * u[uI + j] / 127.5;
174 | }else{
175 | result = l[i + j] + (255 - l[i + j]) * (u[uI + j] - 127.5) / 127.5;
176 | }
177 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
178 | }
179 | break;
180 |
181 | case "差值":
182 | if(indexOfArr[j]){
183 | result = l[i + j] > u[uI + j] ? l[i + j] - u[uI + j] : u[uI + j] - l[i + j];
184 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
185 | }
186 | break;
187 |
188 | case "排除":
189 | if(indexOfArr[j]){
190 | result = l[i + j] + u[uI + j] - (l[i + j] * u[uI + j]) / 127.5;
191 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
192 | }
193 | break;
194 |
195 | case "点光":
196 | if(indexOfArr[j]){
197 | if(l[i + j] < (2 * u[uI + j] - 255)){
198 | result = 2 * u[uI + j] - 255;
199 | }else if(l[i + j] < 2 * u[uI + j]){
200 | result = l[i + j];
201 | }else{
202 | result = 2 * u[uI + j];
203 | }
204 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
205 | }
206 | break;
207 |
208 | case "颜色加深":
209 | if(indexOfArr[j]){
210 | result = 255 - 255 * (255 - l[i + j]) / u[uI + j];
211 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
212 | }
213 | break;
214 |
215 | case "线性加深":
216 | if(indexOfArr[j]){
217 | var tempR = l[i + j] + u[uI + j];
218 | result = tempR > 255 ? tempR - 255 : 0;
219 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
220 | }
221 | break;
222 |
223 | case "线性减淡":
224 | if(indexOfArr[j]){
225 | var tempR = l[i + j] + u[uI + j];
226 | result = tempR > 255 ? 255 : tempR;
227 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
228 | }
229 | break;
230 |
231 | case "柔光":
232 | if(indexOfArr[j]){
233 | if(u[uI + j] < 127.5){
234 | result = ((2 * u[uI + j] - 255) * (255 - l[i + j]) / (255 * 255) + 1) * l[i + j];
235 | }else{
236 | result = (2 * u[uI + j] - 255) * (Math.sqrt(l[i + j] / 255) - l[i + j] / 255) + l[i + j];
237 | }
238 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
239 | }
240 | break;
241 |
242 | case "亮光":
243 | if(indexOfArr[j]){
244 | if(u[uI + j] < 127.5){
245 | result = (1 - (255 - l[i + j]) / (2 * u[uI + j])) * 255;
246 | }else{
247 | result = l[i + j] / (2 * (1 - u[uI + j] / 255));
248 | }
249 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
250 | }
251 | break;
252 |
253 | case "线性光":
254 | if(indexOfArr[j]){
255 | var tempR = l[i + j] + 2 * u[uI + j] - 255;
256 | result = tempR > 255 ? 255 : tempR;
257 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
258 | }
259 | break;
260 |
261 | case "实色混合":
262 | if(indexOfArr[j]){
263 | if(u[uI + j] < (255 - l[i + j])){
264 | result = 0;
265 | }else{
266 | result = 255;
267 | }
268 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
269 | }
270 | break;
271 |
272 | default:
273 | if(indexOfArr[j]){
274 | result = u[uI + j];
275 | l[i + j] = (1 - alpha) * l[i + j] + (alpha) * result;
276 | }
277 | }//end switch
278 | }//end for
279 | }//end y
280 |
281 | }//end x
282 |
283 | return lowerData;
284 | }
285 | };
286 |
287 | return Add;
288 |
289 | });
290 |
291 | })("psLib");
292 |
--------------------------------------------------------------------------------
/src/module/dorsyMath.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author: Bin Wang
3 | * @description:数学处理模块-core
4 | * FFT 矩阵 复数 Langrange插值
5 | *
6 | */
7 | ;(function(Ps){
8 |
9 | window[Ps].module("dorsyMath", function(P){
10 |
11 | var M = {
12 | FFT1: function(dataArr){
13 | /*
14 | * @description:快速傅里叶变换
15 | * @按时间抽取
16 | * */
17 | var size = dataArr.length;
18 | var count = 0;
19 |
20 | //------计算权重W------------
21 | var W = [];
22 | for(var i = 0; i < size; i ++){
23 | W[i] = this.exp(-2 * Math.PI * i / size);
24 | }
25 |
26 |
27 | butterflyCal();
28 | return dataArr;
29 |
30 | //蝶形运算单元
31 | function butterflyCal(){
32 | count ++;
33 |
34 | //蝶形单元个数
35 | var singleLength = size / Math.pow(2,count);
36 | var everyLength = size / singleLength;
37 |
38 | for(var i = 0; i < singleLength; i ++){
39 |
40 | //逐次计算蝶形单元
41 | singleButterflyCal(i * everyLength, (i + 1) * everyLength - 1, count);
42 | }
43 |
44 | //如果单元个数大于1继续运算
45 | if(singleLength > 1){
46 |
47 | //递归
48 | butterflyCal();
49 | }else{
50 | }
51 |
52 | }
53 |
54 | //一个蝶形单元 n运算次数 蝶形单元的成对间隔
55 | function singleButterflyCal(start, end, n){
56 |
57 | var delta = Math.pow(2,n - 1);
58 |
59 | for(var i = start, j = 0; i <= (end - delta); i ++){
60 |
61 | //i 的运算对
62 | var pairI = i + delta;
63 |
64 | //计算i运算时的权重下标
65 | var currWeightForI = j * size / Math.pow(2,n);
66 |
67 | //计算i的运算对时候的权重
68 | var currWeightForPairI = currWeightForI + size / 4;
69 |
70 | if(!(dataArr[i] instanceof M.C)) dataArr[i] = new M.C(dataArr[i]);
71 |
72 | if(!(dataArr[pairI] instanceof M.C)) dataArr[pairI] = new M.C(dataArr[pairI]);
73 |
74 | var currResultForI = dataArr[i].plus(dataArr[pairI].mutiply(W[currWeightForI]));
75 | var currResultForPairI = dataArr[i].plus(dataArr[pairI].mutiply(W[currWeightForPairI]));
76 |
77 | dataArr[i] = currResultForI;
78 | dataArr[pairI] = currResultForPairI;
79 |
80 | j++;
81 | }
82 | }
83 |
84 | },
85 |
86 | DFT: function(){
87 | /*
88 | * @description:离散傅里叶变换
89 | * */
90 |
91 | },
92 |
93 | Matrix: function(arr,arg,arg2){
94 | /*
95 | * @descriptiont:矩阵类
96 | * 构造一个矩阵,当然从原始的数据构造,但具有矩阵的所有基本运算方法
97 | * arr参数可以为矩阵,附加字符串参数为构造的行列如 ([0,0],"3*4") 或("构造3*4的1矩阵") ("构造3*4的0矩阵")
98 | * */
99 | var resultArr = [];
100 |
101 | if(arg){
102 |
103 | if(isNaN(arg)){
104 | var m = /(\d+)\s*\*/.exec(arg)[1];
105 | var n = /\*\s*(\d+)/.exec(arg)[1];
106 | }else{
107 | m = arg;
108 | n = arg2;
109 | }
110 |
111 | //本身二维的
112 | if(arr[0] && arr[0][0]){
113 | for(var i = 0;i < m;i ++){
114 | resultArr[i] = [];
115 | for(var j = 0;j < n;j ++){
116 | resultArr[i][j] = arr[i][j] || 0;
117 | }
118 | }
119 |
120 | //一维的
121 | }else{
122 |
123 | for(var i = 0;i < m;i ++){
124 | resultArr[i] = [];
125 | for(var j = 0;j < n;j ++){
126 | var t = i * n + j;
127 | resultArr[i][j] = arr[i * n + j] || 0;
128 | }
129 | }
130 |
131 | }
132 |
133 | this.m = m;
134 | this.n = n;
135 |
136 | }else{
137 | this.m = arr.length;
138 | this.n = arr[0].length;
139 | }
140 |
141 | this.data = resultArr;
142 | },
143 |
144 | C: function(r,i){
145 | /*
146 | * @description:复数对象
147 | *
148 | * */
149 | this.r = r || 0;//实部
150 | this.i = i || 0;//虚部
151 | },
152 |
153 | exp: function(theta,r){// r e^(i * theta) = r cos theta + r i * sin theta
154 |
155 | theta = theta || 0;
156 | r = r || 1;
157 |
158 | var tempC = new M.C();
159 | tempC.r = r * Math.cos(theta);
160 | tempC.i = r * Math.sin(theta);
161 |
162 | return tempC;
163 | },
164 |
165 | lagrange: function(xArr,yArr){
166 | /*
167 | * Lagrange插值
168 | * @usage M.lagrange([1,2],[2,4])(3);
169 | * */
170 | var num = xArr.length;
171 | function getLk(x,k){//计算lk
172 | var omigaXk = 1;
173 | var omigaX = 1;
174 | for(var i = 0;i < num;i ++){
175 | if(i != k){
176 | omigaXk *= xArr[k] - xArr[i];
177 | omigaX *= x - xArr[i];
178 | }
179 | }
180 | var lk = omigaX / omigaXk;
181 | return lk;
182 | }
183 | var getY = function(x){
184 | var L = 0;
185 | for(var k = 0;k < num;k ++){
186 | var lk = getLk(x,k);
187 | L += yArr[k] * lk;
188 |
189 | }
190 | return L;
191 | };
192 | return getY;
193 |
194 | },
195 |
196 | applyMatrix: function(imgData,matrixArr,low){//对图象信号实行掩模算子变换 low为阈值,滤波运算
197 |
198 | low = low || 0;
199 | var data = imgData.data;
200 | var width = imgData.width;
201 | var height = imgData.height;
202 | var matrixSize = matrixArr.length;
203 | var template = new M.Matrix(matrixArr,matrixSize,1);
204 | var tempData = [];
205 | var start = -(Math.sqrt(matrixSize) - 1) / 2;
206 |
207 | for(var i = 0,n = data.length;i < n;i += 4){
208 | var ii = i / 4;
209 | var row = parseInt(ii / width);
210 | var col = ii % width;
211 | if(row == 0 || col == 0) continue;
212 |
213 | var pixelArr = [[],[],[]];
214 | for(var k = start;k <= -start;k ++){
215 | var currRow = row + k;
216 |
217 | for(var kk = start;kk <= -start;kk ++){
218 |
219 | var currCol = col + kk;
220 | var currI = (currRow * width + currCol) * 4;
221 |
222 | for(var j = 0;j < 3;j ++){
223 | var tempI = currI + j;
224 | pixelArr[j].push(data[tempI]);
225 | }
226 |
227 | }
228 |
229 | }
230 |
231 | var pixelMatrix = new P.lib.dorsyMath.Matrix(pixelArr,3,matrixSize);
232 | var resultMatrix = pixelMatrix.mutiply(template);
233 |
234 | for(var j = 0;j < 3;j ++){
235 | tempData[i + j] = resultMatrix.data[j];
236 | }
237 | tempData[i + 4] = data[i + 4];
238 | }
239 |
240 | for(var i = 0,n = data.length;i < n;i ++){
241 | if(tempData[i]){
242 | data[i] = tempData[i] < low ? tempData[i] : data[i];
243 | }
244 | }
245 |
246 | return imgData;
247 | },
248 |
249 | RGBToHSI: function(R,G,B){
250 | var theta = ((R - G + R - B) / 2) / Math.sqrt((R - G) * (R - G) + (R - B) * (G - B)) || 0;
251 | theta = Math.acos(theta);
252 | var H = B > G ? (2 * Math.PI - theta) : theta;
253 |
254 | if(R + G + B > 0){
255 | var S = 1 - 3 * Math.min(R,G,B) / (R + G + B);
256 | }else{
257 | var S = 0;
258 | }
259 |
260 | var I = (R + G + B) / 3;
261 |
262 | if(H > 2 * Math.PI) H = 2 * Math.PI;
263 | if(H < 0) H = 0;
264 |
265 | return {
266 | H: H,
267 | S: S,
268 | I: I
269 | };
270 |
271 | },
272 |
273 | HSIToRGB: function(H,S,I){//H为弧度值
274 | //H (-Math.PI , Math.PI) S (-1,1) I (-255,255)
275 | if(H < 0){
276 | H %= 2 * Math.PI;
277 | H += 2 * Math.PI
278 | }else{
279 | H %= 2 * Math.PI;
280 | }
281 |
282 | if(H <= Math.PI * 2 / 3){
283 | var B = I * (1 - S);
284 | var R = I * (1 + S * Math.cos(H) / Math.cos(Math.PI / 3 - H));
285 | var G = 3 * I - (R + B);
286 |
287 | }else if(H <= Math.PI * 4 / 3){
288 | H = H - Math.PI * 2 / 3;
289 |
290 | var R = I * (1 - S);
291 | var G = I * (1 + S * Math.cos(H) / Math.cos(Math.PI / 3 - H));
292 | var B = 3 * I - (G + R);
293 |
294 | }else{
295 | H = H - Math.PI * 4 / 3;
296 |
297 | var G = I * (1 - S);
298 | var B = I * (1 + S * Math.cos(H) / Math.cos(Math.PI / 3 - H));
299 | var R = 3 * I - (G + B);
300 |
301 | }
302 |
303 | return {
304 | R: R,
305 | G: G,
306 | B: B
307 | };
308 | },
309 |
310 | applyInHSI: function(imgData, func){//在hsi空间上应用func
311 | /*
312 | * function(i){
313 | * i.H += 3;
314 | * }
315 | * H (-2*Math.PI , 2 * Math.PI) S (-1,1) I (-255,255)
316 | * */
317 | var colorMap = ["R", "Y", "G", "C", "B", "M"];
318 | var data = imgData.data;
319 |
320 | var d30 = Math.PI / 6;
321 | var d60 = Math.PI / 3;
322 | for(var i = 0, n = data.length; i < n; i += 4){
323 | var hsiObj = this.RGBToHSI(data[i], data[i + 1], data[i + 2]);
324 |
325 | //得到颜色属性
326 | var h = hsiObj.H + d30;
327 | var color = ~~ (h / d60);
328 | var rColor = colorMap[color % 6];
329 |
330 | func(hsiObj, rColor, data[i + 3]);
331 |
332 | if(hsiObj.S > 1) hsiObj.S = 1;
333 | if(hsiObj.S < 0) hsiObj.S = 0;
334 |
335 | var rgbObj = this.HSIToRGB(hsiObj.H,hsiObj.S,hsiObj.I);
336 | data[i] = rgbObj.R;
337 | data[i + 1] = rgbObj.G;
338 | data[i + 2] = rgbObj.B;
339 | }
340 |
341 | },
342 |
343 | applyInCoordinate: function(imgData,func){//在坐标空间上应用func
344 | /*
345 | * function(dot){
346 | *
347 | * }
348 | * */
349 | },
350 |
351 | //计算两个点之间的距离
352 | //p1 array
353 | //p2 array
354 | distance: function(p1, p2){
355 | p2 = p2 || [0, 0];
356 |
357 | p1 = new M.C(p1[0], p1[1]);
358 | p2 = new M.C(p2[0], p2[1]);
359 |
360 | var p3 = p1.minus(p2);
361 | return p3.distance();
362 | },
363 |
364 | //将(x,y)的坐标转为单维的i
365 | xyToIFun: function(width){
366 | return function(x, y, z){
367 | z = z || 0;
368 | return (y * width + x) * 4 + z;
369 | };
370 | },
371 |
372 | //在(x,y)进行运算
373 | //rgbfun 在rgb三个上进行的操作 aFun在alpha进行的操作
374 | //rgbFun: function(r, g, b){
375 | // return [r, g, b]
376 | //
377 | //}
378 | xyCal: function(imgData, x, y, rgbFun, aFun){
379 | var xyToIFun = this.xyToIFun(imgData.width);
380 | var j = xyToIFun(x, y, 0);
381 | var data = imgData.data;
382 | var processedData = rgbFun(data[j], data[j + 1], data[j + 2]);
383 |
384 | if(processedData){
385 | data[j] = processedData[0];
386 | data[j + 1] = processedData[1];
387 | data[j + 2] = processedData[2];
388 | }
389 |
390 | if(aFun){
391 | data[j + 3] = aFun(data[j + 3]);
392 | }
393 |
394 | }
395 |
396 | };
397 |
398 | /*
399 | var t = M.RGBToHSI(255,5,25);
400 | var f = M.HSIToRGB(t.H+2 * Math.PI,t.S,t.I);
401 | alert(f.R + "|" + f.G + "|" + f.B);
402 | */
403 |
404 | M.Matrix.prototype = {
405 | /*m: 0,//数学上传统的m*n矩阵
406 | n: 0,
407 | */
408 | plus: function(matrix){
409 | if(this.m != matrix.m || this.n != matrix.n){
410 | throw new Error("矩阵加法行列不匹配");
411 | }
412 |
413 |
414 | var tempM = new M.Matrix([],this.m,this.n);
415 | for(var i = 0;i < this.m;i ++){
416 | for(var j = 0;j < this.n;j ++){
417 | tempM.data[i][j] = this.data[i][j] + matrix.data[i][j];
418 | }
419 | }
420 | return tempM;
421 | },
422 |
423 | minus: function(matrix){
424 | if(this.m != matrix.m || this.n != matrix.n){
425 | throw new Error("矩阵减法法行列不匹配");
426 | }
427 |
428 |
429 | var tempM = new M.Matrix([],this.m,this.n);
430 | for(var i = 0;i < this.m;i ++){
431 | for(var j = 0;j < this.n;j ++){
432 | tempM.data[i][j] = this.data[i][j] - matrix.data[i][j];
433 | }
434 | }
435 | return tempM;
436 | },
437 |
438 | mutiply: function(matrix){//左乘另一矩阵
439 | if(this.n != matrix.m){
440 | throw new Error("矩阵乘法行列不匹配");
441 | }
442 |
443 |
444 | var tempM = new M.Matrix([],this.m,matrix.n);
445 | for(var i = 0;i < this.m;i ++){
446 | for(var j = 0;j < matrix.n;j ++){
447 |
448 | var sum = 0;
449 | for(var ii = 0;ii < this.n;ii ++){
450 | sum += this.data[i][ii] * matrix.data[ii][j];
451 | }
452 | tempM.data[i][j] = sum;
453 | }
454 | }
455 | return tempM;
456 |
457 | }
458 | };
459 |
460 | M.C.prototype = {
461 | plus: function(c){
462 | var tempC = new M.C();
463 | tempC.r = this.r + c.r;
464 | tempC.i = this.i + c.i;
465 |
466 | return tempC;
467 | },
468 | minus:function(c){
469 | var tempC = new M.C();
470 | tempC.r = this.r - c.r;
471 | tempC.i = this.i - c.i;
472 |
473 | return tempC;
474 | },
475 | mutiply: function(c){
476 | var tempC = new M.C();
477 | tempC.r = this.r * c.r - this.i * c.i;
478 | tempC.i = this.r * c.i + this.i * c.r;
479 |
480 | return tempC;
481 | },
482 | divide: function(c){
483 |
484 | var tempC = new M.C();
485 |
486 | var m = c.mutiply(c.conjugated());
487 | var f = this.mutiply(c.conjugated());
488 | tempC.r = f.r / m.r;
489 | tempC.i = f.i / m.r;
490 |
491 | return tempC;
492 | },
493 | conjugated: function(){//取共轭
494 | var tempC = new M.C(this.r,-this.i);
495 | return tempC;
496 | },
497 |
498 | //取模
499 | distance: function(){
500 | return Math.sqrt(this.r * this.r + this.i * this.i);
501 | }
502 | }
503 | /*
504 | var l = new M.Matrix([1,1,2,3],2,2);
505 | var j = new M.Matrix([1,0,1,2],2,2);
506 | var t = l.mutiply(j);
507 | */
508 | return M;
509 |
510 | });
511 |
512 | })("psLib");
513 |
--------------------------------------------------------------------------------
/release/alloyimage-1.1.js:
--------------------------------------------------------------------------------
1 | Array.prototype.del=function(h){h.sort();for(var p=this.concat([]),c=h.length-1;0<=c;c--)p=p.slice(0,h[c]).concat(p.slice(h[c]+1));return p};try{HTMLImageElement.prototype.loadOnce=function(h){var p=0;this.onload=function(){p||h.call(this,null);p++}}}catch(e$$10){window={}}
2 | (function(h){function p(){this.readyState&&(this.readyState=0,this.dorsyWorker.startWorker())}var c={lib:[],init:function(){this.require("config")},module:function(a,b){this.lib[a]=b.call(null,this)},require:function(a){var b=this,f=document.createElement("script");document.body.appendChild(f);f.src="./js/module/"+a+".js";f.onload=f.onerror=function(a){b.handlerror(a)}},handlerror:function(){},destroySelf:function(a){delete window[h];throw Error(a);},reflect:function(a,b,f){a=this.lib.config.getModuleName(a);
3 | return this.lib[a].process(b,f)},reflectEasy:function(a){a=this.lib.config.getEasyFun(a);return this.lib.easy.getFun(a)},add:function(a,b,f,i,d,g,c,m){return this.lib.addLayer.add(a,b,f,i,d,g,c,m)},worker:function(){},applyMatrix:function(){}};window[h]=function(a,b,f){if(this instanceof window[h]){this.startTime=+new Date;var i=document.createElement("canvas"),d=i.getContext("2d");isNaN(a)?(i.width=parseInt(a.width),i.height=parseInt(a.height),b=getComputedStyle(a),imgWidth=parseInt(b.getPropertyValue("width")),
4 | imgHeight=parseInt(b.getPropertyValue("height")),isNaN(imgWidth)?d.drawImage(a,0,0):d.drawImage(a,0,0,imgWidth,imgHeight)):(i.width=a,i.height=b,d.fillStyle=f||"#fff",d.fillRect(0,0,a,b));this.canvas=i;this.context=d;this.imgData=d.getImageData(0,0,i.width,i.height);this.name=h+"_"+Math.random();this.canvas.id=this.name;this.layers=[];a=document.createElement("canvas");a.width=i.width;a.height=i.height;this.ctxCanvas=a;this.ctxContext=i.getContext("2d");this.useWorker=c.useWorker;this.readyState=
5 | 1;this.useWorker&&(this.dorsyWorker=c.lib.dorsyWorker(this))}else return new window[h](a,b,f)};window[h].module=function(a,b){c.module(a,b)};window[h].dorsyMath=function(){return c.lib.dorsyMath};window[h].setName=function(a){c.name=a||"alloyimage.js"};window[h].useWorker=function(a){if(window.Worker){a=a||"";/[\/\\]$/.test(a)&&(a+=c.name);""==a&&(a="alloyimage.js");c.useWorker=1;c.path=a;var b=new XMLHttpRequest;b.onreadystatechange=function(){4==b.readyState&&"404"==b.status&&c.destroySelf("AI_ERROR\uff1a\u4f7f\u7528worker\u65f6\uff0cai\u6587\u4ef6\u8def\u5f84\u6307\u5b9a\u9519\u8bef\nAI_ERROR: error occured while using web worker since indicate the wrong path of file ai")};
6 | b.open("GET",a,!1);b.send()}else this.useWorker=0,console.log("AI_WARNING: \u6d4f\u89c8\u5668\u4e0d\u652f\u6301web worker, \u81ea\u52a8\u5207\u6362\u4e3a\u5355\u7ebf\u7a0b\nAI_WARNING: the brower doesn't support Web Worker")};onmessage=function(a){var a=a.data,b;"act"==a[0]?b=c.reflect(a[1],a[2],a[3]):"add"==a[0]&&(b=c.add.apply(c,a[1]));postMessage(b)};window[h].prototype={act:function(a,b){var f=[],f=Array.prototype.slice.call(arguments,1);this.useWorker?(this.dorsyWorker.queue.push(["act",a,f]),
7 | p.call(this)):c.reflect(a,this.imgData,f);return this},view:function(a,b,f,i,d){var c=this.clone();c.type=1;this.addLayer(c,"\u6b63\u5e38",0,0);c.act(a,b,f,i,d);return this},excute:function(){var a=this.layers,b=a.length;a[b-1]&&1==a[b-1][0].type&&(this.imgData=a[b-1][0].imgData,delete a[b-1])},cancel:function(){var a=this.layers,b=a.length;a[b-1]&&1==a[b-1][0].type&&delete a[b-1]},show:function(a,b,f){if(!f&&this.useWorker)return this.dorsyWorker.queue.push(["show",a,b]),this;if(0==this.layers.length)this.tempPsLib=
8 | {imgData:this.imgData};else{f=new window[h](this.canvas.width,this.canvas.height);f.add(this,"\u6b63\u5e38",0,0,b);this.tempPsLib=f;for(var i=0;id;d++)f[d]>c&&(c=f[d]);for(d=0;255>d;d++)g=f[d]||0,g=a.height-0.8*(g/c)*a.height,b.lineTo(d/256*a.width,g,1,1);b.lineTo(a.width+10,a.height);b.fill()},ps:function(a){var b;b=c.reflectEasy(a).call(this);this.logTime("\u7ec4\u5408\u6548\u679c"+a);return b},logTime:function(a){console.log(a+": "+(+new Date-this.startTime)/1E3+"s")},ctx:function(a){var b=
14 | this.ctxContext;b.putImageData(this.imgData,0,0);a.call(b);this.imgData=b.getImageData(0,0,this.canvas.width,this.canvas.height);return this},notify:function(a){"readyStateOK"==a&&(this.readyState=1)},complete:function(a){this.useWorker?this.dorsyWorker.queue.push(["complete",a]):a()}}})("psLib");window.AlloyImage=$AI=window.psLib;(function(h){window[h].module("ImageEnhance",function(){return{process:function(p){for(var c=p.data,a=0,b=c.length;ae&&0!=j[n+3];e++)switch(d[l+3]=j[n+3],a){case "\u989c\u8272\u51cf\u6de1":m[e]&&
16 | (k=d[l+e]+d[l+e]*j[n+e]/(255-j[n+e]),d[l+e]=(1-b)*d[l+e]+b*k);break;case "\u53d8\u6697":m[e]&&(k=d[l+e]j[n+e]?d[l+e]:j[n+e],d[l+e]=(1-b)*d[l+e]+b*k);break;case "\u6b63\u7247\u53e0\u5e95":m[e]&&(k=parseInt(d[l+e]*j[n+e]/255),d[l+e]=(1-b)*d[l+e]+b*k);break;case "\u6ee4\u8272":m[e]&&(k=parseInt(255-(255-d[l+e])*(255-j[n+e])/255),d[l+e]=(1-b)*d[l+e]+b*k);break;case "\u53e0\u52a0":m[e]&&(k=127.5>=d[l+e]?d[l+e]*j[n+
17 | e]/127.5:255-(255-d[l+e])*(255-j[n+e])/127.5,d[l+e]=(1-b)*d[l+e]+b*k);break;case "\u5f3a\u5149":m[e]&&(k=127.5>=j[n+e]?d[l+e]*j[n+e]/127.5:d[l+e]+(255-d[l+e])*(j[n+e]-127.5)/127.5,d[l+e]=(1-b)*d[l+e]+b*k);break;case "\u5dee\u503c":m[e]&&(k=d[l+e]>j[n+e]?d[l+e]-j[n+e]:j[n+e]-d[l+e],d[l+e]=(1-b)*d[l+e]+b*k);break;case "\u6392\u9664":m[e]&&(k=d[l+e]+j[n+e]-d[l+e]*j[n+e]/127.5,d[l+e]=(1-b)*d[l+e]+b*k);break;case "\u70b9\u5149":m[e]&&(k=d[l+e]<2*j[n+e]-255?2*j[n+e]-255:d[l+e]<2*j[n+e]?d[l+e]:2*j[n+e],
18 | d[l+e]=(1-b)*d[l+e]+b*k);break;case "\u989c\u8272\u52a0\u6df1":m[e]&&(k=255-255*(255-d[l+e])/j[n+e],d[l+e]=(1-b)*d[l+e]+b*k);break;case "\u7ebf\u6027\u52a0\u6df1":m[e]&&(k=d[l+e]+j[n+e],k=255j[n+e]?((2*j[n+e]-255)*(255-d[l+e])/65025+1)*d[l+e]:(2*j[n+e]-255)*(Math.sqrt(d[l+e]/255)-d[l+e]/255)+d[l+e],d[l+e]=(1-b)*d[l+e]+b*k);
19 | break;case "\u4eae\u5149":m[e]&&(k=127.5>j[n+e]?255*(1-(255-d[l+e])/(2*j[n+e])):d[l+e]/(2*(1-j[n+e]/255)),d[l+e]=(1-b)*d[l+e]+b*k);break;case "\u7ebf\u6027\u5149":m[e]&&(k=d[l+e]+2*j[n+e]-255,k=255g;g++)a[i+g]=(a[i+g]-127.5*(1-b))*f+127.5*(1+b);return p}}})})("psLib");
21 | (function(h){window[h].module("applyMatrix",function(p){return{process:function(c){for(var a=c.data,b=c.width,f=new p.lib.dorsyMath.Matrix([-2,-4,-4,-4,-2,-4,0,8,0,-4,-4,8,24,8,-4,-4,0,8,0,-4,-2,-4,-4,-4,-2],25,1),i=[],d=0,g=a.length;de;e++)for(var n=m+e,l=-2;3>l;l++)for(var r=4*(n*b+(k+l)),j=0;3>j;j++)h[j].push(a[r+j]);m=(new p.lib.dorsyMath.Matrix(h,3,matrixSize)).mutiply(f);for(j=0;3>j;j++)i[d+j]=m.data[j];i[d+
22 | 4]=a[d+4]}}d=0;for(g=a.length;dm;m++)b[4*k+m]=b[4*j+m];return p}}})})("psLib");
26 | (function(h){window[h].module("curve",function(p){return{process:function(c,a){for(var b=p.lib.dorsyMath.lagrange(a[0],a[1]),f=c.data,i=c.width,d=c.height,g=0;gk;k++)f[4*m+k]=b(f[4*m+k]);return c}}})})("psLib");
27 | (function(h){window[h].module("darkCorner",function(p){return{process:function(c,a){for(var b=parseInt(a[0])||3,f=a[1]||30,i=c.data,d=c.width,g=c.height,j=2*d/3,m=1*g/2,k=p.lib.dorsyMath.distance([j,m]),b=k*(1-b/10),h=0;hl;l++){var r;r=i[4*n+l];var q=(p.lib.dorsyMath.distance([h,e],[j,m])-b)/(k-b);0>q&&(q=0);r=(0*Math.pow(1-q,3)+0.06*q*Math.pow(1-q,2)+3*0.3*q*q*(1-q)+1*Math.pow(q,3))*r*f/255;i[4*n+l]-=r}return c}}})})("psLib");
28 | (function(h){window[h].module("dorsyMath",function(p){var c={FFT1:function(a){function b(){i++;for(var g=f/Math.pow(2,i),m=f/g,k=0;ke;e++)r[e].push(i[v+e]);n=(new p.lib.dorsyMath.Matrix(r,3,g)).mutiply(b);for(e=0;3>
31 | e;e++)j[k+e]=n.data[e];j[k+4]=i[k+4]}}k=0;for(h=i.length;kb?2*Math.PI-c:c,d=1-3*Math.min(a,b,f)/(a+b+f);c>2*Math.PI&&(c=2*Math.PI);0>c&&(c=0);return{H:c,S:d,I:(a+b+f)/3}},HSIToRGB:function(a,b,f){0>a?(a%=2*Math.PI,a+=2*Math.PI):a%=2*Math.PI;if(a<=2*Math.PI/3)var c=f*(1-b),d=f*(1+b*Math.cos(a)/Math.cos(Math.PI/3-a)),g=3*f-(d+c);else a<=4*Math.PI/3?(a-=2*
32 | Math.PI/3,d=f*(1-b),g=f*(1+b*Math.cos(a)/Math.cos(Math.PI/3-a)),c=3*f-(g+d)):(a-=4*Math.PI/3,g=f*(1-b),c=f*(1+b*Math.cos(a)/Math.cos(Math.PI/3-a)),d=3*f-(g+c));return{R:d,G:g,B:c}},applyInHSI:function(a,b){for(var f=a.data,c=0,d=f.length;cg.S&&(g.S=0);g=this.HSIToRGB(g.H,g.S,g.I);f[c]=g.R;f[c+1]=g.G;f[c+2]=g.B}},applyInCoordinate:function(){},distance:function(a,b){b=b||[0,0];a=new c.C(a[0],a[1]);b=new c.C(b[0],b[1]);return a.minus(b).distance()},
33 | xyToIFun:function(a){return function(b,c,i){return 4*(c*a+b)+(i||0)}},xyCal:function(a,b,c,i,d){for(var g=this.xyToIFun(a.width),j=0;3>j;j++){var m=g(b,c,j);a[m]=i(a[m])}d&&(a[m+1]=d(a[m+1]))}};c.Matrix.prototype={plus:function(a){if(this.m!=a.m||this.n!=a.n)throw Error("\u77e9\u9635\u52a0\u6cd5\u884c\u5217\u4e0d\u5339\u914d");for(var b=new c.Matrix([],this.m,this.n),f=0;fk&&m.push([f,h]);b=p.lib.dorsyMath.xyToIFun(d);f=0;for(d=parseInt(d/j);fg;g++)b[f+g]=c[d+g]-c[m+g]+127.5;b[f+4]=c[f+4]}}f=0;for(i=c.length;fm;m++){var k=parseInt(2*Math.random()*a)-a;b[4*j+m]+=k}return h}}})})("psLib");
48 | (function(h){window[h].module("oilPainting",function(){return{process:function(h,c){for(var a=parseInt(c[0])||16,b=h.data,f=h.width,i=h.height,d=0;dk;k++)m+=b[4*j+k];m/=3;m=parseInt(m/a)*a;for(k=0;3>k;k++)b[4*j+k]=m}return h}}})})("psLib");
49 | (function(h){window[h].module("setHSI",function(h){return{process:function(c,a){a[0]=a[0]/180*Math.PI;a[1]=a[1]/100||0;a[2]=255*(a[2]/100)||0;a[3]=a[3]||!1;h.lib.dorsyMath.applyInHSI(c,function(b){a[3]?(b.H=a[0],b.S=a[1]):(b.H+=a[0],b.S+=a[1]);b.I+=a[2]});return c}}})})("psLib");
50 | (function(h){window[h].module("sharp",function(){return{process:function(h,c){for(var a=c[0]||0.6,b=h.data,f=h.width,i=0,d=b.length;im;m++)b[i+m]+=(b[i+m]-(b[j+m]+b[g+m]+b[k+m])/3)*a}return h}}})})("psLib");
51 | (function(h){window[h].module("toGray",function(){return{process:function(h){for(var c=h.data,a=0,b=c.length;aa?255:0);c.data=b;return c}}})})("psLib");
53 |
--------------------------------------------------------------------------------
/nsrc/alloyimage.base.js:
--------------------------------------------------------------------------------
1 | /**
2 | * AlloyImage base module
3 | * Just Like AlloyImage, It's Powerful and Easily to use!
4 | * @author dorsywang From Tencent AlloyTeam
5 | */
6 |
7 | //define the base module module: AlloyImage or $AI;
8 | AIDefine('AlloyImage', ['process', 'info', 'fix', 'util'], function(P, Info, Fix, Util){
9 |
10 | var device = Util.getDevice();
11 |
12 | var AlloyImage = function(img, width, height){
13 | var _this = this;
14 |
15 | if(this instanceof AlloyImage){
16 | //记录时间 time trace
17 | this.startTime = + new Date();
18 |
19 | var canvas = document.createElement("canvas");
20 | var context = canvas.getContext("2d");
21 |
22 | //var l = psLib(20,30);构造适配
23 | if(!isNaN(img)){
24 |
25 | canvas.width = img;
26 | canvas.height = width;
27 | height = height || "#fff";
28 | context.fillStyle = height;
29 | context.fillRect(0, 0, img, width);
30 |
31 | this.srcImg = "";
32 |
33 | }else if(typeof img == "string"){
34 | var tmpImg = new Image();
35 | tmpImg.onload = function(){
36 | canvas.width = parseInt(this.width);
37 | canvas.height = parseInt(this.height);
38 |
39 | context.drawImage(this, 0, 0, this.width, this.height);
40 | };
41 | tmpImg.src = img;
42 | }else{
43 | var dw = width, dh = height;
44 |
45 | var sw = img.width, sh = img.height;
46 | var ratio = sw / sh;
47 |
48 | if(width || height){
49 | if(! height){
50 | dh = ~~ (dw / ratio);
51 | }else if(! width){
52 | dw = dh * ratio;
53 | }
54 | }else{
55 | dw = sw;
56 | dh = sh;
57 | }
58 |
59 | canvas.width = dw;
60 | canvas.height = dh;
61 |
62 | if(! isNaN(dw)){
63 | if(device == "ios"){
64 | Fix.drawImageIOS(context, img, dw, dh);
65 | }else{
66 | context.drawImage(img, 0, 0, dw, dh);
67 | }
68 |
69 | }else context.drawImage(img, 0, 0);
70 |
71 | this.srcImg = img;
72 |
73 | }
74 |
75 | //将引用的canvas对象挂接到对象上
76 | this.canvas = canvas;
77 | this.context = context;
78 | this.imgData = context.getImageData(0, 0, canvas.width, canvas.height);
79 |
80 | //赋予对象唯一ID
81 | this.name = "AlloyImage_" + Math.random();
82 | this.canvas.id = this.name;
83 |
84 | //记录挂接到图层上的对象的引用
85 | this.layers = [];
86 |
87 | //原生canvas支持时的临时canvas
88 | var ctxCanvas = document.createElement("canvas");
89 | ctxCanvas.width = canvas.width;
90 | ctxCanvas.height = canvas.height;
91 |
92 | this.ctxCanvas = ctxCanvas;
93 | this.ctxContext = canvas.getContext("2d");
94 |
95 | //设置对象的宽高
96 | this.width = this.canvas.width;
97 | this.height = this.canvas.height;
98 |
99 | //默认使用worker进行处理
100 | this.useWorker = P.useWorker;
101 |
102 | //初始化readyState为ready,readyState表明处理就绪
103 | this.readyState = 1;
104 |
105 | if(this.useWorker){
106 | //如果使用worker,则初始化一个dorsyWorker封装实例出来
107 | this.dorsyWorker = P.lib.dorsyWorker(this);
108 | }
109 |
110 | //mix P.lib.Tools method to $AI.Tools
111 | if(P.lib.Tools){
112 | for(var i in P.lib.Tools){
113 | this.Tools[i] = (function(i){
114 | return function(args){
115 | return _this.Tools(i, args);
116 | };
117 | })(i);
118 | }
119 | }
120 |
121 | }else{
122 |
123 | //返回自身构造对象
124 | return new AlloyImage(img, width, height);
125 | }
126 | };
127 |
128 | //原型对象
129 | window[Ps].prototype = {
130 | set width(w){
131 | this.canvas.width = w;
132 | },
133 |
134 | set height(h){
135 | this.canvas.height = h;
136 | },
137 |
138 | get width(){
139 | return this.canvas.width;
140 | },
141 |
142 | get height(){
143 | return this.canvas.height;
144 | },
145 |
146 | //动作
147 | act: function(method, arg){
148 | //console.log("actStart");
149 | var args = [];
150 |
151 | //提取参数为数组
152 | args = Array.prototype.slice.call(arguments, 1);
153 |
154 | if(this.useWorker){
155 | this.dorsyWorker.queue.push(["act", method, args]);
156 |
157 | checkStartWorker.call(this);
158 |
159 | }else{
160 | //做一次转发映射
161 | P.reflect(method, this.imgData, args);
162 |
163 | }
164 |
165 | return this;
166 | },
167 |
168 | //预览模式 ,所有的再操作全部基于原点,不会改变本图层的效果,直到act会去除这部分图层
169 | view: function(method, arg1, arg2, arg3, arg4){
170 |
171 | //克隆本图层对象
172 | var newLayer = this.clone();
173 |
174 | //标记本图层的种类为预览的已合并的图层
175 | newLayer.type = 1;
176 |
177 | //挂接克隆图层副本到对象
178 | this.addLayer(newLayer, "正常", 0, 0);
179 | newLayer.act(method, arg1, arg2, arg3, arg4);
180 |
181 | return this;
182 | },
183 |
184 | //将view的结果执行到图层
185 | excute: function(){
186 | var layers = this.layers;
187 | var n = layers.length;
188 | if(layers[n - 1] && layers[n - 1][0].type == 1){
189 | this.imgData = layers[n - 1][0].imgData;
190 | delete layers[n - 1];
191 | }
192 | },
193 |
194 | //取消view的结果执行
195 | cancel: function(){
196 | var layers = this.layers;
197 | var n = layers.length;
198 | if(layers[n - 1] && layers[n - 1][0].type == 1){
199 | delete layers[n - 1];
200 | }
201 | },
202 |
203 | //显示对象 isFast用于快速显示
204 | show: function(selector, isFast, flag){
205 |
206 | if(flag){
207 | }else{
208 | if(this.useWorker){
209 | this.dorsyWorker.queue.push(["show", selector, isFast]);
210 | return this;
211 | }
212 | }
213 |
214 | //如果其上无其他挂载图层,加快处理
215 | if(this.layers.length == 0){
216 | this.tempPsLib = {
217 | imgData: this.imgData
218 | };
219 | }else{
220 |
221 | //创建一个临时的psLib对象,防止因为合并显示对本身imgData影响
222 | var tempPsLib = new window[Ps](this.canvas.width, this.canvas.height);
223 | tempPsLib.add(this, "正常", 0, 0, isFast);
224 | this.tempPsLib = tempPsLib;
225 |
226 | //将挂接到本对象上的图层对象 一起合并到临时的psLib对象上去 用于显示合并的结果,不会影响每个图层,包括本图层
227 | for(var i = 0; i < this.layers.length; i ++){
228 | var tA = this.layers[i];
229 | var layers = tA[0].layers;
230 | var currLayer = tA[0];
231 |
232 | if(layers[layers.length - 1] && layers[layers.length - 1][0].type == 1) currLayer = layers[layers.length - 1][0];
233 | tempPsLib.add(currLayer, tA[1], tA[2], tA[3], isFast);
234 | }
235 |
236 | this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
237 |
238 | }
239 |
240 | //以临时对象data显示
241 | this.context.putImageData(this.tempPsLib.imgData, 0, 0);
242 |
243 | if(selector){
244 | if(typeof selector == "string"){
245 | var el = document.querySelector(selector);
246 | el.appendChild(this.canvas);
247 | }else{
248 | selector.appendChild(this.canvas);
249 | }
250 | }else{
251 | document.body.appendChild(this.canvas);
252 | }
253 |
254 | return this;
255 | },
256 |
257 | //替换到某元素里
258 | replaceChild: function(selector){
259 | var el;
260 | if(typeof selector == "string"){
261 | el = document.querySelector(selector);
262 | }else{
263 | el = selector;
264 | }
265 |
266 | el.innerHTML = "";
267 | return this.show(el);
268 | },
269 |
270 | //替换原来的图片
271 | replace: function(img, workerFlag){
272 | if(workerFlag){
273 | }else{
274 | if(this.useWorker){
275 | this.dorsyWorker.queue.push(['replace', img]);
276 | checkStartWorker.call(this);
277 |
278 | return this;
279 | }
280 | }
281 |
282 | if(img){
283 | img.onload = function(){};
284 | img.src = this.save(0, 1, workerFlag);
285 | }
286 |
287 | return this;
288 | },
289 |
290 | //合并一个AlloyImage图层上去
291 | add: function(){
292 |
293 | var numberArr = [], psLibObj, method, alpha, dx, dy, isFast, channel;
294 |
295 | //做重载
296 | for(var i = 0; i < arguments.length; i ++){
297 | if(!i) continue;
298 |
299 | switch(typeof(arguments[i])){
300 | case "string":
301 | if(/\d+%/.test(arguments[i])){//alpha
302 | alpha = arguments[i].replace("%", "");
303 | }else if(/[RGB]+/.test(arguments[i])){//channel
304 | channel = arguments[i];
305 | }else{//method
306 | method = arguments[i];
307 | }
308 | break;
309 |
310 | case "number":
311 | numberArr.push(arguments[i]);
312 | break;
313 |
314 | case "boolean":
315 | isFast = arguments[i];
316 | break;
317 | }
318 | }
319 |
320 | //赋值
321 | dx = numberArr[0] || 0;
322 | dy = numberArr[1] || 0;
323 | method = method || "正常";
324 | alpha = alpha / 100 || 1;
325 | isFast = isFast || false;
326 | channel = channel || "RGB";
327 |
328 | psLibObj = arguments[0];
329 |
330 | //console.log("add init");
331 |
332 | if(this.useWorker){
333 | this.dorsyWorker.queue.push(['add', psLibObj, method, alpha, dx, dy, isFast, channel]);
334 |
335 | checkStartWorker.call(this);
336 |
337 | }else{
338 | //做映射转发
339 | P.add(this.imgData, psLibObj.imgData, method, alpha, dx, dy, isFast, channel);
340 | }
341 |
342 | return this;
343 | },
344 |
345 | //挂载一个图层上去,不会影响本身,只是显示有变化
346 | addLayer: function(psLibObj, method, dx, dy){
347 | this.layers.push([psLibObj, method, dx, dy]);
348 |
349 | return this;
350 | },
351 |
352 | clone: function(workerFlag){
353 |
354 | /*
355 | if(workerFlag){
356 | }else{
357 |
358 | if(this.useWorker){
359 | this.dorsyWorker.queue.push(['clone']);
360 | return this;
361 | }
362 | }
363 | */
364 |
365 | var tempPsLib = new window[Ps](this.canvas.width, this.canvas.height);
366 | tempPsLib.context.putImageData(this.imgData, 0, 0);
367 | tempPsLib.imgData = tempPsLib.context.getImageData(0, 0, this.canvas.width, this.canvas.height);
368 | /*
369 | tempPsLib.add(this);
370 | */
371 |
372 | return tempPsLib;
373 | },
374 |
375 | //交换a,b图层的顺序,ab代表当前序号
376 | swap: function(a, b){
377 | var temp = this.layers[a];
378 | this.layers[a] = this.layers[b];
379 | this.layers[b] = temp;
380 |
381 | return this;
382 | },
383 |
384 | //删除几个图层序号
385 | deleteLayers: function(arr){
386 | this.layers = this.layers.del(arr);
387 | },
388 |
389 | //返回一个合成后的图像 png base64
390 | //comRatio为压缩质量
391 | save: function(type, comRatio, workerFlag){
392 | type = type || "png";
393 | type = type.toLowerCase();
394 |
395 | comRatio = comRatio || 0.8;
396 |
397 | if(type == "jpg") type = "jpeg";
398 |
399 | var mimeType = "image/" + type;
400 |
401 | if(workerFlag){
402 | }else{
403 | if(this.useWorker){
404 | this.dorsyWorker.queue.push(['save']);
405 | checkStartWorker.call(this);
406 |
407 | return this;
408 | }
409 | }
410 |
411 | //如果没有挂接图片 直接返回
412 | if(! this.layers.length){
413 | this.context.putImageData(this.imgData, 0, 0);
414 | return this.canvas.toDataURL(mimeType, comRatio);
415 | }
416 |
417 |
418 | //创建一个临时的psLib对象,防止因为合并显示对本身imgData影响
419 | var tempPsLib = new window[Ps](this.canvas.width, this.canvas.height);
420 | tempPsLib.add(this, "正常", 0, 0, isFast);
421 | this.tempPsLib = tempPsLib;
422 |
423 | //将挂接到本对象上的图层对象 一起合并到临时的psLib对象上去 用于显示合并的结果,不会影响每个图层,包括本图层
424 | for(var i = 0; i < this.layers.length; i ++){
425 | var tA = this.layers[i];
426 | var layers = tA[0].layers;
427 | var currLayer = tA[0];
428 |
429 | if(layers[layers.length - 1] && layers[layers.length - 1][0].type == 1) currLayer = layers[layers.length - 1][0];
430 |
431 | tempPsLib.add(currLayer, tA[1], tA[2], tA[3], isFast);
432 | }
433 |
434 | this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
435 |
436 | //以临时对象data显示
437 | this.context.putImageData(tempPsLib.imgData, 0, 0);
438 |
439 | return this.canvas.toDataURL(mimeType, comRatio);
440 | },
441 |
442 | //下载图片
443 | saveFile: function(fileName, comRatio){
444 | fileName = fileName || "AlloyImage合成图像.jpg";
445 | comRatio = comRatio || 1;
446 |
447 | var formatReg = /.*.(jpg|png|gif|jpeg)$/g;
448 | var format = "png";
449 |
450 | if(formatReg.test(fileName)){
451 | formatReg.lastIndex = 0;
452 | format = formatReg.exec(fileName)[1];
453 | }else{
454 | fileName += ".png";
455 | }
456 |
457 | var fileData = this.save(format, comRatio);
458 |
459 | var a = document.createElement('a');
460 | a.href = fileData;
461 | a.download = fileName;
462 |
463 | var e = document.createEvent("HTMLEvents");
464 | e.initEvent("click", false, false);
465 |
466 | a.dispatchEvent(e);
467 |
468 | },
469 |
470 | download: function(fileName, comRatio){
471 | this.saveFile(fileName, comRatio);
472 | },
473 |
474 | saveAsDataURL: function(){
475 | },
476 |
477 | saveAsBlob: function(){
478 | },
479 |
480 | saveAsBuffer: function(){
481 | },
482 |
483 | //绘制直方图
484 | drawRect: function(selector){
485 | var canvas;
486 |
487 | if(canvas = document.getElementById("imgRect")){
488 | }else{
489 | canvas = document.createElement("canvas");
490 | canvas.id = "imgRect";
491 | document.body.appendChild(canvas);
492 | canvas.width = parseInt(this.canvas.width);
493 | canvas.height = parseInt(this.canvas.height);
494 | }
495 |
496 | var context = canvas.getContext("2d");
497 | context.clearRect(0, 0, canvas.width, canvas.height);
498 |
499 | var result = [];
500 | var data = this.tempPsLib.imgData.data;
501 |
502 | for(var i = 0, n = data.length; i < n; i ++){
503 | if(!result[data[i]]){
504 | result[data[i]] = 1;
505 | }else{
506 | result[data[i]] ++;
507 | }
508 | }
509 |
510 | context.beginPath();
511 | context.moveTo(0, canvas.height);
512 |
513 | var max = 0;
514 |
515 | for(var i = 0; i < 255; i ++){
516 | if(result[i] > max) max = result[i];
517 | }
518 |
519 | for(var i = 0; i < 255; i ++){
520 | var currY = result[i] || 0;
521 | currY = canvas.height - currY / max * 0.8 * canvas.height;
522 | context.lineTo(i / 256 * canvas.width, currY, 1, 1);
523 | }
524 |
525 | context.lineTo(canvas.width + 10, canvas.height);
526 | context.fill();
527 | },
528 |
529 | //组合效果
530 | ps: function(effect){
531 | if(effect == "原图" || effect == "origin" || effect == ""){
532 | return this;
533 | }
534 |
535 | var fun = P.reflectEasy(effect);
536 | var psedPic = fun.call(this, this.canvas);
537 |
538 | //this.logTime("组合效果" + effect);
539 |
540 | return psedPic;
541 | },
542 |
543 | //记录运行时间
544 | logTime: function(msg){
545 | //console.log(msg + ": " + (+ new Date() - this.startTime) / 1000 + "s");
546 | },
547 |
548 | //调用原生canvas.context接口
549 | ctx: function(func){
550 | //func中的this指向context
551 | var ctx = this.ctxContext;
552 |
553 | ctx.putImageData(this.imgData, 0, 0);
554 |
555 | //调用func
556 | func.call(ctx);
557 | this.imgData = ctx.getImageData(0, 0, this.canvas.width, this.canvas.height);
558 |
559 | return this;
560 | },
561 |
562 | notify: function(msg){
563 | //通知
564 | if(msg == "readyStateOK") this.readyState = 1;
565 | },
566 |
567 | //所有动作异步执行完了的回调
568 | complete: function(func){
569 | if(this.useWorker){
570 | //console.log("complete init");
571 | this.dorsyWorker.queue.push(['complete', func]);
572 | }else{
573 | func();
574 | }
575 | },
576 |
577 | //变换Matrix
578 | //x0, y0坐标原点
579 | transform: function(matrix, x0, y0){
580 | //获取dorsyMath接口
581 | var dM = window[Ps].dorsyMath();
582 |
583 | var ctx = this.ctxContext;
584 | ctx.putImageData(this.imgData, 0, 0);
585 |
586 | //建立一个空的临时canvas
587 | var tempCtx = document.createElement("canvas").getContext("2d");
588 |
589 | //计算变换后的canvas宽度
590 | //原则 所有的变换不会记录平移带来的变的换,但会记录下平移导致的原点的平移,以叠加图层的时候减去这些平移造成的影响
591 | //意味着图层自身所有的变换都不会丢失自己的图像信息 但会原点位置发生变化
592 | //这样做会节省很大的无图像空间
593 |
594 | //计算原有点变换后的点
595 | var originPoint = [
596 | new dM.Matrix([0, 0], "1*2"),
597 | new dM.Matrix([0, this.canvas.height], "1*2"),
598 | new dM.Matrix([this.canvas.width, 0], "1 * 2"),
599 | new dM.Matrix([this.canvas.width, this.canvas.height], "1*2")
600 | ];
601 |
602 | var transformedPoint = [];
603 | var transformMatrix = new dM.Matrix(matrix, "2*2");
604 |
605 | for(var i = 0; i < originPoint.length; i ++){
606 | transformedPoint.push(originPoint[i].mutiply(transformMatrix));
607 | }
608 |
609 | var maxX = Math.max(
610 | transformedPoint[0].data[0][0],
611 | transformedPoint[1].data[0][0],
612 | transformedPoint[2].data[0][0],
613 | transformedPoint[3].data[0][0]
614 | );
615 |
616 | var minX = Math.min(
617 | transformedPoint[0].data[0][0],
618 | transformedPoint[1].data[0][0],
619 | transformedPoint[2].data[0][0],
620 | transformedPoint[3].data[0][0]
621 | );
622 |
623 | var maxY = Math.max(
624 | transformedPoint[0].data[0][1],
625 | transformedPoint[1].data[0][1],
626 | transformedPoint[2].data[0][1],
627 | transformedPoint[3].data[0][1]
628 | );
629 |
630 | var minY = Math.min(
631 | transformedPoint[0].data[0][1],
632 | transformedPoint[1].data[0][1],
633 | transformedPoint[2].data[0][1],
634 | transformedPoint[3].data[0][1]
635 | );
636 |
637 | var width = ~~ (maxX - minX);
638 | var height = ~~ (maxY - minY);
639 |
640 | tempCtx.canvas.width = width;
641 | tempCtx.canvas.height = height;
642 |
643 | //将原点平移使图像显示出来 但图像的原点会发生变化
644 | tempCtx.translate(- minX, - minY);
645 | tempCtx.transform.apply(tempCtx, matrix);
646 | tempCtx.drawImage(ctx.canvas, 0, 0);
647 |
648 | this.canvas.width = width;
649 | this.canvas.height = height;
650 |
651 | this.width = width;
652 | this.height = height;
653 |
654 | this.imgData = tempCtx.getImageData(0, 0, width, height);
655 |
656 | return this;
657 | },
658 |
659 | scale: function(x, y){
660 | var y = y || x;
661 | return this.transform([x, 0, 0, y, 0, 0]);
662 | },
663 |
664 | //缩放到宽度和高度
665 | scaleTo: function(w, h){
666 | var _this = this;
667 | var width = this.width;
668 | var height = this.height;
669 |
670 | var scaleSizeX, scaleSizeY;
671 |
672 | if(! h){
673 | h = w * height / width;
674 | }
675 |
676 | if(! w){
677 | w = h * (width / height);
678 | }
679 |
680 | //这里的代码在iphone上会导致倾斜
681 | if(0 && this.srcImg){
682 | var img = new Image();
683 | img.width = w;
684 | img.height = h;
685 |
686 | document.body.appendChild(img);
687 |
688 | img.style.width = w + "px";
689 | img.style.height = ~~ h + "px";
690 |
691 | img.src = this.srcImg.src;
692 |
693 |
694 | var newAIObj = window[Ps](img, w, h);
695 |
696 | document.body.removeChild(img);
697 | img = null;
698 |
699 | setTimeout(function(){
700 | if(_this.canvas.parentNode){
701 | _this.canvas.parentNode.replaceChild(newAIObj.canvas, _this.canvas);
702 | newAIObj.show();
703 | }
704 | }, 10);
705 |
706 | return newAIObj;
707 |
708 | }else{
709 |
710 | if(w && h){
711 | scaleSizeX = w / width;
712 | scaleSizeY = h / height;
713 |
714 | return this.scale(scaleSizeX, scaleSizeY);
715 | }
716 | }
717 | },
718 |
719 | //旋转 度
720 | rotate: function(deg){
721 | //转为弧度
722 | var r = deg / 180 * Math.PI;
723 | var matrix = [
724 | Math.cos(r), Math.sin(r), -Math.sin(r), Math.cos(r), 0, 0
725 | ];
726 |
727 | return this.transform(matrix);
728 | },
729 |
730 | //平移
731 | moveTo: function(x, y){
732 | x = x || 0;
733 | y = y || 0;
734 |
735 | return this.transform([1, 0, 0, 1, x, y]);
736 | },
737 |
738 | //裁切
739 | clip: function(sx, sy, w, h){
740 | // @todo 多图层挂接支持
741 |
742 | //将图像信息放置于临时canvas上
743 | this.ctxContext.putImageData(this.imgData, 0, 0);
744 |
745 | //取到相关矩阵的图像信息
746 | this.imgData = this.ctxContext.getImageData(sx, sy, w, h);
747 |
748 | this.context.canvas.width = w;
749 | this.context.canvas.height = h;
750 |
751 | return this;
752 | },
753 |
754 | //图像的工具方法 不会返回AI本身
755 | Tools: function(args){
756 | return P.tools(this.imgData, arguments);
757 | }
758 | };
759 |
760 | //out put APIs of AlloyImage;
761 | AIExport.external('AlloyImage', AlloyImage);
762 | AIExport.external('$AI', AlloyImage);
763 | });
764 |
--------------------------------------------------------------------------------