簡體   English   中英

使HTML5 canvas floodfill高效

[英]Making HTML5 canvas floodfill efficient

我正在使用socket.io和canvas創建一個協作圖像繪制應用程序。 必要時,畫布必須經常刷新,目前大約每50毫秒刷新一次。 我想在應用程序中添加填充工具,因此我使用了有限的洪水填充知識來創建填充工具。 因為必須傳輸所有這些數據,所以我將每個填充命令存儲為一個簡單的對象

{
    tool: 'fill',
    coordinate: {
        x: 5,
        y: 5
    }
    fillcolor: '#000'
}

然后每個客戶端的畫布運行算法並使用“getImageData”和“putImageData”為每個單獨的像素填充。 這是我的實現的(縮寫)版本。

function floodfill (start,target_color,fill_color)
{
    var pixelStack = [start]; //the stack of pixels to check

    while (pixelStack.length > 0) 
    {
        var current = pixelStack[pixelStack.length-1]; //check the last pixel of the pixelstack
        pixelStack.pop(); //delete current from stack

        if (isSameColor(current)) //matches our target color
        {
            var mydat = ctx.createImageData(1,1);
            mydat.data = new Array();
            mydat.data[0] = hexToRGB(fill_color).r; //red
            mydat.data[1] = hexToRGB(fill_color).g; //green
            mydat.data[2] = hexToRGB(fill_color).b; //blue
            mydat.data[3] = 255;
            ctx.putImageData(mydat,current.x,current.y);

            pixelStack.push(bit(current.x+1,current.y)); //right
            pixelStack.push(bit(current.x-1,current.y)); //left
            pixelStack.push(bit(current.x,current.y+1)); //up
            pixelStack.push(bit(current.x,current.y-1)); //down
        }
    }

    function isSameColor (pixel)
    {
        var imgdat = ctx.getImageData(pixel.x,pixel.y,1,1).data;
        if (imgdat[0]== hexToRGB(target_color).r && imgdat[1]== hexToRGB(target_color).g, imgdat[2]== hexToRGB(target_color).b)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    function hexToRGB (hex)
    {
        var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
        return result ? {
            r: parseInt(result[1], 16),
            g: parseInt(result[2], 16),
            b: parseInt(result[3], 16),
            rgb: parseInt(result[1], 16) + ", " + parseInt(result[2], 16) + ", " + parseInt(result[3], 16)
        } : null;
    }
}

不幸的是,一旦算法運行,畫布繪圖就會非常慢。 由於我有所有繪畫的鼠標坐標細節,我考慮嘗試使用矢量來填充它,但我的數學背景並不是真的足夠強大,沒有幫助。

我申請的緩慢部分是什么? 我該如何解決?

編輯:正如我在評論中提到的,我已經嘗試過只使用一個大的putImageData(非常慢),並使用createImageData而不是getImageData(稍微快一些)。

EDIT2:每個畫筆描邊都存儲為一系列xy坐標,當用戶點擊並拖動時會記錄這些坐標。 但是,它們不是封閉的路徑。 相反,它們被繪制為一系列線條,當用戶抬起鼠標時,移動到。

代碼已更新以反映我當前的實施。

我意識到這是一個非常古老的問題,但是如果你還在研究這個問題,請暫時在函數的各個部分安排一些代碼,以找到它最慢的位置。 絕對將對getimagedata和putimagedata的調用拉出循環 - 每次“填充”只調用一次。 獲得imagedata后,通過它的底層緩沖區獲取並設置像素的顏色,將其視為Uint32Array。

請參閱https://hacks.mozilla.org/2011/12/faster-canvas-pixel-manipulation-with-typed-arrays/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM