zl程序教程

您现在的位置是:首页 >  前端

当前栏目

JavaScript实现的图像模糊算法代码分享

JavaScript算法代码 实现 分享 图像 模糊
2023-06-13 09:15:25 时间

项目中需要用到HTML5模糊图像,以前用GDI,GDI+中都有现成的组件来实现,HTML5中如何实现?
1.createImageData()
2.getImageData()
3.putImageData()
以上3个函数即可实现,用法和奥义,自己百度吧,我就不重复叙述了,没多大的意义。

以下是实现模糊算法的JS,其实还有种2B级算法就是分布矩阵,这样效率提高很多倍,不过效果很差,羽化的效果不强。
实现代码:

复制代码代码如下:

varmul_table=[
       512,512,456,512,328,456,335,512,405,328,271,456,388,335,292,512,
       454,405,364,328,298,271,496,456,420,388,360,335,312,292,273,512,
       482,454,428,405,383,364,345,328,312,298,284,271,259,496,475,456,
       437,420,404,388,374,360,347,335,323,312,302,292,282,273,265,512,
       497,482,468,454,441,428,417,405,394,383,373,364,354,345,337,328,
       320,312,305,298,291,284,278,271,265,259,507,496,485,475,465,456,
       446,437,428,420,412,404,396,388,381,374,367,360,354,347,341,335,
       329,323,318,312,307,302,297,292,287,282,278,273,269,265,261,512,
       505,497,489,482,475,468,461,454,447,441,435,428,422,417,411,405,
       399,394,389,383,378,373,368,364,359,354,350,345,341,337,332,328,
       324,320,316,312,309,305,301,298,294,291,287,284,281,278,274,271,
       268,265,262,259,257,507,501,496,491,485,480,475,470,465,460,456,
       451,446,442,437,433,428,424,420,416,412,408,404,400,396,392,388,
       385,381,377,374,370,367,363,360,357,354,350,347,344,341,338,335,
       332,329,326,323,320,318,315,312,310,307,304,302,299,297,294,292,
       289,287,285,282,280,278,275,273,271,269,267,265,263,261,259];

  
varshg_table=[
        9,11,12,13,13,14,14,15,15,15,15,16,16,16,16,17,
       17,17,17,17,17,17,18,18,18,18,18,18,18,18,18,19,
       19,19,19,19,19,19,19,19,19,19,19,19,19,20,20,20,
       20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,21,
       21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,
       21,21,21,21,21,21,21,21,21,21,22,22,22,22,22,22,
       22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,
       22,22,22,22,22,22,22,22,22,22,22,22,22,22,22,23,
       23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
       23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
       23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,23,
       23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,
       24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
       24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
       24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,
       24,24,24,24,24,24,24,24,24,24,24,24,24,24,24];

functionstackBlurImage(imageID,canvasID,radius,blurAlphaChannel)
{

    varimg=document.getElementById(imageID);
   varw=img.naturalWidth;
   varh=img.naturalHeight;

   varcanvas=document.getElementById(canvasID);

   canvas.style.width =w+"px";
   canvas.style.height=h+"px";
   canvas.width=w;
   canvas.height=h;

   varcontext=canvas.getContext("2d");
   context.clearRect(0,0,w,h);
   context.drawImage(img,0,0);

   if(isNaN(radius)||radius<1)return;

   if(blurAlphaChannel)
       stackBlurCanvasRGBA(canvasID,0,0,w,h,radius);
   else
       stackBlurCanvasRGB(canvasID,0,0,w,h,radius);
}


