我在目标c中编写了一个递归填充方法,我目前正在iPad应用中使用。
我通过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 :(得分:0)
递归方法是堆栈溢出异常的主要原因,因为每个递归调用都被推送到堆栈直到达到最终条件,特别是在泛洪填充算法中这种方法根本不适合,ipad与现代计算机相比资源有限,考虑使用基于循环的洪水填充算法或扫描线算法实现
有关详细信息,请访问此链接Flood Fill algorithms
答案 1 :(得分:-1)
您必须检查不要超出为图像分配的内存。您在currentPoint.x>=0 && currentPoint.y>=0
的支票中部分执行此操作。但是当你在最后一排时,这并不会阻止你通过图像的末尾。
您需要检查currentPoint.y < height && currentPoint.x < width
。