JavaScript实现的图像模糊算法代码分享
项目中需要用到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;
}
使用方法:
stackBlurCanvasRGBA(targetCanvasID,top_x,top_y,width,height,radius);
stackBlurCanvasRGB(targetCanvasID,top_x,top_y,width,height,radius);
相关文章
- javaScript阶乘算法挑战
- labuladong的算法小抄的javascript实现-动态规划
- 「数据结构与算法Javascript描述」栈
- 「数据结构与算法Javascript描述」二叉树
- 常见的js算法_javascript数据结构与算法
- 101道算法javaScript描述【一】
- JavaScript刷LeetCode-贪心算法
- JavaScript学习总结(二十)——Javascript非构造函数的继承详解编程语言
- JavaScript排序算法详解编程语言
- 关于Javascript的prototype问题。
- javascript算法学习实现代码
- 重构Javascript代码示例(重构前后对比)
- Javascript和HTML5利用canvas构建Web五子棋游戏实现算法
- javascript实现颜色渐变的方法
- javascript去掉前后空格的实例
- 用javascript替换URL中的参数值示例代码
- javascript写的异步加载js文件函数(支持数组传参)
- Javascript冒泡排序算法详解
- javascript实现playfair和hill密码算法
- javascript设计模式之中介者模式Mediator
- javascript事件模型实例分析