① 亮度调整:进度条拖动实现亮度改变。
② 对比度调整:进度条拖动实现对比度改变。
③ 马赛克笔刷:点击图标,在画布上鼠标-点击-拖动实现局部马赛克处理。
④ 放大:点击放大图标,实现图片1.2倍放大。可多次点击。
⑤ 缩小:点击缩小图标,实现图片0.83倍缩小。可多次点击。
⑥ 旋转:点击旋转图标,每次顺时针旋转角度有上方输入框决定。可多次点击。
⑦ 垂直镜像:点击图标,实现垂直翻转。
⑧ 水平镜像:点击图标,实现水平翻转。
⑨ 颜色值显示:点击颜色显示图标,鼠标进入画布移动,可在color块上观测鼠标所在像素的颜色。
叠图:点击贴纸图标,在画布中点击可进行粘贴图样。
旋转的插值有点问题,但是同样的算法使用matlab效果很好。
采用的程序语言是javascript,图形化界面依靠html、css,依托于html的canvas编写。画布呈现长宽均是实际像素个数。
代码和方法有很多不完美的地方。
注:实现借鉴了很多网上帖
滑动轴
1. 色彩变换原理-亮度调整
1.1算法原理:
图象亮度是指画面的明亮程度。灰度图像中,灰度值越高则图像越亮。
原像素灰度f(i,j),转换后为g(i,j),g(i,j)=f(i,j)+b,系数影响图像的亮度。随着增加b (b>0)和减小b (b>0),图像整体的灰度值上移或者下移, 也就是图像整体变亮或者变暗。设置b为light,值域为【-255,255】
1.2亮度调整
亮度度调整公式如下:
RGB’=RGB+ Light
其中RGB’代表了r,g,b各自重新计算后的值。
1.3实施方案
在界面上放置一个滑动轴,范围rgbnum为-50~50,初始值为0。即Light=rgbnum/50*255。除此,叠加对比度调整效果。
拖动条借鉴:https://blog.csdn.net/qq_36818627/article/details/81606778?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase
代码如:注:data[i]、data[i+1]、data[i+2]代表RGB。
后续判断对比度是否改变,改变则叠加。这里没有贴代码。
var rgbnum=parseInt(barleft/(scroll.offsetWidth-bar.offsetWidth) * 100-50) ptxt.innerHTML = parseInt(rgbnum) + "%";//滚动条获取亮度变化值。 //data0储存改变亮度对比度之前的图像,防止调节亮度过低或过高只有黑白色了。 for(var i = 0; i < data.length; i += 4 ) { if(parseInt(data0[i]+parseInt(rgbnum)/50*255)>255) data[i]=255; else if(parseInt(data0[i]+parseInt(rgbnum)/50*255)<0) data[i]=0; else data[i] = data0[i]+parseInt(rgbnum)/50*255; if(parseInt(data0[i+1]+parseInt(rgbnum)/50*255)>255) data[i+1]=255; else if(parseInt(data0[i+1]+parseInt(rgbnum)/50*255)<0) data[i+1]=0; else data[i+1] = data0[i+1]+ parseInt(rgbnum)/50*255; if(parseInt(data0[i+2]+parseInt(rgbnum)/50*255)>255) data[i+2]=255; else if(parseInt(data0[i+2]+parseInt(rgbnum)/50*255)<0) data[i+2]=0; else data[i+2] = data0[i+2]+ parseInt(rgbnum)/50*255; }
2. 色彩变换原理-对比度调整
2.1算法原理:
图像对比度指的是一幅图像中明暗区域最亮的白和最暗的黑之间不同亮度层级的测量,即指一幅图像灰度反差的大小。差异范围越大代表对比越大,差异范围越小代表对比越小。
查阅了图像处理软件Photoshop的对比度调整公式。RGB三个通道分别做相同的调整运算。Contrast是调整参数,取值范围为【-255,255】
2.2对比度调整
对比度调整公式如下:
RGB’=RGB+(RGB-Average)*Contrast/255
其中nRGB’代表了r,g,b各自重新计算后的值。Average是平均亮度,大部分图片是在100~150之间。取127,与实际相近。
所以当Contrast为0时,RGB值不变,表示当前的一个对比度。
为-255时,RGB都为127,亮度都一样,没有差别,呈灰色。
为255时,在Average之上的像素点会变得更亮,反之变得更暗。
2.3实施方案
在界面上放置一个滑动轴,范围rgbnum为-50~50,初始值为0。即Contrast/255=rgbnum/50。除此,叠加亮度调整效果。
代码如:注:data[i]、data[i+1]、data[i+2]代表RGB。
var rgbnum=parseInt(barleft0/(scroll0.offsetWidth-bar0.offsetWidth) * 100-50) ptxt0.innerHTML = parseInt(rgbnum) + "%"; var avg=127; //RGB = RGB + (RGB - avg) * Contrast / 255 for(var i = 0; i < data.length; i += 4 ) { if(parseInt(data0[i]+(data0[i]-127)*parseInt(rgbnum)/50)>255) data[i]=255; else if(parseInt(data0[i]+(data0[i]-127)*parseInt(rgbnum)/50)<0) data[i]=0; else data[i] = data0[i]+(data0[i+1]-127)*parseInt(rgbnum)/50; if(parseInt(data0[i+1]+(data0[i+1]-127)*parseInt(rgbnum)/50)>255) data[i+1]=255; else if(parseInt(data0[i+1]+(data0[i+1]-127)*parseInt(rgbnum)/50)<0) data[i+1]=0; else data[i+1] = data0[i+1]+ (data0[i+1]-127)*parseInt(rgbnum)/50; if(parseInt(data0[i+2]+(data0[i+2]-127)*parseInt(rgbnum)/50)>255) data[i+2]=255; else if(parseInt(data0[i+2]+(data0[i+2]-127)*parseInt(rgbnum)/50)<0) data[i+2]=0; else data[i+2] = data0[i+2]+ (data0[i+2]-127)*parseInt(rgbnum)/50; }
3. 马赛克笔功能
3.1算法原理:
马赛克像素的rgb=这块马赛克内所有像素rgb的平均值。
3.2马赛克笔设置
为了方便查看效果,设定一块马赛克包含(3*2+1)*(3*2+1)=49个像素点。一块马赛克包含的像素点越多,图像模糊化越重。以鼠标点击为中心,一次涂抹马赛克操作包含(3*2)^2个马赛克。
3.3实施方案
处理马赛克画笔的顺序是,鼠标点击(绘制36个马赛克),移动超出一个马赛克1/2长,便会进行下一区域马赛克涂抹。鼠标抬起,绘制完成。
方法借鉴: https://www.jianshu.com/p/3d2a8bd83191
4. 放大
4.1算法原理:
最简单的方式,如果需要将原图像放大为k倍,则将原图像中的每个像素值,填在新图像中对应的k*k大小的子块中。
4.2放大算法
设原图像大小为M*N,放大为k1M*k2N,(k1>1,k2>1)。
算法步骤如下:
1)设旧图像是F(i,j), i=1,2,…,M, j=1,2,…,N.
新图像是G(i’,j’), i’=1,2,…,k1M, j’=1,2,…,k2N.
2)G(i’,j’)=F(c1*I’,c2*j’)
c1=1/k1 c2=1/k2
4.3实施方案
先扩展画布,然后进行等比例填充像素值。
单次放大设置为图像的1.2倍,通过修改代码参数,可修改倍数值,为了界面美观,没有设置可调节倍数。通过点击放大按钮,进行放大图片。
for(var i = 0; i < parseInt(oCanvas.width*oCanvas.height); i++) { var dx=i%oCanvas.width; var dy=(i-dx)/oCanvas.width; var mx=parseInt(dx/1.2); var my=parseInt(dy/1.2); if(parseInt(mx)>parseInt(width)) { mx=width; } if(parseInt(my)>parseInt(height)){ my=height; } data[(dy*oCanvas.width+dx)*4+0]=datatemp[(my*width+mx)*4+0]; data[(dy*oCanvas.width+dx)*4+1]=datatemp[(my*width+mx)*4+1]; data[(dy*oCanvas.width+dx)*4+2]=datatemp[(my*width+mx)*4+2]; data[(dy*oCanvas.width+dx)*4+3]=datatemp[(my*width+mx)*4+3]; }
5.缩小
5.1算法原理:
图像的缩小从物理意义上来说,是将描述图像的每个像素的物理尺寸缩小相应的倍数就可以完成;但如果像素的物理尺寸不允许改变,从数码技术的角度来看,图像的缩小实际上就是通过减少像素个数来实现的。
图像缩小实际上就是对原有的多个数据进行挑选或处理,获得期望 缩小尺寸的数据,并且尽量保持原有的特征不丢失。
最简单的方法就是等间隔地选取数据。
5.2缩小算法
设原图像大小为M*N,缩小为k1M*k2N, (k1<1,k2<1, k1=k2 为按比例缩小, k1!=k2为不按比例缩小)。
算法步骤如下:
1) 设原图为F(i,j), i=1,2,…,M, j=1,2,…,N.
压缩后图像是G(i’,j’), i’=1,2,…,k1M, j’=1,2,…,k2N.
2)G(i’,j’)=F(c1*i’,c2*j’)
其中,c1=1/k1 c2=1/k2
5.3实施方案
先缩小画布,然后进行等间隔取像素值。
单次缩小设置为图像的0.83倍,通过修改代码参数,可修改倍数值,为了界面美观,没有设置可调节倍数。通过点击缩小按钮,进行缩小图片。
for(var i = 0; i < parseInt(oCanvas.width*oCanvas.height); i++) { var dx=i%oCanvas.width; var dy=(i-dx)/oCanvas.width; var mx=parseInt(dx*1.2); var my=parseInt(dy*1.2); if(parseInt(mx)>parseInt(width)) { mx=width; } if(parseInt(my)>parseInt(height)){ my=height; } data[(dy*oCanvas.width+dx)*4+0]=datatemp[(my*width+mx)*4+0]; data[(dy*oCanvas.width+dx)*4+1]=datatemp[(my*width+mx)*4+1]; data[(dy*oCanvas.width+dx)*4+2]=datatemp[(my*width+mx)*4+2]; data[(dy*oCanvas.width+dx)*4+3]=datatemp[(my*width+mx)*4+3]; }
6. 旋转
6.1旋转原理:
以图像原点逆时针旋转θ角, 设原图像的坐标点为(x0,y0), 则旋转后图像坐标点的计算公式如下:
6.2旋转方案
图像旋转之前的两个问题:
1)图像旋转计算出的值为小数,而坐标值为正整数。
2)图像旋转计算的结果值所在范围与原来的值所在的范围不同。
因此图像旋转需要做扩大画布,取整处理,平移处理 。
图像旋转之后的两个问题:
1)像素的排列不是完全按照原有的相邻关系。这是因为相邻像素之间只能有8个方向(相邻为45度)
2)会出现许多的空洞点。
因此图像旋转之后需要进行插值处理。
6.3双线性插值
双线性插值,又称为双线性内插。在数学上,双线性插值是有两个变量的插值函数的线性插值扩展,其核心思想是在两个方向分别进行一次线性插值。
红色的数据点与待插值得到的绿色点
假如我们想得到未知函数 f 在点 P = (x, y) 的值,假设我们已知函数 f 在 Q11 = (x1, y1)、Q12 = (x1, y2), Q21 = (x2, y1) 以及 Q22 = (x2, y2) 四个点的值。
首先在 x 方向进行线性插值,得到:
然后在 y 方向进行线性插值,得到:
这样就得到所要的结果 f(x, y),
如果选择一个坐标系统使得 f 的四个已知点坐标分别为 (0, 0)、(0, 1)、(1, 0) 和 (1, 1),那么插值公式就可以化简为:
f(x,y)=f(0,0)(1-x)(1-y)+f(1,0)x(1-y)+f(0,1)(1-x)y+f(1,1)xy
插值空洞太多,效果不好。。。
输入逆时针旋转角度,点击旋转,便可实现旋转功能。 var text=document.getElementById("id_xz0").value; console.log(text); if(text==NaN||text==undefined ||text==0 ||text==null){ alert("填入角度"); } var num0=parseInt(text); console.log(num0); imageData=ctx.getImageData(0,0,oCanvas.width,oCanvas.height); data=imageData.data; var datatemp0=new Array(data.length); var datatemp1=new Array(data.length); for(var i=0;i<data.length;i++){ datatemp0[i]=0; datatemp1[i]=0; } var thita=parseFloat(Math.PI*num0/180); console.log(oCanvas.width); console.log(oCanvas.height); for(var i=0;i < parseInt(oCanvas.width*oCanvas.height);i++){ var dx=i%parseInt(oCanvas.width); var dy=(i-dx)/oCanvas.width; datatemp0[(dy*oCanvas.width+dx)*4+0]=parseInt(dy+1); datatemp0[(dy*oCanvas.width+dx)*4+1]=parseInt(dy+1); datatemp0[(dy*oCanvas.width+dx)*4+2]=parseInt(dy+1); datatemp0[(dy*oCanvas.width+dx)*4+3]=parseInt(dy+1); datatemp1[(dy*oCanvas.width+dx)*4+0]=parseInt(dx+1); datatemp1[(dy*oCanvas.width+dx)*4+1]=parseInt(dx+1); datatemp1[(dy*oCanvas.width+dx)*4+2]=parseInt(dx+1); datatemp1[(dy*oCanvas.width+dx)*4+3]=parseInt(dx+1); } console.log(datatemp0); console.log(datatemp1); var datatemp00=new Array(datatemp0.length); var datatemp11=new Array(datatemp0.length); var max0=0; var min0=oCanvas.width+oCanvas.height; var max1=0; var min1=oCanvas.width+oCanvas.height; console.log(Math.cos(thita)); console.log(Math.sin(thita)); for(var i=0;i<parseInt(oCanvas.width*oCanvas.height);i++){ var dx=i%oCanvas.width; var dy=(i-dx)/oCanvas.width; //逆时针旋转thita度 datatemp00[(dy*oCanvas.width+dx)*4+0]= parseInt(datatemp0[(dy*oCanvas.width+dx)*4+0]*Math.cos(thita)- datatemp1[(dy*oCanvas.width+dx)*4+0]*Math.sin(thita)); datatemp11[(dy*oCanvas.width+dx)*4+0]= parseInt(datatemp0[(dy*oCanvas.width+dx)*4+0]*Math.sin(thita)+ datatemp1[(dy*oCanvas.width+dx)*4+0]*Math.cos(thita)); datatemp00[(dy*oCanvas.width+dx)*4+1]= parseInt(datatemp0[(dy*oCanvas.width+dx)*4+1]*Math.cos(thita)- datatemp1[(dy*oCanvas.width+dx)*4+1]*Math.sin(thita)); datatemp11[(dy*oCanvas.width+dx)*4+1]= parseInt(datatemp0[(dy*oCanvas.width+dx)*4+1]*Math.sin(thita)+ datatemp1[(dy*oCanvas.width+dx)*4+1]*Math.cos(thita)); datatemp00[(dy*oCanvas.width+dx)*4+2]= parseInt(datatemp0[(dy*oCanvas.width+dx)*4+2]*Math.cos(thita)- datatemp1[(dy*oCanvas.width+dx)*4+2]*Math.sin(thita)); datatemp11[(dy*oCanvas.width+dx)*4+2]= parseInt(datatemp0[(dy*oCanvas.width+dx)*4+2]*Math.sin(thita)+ datatemp1[(dy*oCanvas.width+dx)*4+2]*Math.cos(thita)); datatemp00[(dy*oCanvas.width+dx)*4+3]= parseInt(datatemp0[(dy*oCanvas.width+dx)*4+3]*Math.cos(thita)- datatemp1[(dy*oCanvas.width+dx)*4+3]*Math.sin(thita)); datatemp11[(dy*oCanvas.width+dx)*4+3]= parseInt(datatemp0[(dy*oCanvas.width+dx)*4+3]*Math.sin(thita)+ datatemp1[(dy*oCanvas.width+dx)*4+3]*Math.cos(thita)); if(min0>parseInt(datatemp00[(dy*oCanvas.width+dx)*4+0])){ min0=datatemp00[(dy*oCanvas.width+dx)*4+0]; } if(min1>parseInt(datatemp11[(dy*oCanvas.width+dx)*4+0])){ min1=datatemp11[(dy*oCanvas.width+dx)*4+0]; } } console.log(min0); console.log(min1); for(var j=0;j<datatemp00.length;j++){ datatemp00[j]=datatemp00[j]+(1-min0); datatemp11[j]=datatemp11[j]+(1-min1); } console.log(datatemp00); for(var i=0;i<parseInt(oCanvas.width*oCanvas.height);i++){ var dx=i%oCanvas.width; var dy=(i-dx)/oCanvas.width; //逆时针旋转thita度 if(max0<parseInt(datatemp00[(dy*oCanvas.width+dx)*4+0])){ max0=datatemp00[(dy*oCanvas.width+dx)*4+0]; } if(max1<parseInt(datatemp11[(dy*oCanvas.width+dx)*4+0])){ max1=datatemp11[(dy*oCanvas.width+dx)*4+0]; } } console.log(max0); console.log(max1); console.log(datatemp00); console.log(datatemp11); oCanvas.width=max1; oCanvas.height=max0; var len=oCanvas.width*oCanvas.height*4; var imageDatatemp0=ctx.getImageData(0,0,oCanvas.width,oCanvas.height); var data_ =imageDatatemp0.data; for(var j=0;j<len;j++){ data_[j]=0; } var datalast=data; console.log(datalast); for(var i=0;i<parseInt(width*height);i++){ var dx=i%width; var dy=(i-dx)/width; var mx; var my; mx=parseInt(datatemp11[(dy*width+dx)*4+0])-1; my=parseInt(datatemp00[(dy*width+dx)*4+0])-1; data_[(my*oCanvas.width+mx)*4+0]=datalast[(dy*width+dx)*4+0]; mx=parseInt(datatemp11[(dy*width+dx)*4+1])-1; my=parseInt(datatemp00[(dy*width+dx)*4+1])-1; data_[(my*oCanvas.width+mx)*4+1]=datalast[(dy*width+dx)*4+1]; mx=parseInt(datatemp11[(dy*width+dx)*4+2])-1; my=parseInt(datatemp00[(dy*width+dx)*4+2])-1; data_[(my*oCanvas.width+mx)*4+2]=datalast[(dy*width+dx)*4+2]; mx=parseInt(datatemp11[(dy*width+dx)*4+3])-1; my=parseInt(datatemp00[(dy*width+dx)*4+3])-1; data_[(my*oCanvas.width+mx)*4+3]=datalast[(dy*width+dx)*4+3]; } console.log(datalast); thita=-thita; for(var i=0;i<parseInt(oCanvas.width*oCanvas.height);i++){ var dx=i%oCanvas.width; var dy=(i-dx)/oCanvas.width; var di=dy+1; var dj=dx+1; var mx=parseInt(di-(1-min0)); var my=parseInt(dj-(1-min1)); var fx=mx*Math.cos(thita)-my*Math.sin(thita); var fy=mx*Math.sin(thita)+my*Math.cos(thita); var invx=parseInt(mx*Math.cos(thita)-my*Math.sin(thita));//逆时针旋转thita度 var invy=parseInt(mx*Math.sin(thita)+my*Math.cos(thita)); var temp; if(invx>1 && parseInt(invx)<=height && parseInt(invy)>1 && parseInt(invy)<=width){ if(data_[(dy*oCanvas.width+dx)*4+3]==0 && data_[(dy*oCanvas.width+dx)*4+2]==0 && data_[(dy*oCanvas.width+dx)*4+1]==0 && data_[(dy*oCanvas.width+dx)*4+0]==0) { temp = datalast[((invy-2)*height+(invx-2))*4+0]*(invx-fx)*(invy-fy)+datalast[((invy-2)*height+(invx-1))*4+0]*(fx+1-invx)*(invy-fy)+datalast[((invy-1)*height+(invx-2))*4+0]*(fy+1-invy)*(invx-fx)+datalast[((invy-1)*height+(invx-1))*4+0]*(fx+1-invx)*(fy+1-invy); data_[(dy*oCanvas.width+dx)*4+0]=parseInt(temp); temp = datalast[((invy-2)*height+(invx-2))*4+1]*(invx-fx)*(invy-fy)+datalast[((invy-2)*height+(invx-1))*4+1]*(fx+1-invx)*(invy-fy)+datalast[((invy-1)*height+(invx-2))*4+1]*(fy+1-invy)*(invx-fx)+datalast[((invy-1)*height+(invx-1))*4+1]*(fx+1-invx)*(fy+1-invy); data_[(dy*oCanvas.width+dx)*4+1]=parseInt(temp); temp = datalast[((invy-2)*height+(invx-2))*4+2]*(invx-fx)*(invy-fy)+datalast[((invy-2)*height+(invx-1))*4+2]*(fx+1-invx)*(invy-fy)+datalast[((invy-1)*height+(invx-2))*4+2]*(fy+1-invy)*(invx-fx)+datalast[((invy-1)*height+(invx-1))*4+2]*(fx+1-invx)*(fy+1-invy); data_[(dy*oCanvas.width+dx)*4+2]=parseInt(temp); temp = datalast[((invy-2)*height+(invx-2))*4+3]*(invx-fx)*(invy-fy)+datalast[((invy-2)*height+(invx-1))*4+3]*(fx+1-invx)*(invy-fy)+datalast[((invy-1)*height+(invx-2))*4+3]*(fy+1-invy)*(invx-fx)+datalast[((invy-1)*height+(invx-1))*4+3]*(fx+1-invx)*(fy+1-invy); data_[(dy*oCanvas.width+dx)*4+3]=parseInt(temp); } } }
7.镜像
7.1垂直镜像原理:
垂直镜像计算公式如下:(图像大小为M*N)
for(var i=0;i<oCanvas.width*oCanvas.height;i++){ var dx=i%oCanvas.width; var dy=(i-dx)/oCanvas.width; data[(dy*oCanvas.width+(oCanvas.width-dx-1))*4+0]=datatemp[(dy*oCanvas.width+dx)*4+0]; data[(dy*oCanvas.width+(oCanvas.width-dx-1))*4+1]=datatemp[(dy*oCanvas.width+dx)*4+1]; data[(dy*oCanvas.width+(oCanvas.width-dx-1))*4+2]=datatemp[(dy*oCanvas.width+dx)*4+2]; data[(dy*oCanvas.width+(oCanvas.width-dx-1))*4+3]=datatemp[(dy*oCanvas.width+dx)*4+3]; }
8. 水平镜像
水平镜像计算公式如下:(图像大小为M*N)
因为表示图像的矩阵坐标不能为负,因此需要在进行镜像计算之后再进行坐标的平移。
for(var i=0;i<oCanvas.width*oCanvas.height;i++){ var dx=i%oCanvas.width; var dy=(i-dx)/oCanvas.width; data[((oCanvas.height-dy-1)*oCanvas.width+(dx))*4+0]=datatemp[(dy*oCanvas.width+dx)*4+0]; data[((oCanvas.height-dy-1)*oCanvas.width+(dx))*4+1]=datatemp[(dy*oCanvas.width+dx)*4+1]; data[((oCanvas.height-dy-1)*oCanvas.width+(dx))*4+2]=datatemp[(dy*oCanvas.width+dx)*4+2]; data[((oCanvas.height-dy-1)*oCanvas.width+(dx))*4+3]=datatemp[(dy*oCanvas.width+dx)*4+3]; }
9. 颜色值显示
原理:鼠标获取鼠标在画布上的位置。通过数据定位获取rgb值显示出来。
截图鼠标截不进去。。。
oCanvas.onmousemove=function(ev){ var datatemp=imageData0.data; var ev=window.event||ev; var dx = ev.pageX-oCanvas.offsetLeft; var dy = ev.pageY-oCanvas.offsetTop; var pp = parseInt(dy*oCanvas.width+dx); var temp0=parseInt(pp*4); var R0 = parseInt(datatemp[temp0+0]); var G0 = parseInt(datatemp[temp0+1]); var B0 = parseInt(datatemp[temp0+2]); display.style.background="rgb("+R0+","+G0+","+B0+")"; }
10.叠图贴纸
原理:在画布上覆盖原有像素。
点击贴纸按钮,蓝色选中后,便可以直接在画布中任意叠加。 var imgObj=new Image(); imgObj.crossOrigin="Anonymous"; imgObj.src="./good.png"; var img_width = 50; var img_height = 50; oCanvas.onmousedown=function(ev){ console.log("贴图"); var ev=window.event||ev; var dx = ev.pageX-oCanvas.offsetLeft; var dy = ev.pageY-oCanvas.offsetTop; ctx.drawImage(imgObj, parseInt(dx-(img_width)/2), parseInt(dy-(img_height)/2),50,50);
html布局代码:
<html> <head> <title>图像处理大作业</title> <link rel="stylesheet" href="./style.css"> </head> <body> <div class="background"> <div class="body-wrapping"> <!-- 图片处理前后展示 --> <div class="container0"> <div> <p>原图:</p> <input type="file" id="input-upload" accept=".jpg,.jpeg,.png,.gif,.svg" placeholder="上传本地图片" /> <div class=""> <img id="input-img" class=""> </div> </div> </div> <div class="container0"> <div class="container"> <p>亮度调节:</p> <div class="scroll" id="scroll"> <div class="bar" id="bar"> </div> <div class="mask" id="mask"></div> </div> <p id="light">0</p> </div> <div class="container"> <p>对比度调节:</p> <div class="scroll" id="scroll0"> <div class="bar" id="bar0"> </div> <div class="mask" id="mask0"></div> </div> <p id="compare">0</p> </div> </div> <input id="id_xz0" class="text" placeholder="角度°"/> <div class="icons"> <li id="msk" onclick="drawmsk(0)"><img src="./msk.png" id="id_msk" class="icon-wrapping"></li> <li id="fd" onclick="zoomin(1)"><img src="./fd.png" id="id_fd" class="icon-wrapping"></li> <li id="sx" onclick="zoomout(2)"><img src="./sx.png" id="id_sx" class="icon-wrapping"></li> <li id="xz" onclick="rotate(3)"><img src="./xz.png" id="id_xz" class="icon-wrapping"></li> <li id="jx" onclick="mirror(4)"><img src="./hjx.png" id="id_jx" class="icon-wrapping"></li> <li id="hjx" onclick="hmirror(5)"><img src="./jx.png" id="id_hjx" class="icon-wrapping"></li> </div> <div class="icons"> <li id="right" onclick="addcanvas0(6)"><img src="./right.png" id="img_right" class="icon-wrapping"></li> <li id="wrong" onclick="addcanvas1(7)"><img src="./wrong.png" id="img_wrong" class="icon-wrapping"></li> <li id="comeon" onclick="addcanvas2(8)"><img src="./comeon.png" id="img_comeon" class="icon-wrapping"></li> <li id="good" onclick="addcanvas3(9)"><img src="./good.png" id="img_good" class="icon-wrapping"></li> <li id="displayxy" onclick="addcanvas4(10)"><div class="icon-wrapping icon-text" id="img_displayxy">颜色显示</div></li> <li id="display"><div class="icon-wrapping icon-text" id="img_display">color</div></li> </div> <p>处理后图像:</p> <div class="container0"> <div class=""> <div class="img-container" > <canvas id="my-canvas" width="600" height="600"></canvas> </div> </div> </div> <a href="void(0);" id="download">点我保存图片</a> </div> </div> <script src="./draw.js"></script> </body> </html>
css
body { font-family: ‘JetBrains Mono Medium‘; display: flex; align-items: center; justify-content: center; background-color: #0e92b3; } li{ list-style-type: none; } #input-upload { width: 200px; } .background{ width: 100%; display: flex; padding-top: 35px; padding-bottom: 100px; align-items: center; justify-content: center; } .body-wrapping{ background-color: rgb(41, 45, 62); width: 80%; color: #fff; align-items: center; } /* 图片背景纹理 */ .img-container { font-size: 0; background-color: #000; background-size: 10px 10px; } .img{ width: 200px; height: auto; } .img-display{ width: 200px; height: auto; } .err { border: 1px solid red; } .container0{ color: #fff; display:flex; justify-content: space-around; } .container{ width:200px; align-items: center; justify-content: center; } .text{ width: 40px; margin-left: 285px; } .icons{ display:flex; justify-content: space-around; } .icon-wrapping{ width: 40px; height: 40px; background-color: #fff; padding: 8%; margin-bottom: 20px; margin-top: 10px; border-radius: 10px; } .icon-wrapping:hover{ background-color: rgb(41, 45, 62); } .icon-text{ color: red; text-align: center; } .scroll{ margin:30px; width: 200px; height: 5px; background: #ccc; position: relative; } .bar{ width: 10px; height: 20px; background: #369; position: absolute; top: -7px; left: 95; cursor: pointer; } .mask{ position: absolute; left: 0; top: 0; background: #369; width: 0; height: 5px; }
js:
1 const oUpload = document.getElementById(‘input-upload‘); 2 const oImg = document.getElementById(‘input-img‘); 3 oUpload.onchange = loadFile; 4 //oInput.onchange = loadUrl; 5 6 // 读取本地文件 7 function loadFile(e) { 8 const file = e.target.files[0]; 9 const reader = new FileReader(); 10 reader.onload = onFileLoad; 11 reader.readAsDataURL(file); 12 } 13 14 // 加载图片数据 15 function onFileLoad(src) { 16 oImg.onload = function() { 17 onImageLoad(oImg)// 这里使用图像数据 18 }; 19 oImg.src = (src.target ? src.target.result : src); 20 } 21 22 const oCanvas = document.getElementById(‘my-canvas‘); 23 var ctx; 24 var width; 25 var height; 26 var imageData; 27 var data; 28 var imageData0;//原图,防止亮度、对比度调节不可逆 29 // 上面读取资源的操作后,将图像画到canvas上 30 function onImageLoad(img) { 31 width =oCanvas.width= img.naturalWidth || img.width; 32 height =oCanvas.height= img.naturalHeight || img.height; 33 ctx = oCanvas.getContext("2d"); 34 35 ctx.drawImage(img, 0, 0,width,height); 36 // 获取画布像素信息 37 imageData = ctx.getImageData(0, 0, width, height); 38 data = imageData.data; 39 console.log(data); 40 imageData0=ctx.getImageData(0, 0, width, height); 41 } 42 43 //亮度调节,没有调很暗 44 var scroll = document.getElementById(‘scroll‘); 45 var bar = document.getElementById(‘bar‘); 46 var mask = document.getElementById(‘mask‘); 47 var ptxt = document.getElementsByTagName(‘p‘)[2]; 48 var barleft = 0; 49 var data1 = 0; //获取调完亮度后的图片数据 50 51 //对比度调节 52 var scroll0 = document.getElementById(‘scroll0‘); 53 var bar0 = document.getElementById(‘bar0‘); 54 var mask0 = document.getElementById(‘mask0‘); 55 var ptxt0 = document.getElementsByTagName(‘p‘)[4]; 56 var barleft0 = 0; 57 var data2;//获取调完对比后的图片数据 58 59 var lastImgArr=[];//设置缓存,方便后续的撤销功能 60 61 //亮度调节 62 bar.onmousedown = function(event){ 63 if(data==undefined){ 64 alert("请输入图片"); 65 } 66 var event = event || window.event; 67 var leftVal = event.clientX - this.offsetLeft; 68 var that = this; 69 var data0=imageData0.data; 70 document.onmousemove = function(event){ 71 var event = event || window.event; 72 barleft = event.clientX - leftVal; 73 if(barleft < 0) 74 barleft = 0; 75 else if(barleft > scroll.offsetWidth - bar.offsetWidth) 76 barleft = scroll.offsetWidth - bar.offsetWidth; 77 mask.style.width = barleft +‘px‘ ; 78 that.style.left = barleft + "px"; 79 var rgbnum=parseInt(barleft/(scroll.offsetWidth-bar.offsetWidth) * 100-50) 80 ptxt.innerHTML = parseInt(rgbnum) + "%"; 81 82 for(var i = 0; i < data.length; i += 4 ) { 83 if(parseInt(data0[i]+parseInt(rgbnum)/50*255)>255) 84 data[i]=255; 85 else if(parseInt(data0[i]+parseInt(rgbnum)/50*255)<0) 86 data[i]=0; 87 else data[i] = data0[i]+parseInt(rgbnum)/50*255; 88 if(parseInt(data0[i+1]+parseInt(rgbnum)/50*255)>255) 89 data[i+1]=255; 90 else if(parseInt(data0[i+1]+parseInt(rgbnum)/50*255)<0) 91 data[i+1]=0; 92 else data[i+1] = data0[i+1]+ parseInt(rgbnum)/50*255; 93 if(parseInt(data0[i+2]+parseInt(rgbnum)/50*255)>255) 94 data[i+2]=255; 95 else if(parseInt(data0[i+2]+parseInt(rgbnum)/50*255)<0) 96 data[i+2]=0; 97 else data[i+2] = data0[i+2]+ parseInt(rgbnum)/50*255; 98 } 99 if(barleft0!=0){ 100 for(var i = 0; i < data.length; i += 4 ) { 101 if(parseInt(data[i]+data2[i]-data0[i])>255) 102 data[i]=255; 103 else if(parseInt(data[i]+data2[i]-data0[i])<0) 104 data[i]=0; 105 else data[i] = data[i]+data2[i]-data0[i]; 106 if(parseInt(data[i+1]+data2[i+1]-data0[i+1])>255) 107 data[i+1]=255; 108 else if(parseInt(data[i+1]+data2[i+1]-data0[i+1])<0) 109 data[i+1]=0; 110 else data[i+1] = data[i+1]+data2[i+1]-data0[i+1]; 111 if(parseInt(data[i+2]+data2[i+2]-data0[i+2])>255) 112 data[i+2]=255; 113 else if(parseInt(data[i+2]+data2[i+2]-data0[i+2])<0) 114 data[i+2]=0; 115 else data[i+2] = data[i+2]+data2[i+2]-data0[i+2]; 116 } 117 } 118 119 ctx.putImageData(imageData, 0, 0); 120 data1 = data; 121 window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty(); 122 } 123 124 } 125 126 //对比度调节 127 bar0.onmousedown = function(event){ 128 if(data==undefined){ 129 alert("请输入图片"); 130 } 131 132 var event = event || window.event; 133 var leftVal = event.clientX - this.offsetLeft; 134 var that = this; 135 var data0=imageData0.data; 136 // 拖动一定写到 down 里面才可以 137 document.onmousemove = function(event){ 138 var event = event || window.event; 139 barleft0 = event.clientX - leftVal; 140 if(barleft0 < 0) 141 barleft0 = 0; 142 else if(barleft0 > scroll.offsetWidth - bar0.offsetWidth) 143 barleft = scroll.offsetWidth - bar0.offsetWidth; 144 mask0.style.width = barleft0 +‘px‘; 145 that.style.left = barleft0 + "px"; 146 var rgbnum=parseInt(barleft0/(scroll0.offsetWidth-bar0.offsetWidth) * 100-50) 147 ptxt0.innerHTML = parseInt(rgbnum) + "%"; 148 var avg=127; 149 //RGB = RGB + (RGB - avg) * Contrast / 255 150 for(var i = 0; i < data.length; i += 4 ) { 151 if(parseInt(data0[i]+(data0[i]-127)*parseInt(rgbnum)/50)>255) 152 data[i]=255; 153 else if(parseInt(data0[i]+(data0[i]-127)*parseInt(rgbnum)/50)<0) 154 data[i]=0; 155 else data[i] = data0[i]+(data0[i+1]-127)*parseInt(rgbnum)/50; 156 if(parseInt(data0[i+1]+(data0[i+1]-127)*parseInt(rgbnum)/50)>255) 157 data[i+1]=255; 158 else if(parseInt(data0[i+1]+(data0[i+1]-127)*parseInt(rgbnum)/50)<0) 159 data[i+1]=0; 160 else data[i+1] = data0[i+1]+ (data0[i+1]-127)*parseInt(rgbnum)/50; 161 if(parseInt(data0[i+2]+(data0[i+2]-127)*parseInt(rgbnum)/50)>255) 162 data[i+2]=255; 163 else if(parseInt(data0[i+2]+(data0[i+2]-127)*parseInt(rgbnum)/50)<0) 164 data[i+2]=0; 165 else data[i+2] = data0[i+2]+ (data0[i+2]-127)*parseInt(rgbnum)/50; 166 } 167 if(barleft!=0){ 168 for(var i = 0; i < data.length; i += 4 ) { 169 if(parseInt(data[i]+data1[i]-data0[i])>255) 170 data[i]=255; 171 else if(parseInt(data[i]+data1[i]-data0[i])<0) 172 data[i]=0; 173 else data[i] = data[i]+data1[i]-data0[i]; 174 if(parseInt(data[i+1]+data1[i+1]-data0[i+1])>255) 175 data[i+1]=255; 176 else if(parseInt(data[i+1]+data1[i+1]-data0[i+1])<0) 177 data[i+1]=0; 178 else data[i+1] = data[i+1]+data1[i+1]-data0[i+1]; 179 if(parseInt(data[i+2]+data1[i+2]-data0[i+2])>255) 180 data[i+2]=255; 181 else if(parseInt(data[i+2]+data1[i+2]-data0[i+2])<0) 182 data[i+2]=0; 183 else data[i+2] = data[i+2]+data1[i+2]-data0[i+2]; 184 } 185 } 186 ctx.putImageData(imageData, 0, 0); 187 data2=data; 188 window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty(); 189 } 190 } 191 document.onmouseup = function(){ 192 document.onmousemove = null; //弹起鼠标不做任何操作 193 } 194 195 //功能 196 //马赛克 放大 缩小 旋转 镜像 水平镜像 197 var msk = document.getElementById(‘id_msk‘); 198 var fd = document.getElementById(‘id_fd‘); 199 var sx = document.getElementById(‘id_sx‘); 200 var xz = document.getElementById(‘id_xz‘); 201 var jx = document.getElementById(‘id_jx‘); 202 var hjx = document.getElementById(‘id_hjx‘); 203 //叠图操作 204 var right = document.getElementById(‘img_right‘); 205 var wrong = document.getElementById(‘img_wrong‘); 206 var comeon = document.getElementById(‘img_comeon‘); 207 var good = document.getElementById(‘img_good‘); 208 var displayxy = document.getElementById(‘img_displayxy‘); 209 var display = document.getElementById(‘img_display‘);//色块显示 210 var actions=[msk,fd,sx,xz,jx,hjx,right,wrong,comeon,good,displayxy]; 211 212 //功能选中-》蓝色 213 function setStatus(arr,num,type){ 214 for(var i=0;i<arr.length;i++){ 215 if(i==num){ 216 arr[i].style.background="#0e92b3"; 217 }else{ 218 arr[i].style.background="#fff"; 219 } 220 } 221 } 222 223 224 225 //马赛克,鼠标事件控制 226 var msk_size=3; 227 var msk_num=3; 228 drawLine=function(dx,dy){ 229 230 //原始图像 231 var originalImgData = ctx.getImageData(0,0,oCanvas.width,oCanvas.height); 232 var originalPxData = originalImgData.data; 233 //用于循环修改 234 var modifyImgData = ctx.getImageData(0,0,oCanvas.width,oCanvas.height); 235 var modifyPxData = modifyImgData.data; 236 for(var i=parseInt(dx-(msk_size*2+1)*msk_num);i<parseInt(dx+(msk_size*2+1)*msk_num);i = parseInt(i+2*msk_size+1)){ 237 for(var j=parseInt(dy-(msk_size*2+1)*msk_num);j<parseInt(dy+(msk_size*2+1)*msk_num);j = parseInt(j+2*msk_size+1)){ 238 //中心点(dx,dy) 239 var sumR = parseInt(0); 240 var sumG = parseInt(0); 241 var sumB = parseInt(0); 242 //找他周围的元素 243 for(var x = -msk_size;x<=parseInt(msk_size);x++){ 244 for(var y = -msk_size;y<=parseInt(msk_size);y++){ 245 var xx = i+x; 246 var yy = j+y; 247 var pp = parseInt(yy*oCanvas.width+xx); //周围的元素。 248 var temp0=parseInt(pp*4); 249 sumR += parseInt(originalPxData[temp0+0]); 250 sumG += parseInt(originalPxData[temp0+1]); 251 sumB += parseInt(originalPxData[temp0+2]); 252 } 253 } 254 var totlal = (2*msk_size+1)*(2*msk_size+1); 255 var avgR = sumR/totlal; 256 var avgG = sumG/totlal; 257 var avgB = sumB/totlal; 258 259 for(var x = -msk_size;x<=msk_size;x++){ 260 for(var y = -msk_size;y<=msk_size;y++){ 261 var xx = i+x; 262 var yy = j+y; 263 var pp = yy*oCanvas.width+xx; //周围的元素。 264 modifyPxData[pp*4+0] = avgR; 265 modifyPxData[pp*4+1] = avgG; 266 modifyPxData[pp*4+2] = avgB; 267 } 268 } 269 } 270 } 271 ctx.putImageData(modifyImgData,0,0); 272 273 } 274 function drawmsk(num){ 275 if(data==undefined){ 276 alert("请输入图片"); 277 } 278 setStatus(actions,num,1); 279 var flag=0; 280 var dx; 281 var dy; 282 oCanvas.onmousedown=function(ev){ 283 var ev=window.event||ev; 284 dx = ev.pageX-oCanvas.offsetLeft; 285 dy = ev.pageY-oCanvas.offsetTop; 286 console.log(dx); 287 drawLine(dx,dy); //开始画马塞克 288 flag=1; 289 }; 290 oCanvas.onmousemove=function(ev){ 291 var ev = window.event||ev; 292 var mx = ev.pageX-oCanvas.offsetLeft; 293 var my = ev.pageY-oCanvas.offsetTop; 294 if(flag) 295 if(Math.pow(dx-mx,2)+Math.pow(dy-my,2)>= Math.pow(msk_size,2)){ //超出马赛克1/2长 296 drawLine(mx,my); 297 dx = mx; 298 dy = my; 299 } 300 }; 301 oCanvas.onmouseup=function(){ 302 imageData0=ctx.getImageData(0,0,oCanvas.width,oCanvas.height); 303 flag=0; 304 } 305 oCanvas.onmouseout=function(){ 306 imageData0=ctx.getImageData(0,0,oCanvas.width,oCanvas.height); 307 flag=0; 308 } 309 } 310 //放大,点一次扩大1.2倍 311 function zoomin(num){ 312 if(data==undefined){ 313 alert("请输入图片"); 314 } 315 console.log("fd"); 316 oCanvas.width=parseInt(oCanvas.width*1.2); 317 oCanvas.height=parseInt(oCanvas.height*1.2); 318 var datatemp=imageData0.data; 319 console.log(imageData0); 320 imageData=ctx.getImageData(0,0,oCanvas.width,oCanvas.height); 321 console.log(imageData); 322 data=imageData.data; 323 for(var i = 0; i < parseInt(oCanvas.width*oCanvas.height); i++) { 324 var dx=i%oCanvas.width; 325 var dy=(i-dx)/oCanvas.width; 326 var mx=parseInt(dx/1.2); 327 var my=parseInt(dy/1.2); 328 if(parseInt(mx)>parseInt(width)) 329 { 330 mx=width; 331 } 332 if(parseInt(my)>parseInt(height)){ 333 my=height; 334 } 335 data[(dy*oCanvas.width+dx)*4+0]=datatemp[(my*width+mx)*4+0]; 336 data[(dy*oCanvas.width+dx)*4+1]=datatemp[(my*width+mx)*4+1]; 337 data[(dy*oCanvas.width+dx)*4+2]=datatemp[(my*width+mx)*4+2]; 338 data[(dy*oCanvas.width+dx)*4+3]=datatemp[(my*width+mx)*4+3]; 339 } 340 console.log(data); 341 imageData.data=data; 342 console.log(imageData); 343 ctx.putImageData(imageData,0,0); 344 width=oCanvas.width; 345 height=oCanvas.height; 346 imageData0=imageData; 347 } 348 //缩小 349 function zoomout(num){ 350 if(data==undefined){ 351 alert("请输入图片"); 352 } 353 oCanvas.width=parseInt(oCanvas.width/1.2); 354 oCanvas.height=parseInt(oCanvas.height/1.2); 355 var datatemp=imageData0.data; 356 console.log(imageData0); 357 imageData=ctx.getImageData(0,0,oCanvas.width,oCanvas.height); 358 console.log(imageData); 359 data=imageData.data; 360 for(var i = 0; i < parseInt(oCanvas.width*oCanvas.height); i++) { 361 var dx=i%oCanvas.width; 362 var dy=(i-dx)/oCanvas.width; 363 var mx=parseInt(dx*1.2); 364 var my=parseInt(dy*1.2); 365 if(parseInt(mx)>parseInt(width)) 366 { 367 mx=width; 368 } 369 if(parseInt(my)>parseInt(height)){ 370 my=height; 371 } 372 data[(dy*oCanvas.width+dx)*4+0]=datatemp[(my*width+mx)*4+0]; 373 data[(dy*oCanvas.width+dx)*4+1]=datatemp[(my*width+mx)*4+1]; 374 data[(dy*oCanvas.width+dx)*4+2]=datatemp[(my*width+mx)*4+2]; 375 data[(dy*oCanvas.width+dx)*4+3]=datatemp[(my*width+mx)*4+3]; 376 } 377 console.log(data); 378 imageData.data=data; 379 console.log(imageData); 380 ctx.putImageData(imageData,0,0); 381 width=oCanvas.width; 382 height=oCanvas.height; 383 imageData0=imageData; 384 } 385 386 387 //旋转 388 function rotate(num){ 389 if(data==undefined){ 390 alert("请输入图片"); 391 } 392 var text=document.getElementById("id_xz0").value; 393 console.log(text); 394 if(text==NaN||text==undefined ||text==0 ||text==null){ 395 alert("填入角度"); 396 } 397 var num0=parseInt(text); 398 console.log(num0); 399 imageData=ctx.getImageData(0,0,oCanvas.width,oCanvas.height); 400 data=imageData.data; 401 402 var datatemp0=new Array(data.length); 403 var datatemp1=new Array(data.length); 404 for(var i=0;i<data.length;i++){ 405 datatemp0[i]=0; 406 datatemp1[i]=0; 407 } 408 409 var thita=parseFloat(Math.PI*num0/180); 410 console.log(oCanvas.width); 411 console.log(oCanvas.height); 412 for(var i=0;i < parseInt(oCanvas.width*oCanvas.height);i++){ 413 var dx=i%parseInt(oCanvas.width); 414 var dy=(i-dx)/oCanvas.width; 415 datatemp0[(dy*oCanvas.width+dx)*4+0]=parseInt(dy+1); 416 datatemp0[(dy*oCanvas.width+dx)*4+1]=parseInt(dy+1); 417 datatemp0[(dy*oCanvas.width+dx)*4+2]=parseInt(dy+1); 418 datatemp0[(dy*oCanvas.width+dx)*4+3]=parseInt(dy+1); 419 420 datatemp1[(dy*oCanvas.width+dx)*4+0]=parseInt(dx+1); 421 datatemp1[(dy*oCanvas.width+dx)*4+1]=parseInt(dx+1); 422 datatemp1[(dy*oCanvas.width+dx)*4+2]=parseInt(dx+1); 423 datatemp1[(dy*oCanvas.width+dx)*4+3]=parseInt(dx+1); 424 } 425 console.log(datatemp0); 426 console.log(datatemp1); 427 428 var datatemp00=new Array(datatemp0.length); 429 var datatemp11=new Array(datatemp0.length); 430 var max0=0; 431 var min0=oCanvas.width+oCanvas.height; 432 var max1=0; 433 var min1=oCanvas.width+oCanvas.height; 434 console.log(Math.cos(thita)); 435 console.log(Math.sin(thita)); 436 for(var i=0;i<parseInt(oCanvas.width*oCanvas.height);i++){ 437 var dx=i%oCanvas.width; 438 var dy=(i-dx)/oCanvas.width; 439 //逆时针旋转thita度 440 datatemp00[(dy*oCanvas.width+dx)*4+0]= parseInt(datatemp0[(dy*oCanvas.width+dx)*4+0]*Math.cos(thita)- datatemp1[(dy*oCanvas.width+dx)*4+0]*Math.sin(thita)); 441 datatemp11[(dy*oCanvas.width+dx)*4+0]= parseInt(datatemp0[(dy*oCanvas.width+dx)*4+0]*Math.sin(thita)+ datatemp1[(dy*oCanvas.width+dx)*4+0]*Math.cos(thita)); 442 443 datatemp00[(dy*oCanvas.width+dx)*4+1]= parseInt(datatemp0[(dy*oCanvas.width+dx)*4+1]*Math.cos(thita)- datatemp1[(dy*oCanvas.width+dx)*4+1]*Math.sin(thita)); 444 datatemp11[(dy*oCanvas.width+dx)*4+1]= parseInt(datatemp0[(dy*oCanvas.width+dx)*4+1]*Math.sin(thita)+ datatemp1[(dy*oCanvas.width+dx)*4+1]*Math.cos(thita)); 445 446 datatemp00[(dy*oCanvas.width+dx)*4+2]= parseInt(datatemp0[(dy*oCanvas.width+dx)*4+2]*Math.cos(thita)- datatemp1[(dy*oCanvas.width+dx)*4+2]*Math.sin(thita)); 447 datatemp11[(dy*oCanvas.width+dx)*4+2]= parseInt(datatemp0[(dy*oCanvas.width+dx)*4+2]*Math.sin(thita)+ datatemp1[(dy*oCanvas.width+dx)*4+2]*Math.cos(thita)); 448 449 datatemp00[(dy*oCanvas.width+dx)*4+3]= parseInt(datatemp0[(dy*oCanvas.width+dx)*4+3]*Math.cos(thita)- datatemp1[(dy*oCanvas.width+dx)*4+3]*Math.sin(thita)); 450 datatemp11[(dy*oCanvas.width+dx)*4+3]= parseInt(datatemp0[(dy*oCanvas.width+dx)*4+3]*Math.sin(thita)+ datatemp1[(dy*oCanvas.width+dx)*4+3]*Math.cos(thita)); 451 452 if(min0>parseInt(datatemp00[(dy*oCanvas.width+dx)*4+0])){ 453 min0=datatemp00[(dy*oCanvas.width+dx)*4+0]; 454 } 455 if(min1>parseInt(datatemp11[(dy*oCanvas.width+dx)*4+0])){ 456 min1=datatemp11[(dy*oCanvas.width+dx)*4+0]; 457 } 458 } 459 460 console.log(min0); 461 console.log(min1); 462 for(var j=0;j<datatemp00.length;j++){ 463 datatemp00[j]=datatemp00[j]+(1-min0); 464 datatemp11[j]=datatemp11[j]+(1-min1); 465 } 466 console.log(datatemp00); 467 for(var i=0;i<parseInt(oCanvas.width*oCanvas.height);i++){ 468 var dx=i%oCanvas.width; 469 var dy=(i-dx)/oCanvas.width; 470 //逆时针旋转thita度 471 if(max0<parseInt(datatemp00[(dy*oCanvas.width+dx)*4+0])){ 472 max0=datatemp00[(dy*oCanvas.width+dx)*4+0]; 473 } 474 if(max1<parseInt(datatemp11[(dy*oCanvas.width+dx)*4+0])){ 475 max1=datatemp11[(dy*oCanvas.width+dx)*4+0]; 476 } 477 } 478 console.log(max0); 479 console.log(max1); 480 console.log(datatemp00); 481 console.log(datatemp11); 482 oCanvas.width=max1; 483 oCanvas.height=max0; 484 var len=oCanvas.width*oCanvas.height*4; 485 var imageDatatemp0=ctx.getImageData(0,0,oCanvas.width,oCanvas.height); 486 var data_ =imageDatatemp0.data; 487 for(var j=0;j<len;j++){ 488 data_[j]=0; 489 } 490 var datalast=data; 491 console.log(datalast); 492 493 for(var i=0;i<parseInt(width*height);i++){ 494 var dx=i%width; 495 var dy=(i-dx)/width; 496 var mx; 497 var my; 498 mx=parseInt(datatemp11[(dy*width+dx)*4+0])-1; 499 my=parseInt(datatemp00[(dy*width+dx)*4+0])-1; 500 data_[(my*oCanvas.width+mx)*4+0]=datalast[(dy*width+dx)*4+0]; 501 502 mx=parseInt(datatemp11[(dy*width+dx)*4+1])-1; 503 my=parseInt(datatemp00[(dy*width+dx)*4+1])-1; 504 data_[(my*oCanvas.width+mx)*4+1]=datalast[(dy*width+dx)*4+1]; 505 506 mx=parseInt(datatemp11[(dy*width+dx)*4+2])-1; 507 my=parseInt(datatemp00[(dy*width+dx)*4+2])-1; 508 data_[(my*oCanvas.width+mx)*4+2]=datalast[(dy*width+dx)*4+2]; 509 510 mx=parseInt(datatemp11[(dy*width+dx)*4+3])-1; 511 my=parseInt(datatemp00[(dy*width+dx)*4+3])-1; 512 data_[(my*oCanvas.width+mx)*4+3]=datalast[(dy*width+dx)*4+3]; 513 514 } 515 console.log(datalast); 516 517 thita=-thita; 518 for(var i=0;i<parseInt(oCanvas.width*oCanvas.height);i++){ 519 var dx=i%oCanvas.width; 520 var dy=(i-dx)/oCanvas.width; 521 var di=dy+1; 522 var dj=dx+1; 523 var mx=parseInt(di-(1-min0)); 524 var my=parseInt(dj-(1-min1)); 525 var fx=mx*Math.cos(thita)-my*Math.sin(thita); 526 var fy=mx*Math.sin(thita)+my*Math.cos(thita); 527 var invx=parseInt(mx*Math.cos(thita)-my*Math.sin(thita));//逆时针旋转thita度 528 var invy=parseInt(mx*Math.sin(thita)+my*Math.cos(thita)); 529 var temp; 530 if(invx>1 && parseInt(invx)<=height && parseInt(invy)>1 && parseInt(invy)<=width){ 531 if( data_[(dy*oCanvas.width+dx)*4+2]==0 && data_[(dy*oCanvas.width+dx)*4+1]==0 && data_[(dy*oCanvas.width+dx)*4+0]==0) 532 { 533 temp = datalast[((invy-2)*height+(invx-2))*4+0]*(invx-fx)*(invy-fy)+datalast[((invy-2)*height+(invx-1))*4+0]*(fx+1-invx)*(invy-fy)+datalast[((invy-1)*height+(invx-2))*4+0]*(fy+1-invy)*(invx-fx)+datalast[((invy-1)*height+(invx-1))*4+0]*(fx+1-invx)*(fy+1-invy); 534 data_[(dy*oCanvas.width+dx)*4+0]=parseInt(temp); 535 536 temp = datalast[((invy-2)*height+(invx-2))*4+1]*(invx-fx)*(invy-fy)+datalast[((invy-2)*height+(invx-1))*4+1]*(fx+1-invx)*(invy-fy)+datalast[((invy-1)*height+(invx-2))*4+1]*(fy+1-invy)*(invx-fx)+datalast[((invy-1)*height+(invx-1))*4+1]*(fx+1-invx)*(fy+1-invy); 537 data_[(dy*oCanvas.width+dx)*4+1]=parseInt(temp); 538 539 temp = datalast[((invy-2)*height+(invx-2))*4+2]*(invx-fx)*(invy-fy)+datalast[((invy-2)*height+(invx-1))*4+2]*(fx+1-invx)*(invy-fy)+datalast[((invy-1)*height+(invx-2))*4+2]*(fy+1-invy)*(invx-fx)+datalast[((invy-1)*height+(invx-1))*4+2]*(fx+1-invx)*(fy+1-invy); 540 data_[(dy*oCanvas.width+dx)*4+2]=parseInt(temp); 541 542 temp = datalast[((invy-2)*height+(invx-2))*4+3]*(invx-fx)*(invy-fy)+datalast[((invy-2)*height+(invx-1))*4+3]*(fx+1-invx)*(invy-fy)+datalast[((invy-1)*height+(invx-2))*4+3]*(fy+1-invy)*(invx-fx)+datalast[((invy-1)*height+(invx-1))*4+3]*(fx+1-invx)*(fy+1-invy); 543 data_[(dy*oCanvas.width+dx)*4+3]=parseInt(temp); 544 } 545 } 546 } 547 ctx.putImageData(imageDatatemp0,0,0); 548 width=oCanvas.width; 549 height=oCanvas.height; 550 imageData0=imageDatatemp0; 551 } 552 //镜像 553 function mirror(num){ 554 if(data==undefined){ 555 alert("请输入图片"); 556 } 557 imageData=ctx.getImageData(0,0,oCanvas.width,oCanvas.height); 558 data=imageData.data; 559 var datatemp=imageData0.data; 560 for(var i=0;i<oCanvas.width*oCanvas.height;i++){ 561 var dx=i%oCanvas.width; 562 var dy=(i-dx)/oCanvas.width; 563 data[(dy*oCanvas.width+(oCanvas.width-dx-1))*4+0]=datatemp[(dy*oCanvas.width+dx)*4+0]; 564 data[(dy*oCanvas.width+(oCanvas.width-dx-1))*4+1]=datatemp[(dy*oCanvas.width+dx)*4+1]; 565 data[(dy*oCanvas.width+(oCanvas.width-dx-1))*4+2]=datatemp[(dy*oCanvas.width+dx)*4+2]; 566 data[(dy*oCanvas.width+(oCanvas.width-dx-1))*4+3]=datatemp[(dy*oCanvas.width+dx)*4+3]; 567 } 568 ctx.putImageData(imageData,0,0); 569 width=oCanvas.width; 570 height=oCanvas.height; 571 imageData0=imageData; 572 } 573 //水平镜像 574 function hmirror(num){ 575 if(data==undefined){ 576 alert("请输入图片"); 577 } 578 imageData=ctx.getImageData(0,0,oCanvas.width,oCanvas.height); 579 data=imageData.data; 580 var datatemp=imageData0.data; 581 for(var i=0;i<oCanvas.width*oCanvas.height;i++){ 582 var dx=i%oCanvas.width; 583 var dy=(i-dx)/oCanvas.width; 584 data[((oCanvas.height-dy-1)*oCanvas.width+(dx))*4+0]=datatemp[(dy*oCanvas.width+dx)*4+0]; 585 data[((oCanvas.height-dy-1)*oCanvas.width+(dx))*4+1]=datatemp[(dy*oCanvas.width+dx)*4+1]; 586 data[((oCanvas.height-dy-1)*oCanvas.width+(dx))*4+2]=datatemp[(dy*oCanvas.width+dx)*4+2]; 587 data[((oCanvas.height-dy-1)*oCanvas.width+(dx))*4+3]=datatemp[(dy*oCanvas.width+dx)*4+3]; 588 } 589 ctx.putImageData(imageData,0,0); 590 width=oCanvas.width; 591 height=oCanvas.height; 592 imageData0=imageData; 593 } 594 595 //叠图 596 function addcanvas0(num){ 597 if(data==undefined){ 598 alert("请输入图片"); 599 } 600 setStatus(actions,num,1); 601 var imgObj=new Image(); 602 imgObj.crossOrigin="Anonymous"; 603 imgObj.src="./right.png"; 604 var img_width = 50; 605 var img_height = 50; 606 607 oCanvas.onmousedown=function(ev){ 608 console.log("贴图"); 609 var ev=window.event||ev; 610 var dx = ev.pageX-oCanvas.offsetLeft; 611 var dy = ev.pageY-oCanvas.offsetTop; 612 ctx.drawImage(imgObj, parseInt(dx-(img_width)/2), parseInt(dy-(img_height)/2),50,50); 613 } 614 } 615 616 function addcanvas1(num){ 617 if(data==undefined){ 618 alert("请输入图片"); 619 } 620 setStatus(actions,num,1); 621 var imgObj=new Image(); 622 imgObj.crossOrigin="Anonymous"; 623 imgObj.src="./wrong.png"; 624 var img_width = 50; 625 var img_height = 50; 626 627 oCanvas.onmousedown=function(ev){ 628 console.log("贴图"); 629 var ev=window.event||ev; 630 var dx = ev.pageX-oCanvas.offsetLeft; 631 var dy = ev.pageY-oCanvas.offsetTop; 632 ctx.drawImage(imgObj, parseInt(dx-(img_width)/2), parseInt(dy-(img_height)/2),50,50); 633 } 634 } 635 function addcanvas2(num){ 636 if(data==undefined){ 637 alert("请输入图片"); 638 } 639 setStatus(actions,num,1); 640 var imgObj=new Image(); 641 imgObj.crossOrigin="Anonymous"; 642 imgObj.src="./comeon.png"; 643 var img_width = 50; 644 var img_height = 50; 645 646 oCanvas.onmousedown=function(ev){ 647 console.log("贴图"); 648 var ev=window.event||ev; 649 var dx = ev.pageX-oCanvas.offsetLeft; 650 var dy = ev.pageY-oCanvas.offsetTop; 651 ctx.drawImage(imgObj, parseInt(dx-(img_width)/2), parseInt(dy-(img_height)/2),50,50); 652 } 653 } 654 function addcanvas3(num){ 655 if(data==undefined){ 656 alert("请输入图片"); 657 } 658 setStatus(actions,num,1); 659 var imgObj=new Image(); 660 imgObj.crossOrigin="Anonymous"; 661 imgObj.src="./good.png"; 662 var img_width = 50; 663 var img_height = 50; 664 665 oCanvas.onmousedown=function(ev){ 666 console.log("贴图"); 667 var ev=window.event||ev; 668 var dx = ev.pageX-oCanvas.offsetLeft; 669 var dy = ev.pageY-oCanvas.offsetTop; 670 ctx.drawImage(imgObj, parseInt(dx-(img_width)/2), parseInt(dy-(img_height)/2),50,50); 671 672 } 673 } 674 //颜色显示 675 function addcanvas4(num){ 676 if(data==undefined){ 677 alert("请输入图片"); 678 } 679 setStatus(actions,num,1); 680 oCanvas.onmousemove=function(ev){ 681 var datatemp=imageData0.data; 682 var ev=window.event||ev; 683 var dx = ev.pageX-oCanvas.offsetLeft; 684 var dy = ev.pageY-oCanvas.offsetTop; 685 var pp = parseInt(dy*oCanvas.width+dx); 686 var temp0=parseInt(pp*4); 687 var R0 = parseInt(datatemp[temp0+0]); 688 var G0 = parseInt(datatemp[temp0+1]); 689 var B0 = parseInt(datatemp[temp0+2]); 690 display.style.background="rgb("+R0+","+G0+","+B0+")"; 691 } 692 }