1

私は現在iPadアプリで使用しているObjectivecで再帰的フラッドフィルメソッドを作成しました。

ユーザーがUIImageで触れたポイントの色を、画像のRGBA生データを介して取得します。

問題は、しばらくの間実行された後、生データにアクセスしているときにアプリがEXC_BAD_ACCESSでクラッシュすることです。私の質問は、なぜこれが「スタックオーバーフロー」なのかということです。そして、誰もがこれを修正する/このアプローチを改善する方法を提案することができるでしょうか。

これが私の方法です(もっときれいかもしれません、お詫びします)。

-(unsigned char *)floodFill:(unsigned char *)data withImageRef:(CGImageRef)imgRef withColor:(UIColor *)color whereColor:(UIColor *)pixelColor atX:(int)xx andY:(int)yy
    {
        //create points for top bottom left and right pixel
        CGPoint top = CGPointMake(xx, yy-1);
        CGPoint bottom = CGPointMake(xx, yy+1);
        CGPoint left = CGPointMake(xx-1, yy);
        CGPoint right = CGPointMake(xx+1, yy);

        //convert new color to rgba values
        const CGFloat *rgb = CGColorGetComponents(color.CGColor);

        float newRed = rgb[0];
        float newGreen = rgb[1];
        float newBlue = rgb[2];
        float newAlpha = CGColorGetAlpha(color.CGColor);

        //convert old color to rgba values
        const CGFloat *rgb2 = CGColorGetComponents(pixelColor.CGColor);

        float oldRed = rgb2[0];
        float oldGreen = rgb2[1];
        float oldBlue = rgb2[2];
        float oldAlpha = CGColorGetAlpha(pixelColor.CGColor);

        NSUInteger width = CGImageGetWidth(imgRef);
        NSUInteger bytesPerPixel = 4;
        NSUInteger bytesPerRow = bytesPerPixel * width;
        int byteIndex = (bytesPerRow * yy) + xx * bytesPerPixel;

        //color current pixel
        data[byteIndex] = (char)newRed*255;
        data[byteIndex+1] = (char)newGreen*255;
        data[byteIndex+2] = (char)newBlue*255;
        data[byteIndex+3] = (char)newAlpha*255;


        CGFloat red, green, blue, alpha;
        CGPoint currentPoint;

        //check top pixel
        currentPoint=top;
        if(currentPoint.x>=0 && currentPoint.y>=0)
        {
            byteIndex = (bytesPerRow * currentPoint.y) + currentPoint.x * bytesPerPixel;
            red   = (data[byteIndex]     * 1.0) / 255.0;
            green = (data[byteIndex + 1] * 1.0) / 255.0;
            blue  = (data[byteIndex + 2] * 1.0) / 255.0;
            alpha = (data[byteIndex + 3] * 1.0) / 255.0;
            if(red==oldRed&&green==oldGreen&&blue==oldBlue&&alpha==oldAlpha)
                data=[self floodFill:data withImageRef:imgRef withColor:color whereColor:pixelColor atX:currentPoint.x andY:currentPoint.y];
        }

        //check bottom pixel
        currentPoint=bottom;
        if(currentPoint.x>=0 && currentPoint.y>=0)
        {
            byteIndex = (bytesPerRow * currentPoint.y) + currentPoint.x * bytesPerPixel;
            red   = (data[byteIndex]     * 1.0) / 255.0;
            green = (data[byteIndex + 1] * 1.0) / 255.0;
            blue  = (data[byteIndex + 2] * 1.0) / 255.0;
            alpha = (data[byteIndex + 3] * 1.0) / 255.0;
            if(red==oldRed&&green==oldGreen&&blue==oldBlue&&alpha==oldAlpha)
                data=[self floodFill:data withImageRef:imgRef withColor:color whereColor:pixelColor atX:currentPoint.x andY:currentPoint.y];
        }

        //check left pixel
        currentPoint=left;
        if(currentPoint.x>=0 && currentPoint.y>=0)
        {
            byteIndex = (bytesPerRow * currentPoint.y) + currentPoint.x * bytesPerPixel;
            red   = (data[byteIndex]     * 1.0) / 255.0;
            green = (data[byteIndex + 1] * 1.0) / 255.0;
            blue  = (data[byteIndex + 2] * 1.0) / 255.0;
            alpha = (data[byteIndex + 3] * 1.0) / 255.0;
            if(red==oldRed&&green==oldGreen&&blue==oldBlue&&alpha==oldAlpha)
                data=[self floodFill:data withImageRef:imgRef withColor:color whereColor:pixelColor atX:currentPoint.x andY:currentPoint.y];
        }

        //check right pixel
        currentPoint=right;
        if(currentPoint.x>=0 && currentPoint.y>=0)
        {
            byteIndex = (bytesPerRow * currentPoint.y) + currentPoint.x * bytesPerPixel;
            red   = (data[byteIndex]     * 1.0) / 255.0;
            green = (data[byteIndex + 1] * 1.0) / 255.0;
            blue  = (data[byteIndex + 2] * 1.0) / 255.0;
            alpha = (data[byteIndex + 3] * 1.0) / 255.0;
            if(red==oldRed&&green==oldGreen&&blue==oldBlue&&alpha==oldAlpha)
                data=[self floodFill:data withImageRef:imgRef withColor:color whereColor:pixelColor atX:currentPoint.x andY:currentPoint.y];
        }



        return data;
    }

ありがとう-TJ

4

2 に答える 2

0

再帰的メソッドは、スタックオーバーフロー例外の主な原因です。これは、すべての再帰的呼び出しが終了条件に達するまでスタックにプッシュされるためです。特に、フラッドフィルアルゴリズムでは、このアプローチはまったく適していません。ipadのリソースは、最新のコンピューターと比較して限られています。ループベースの使用を検討してください。フラッドフィルアルゴリズムまたはスキャンラインアルゴリズムの実装

詳細については、このリンクをご覧ください。フラッドフィルアルゴリズム

于 2012-11-28T04:12:32.727 に答える
-1

イメージに割り当てられたメモリの外に出ないことを確認する必要があります。のチェックでこれを部​​分的に行っていますcurrentPoint.x>=0 && currentPoint.y>=0。しかし、それはあなたが最後の行にいるときにあなたが画像の終わりを通過するのを止めません。

チェックする必要がありますcurrentPoint.y < height && currentPoint.x < width

于 2012-11-28T04:12:15.377 に答える