functionstackBlurCanvasRGBA(id,top_x,top_y,width,height,radius)
{
   if(isNaN(radius)||radius<1)return;
   radius|=0;

   varcanvas =document.getElementById(id);
   varcontext=canvas.getContext("2d");
   varimageData;

   try{
     try{
       imageData=context.getImageData(top_x,top_y,width,height);
     }catch(e){

    
       try{
           netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
           imageData=context.getImageData(top_x,top_y,width,height);
       }catch(e){
           alert("Cannotaccesslocalimage");
           thrownewError("unabletoaccesslocalimagedata:"+e);
           return;
       }
     }
   }catch(e){
     alert("Cannotaccessimage");
     thrownewError("unabletoaccessimagedata:"+e);
   }

   varpixels=imageData.data;

   varx,y,i,p,yp,yi,yw,r_sum,g_sum,b_sum,a_sum,
   r_out_sum,g_out_sum,b_out_sum,a_out_sum,
   r_in_sum,g_in_sum,b_in_sum,a_in_sum,
   pr,pg,pb,pa,rbs;

   vardiv=radius+radius+1;
   varw4=width<<2;
   varwidthMinus1 =width-1;
   varheightMinus1=height-1;
   varradiusPlus1 =radius+1;
   varsumFactor=radiusPlus1*(radiusPlus1+1)/2;

   varstackStart=newBlurStack();
   varstack=stackStart;
   for(i=1;i<div;i++)
   {
       stack=stack.next=newBlurStack();
       if(i==radiusPlus1)varstackEnd=stack;
   }
   stack.next=stackStart;
   varstackIn=null;
   varstackOut=null;

   yw=yi=0;

   varmul_sum=mul_table[radius];
   varshg_sum=shg_table[radius];

   for(y=0;y<height;y++)
   {
       r_in_sum=g_in_sum=b_in_sum=a_in_sum=r_sum=g_sum=b_sum=a_sum=0;

       r_out_sum=radiusPlus1*(pr=pixels[yi]);
       g_out_sum=radiusPlus1*(pg=pixels[yi+1]);
       b_out_sum=radiusPlus1*(pb=pixels[yi+2]);
       a_out_sum=radiusPlus1*(pa=pixels[yi+3]);

       r_sum+=sumFactor*pr;
       g_sum+=sumFactor*pg;
       b_sum+=sumFactor*pb;
       a_sum+=sumFactor*pa;

       stack=stackStart;

       for(i=0;i<radiusPlus1;i++)
       {
           stack.r=pr;
           stack.g=pg;
           stack.b=pb;
           stack.a=pa;
           stack=stack.next;
       }

       for(i=1;i<radiusPlus1;i++)
       {
           p=yi+((widthMinus1<i?widthMinus1:i)<<2);
           r_sum+=(stack.r=(pr=pixels[p]))*(rbs=radiusPlus1-i);
           g_sum+=(stack.g=(pg=pixels[p+1]))*rbs;
           b_sum+=(stack.b=(pb=pixels[p+2]))*rbs;
           a_sum+=(stack.a=(pa=pixels[p+3]))*rbs;

           r_in_sum+=pr;
           g_in_sum+=pg;
           b_in_sum+=pb;
           a_in_sum+=pa;

           stack=stack.next;
       }

       
       stackIn=stackStart;
       stackOut=stackEnd;
       for(x=0;x<width;x++)
       {
           pixels[yi+3]=pa=(a_sum*mul_sum)>>shg_sum;
           if(pa!=0)
           {
               pa=255/pa;
               pixels[yi]  =((r_sum*mul_sum)>>shg_sum)*pa;
               pixels[yi+1]=((g_sum*mul_sum)>>shg_sum)*pa;
               pixels[yi+2]=((b_sum*mul_sum)>>shg_sum)*pa;
           }else{
               pixels[yi]=pixels[yi+1]=pixels[yi+2]=0;
           }

           r_sum-=r_out_sum;
           g_sum-=g_out_sum;
           b_sum-=b_out_sum;
           a_sum-=a_out_sum;

           r_out_sum-=stackIn.r;
           g_out_sum-=stackIn.g;
           b_out_sum-=stackIn.b;
           a_out_sum-=stackIn.a;

           p= (yw+((p=x+radius+1)<widthMinus1?p:widthMinus1))<<2;

           r_in_sum+=(stackIn.r=pixels[p]);
           g_in_sum+=(stackIn.g=pixels[p+1]);
           b_in_sum+=(stackIn.b=pixels[p+2]);
           a_in_sum+=(stackIn.a=pixels[p+3]);

           r_sum+=r_in_sum;
           g_sum+=g_in_sum;
           b_sum+=b_in_sum;
           a_sum+=a_in_sum;

           stackIn=stackIn.next;

           r_out_sum+=(pr=stackOut.r);
           g_out_sum+=(pg=stackOut.g);
           b_out_sum+=(pb=stackOut.b);
           a_out_sum+=(pa=stackOut.a);

           r_in_sum-=pr;
           g_in_sum-=pg;
           b_in_sum-=pb;
           a_in_sum-=pa;

           stackOut=stackOut.next;

           yi+=4;
       }
       yw+=width;
   }

   
   for(x=0;x<width;x++)
   {
       g_in_sum=b_in_sum=a_in_sum=r_in_sum=g_sum=b_sum=a_sum=r_sum=0;

       yi=x<<2;
       r_out_sum=radiusPlus1*(pr=pixels[yi]);
       g_out_sum=radiusPlus1*(pg=pixels[yi+1]);
       b_out_sum=radiusPlus1*(pb=pixels[yi+2]);
       a_out_sum=radiusPlus1*(pa=pixels[yi+3]);

       r_sum+=sumFactor*pr;
       g_sum+=sumFactor*pg;
       b_sum+=sumFactor*pb;
       a_sum+=sumFactor*pa;

       stack=stackStart;

       for(i=0;i<radiusPlus1;i++)
       {
           stack.r=pr;
           stack.g=pg;
           stack.b=pb;
           stack.a=pa;
           stack=stack.next;
       }

       yp=width;

       for(i=1;i<=radius;i++)
       {
           yi=(yp+x)<<2;

           r_sum+=(stack.r=(pr=pixels[yi]))*(rbs=radiusPlus1-i);
           g_sum+=(stack.g=(pg=pixels[yi+1]))*rbs;
           b_sum+=(stack.b=(pb=pixels[yi+2]))*rbs;
           a_sum+=(stack.a=(pa=pixels[yi+3]))*rbs;

           r_in_sum+=pr;
           g_in_sum+=pg;
           b_in_sum+=pb;
           a_in_sum+=pa;

           stack=stack.next;

           if(i<heightMinus1)
           {
               yp+=width;
           }
       }

       yi=x;
       stackIn=stackStart;
       stackOut=stackEnd;
       for(y=0;y<height;y++)
       {
           p=yi<<2;
           pixels[p+3]=pa=(a_sum*mul_sum)>>shg_sum;
           if(pa>0)
           {
               pa=255/pa;
               pixels[p]  =((r_sum*mul_sum)>>shg_sum)*pa;
               pixels[p+1]=((g_sum*mul_sum)>>shg_sum)*pa;
               pixels[p+2]=((b_sum*mul_sum)>>shg_sum)*pa;
           }else{
               pixels[p]=pixels[p+1]=pixels[p+2]=0;
           }

           r_sum-=r_out_sum;
           g_sum-=g_out_sum;
           b_sum-=b_out_sum;
           a_sum-=a_out_sum;

           r_out_sum-=stackIn.r;
           g_out_sum-=stackIn.g;
           b_out_sum-=stackIn.b;
           a_out_sum-=stackIn.a;

           p=(x+(((p=y+radiusPlus1)<heightMinus1?p:heightMinus1)*width))<<2;

           r_sum+=(r_in_sum+=(stackIn.r=pixels[p]));
           g_sum+=(g_in_sum+=(stackIn.g=pixels[p+1]));
           b_sum+=(b_in_sum+=(stackIn.b=pixels[p+2]));
           a_sum+=(a_in_sum+=(stackIn.a=pixels[p+3]));

           stackIn=stackIn.next;

           r_out_sum+=(pr=stackOut.r);
           g_out_sum+=(pg=stackOut.g);
           b_out_sum+=(pb=stackOut.b);
           a_out_sum+=(pa=stackOut.a);

           r_in_sum-=pr;
           g_in_sum-=pg;
           b_in_sum-=pb;
           a_in_sum-=pa;

           stackOut=stackOut.next;

           yi+=width;
       }
   }

   context.putImageData(imageData,top_x,top_y);

}


