2012-11-28 59 views
1

我寫了一個遞歸洪水填充方法在目前我目前在iPad應用程序中使用。EXC_BAD_ACCESS洪水填充目標C中

我得到用戶通過圖像的RGBA原始數據在UIImage中觸及的點的顏色。

問題是,它運行了一段時間後,應用程序在訪問原始數據時崩潰了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

+0

你搞清楚增強顏色填充algorithme? –

回答

0

遞歸方法是堆棧溢出異常的主要原因,因爲每次遞歸調用都被推入堆棧直到達到最終狀態,特別是在溢流填充算法中,這種方法根本不適合,與現代計算機相比,ipad資源有限,考慮使用洪水填充算法或掃描線算法

以獲取更多信息的基於循環實現訪問此鏈接Flood Fill algorithms

+0

感謝您的洞察! – nserror

-1

您必須檢查你不要去外面分配給圖像的內存。您在currentPoint.x>=0 && currentPoint.y>=0的支票中部分執行此操作。但是,這並不能阻止你在最後一行時通過圖像的末尾。

您需要檢查currentPoint.y < height && currentPoint.x < width