使用webGL或webworkers加速画布?

时间:2014-02-24 13:35:46

标签: javascript html5 html5-canvas

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

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

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

这是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;}

这就是它在每一页上的激活方式:

            <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>

1 个答案:

答案 0 :(得分:1)

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

之后的效果

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