0

floodfilliPhone用のC言語で関数を実装しています。

2つの問題がありますが、塗りつぶしは機能します。

  1. 以下のコードを数回実行すると、電話機はメモリ警告を表示します。ほとんどの場合、メモリ リークです。unsigned char *data (画像データ) はフラッドフィルの最後で free() されることにも注意してください。

  2. (より少ない問題) おおよそ(r:200,g:200,b:200,a:200)より大きいピクセルにRGBカラーを書き込もうとすると、奇妙なアーティファクトが発生します。これに対する回避策は、単純に値を制限することでした。

これらの問題の両方の間に相関関係があるのではないかと思います。

以下のコードは、スタックを使用したフラッド フィル アルゴリズムを示しています。

.h:

typedef struct {
    int red;
    int green;
    int blue;
    int alpha;
} GUIColor;


struct pixel_st {
    int x;
    int y;
    struct pixel_st *nextPixel;
};
typedef struct pixel_st pixel;

.m:

   void floodFill(CGPoint location, GUIColor tc, GUIColor rc, size_t width, size_t height, unsigned char *data){
    if (isGUIColorEqual(tc, rc)) return;

    pixel* aPixel = (pixel *) malloc(sizeof (struct pixel_st));
    NSLog(@"sizeof aPixel : %i",(int)sizeof(aPixel));

    (*aPixel).x = location.x;
    (*aPixel).y = location.y;
    (*aPixel).nextPixel = NULL;

    int i = 0;

    NSLog(@"Replacement color A%i, R%i, G%i, B%i",rc.alpha,rc.red,rc.green, rc.blue);

    while (aPixel != NULL){
        pixel *oldPixel_p = aPixel;
        pixel currentPixel = *aPixel;
        aPixel = currentPixel.nextPixel;


        //Now we do some boundary checks
        if (!isOutOfBounds(currentPixel.x, currentPixel.y, width, height)){
            //Grab the current Pixel color
            GUIColor currentColor = getGUIColorFromPixelAtLocation(CGPointMake(currentPixel.x, currentPixel.y), width, height, data);

            if (isGUIColorSimilar(currentColor, tc)){
                //Colors are similar, lets continue the spread
                setGUIColorToPixelAtLocation(CGPointMake(currentPixel.x, currentPixel.y), rc, width,height, data);

                pixel *newPixel;


                if ((newPixel = (pixel*) malloc(sizeof(struct pixel_st))) != NULL) {
                    (*newPixel).x = currentPixel.x;
                    (*newPixel).y = currentPixel.y-1;
                    (*newPixel).nextPixel = aPixel;
                    aPixel = newPixel;

                }
                if ((newPixel = (pixel*) malloc(sizeof(struct pixel_st))) != NULL) {
                    (*newPixel).x = currentPixel.x;
                    (*newPixel).y = currentPixel.y+1;
                    (*newPixel).nextPixel = aPixel;
                    aPixel = newPixel;
                }
                if ((newPixel = (pixel*) malloc(sizeof(struct pixel_st))) != NULL) {
                    (*newPixel).x = currentPixel.x+1;
                    (*newPixel).y = currentPixel.y;
                    (*newPixel).nextPixel = aPixel;
                    aPixel = newPixel;
                }
                if ((newPixel = (pixel*) malloc(sizeof(struct pixel_st))) != NULL) {
                    (*newPixel).x = currentPixel.x-1;
                    (*newPixel).y = currentPixel.y;
                    (*newPixel).nextPixel = aPixel;
                    aPixel = newPixel;
                }
                free(oldPixel_p);
                i ++;
                if (i == width * height * 4 * 5) break;

            }


        }
    }

    free(aPixel);
}

このスタックの実装は、次の場所に基づいていObjFloodFillます。

https://github.com/OgreSwamp/ObjFloodFill/blob/master/src/FloodFill.m

4

2 に答える 2

1

まずif ((newPixel = (pixel*) malloc(...、ループ内のそれぞれが新しいメモリ ブロックを割り当てるため、ループ内に4 つの割り当てがあり、割り当て解除は1 つだけです。

第二に、スタック上のオブジェクトを単純に使用しない理由がわかりません。newPixeloldPixelなどをヒープに割り当てる必要は本当にありますか? 実装を確認してください。メモリの問題をまったく管理せずに、同じものを実装するはるかに簡単な方法があるかもしれません。

于 2013-03-07T10:20:37.900 に答える
0

の解放は常に「消費」されるためoldPixel_p 、ブロックの外側に移動する必要があります。if

また、finalfreeはリストの最初の要素のみを解放します。リストには複数の要素が含まれる場合があります。リストをステップ実行して、残りのすべての要素を解放する必要があります。

于 2013-03-07T10:31:18.590 に答える