0

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

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

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 player 对我来说很糟糕:) 有人有解决方案吗?干杯!

4

3 回答 3

2

无需直接递归到对角线,因为垂直和水平递归无论如何都会触及这些像素。

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

您提供的例程将用 0x333333 填充整个位图。它不会终止,因为您从不检查是否离开位图边界。

于 2010-02-23T10:51:47.567 回答
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);
}

于 2011-12-12T20:27:51.593 回答
0

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

这是Allan 提到的文章中描述的 FloodFill 的迭代实现:

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 位图。为了获得更好的用户体验,您应该将填充处理分解为多个帧,这样用户就不必盯着等待图标。

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

编辑添加:维基百科上的洪水填充文章有几个算法建议。

于 2010-02-24T21:36:29.957 回答