functionstackBlurCanvasRGB(id,top_x,top_y,width,height,radius)
{
   if(isNaN(radius)||radius<1)return;
   radius|=0;

   varcanvas =document.getElementById(id);
   varcontext=canvas.getContext("2d");
   varimageData;

   try{
     try{
       imageData=context.getImageData(top_x,top_y,width,height);
     }catch(e){

 
       try{
           netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
           imageData=context.getImageData(top_x,top_y,width,height);
       }catch(e){
           alert("Cannotaccesslocalimage");
           thrownewError("unabletoaccesslocalimagedata:"+e);
           return;
       }
     }
   }catch(e){
     alert("Cannotaccessimage");
     thrownewError("unabletoaccessimagedata:"+e);
   }

   varpixels=imageData.data;

   varx,y,i,p,yp,yi,yw,r_sum,g_sum,b_sum,
   r_out_sum,g_out_sum,b_out_sum,
   r_in_sum,g_in_sum,b_in_sum,
   pr,pg,pb,rbs;

   vardiv=radius+radius+1;
   varw4=width<<2;
   varwidthMinus1 =width-1;
   varheightMinus1=height-1;
   varradiusPlus1 =radius+1;
   varsumFactor=radiusPlus1*(radiusPlus1+1)/2;

   varstackStart=newBlurStack();
   varstack=stackStart;
   for(i=1;i<div;i++)
   {
       stack=stack.next=newBlurStack();
       if(i==radiusPlus1)varstackEnd=stack;
   }
   stack.next=stackStart;
   varstackIn=null;
   varstackOut=null;

   yw=yi=0;

   varmul_sum=mul_table[radius];
   varshg_sum=shg_table[radius];

   for(y=0;y<height;y++)
   {
       r_in_sum=g_in_sum=b_in_sum=r_sum=g_sum=b_sum=0;

       r_out_sum=radiusPlus1*(pr=pixels[yi]);
       g_out_sum=radiusPlus1*(pg=pixels[yi+1]);
       b_out_sum=radiusPlus1*(pb=pixels[yi+2]);

       r_sum+=sumFactor*pr;
       g_sum+=sumFactor*pg;
       b_sum+=sumFactor*pb;

       stack=stackStart;

       for(i=0;i<radiusPlus1;i++)
       {
           stack.r=pr;
           stack.g=pg;
           stack.b=pb;
           stack=stack.next;
       }

       for(i=1;i<radiusPlus1;i++)
       {
           p=yi+((widthMinus1<i?widthMinus1:i)<<2);
           r_sum+=(stack.r=(pr=pixels[p]))*(rbs=radiusPlus1-i);
           g_sum+=(stack.g=(pg=pixels[p+1]))*rbs;
           b_sum+=(stack.b=(pb=pixels[p+2]))*rbs;

           r_in_sum+=pr;
           g_in_sum+=pg;
           b_in_sum+=pb;

           stack=stack.next;
       }

       
       stackIn=stackStart;
       stackOut=stackEnd;
       for(x=0;x<width;x++)
       {
           pixels[yi]  =(r_sum*mul_sum)>>shg_sum;
           pixels[yi+1]=(g_sum*mul_sum)>>shg_sum;
           pixels[yi+2]=(b_sum*mul_sum)>>shg_sum;

           r_sum-=r_out_sum;
           g_sum-=g_out_sum;
           b_sum-=b_out_sum;

           r_out_sum-=stackIn.r;
           g_out_sum-=stackIn.g;
           b_out_sum-=stackIn.b;

           p= (yw+((p=x+radius+1)<widthMinus1?p:widthMinus1))<<2;

           r_in_sum+=(stackIn.r=pixels[p]);
           g_in_sum+=(stackIn.g=pixels[p+1]);
           b_in_sum+=(stackIn.b=pixels[p+2]);

           r_sum+=r_in_sum;
           g_sum+=g_in_sum;
           b_sum+=b_in_sum;

           stackIn=stackIn.next;

           r_out_sum+=(pr=stackOut.r);
           g_out_sum+=(pg=stackOut.g);
           b_out_sum+=(pb=stackOut.b);

           r_in_sum-=pr;
           g_in_sum-=pg;
           b_in_sum-=pb;

           stackOut=stackOut.next;

           yi+=4;
       }
       yw+=width;
   }

   
   for(x=0;x<width;x++)
   {
       g_in_sum=b_in_sum=r_in_sum=g_sum=b_sum=r_sum=0;

       yi=x<<2;
       r_out_sum=radiusPlus1*(pr=pixels[yi]);
       g_out_sum=radiusPlus1*(pg=pixels[yi+1]);
       b_out_sum=radiusPlus1*(pb=pixels[yi+2]);

       r_sum+=sumFactor*pr;
       g_sum+=sumFactor*pg;
       b_sum+=sumFactor*pb;

       stack=stackStart;

       for(i=0;i<radiusPlus1;i++)
       {
           stack.r=pr;
           stack.g=pg;
           stack.b=pb;
           stack=stack.next;
       }

       yp=width;

       for(i=1;i<=radius;i++)
       {
           yi=(yp+x)<<2;

           r_sum+=(stack.r=(pr=pixels[yi]))*(rbs=radiusPlus1-i);
           g_sum+=(stack.g=(pg=pixels[yi+1]))*rbs;
           b_sum+=(stack.b=(pb=pixels[yi+2]))*rbs;

           r_in_sum+=pr;
           g_in_sum+=pg;
           b_in_sum+=pb;

           stack=stack.next;

           if(i<heightMinus1)
           {
               yp+=width;
           }
       }

       yi=x;
       stackIn=stackStart;
       stackOut=stackEnd;
       for(y=0;y<height;y++)
       {
           p=yi<<2;
           pixels[p]  =(r_sum*mul_sum)>>shg_sum;
           pixels[p+1]=(g_sum*mul_sum)>>shg_sum;
           pixels[p+2]=(b_sum*mul_sum)>>shg_sum;

           r_sum-=r_out_sum;
           g_sum-=g_out_sum;
           b_sum-=b_out_sum;

           r_out_sum-=stackIn.r;
           g_out_sum-=stackIn.g;
           b_out_sum-=stackIn.b;

           p=(x+(((p=y+radiusPlus1)<heightMinus1?p:heightMinus1)*width))<<2;

           r_sum+=(r_in_sum+=(stackIn.r=pixels[p]));
           g_sum+=(g_in_sum+=(stackIn.g=pixels[p+1]));
           b_sum+=(b_in_sum+=(stackIn.b=pixels[p+2]));

           stackIn=stackIn.next;

           r_out_sum+=(pr=stackOut.r);
           g_out_sum+=(pg=stackOut.g);
           b_out_sum+=(pb=stackOut.b);

           r_in_sum-=pr;
           g_in_sum-=pg;
           b_in_sum-=pb;

           stackOut=stackOut.next;

           yi+=width;
       }
   }

   context.putImageData(imageData,top_x,top_y);

}

functionBlurStack()
{
   this.r=0;
   this.g=0;
   this.b=0;
   this.a=0;
   this.next=null;
}

使用方法:

复制代码代码如下:

stackBlurImage(sourceImageID,targetCanvasID,radius,blurAlphaChannel);
stackBlurCanvasRGBA(targetCanvasID,top_x,top_y,width,height,radius);
stackBlurCanvasRGB(targetCanvasID,top_x,top_y,width,height,radius);