ActionScript 3中的Floodfill

时间:2010-02-23 09:34:07

标签: flash actionscript-3 actionscript flood-fill

我正在尝试在ActionScript3中编写自己的Floodfill函数,因为Adobe提供的功能不够灵活(您只能提供一种目标颜色,我想提供一系列目标颜色。)

所以,到目前为止我提出的可怕代码是:

private function beginAlgortime(xx:int,yy:int):void
{
    if (bmp.bitmapData.getPixel(xx, yy) != 0x333333) {

        bmp.bitmapData.setPixel(xx, yy, 0x333333);

        beginAlgortime(xx + 1, yy);
        beginAlgortime(xx + 1, yy+1);
        beginAlgortime(xx + 1, yy - 1);

        beginAlgortime(xx , yy+1);
        beginAlgortime(xx , yy - 1);

        beginAlgortime(xx - 1, yy);
        beginAlgortime(xx - 1, yy+1);
        beginAlgortime(xx - 1, yy-1);
    }
}

一个非常基本的递归函数..但显然使用这种方法,flash播放器对我疯狂:)任何人都有这个解决方案吗? 干杯!

3 个答案:

答案 0 :(得分:2)

没有必要直接递归到对角线,因为垂直和水平递归无论如何都会碰到那些像素。

洪水填充到底是什么意思?你的“颜色范围”是什么意思?

您提供的例程将使用0x333333填充整个位图。它不会终止,因为你永远不会检查你是否留下了位图界限。

答案 1 :(得分:0)

你可以尝试将它从递归函数转换为使用数组而不是程序堆栈的迭代函数。

这是FloodFill的迭代实现,如the article Allan mentioned中所述:

function floodFill(bmpData:BitmapData, startX:int, startY:int, fill:uint, old:uint):void
{
    var queue:Array = new Array();

    queue.push(new Point(startX, startY));

    var iterations:uint = 0;
    var bmpWidth:int = bmpData.width;
    var bmpHeight:int = bmpData.height;

    var searchBmp:BitmapData = new BitmapData(bmpData.width, bmpData.height);
    var currPoint:Point, newPoint:Point;
    while (queue.length > 0)
    {
        currPoint = queue.shift();
        ++iterations;

        if (currPoint.x < 0 || currPoint.x >= bmpWidth) continue;
        if (currPoint.y < 0 || currPoint.y >= bmpHeight) continue;

        searchBmp.setPixel(currPoint.x, currPoint.y, 0x00);

        if (bmpData.getPixel(currPoint.x, currPoint.y) == old)
        {
            bmpData.setPixel(currPoint.x, currPoint.y, fill);

            if (searchBmp.getPixel(currPoint.x + 1, currPoint.y) == 0xFFFFFF)
            {
                queue.push(new Point(currPoint.x + 1, currPoint.y));
            }
            if (searchBmp.getPixel(currPoint.x, currPoint.y + 1) == 0xFFFFFF)
            {
                queue.push(new Point(currPoint.x, currPoint.y + 1));
            }
            if (searchBmp.getPixel(currPoint.x - 1, currPoint.y) == 0xFFFFFF)
            {
                queue.push(new Point(currPoint.x - 1, currPoint.y));
            }
            if (searchBmp.getPixel(currPoint.x, currPoint.y - 1) == 0xFFFFFF)
            {
                queue.push(new Point(currPoint.x, currPoint.y - 1));
            }
        }

    }       
    trace("iterations: " + iterations);
}

编辑:尝试了几种方法来跟踪哪些像素已经被搜索过后,我意识到使用第二个BitmapData实例效果非常好。我已相应更新了代码。

此代码在我的计算机上在~14秒内填充2000x1400位图。为了获得更好的用户体验,您应该在多个帧上分解填充处理,这样用户就不必盯着等待的图标。

哦,这仍然只影响一种颜色,但应该很容易修改它以采用多种颜色,颜色阈值或类似颜色。

编辑添加:维基百科上的Flood fill文章有几个算法建议。

答案 2 :(得分:0)

这就是我用过的:


private function floodFill(bitmapData: BitmapData, x: int, y: int, backColor: uint, fillColor: uint): void
{
    var data: Vector. = bitmapData.getVector(bitmapData.rect);

    var queueX:Vector. = new Vector.();
    var queueY:Vector. = new Vector.();

    queueX.push(x);
    queueY.push(y);

    while (queueX.length > 0) {
        x = queueX.shift();
        y = queueY.shift();

        if (x = width || y = height)
            return;

        if (data[y*width + x] == backColor) {
            data[y*width + x] = fillColor;

            queueX.push(x+1);
            queueY.push(y);

            queueX.push(x-1);
            queueY.push(y);

            queueX.push(x);
            queueY.push(y+1);

            queueX.push(x);
            queueY.push(y-1);
        }
    }

    bitmapData.setVector(bitmapData.rect, data);
}