2012-10-04 109 views
2

我已經使用畫布標記完成了一點全屏幕背景疊加,但已經擊中了性能牆。我所做的是創建一個名爲#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); 
     }; 

    }; 
}, 

該函數在2個地方被調用。

  1. 當用戶單擊指定的元素時,疊加層將淡入,並且畫布將加載已過濾的圖像。

  2. 在窗口調整大小事件(onResize arg)上,爲了維護應用的過濾器,否則它只是默認回到原始圖像?

有沒有人有任何優化建議?謝謝!

回答

1

好了,你看,你有一個巨人的形象,即使它只有600×600,這仍然是36000個像素,所以即使你的//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 

    } 

所以,你看,你有(對於每個像素1)做多3600倍X 4倍

這就是測試是很重要的 - 不同的瀏覽器

使用/ 4有時比由一個小數乘以較慢除以比較性能增益相同的東西* 。 25 如果除以2的倍數,如x/2,則可以執行x >> 1或x < < 1,稱爲按位移,儘管一些瀏覽器已經加強了它們的乘法以至於它實際上是不再更快地做到這一點(鉻)

這一切都說,這是假設你不能使用網絡gl着色器。到目前爲止,我們已經有了一個函數來循環每個像素,一次一個,通過單線程和慢速的處理器。

進來https://github.com/mrdoob/three.js/ - THREE.js,它允許您使用着色器,因此您可以通過視頻卡一次渲染多個像素,這是真正增加速度的唯一方法,當您必須觸摸每一個像素。這需要一個支持webGL的瀏覽器,這意味着你可能會支持畫布,所以希望這個答案能夠奏效。