【问题标题】:Canvas Image Pixel Manipulation Optimization画布图像像素处理优化
【发布时间】:2012-10-20 00:09:21
【问题描述】:

我已经使用 canvas 标签完成了一个小的全屏背景覆盖,但是遇到了性能障碍。我所做的是创建一个名为#OverlayPic 的容器并将其设置为100% x 100%,显示:无。这个容器里面是我的画布元素。

当触发时,jQuery 将图像加载到画布上并将像素信息作为数组获取。 switch 语句接受用户为他们想要的过滤效果设置的选项。代码一切正常,但速度非常慢(我认为这主要是由于我的结构,但我不确定更好的方法)。

updateCanvas:function(onResize){
    var img=new Image(); img.src=Main.ConSRC,
    img.onload=function(){
        var canvas=document.getElementById('Box_Canvas'),  
            ctx=canvas.getContext("2d"),
        winW=$(window).width(), winH=$(window).height(), 
            imgW=this.width, imgH=this.height, smallestSide=Math.min(imgW,imgH);

    // SETUP IMAGE PROPORTIONS
    switch(smallestSide){
       case imgW: 
           var width=winW,height=width*(imgW/imgH);
           if(height < winH){ var height=winH, width=height*(imgW/imgH); };
        break;
        case imgH: 
           var height=winH,width=height*(imgW/imgH);
           if(width < winW){ var width=winW, height=width*(imgH/imgW); };
        break;
    };

        // DRAW IMAGE ON THE CANVAS
        ctx.clearRect(0, 0, width*1.3, height*1.3 );
    ctx.drawImage(img,0,0,width*1.3,height*1.3);

    // IMAGE FILTERS
    var imgdata=ctx.getImageData(0, 0, width, height), pix=imgdata.data, l=pix.length;
    switch($this.data.bg_pic_filter){
          // all filter code cases are here...
    };          

    // APPLY THE FILER
    ctx.putImageData(imgdata, 0, 0);

    // FADE IN OVERLAY
    if(!onResize){
           Main.OBJ.$OverlayPic.fadeTo( $this.data.bg_pic_speed, $this.data.bg_pic_opacity);
        };

    };
},

这个函数在两个地方被调用。

  1. 当用户单击分配的元素时,叠加层会淡入,并且画布会加载过滤后的图像。

  2. 在窗口调整大小事件(onResize arg)上,为了保持应用的滤镜,否则就默认回到原图?

有人有优化建议吗?谢谢!

【问题讨论】:

    标签: jquery html canvas


    【解决方案1】:

    嗯,你看,你有一个巨大的图像,即使它只有 600x600,它仍然是 36,000 像素,所以即使你的 //all filter code cases are here... 有类似的东西

    case default:
       var totalPixels = imagedata.data.length * .25; //divide by 4 now, since dividing is expensive compared to multiplication ( multiply by a decimal place is sometimes cheaper than dividing using /, most browsers have fixed this though[ this is important if you need to know multiple colors at once ] )
       _data = imagedata.data
       for( var i = totalPixels-1; i>=0; i-- ){
    
         var index = i * 4 // this might be slower (creating a variable inside the loop) -- see next 2 lines
    
         _data[i * 4] += 1 // these next 2 lines are identical
         _data[index] += 1 // it might be faster to create an index, so you don't have to multiply, though usually multiplying is cheap and creating a variable inside a loop is expensive, so even if you have to multiple i * 4 a bunch, it might be faster than creating index
    
          _data[index + 1] +=2 //green
          _data[index + 2] +=2 //blue
          _data[index + 3] +=2 //blue
    
       }
    

    所以,如您所见,您已经做了多次 3600 次 X 4 次(每个像素 1 次)

    这就是测试很重要的地方——比较相同的东西在不同浏览器中的性能提升

    使用 / 4 进行除法有时比乘以小数 * .25 慢 如果你除以 2 的倍数,例如 x / 2,你可以做 x >> 1 或 x

    话虽如此,但前提是您不能使用 web gl 着色器。看,到目前为止,我们已经有一个函数循环遍历每个像素,一次 1 个,通过处理器,它是单线程的,而且速度很慢。

    引入了https://github.com/mrdoob/three.js/ -- THREE.js,它允许您使用着色器,因此您可以通过显卡一次渲染多个像素,这确实是您必须触摸时获得更快速度的唯一方法每个像素。这需要一个支持 webGL 的浏览器,这意味着无论如何你都可能支持画布,所以希望这个答案有效。

    【讨论】:

      猜你喜欢
      • 2021-10-27
      • 1970-01-01
      • 2012-09-16
      • 1970-01-01
      • 2011-09-01
      • 2013-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多