• js+html canvas进行数字图像处理:亮度、对比度、马赛克画笔、放大缩小、镜像、贴纸、旋转、颜色值显示


    ①  亮度调整:进度条拖动实现亮度改变。

    ②  对比度调整:进度条拖动实现对比度改变。

    ③  马赛克笔刷:点击图标,在画布上鼠标-点击-拖动实现局部马赛克处理。

    ④  放大:点击放大图标,实现图片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 }
    View Code
  • 相关阅读:
    1114 Family Property (25 分)(并查集)
    【专题复习4:Dijkstra】1003、1018、1030、1072、1087、1111
    1133 Splitting A Linked List (25 分)(链表)
    【专题复习5:并查集】1107、1114、1118
    Java Window 下安装 java
    OpenShift4 节点TimeZone修改
    PHP魔术方法
    .NET中的HashSet
    格式化字符串
    Jetpack Compose
  • 原文地址:https://www.cnblogs.com/jwm1999/p/13056344.html
Copyright © 2020-2023  润新知