使用webGL或webworkers加速画布? [英] Speed up canvas with webGL or webworkers?

查看:90
本文介绍了使用webGL或webworkers加速画布?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用此脚本从画布中的图像创建模糊背景: http:// www.quasimondo.com/BoxBlurForCanvas/FastBlur2Demo.html



您可以在我的页面上看到一个演示: http://www.cphrecmedia.dk/musikdk/stage/prelisten.php



我发现速度有点慢,我知道只需进行1次迭代就能让它更快,但它并不那么漂亮。我可以以某种方式使用WEbGL或任何其他类型的技术加速画布吗?



这是堆栈箱代码:



'pre> 变种mul_table = [1,171,205,293,57,373,79,137,241,27,391,357,41,19,283,265,497,469,443,421,25,191,365,349,335,161,155,149,9,278,269,261,505,245,475,231,449,437,213,415,405,395,193,377,369,361,353,345,169,331,325,319,313,307,301,37,145,285,281,69,271,267,263,259,509,501,493,243,479,118,465,459,113,446,55,435,429,423,209,413,51,403,199,393,97,3,379,375,371,367,363,359,355,351,347,43,85,337,333,165,327,323 ,5,317,157,311,77,305,303,75,297,294,73,289,287,71,141,279,277,275,68,135,67,133,33,262,260,129,511,507,503,499,495,491,61,121,481,477,237,235,467,232,115,457,227,451,7,445,221,439,218,433,215,427,425,211,419,417,207,411,409,203,202,401,399,396,197,49,389,387,385,383,95,189,47,187,93,185,23,183,91,181,45,179,89,177,11,175,87,173,345,343,341,339,337,21,167,83,331,329,327,163,81,323,321,319,159,79,315,313,39,155,309,307,153,305 , 303,151,75,299,149,37,295,147,73,291,145,289,287,143,285,71,141,281,35,279,139,69,275,137,273,17,271,135,269,267,133,265,33,263,131,261,130,259,129,257,1]; var shg_table = [0,9,10,11,9,12,10,11,12,9,13,13,10 ,9,13,13,14,14,14,14,10,13,14,14,14,13,13,13,9,14,14,14,15,14,15,14,15,15 ,14,15,15,15,14,15,15,15,15,15,14,15,15,15,15,15,15,12,14,15,15,13,​​15,15,15 ,15,16,16,16,15,16,14,16,16,14,16,13,16,16,16,15,16,13,16,15,16,14,9,16,16 ,16,16,16,16,16,16,16,13,14,16,16,15,16,16,10,16,15,16,14,16,16,14,16,16,14 ,16,16,14,15,16,16,16,14,15,14,15,13,​​16,16,15,17,17,17,17,17,17,14,15,17,17 ,16,16,17,16,15,17,16,17,11,17,16,17,16,17,16,17,17,16,17,17,16,17,17,16,16 ,17,17,17,16,14,17,17,17,17,15,16,14,16,15,16,13,16,15,16,14,16,15,16,12,16 ,15,16,17,17,17,17,17,13,16,15,17,17,17,16,15,17,17,17,16,15,17,17,14,16,17 ,17,16,17,17,16,15,17,16,14,17,16,15,17,16,17,17,16,17,15,16,17,14,17,16,15 ,17,16,17,13,17,16,17,17,16,17,14,17,16,17,16,17,16,17,9];函数stackBoxBlurCanvasRGB(ctxt,top_x,top_y,width ,高度,radiu S,迭代){如果(isNaN(半径)||半径。1)回报;半径| = 0;如果(isNaN(迭代))迭代= 1;迭代| = 0;如果(迭代→3)迭代= 3; if(iterations< 1)iterations = 1; var imageData; try {try {imageData = ctxt.getImageData(top_x,top_y,width,height);} catch(e){try {netscape.security.PrivilegeManager.enablePrivilege(UniversalBrowserRead ); imageData = ctxt.getImageData(top_x,top_y,width,height);} catch(e){alert(无法访问本地图像);抛出新错误(无法访问本地图像数据:+ e) ; return;}}} catch(e){alert(无法访问图像);抛出新错误(无法访问图像数据:+ e);}
var pixels = imageData.data; var x ,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; var div = radius + radius + 1; var w4 = width<< 2; var widthMinus1 = width-1; var heightMinus1 = height-1; var radiusPlus1 = radius + 1; var stackStart = new BlurStack(); var stack = stackStart; for(i = 1; i< div ; i ++){stack = stack.next = new BlurStack(); if(i == radiusPlus1)var sta ckEnd = stack;}
stack.next = stackStart; var stackIn = null; var mul_sum = mul_table [radius]; var shg_sum = shg_table [radius]; while(iterations - > 0){yw = yi = 0;对于(Y =高度; - Y'-1个;){R_SUM = radiusPlus1 *(PR =像素[义]); G_SUM = radiusPlus1 *(PG =像素[义+ 1]); B_SUM = radiusPlus1 *( PB =像素[义+ 2]);堆栈= stackStart;对于(i = radiusPlus1; - I -1个;){stack.r = PR; stack.g = PG; stack.b = PB;堆=堆.next;}
for(i = 1; i< radiusPlus1; i ++){p = yi +((widthMinus1< i?widthMinus1:i)<< 2); r_sum + =(stack.r = pixels [ p ++]); g_sum + =(stack.g = pixels [p ++]); b_sum + =(stack.b = pixels [p]); stack = stack.next;}
stackIn = stackStart; for(x = 0 ; X<宽度; X ++){像素[义++] =(R_SUM * mul_sum)GT;>> shg_sum;像素[义++] =(G_SUM * mul_sum)GT;>> shg_sum;像素[义++] =( B_SUM * mul_sum)GT;>> shg_sum;易++; p =(YW +((p值= X +半径+ 1) - ; widthMinus1号码:?widthMinus1))≤;&2; r_sum- = stackIn.r- (stackIn.r =像素[p ++]); g_sum- = stackIn.g-(stackIn.g =像素[p ++]); b_sum- = stackIn.b-(stackIn.b =像素[p]); stackIn = stackIn .next;}
yw + = width;}
for(x = 0; x< width; x ++){yi = x<< 2; r_sum = radiusPlus1 *(pr = pixels [yi ++]) ; G_SUM = radiusPlus1 *(PG =像素[义++]); B_SUM = radiusPlus1 *(PB =像素[义]);堆栈= stackStart;对于(i = 0; I< radiusPlus1;我++){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 =像素[义++]); G_SUM + =(stack.g =像素[义++]); B_SUM + =(stack.b =像素[义]);堆栈= stack.next;如果(i< heightMinus1)yp + = width;}
yi = x; stackIn = stackStart; for(y = 0; y< height; y ++){p = yi<< 2; pixels [p] =(r_sum * mul_sum)GT;>> shg_sum;像素[p + 1] =(G_SUM * mul_sum)GT;>> shg_sum;像素[p + 2] =(B_SUM * mul_sum)GT;>> shg_sum ; p =(X +(((p值= Y + radiusPlus1)LT; heightMinus1号码:?heightMinus1)*宽度))≤;&2; r_sum- = stackIn.r-(stackIn.r =像素[p]); g_sum- = stackIn.g-(stackIn.g =像素[p + 1]); b_sum- = stackIn.b-(stackIn.b =像素[p + 2]); stackIn = stackIn.next;苡+ =宽度;
ctxt.putImageData(imageData, top_x,top_y);}
函数BlurStack(){this.r = 0; this.g = 0; this.b = 0; this.a = 0; this.next = null;}

以下是每页激活的方式:

 < script type ='text / javascript'> window.onload = function(){


//创建图片对象
var imageObj = new Image();

//图片完成后加载
imageObj.onload = function(){
//获取尺寸
var w = imageObj.naturalWidth;
var h = imageObj.naturalHeight;

var canvas = document.createElement(canvas);
canvas.width = w;
canvas.height = h;
//创建虚拟画布
var ctx = canvas.getContext('2d');

//在其上绘制图像
ctx.drawImage(imageObj,0,0);

//应用模糊
stackBoxBlurCanvasRGB(ctx,0,0,w,h,11,2);

//添加灰色过滤器
ctx.fillStyle ='rgba(64,64,64,0.4)';
ctx.fillRect(0,0,w,h);

//并使用淡入淡出
var $ canvas = $(画布)

$(#bgc)显示1秒钟。附加(画布) );
$ canvas.show();
var canvasRatio = $ canvas.width()/ $ canvas.height();
var windowRatio = $(window).width()/ $(window).height();
if(canvasRatio> windowRatio){
$ canvas.css({
height:100%,
width:auto
});
} else {
$ canvas.css({
width:100%,
height:auto
});
}
$ canvas.css({
marginLeft: - $ canvas.width()/ 2+px,
marginTop: - $ canvas.height ()/ 2 +px
});
window.onresize = function(){
var canvasRatio = $ canvas.width()/ $ canvas.height();
var windowRatio = $(window).width()/ $(window).height();
if(canvasRatio> windowRatio){
$ canvas.css({
height:100%,
width:auto
});
} else {
$ canvas.css({
width:100%,
height:auto
});
}
$ canvas.css({
marginLeft: - $ canvas.width()/ 2+px,
marginTop: - $ canvas.height ()/ 2 +px
});
}

};

//从数据源设置图像的来源
imageObj.src = $('#bgc')。data(src);

}
< / script>


解决方案

也许看看 Pixi.js 它是一个包装画布的库,将使用基于浏览器功能的2D上下文或WebGL上下文。它有一个内置的模糊滤镜,可以实现 http:/后的效果/www.goodboydigital.com/pixijs/docs/classes/BlurFilter.html



如果您正在使用基于WebKit的浏览器,那么CSS的草案实现过滤器应该快速 https://developer.mozilla.org/en-美国/ docs / Web / CSS /过滤器


I'm creating a blurred background from an image in canvas with this script: http://www.quasimondo.com/BoxBlurForCanvas/FastBlur2Demo.html

You can see a demo on my page here: http://www.cphrecmedia.dk/musikdk/stage/prelisten.php

I find the speed a little bit slow and I know I can make it faster by only make 1 iterations, but its not that pretty then. Can I somehow use WEbGL or any other kind of tech to speed up the canvas for this?

This is the stackbox-code:

            var mul_table=[1,171,205,293,57,373,79,137,241,27,391,357,41,19,283,265,497,469,443,421,25,191,365,349,335,161,155,149,9,278,269,261,505,245,475,231,449,437,213,415,405,395,193,377,369,361,353,345,169,331,325,319,313,307,301,37,145,285,281,69,271,267,263,259,509,501,493,243,479,118,465,459,113,446,55,435,429,423,209,413,51,403,199,393,97,3,379,375,371,367,363,359,355,351,347,43,85,337,333,165,327,323,5,317,157,311,77,305,303,75,297,294,73,289,287,71,141,279,277,275,68,135,67,133,33,262,260,129,511,507,503,499,495,491,61,121,481,477,237,235,467,232,115,457,227,451,7,445,221,439,218,433,215,427,425,211,419,417,207,411,409,203,202,401,399,396,197,49,389,387,385,383,95,189,47,187,93,185,23,183,91,181,45,179,89,177,11,175,87,173,345,343,341,339,337,21,167,83,331,329,327,163,81,323,321,319,159,79,315,313,39,155,309,307,153,305,303,151,75,299,149,37,295,147,73,291,145,289,287,143,285,71,141,281,35,279,139,69,275,137,273,17,271,135,269,267,133,265,33,263,131,261,130,259,129,257,1];var shg_table=[0,9,10,11,9,12,10,11,12,9,13,13,10,9,13,13,14,14,14,14,10,13,14,14,14,13,13,13,9,14,14,14,15,14,15,14,15,15,14,15,15,15,14,15,15,15,15,15,14,15,15,15,15,15,15,12,14,15,15,13,15,15,15,15,16,16,16,15,16,14,16,16,14,16,13,16,16,16,15,16,13,16,15,16,14,9,16,16,16,16,16,16,16,16,16,13,14,16,16,15,16,16,10,16,15,16,14,16,16,14,16,16,14,16,16,14,15,16,16,16,14,15,14,15,13,16,16,15,17,17,17,17,17,17,14,15,17,17,16,16,17,16,15,17,16,17,11,17,16,17,16,17,16,17,17,16,17,17,16,17,17,16,16,17,17,17,16,14,17,17,17,17,15,16,14,16,15,16,13,16,15,16,14,16,15,16,12,16,15,16,17,17,17,17,17,13,16,15,17,17,17,16,15,17,17,17,16,15,17,17,14,16,17,17,16,17,17,16,15,17,16,14,17,16,15,17,16,17,17,16,17,15,16,17,14,17,16,15,17,16,17,13,17,16,17,17,16,17,14,17,16,17,16,17,16,17,9];function stackBoxBlurCanvasRGB(ctxt,top_x,top_y,width,height,radius,iterations){if(isNaN(radius)||radius<1)return;radius|=0;if(isNaN(iterations))iterations=1;iterations|=0;if(iterations>3)iterations=3;if(iterations<1)iterations=1;var imageData;try{try{imageData=ctxt.getImageData(top_x,top_y,width,height);}catch(e){try{netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");imageData=ctxt.getImageData(top_x,top_y,width,height);}catch(e){alert("Cannot access local image");throw new Error("unable to access local image data: "+e);return;}}}catch(e){alert("Cannot access image");throw new Error("unable to access image data: "+e);}
            var pixels=imageData.data;var x,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;var div=radius+radius+1;var w4=width<<2;var widthMinus1=width-1;var heightMinus1=height-1;var radiusPlus1=radius+1;var stackStart=new BlurStack();var stack=stackStart;for(i=1;i<div;i++){stack=stack.next=new BlurStack();if(i==radiusPlus1)var stackEnd=stack;}
            stack.next=stackStart;var stackIn=null;var mul_sum=mul_table[radius];var shg_sum=shg_table[radius];while(iterations-->0){yw=yi=0;for(y=height;--y>-1;){r_sum=radiusPlus1*(pr=pixels[yi]);g_sum=radiusPlus1*(pg=pixels[yi+1]);b_sum=radiusPlus1*(pb=pixels[yi+2]);stack=stackStart;for(i=radiusPlus1;--i>-1;){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=pixels[p++]);g_sum+=(stack.g=pixels[p++]);b_sum+=(stack.b=pixels[p]);stack=stack.next;}
            stackIn=stackStart;for(x=0;x<width;x++){pixels[yi++]=(r_sum*mul_sum)>>>shg_sum;pixels[yi++]=(g_sum*mul_sum)>>>shg_sum;pixels[yi++]=(b_sum*mul_sum)>>>shg_sum;yi++;p=(yw+((p=x+radius+1)<widthMinus1?p:widthMinus1))<<2;r_sum-=stackIn.r-(stackIn.r=pixels[p++]);g_sum-=stackIn.g-(stackIn.g=pixels[p++]);b_sum-=stackIn.b-(stackIn.b=pixels[p]);stackIn=stackIn.next;}
            yw+=width;}
            for(x=0;x<width;x++){yi=x<<2;r_sum=radiusPlus1*(pr=pixels[yi++]);g_sum=radiusPlus1*(pg=pixels[yi++]);b_sum=radiusPlus1*(pb=pixels[yi]);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=pixels[yi++]);g_sum+=(stack.g=pixels[yi++]);b_sum+=(stack.b=pixels[yi]);stack=stack.next;if(i<heightMinus1)yp+=width;}
            yi=x;stackIn=stackStart;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;p=(x+(((p=y+radiusPlus1)<heightMinus1?p:heightMinus1)*width))<<2;r_sum-=stackIn.r-(stackIn.r=pixels[p]);g_sum-=stackIn.g-(stackIn.g=pixels[p+1]);b_sum-=stackIn.b-(stackIn.b=pixels[p+2]);stackIn=stackIn.next;yi+=width;}}}
            ctxt.putImageData(imageData,top_x,top_y);}
            function BlurStack(){this.r=0;this.g=0;this.b=0;this.a=0;this.next=null;}

And this is how its activated on each page:

            <script type='text/javascript'>window.onload=function(){


                    //create image object
                var imageObj = new Image();

                    //when image is finished loading
                imageObj.onload = function() {
                            //get size
                            var w = imageObj.naturalWidth;
                            var h = imageObj.naturalHeight;

                            var canvas = document.createElement("canvas");
                            canvas.width = w;
                            canvas.height = h;
                            //create virtual canvas
                            var ctx = canvas.getContext('2d');

                            //draw the image on it
                            ctx.drawImage(imageObj, 0, 0);

                            //apply the blur
                            stackBoxBlurCanvasRGB(ctx, 0, 0, w, h, 11, 2);

                            //add grey filter
                            ctx.fillStyle='rgba(64,64,64,0.4)';
                            ctx.fillRect(0,0,w,h);

                            //and display it in 1 second using a fade
                            var $canvas = $(canvas) 

                            $("#bgc").append(canvas);
                            $canvas.show();
                            var canvasRatio = $canvas.width()/$canvas.height();
                            var windowRatio = $(window).width()/$(window).height();
                            if (canvasRatio > windowRatio){
                                $canvas.css({
                                    "height": "100%",
                                    "width" : "auto"
                                });
                            } else {
                                $canvas.css({
                                    "width": "100%",
                                    "height": "auto"
                                });
                            }
                            $canvas.css({
                                "marginLeft" : -$canvas.width()/2+"px",
                                "marginTop" : -$canvas.height()/2+"px"
                            });
                            window.onresize = function(){
                                var canvasRatio = $canvas.width()/$canvas.height();
                                var windowRatio = $(window).width()/$(window).height();
                                if (canvasRatio > windowRatio){
                                    $canvas.css({
                                        "height": "100%",
                                        "width" : "auto"
                                    });
                                } else {
                                    $canvas.css({
                                        "width": "100%",
                                        "height": "auto"
                                    });
                                }
                                $canvas.css({
                                    "marginLeft" : -$canvas.width()/2+"px",
                                    "marginTop" : -$canvas.height()/2+"px"
                                 });
                            }

                };

                    //set the source of the image from the data source
                imageObj.src = $('#bgc').data("src");

            }
            </script>

解决方案

Maybe have a look at Pixi.js it is a library that wraps canvas and will use either the 2D context or the WebGL context based on browser capabilities. It has a built in Blur Filter that could possibly achieve the effect you are after http://www.goodboydigital.com/pixijs/docs/classes/BlurFilter.html

If you are working with WebKit based browsers there is a draft implementation of CSS filters that should be fast https://developer.mozilla.org/en-US/docs/Web/CSS/filter

这篇关于使用webGL或webworkers加速画布?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