Not able to find gradient colour different in Floodfill

0

I have used this "https://github.com/Chintan-Dave/UIImageScanlineFloodfill" Github for replace the colour of wall in UIImage. The problem is ,while using above Floodfill method, can't find the difference between wall and the objects.Not able find the gradient colour difference between wall and the objects.

- (UIImage *) floodFillFromPoint:(CGPoint)startPoint withColor:(UIColor *)newColor andTolerance:(NSInteger)tolerance
{
  return [self floodFillFromPoint:startPoint withColor:newColor andTolerance:tolerance useAntiAlias:YES];
 }

- (UIImage *) floodFillFromPoint:(CGPoint)startPoint withColor:(UIColor *)newColor andTolerance:(NSInteger)tolerance useAntiAlias:(BOOL)antiAlias
  {
@try
{
   CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    //CGImageRef imageRef = [self CGImage];
    CGDataProviderRef imgDataProvider = CGDataProviderCreateWithCFData((CFDataRef)UIImagePNGRepresentation(self));
   CGImageRef imageRef = CGImageCreateWithPNGDataProvider(imgDataProvider, NULL, true, kCGRenderingIntentDefault);

    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    NSUInteger bytesPerPixel = CGImageGetBitsPerPixel(imageRef) / 8;
    NSUInteger bytesPerRow = CGImageGetBytesPerRow(imageRef);
    NSUInteger bitsPerComponent = CGImageGetBitsPerComponent(imageRef);

    unsigned char *imageData = malloc(height * width * bytesPerPixel);

    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);

    if (kCGImageAlphaLast == (uint32_t)bitmapInfo ||
        kCGImageAlphaFirst == (uint32_t)bitmapInfo)
    {
        bitmapInfo = (uint32_t)kCGImageAlphaPremultipliedLast;
    }

    CGContextRef context = CGBitmapContextCreate(imageData,
                                                 width,
                                                 height,
                                                 bitsPerComponent,
                                                 bytesPerRow,
                                                 colorSpace,
                                                 bitmapInfo);
    CGColorSpaceRelease(colorSpace);

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);

    //Get color at start point
    NSUInteger byteIndex = (bytesPerRow * roundf(startPoint.y)) + roundf(startPoint.x) * bytesPerPixel;
    NSLog(@"%s", imageData);
    NSLog(@"%i", byteIndex);
    NSUInteger ocolor = getColorCode(byteIndex, imageData);

    if (compareColor(ocolor, 0, 0))
    {
        return nil;
    }

    //Convert newColor to RGBA value so we can save it to image.
    NSInteger newRed, newGreen, newBlue, newAlpha;

    const CGFloat *components = CGColorGetComponents(newColor.CGColor); 

     if(CGColorGetNumberOfComponents(newColor.CGColor) == 2)
    {
        newRed   = newGreen = newBlue = components[0] * 255;
        newAlpha = components[1] * 255;
    }
    else if (CGColorGetNumberOfComponents(newColor.CGColor) == 4)
    {
        if ((bitmapInfo&kCGBitmapByteOrderMask) == kCGBitmapByteOrder32Little)
        {
            newRed   = components[2] * 255;
            newGreen = components[1] * 255;
            newBlue  = components[0] * 255;
            newAlpha = 255;
        }
        else
        {
            newRed   = components[0] * 255;
            newGreen = components[1] * 255;
            newBlue  = components[2] * 255;
            newAlpha = 255;
        }
    }

    NSUInteger ncolor = (newRed << 24) | (newGreen << 16) | (newBlue << 8) | newAlpha;
LinkedListStack *points = [[LinkedListStack alloc] initWithCapacity:500 incrementSize:500 andMultiplier:height];
    LinkedListStack *antiAliasingPoints = [[LinkedListStack alloc] initWithCapacity:500 incrementSize:500 andMultiplier:height];

    NSInteger x = roundf(startPoint.x);
    NSInteger y = roundf(startPoint.y);

    [points pushFrontX:x andY:y];

    /*
        This algorithem is prety simple though it llook odd in Objective C syntex.
        To get familer with this algorithm visit following link.
        http://lodev.org/cgtutor/floodfill.html
        You can read hole artical for knowledge. 
        If you are familer with flood fill than got to Scanline Floodfill Algorithm With Stack (floodFillScanlineStack)
    */

    NSUInteger color;
    BOOL spanLeft,spanRight;

    while ([points popFront:&x andY:&y] != INVALID_NODE_CONTENT)
    {
        byteIndex = (bytesPerRow * roundf(y)) + roundf(x) * bytesPerPixel;

        color = getColorCode(byteIndex, imageData);

        while(y >= 0 && compareColor(ocolor, color, tolerance))
        {
            y--;

            if(y >= 0)
            {
                byteIndex = (bytesPerRow * roundf(y)) + roundf(x) * bytesPerPixel;

                color = getColorCode(byteIndex, imageData);
            }
        }

        // Add the top most point on the antialiasing list
        if(y >= 0 && !compareColor(ocolor, color, 0))
        {
            [antiAliasingPoints pushFrontX:x andY:y];
        }

        y++;

        spanLeft = spanRight = NO;

        byteIndex = (bytesPerRow * roundf(y)) + roundf(x) * bytesPerPixel;

        color = getColorCode(byteIndex, imageData);

        while (y < height && compareColor(ocolor, color, tolerance) && ncolor != color)
        {
            //Change old color with newColor RGBA value
            imageData[byteIndex + 0] = newRed;
            imageData[byteIndex + 1] = newGreen;
            imageData[byteIndex + 2] = newBlue;
            imageData[byteIndex + 3] = newAlpha;

            if(x > 0)
            {
                byteIndex = (bytesPerRow * roundf(y)) + roundf(x - 1) * bytesPerPixel;

                color = getColorCode(byteIndex, imageData);

                if(!spanLeft && x > 0 && compareColor(ocolor, color, tolerance))
                {
                    [points pushFrontX:(x - 1) andY:y];

                    spanLeft = YES;
                }
                else if(spanLeft && x > 0 && !compareColor(ocolor, color, tolerance))
                {
                    spanLeft = NO;
                }

                // we can't go left. Add the point on the antialiasing list
                if(!spanLeft && x > 0 && !compareColor(ocolor, color, tolerance) && !compareColor(ncolor, color, tolerance))
                {
                    [antiAliasingPoints pushFrontX:(x - 1) andY:y];
                }
            }

            if(x < width - 1)
            {
                byteIndex = (bytesPerRow * roundf(y)) + roundf(x + 1) * bytesPerPixel;;

                color = getColorCode(byteIndex, imageData);

                if(!spanRight && compareColor(ocolor, color, tolerance))
                {
                    [points pushFrontX:(x + 1) andY:y];

                    spanRight = YES;
                }
                else if(spanRight && !compareColor(ocolor, color, tolerance))
                {
                    spanRight = NO;
                }

                // we can't go right. Add the point on the antialiasing list
                if(!spanRight && !compareColor(ocolor, color, tolerance) && !compareColor(ncolor, color, tolerance))
                {
                    [antiAliasingPoints pushFrontX:(x + 1) andY:y];
                }
            }

            y++;

            if(y < height)
            {
                byteIndex = (bytesPerRow * roundf(y)) + roundf(x) * bytesPerPixel;

                color = getColorCode(byteIndex, imageData);
            }
        }

        if (y<height)
        {
            byteIndex = (bytesPerRow * roundf(y)) + roundf(x) * bytesPerPixel;
            color = getColorCode(byteIndex, imageData);

            // Add the bottom point on the antialiasing list
            if (!compareColor(ocolor, color, 0))
                [antiAliasingPoints pushFrontX:x andY:y];
        }
    }
     NSUInteger antialiasColor =  getColorCodeFromUIColor(newColor,bitmapInfo&kCGBitmapByteOrderMask );
    NSInteger red1   = ((0xff000000 & antialiasColor) >> 24);
    NSInteger green1 = ((0x00ff0000 & antialiasColor) >> 16);
    NSInteger blue1  = ((0x0000ff00 & antialiasColor) >> 8);
    NSInteger alpha1 =  (0x000000ff & antialiasColor);

    while ([antiAliasingPoints popFront:&x andY:&y] != INVALID_NODE_CONTENT)
    {
        byteIndex = (bytesPerRow * roundf(y)) + roundf(x) * bytesPerPixel;
        color = getColorCode(byteIndex, imageData);

        if (!compareColor(ncolor, color, 0))
        {
            NSInteger red2   = ((0xff000000 & color) >> 24);
            NSInteger green2 = ((0x00ff0000 & color) >> 16);
            NSInteger blue2 = ((0x0000ff00 & color) >> 8);
            NSInteger alpha2 =  (0x000000ff & color);

            if (antiAlias)
            {
                imageData[byteIndex + 0] = (red1 + red2) / 2;
                imageData[byteIndex + 1] = (green1 + green2) / 2;
                imageData[byteIndex + 2] = (blue1 + blue2) / 2;
                imageData[byteIndex + 3] = (alpha1 + alpha2) / 2;
            }
            else
            {
                imageData[byteIndex + 0] = red2;
                imageData[byteIndex + 1] = green2;
                imageData[byteIndex + 2] = blue2;
                imageData[byteIndex + 3] = alpha2;
            }
             #if DEBUG_ANTIALIASING
            imageData[byteIndex + 0] = 0;
            imageData[byteIndex + 1] = 0;
            imageData[byteIndex + 2] = 255;
            imageData[byteIndex + 3] = 255;
             #endif
        }

                    if (x>0)
        {
            byteIndex = (bytesPerRow * roundf(y)) + roundf(x - 1) * bytesPerPixel;
            color = getColorCode(byteIndex, imageData);

            if (!compareColor(ncolor, color, 0))
            {
                NSInteger red2   = ((0xff000000 & color) >> 24);
                NSInteger green2 = ((0x00ff0000 & color) >> 16);
                NSInteger blue2 = ((0x0000ff00 & color) >> 8);
                NSInteger alpha2 =  (0x000000ff & color);

                if (antiAlias) {
                    imageData[byteIndex + 0] = (red1 + red2) / 2;
                    imageData[byteIndex + 1] = (green1 + green2) / 2;
                    imageData[byteIndex + 2] = (blue1 + blue2) / 2;
                    imageData[byteIndex + 3] = (alpha1 + alpha2) / 2;
                } else {
                    imageData[byteIndex + 0] = red2;
                    imageData[byteIndex + 1] = green2;
                    imageData[byteIndex + 2] = blue2;
                    imageData[byteIndex + 3] = alpha2;
                }

                  #if DEBUG_ANTIALIASING
                imageData[byteIndex + 0] = 0;
                imageData[byteIndex + 1] = 0;
                imageData[byteIndex + 2] = 255;
                imageData[byteIndex + 3] = 255;
                  #endif
            }
        }

        if (x<width)
        {
            byteIndex = (bytesPerRow * roundf(y)) + MIN(width,roundf(x + 1)) * bytesPerPixel;
            color = getColorCode(byteIndex, imageData);

            if (!compareColor(ncolor, color, 0))
            {
                NSInteger red2   = ((0xff000000 & color) >> 24);
                NSInteger green2 = ((0x00ff0000 & color) >> 16);
                NSInteger blue2 = ((0x0000ff00 & color) >> 8);
                NSInteger alpha2 =  (0x000000ff & color);

                if (antiAlias)
                {
                    imageData[byteIndex + 0] = (red1 + red2) / 2;
                    imageData[byteIndex + 1] = (green1 + green2) / 2;
                    imageData[byteIndex + 2] = (blue1 + blue2) / 2;
                    imageData[byteIndex + 3] = (alpha1 + alpha2) / 2;
                }
                else
                {
                    imageData[byteIndex + 0] = red2;
                    imageData[byteIndex + 1] = green2;
                    imageData[byteIndex + 2] = blue2;
                    imageData[byteIndex + 3] = alpha2;
                }

             #if DEBUG_ANTIALIASING
                imageData[byteIndex + 0] = 0;
                imageData[byteIndex + 1] = 0;
                imageData[byteIndex + 2] = 255;
                imageData[byteIndex + 3] = 255;
               #endif
            }
        }

                  if (y>0)
        {
            byteIndex = (bytesPerRow * roundf(y - 1)) + roundf(x) * bytesPerPixel;
            color = getColorCode(byteIndex, imageData);

            if (!compareColor(ncolor, color, 0))
            {
                NSInteger red2   = ((0xff000000 & color) >> 24);
                NSInteger green2 = ((0x00ff0000 & color) >> 16);
                NSInteger blue2 = ((0x0000ff00 & color) >> 8);
                NSInteger alpha2 =  (0x000000ff & color);

                if (antiAlias)
                {
                    imageData[byteIndex + 0] = (red1 + red2) / 2;
                    imageData[byteIndex + 1] = (green1 + green2) / 2;
                    imageData[byteIndex + 2] = (blue1 + blue2) / 2;
                    imageData[byteIndex + 3] = (alpha1 + alpha2) / 2;
                }
                else
                {
                    imageData[byteIndex + 0] = red2;
                    imageData[byteIndex + 1] = green2;
                    imageData[byteIndex + 2] = blue2;
                    imageData[byteIndex + 3] = alpha2;
                }
    #if DEBUG_ANTIALIASING
                imageData[byteIndex + 0] = 0;
                imageData[byteIndex + 1] = 0;
                imageData[byteIndex + 2] = 255;
                imageData[byteIndex + 3] = 255;
       #endif
            }
        }

                 if (y<height)
        {
            byteIndex = (bytesPerRow * MIN(height,roundf(y + 1))) + roundf(x) * bytesPerPixel;
            color = getColorCode(byteIndex, imageData);
            if (!compareColor(ncolor, color, 0))
            {
                NSInteger red2   = ((0xff000000 & color) >> 24);
                NSInteger green2 = ((0x00ff0000 & color) >> 16);
                NSInteger blue2 = ((0x0000ff00 & color) >> 8);
                NSInteger alpha2 =  (0x000000ff & color);

                if (antiAlias)
                {
                    imageData[byteIndex + 0] = (red1 + red2) / 2;
                    imageData[byteIndex + 1] = (green1 + green2) / 2;
                    imageData[byteIndex + 2] = (blue1 + blue2) / 2;
                    imageData[byteIndex + 3] = (alpha1 + alpha2) / 2;
                }
                else
                {
                    imageData[byteIndex + 0] = red2;
                    imageData[byteIndex + 1] = green2;
                    imageData[byteIndex + 2] = blue2;
                    imageData[byteIndex + 3] = alpha2;
                }
          #if DEBUG_ANTIALIASING
                imageData[byteIndex + 0] = 0;
                imageData[byteIndex + 1] = 0;
                imageData[byteIndex + 2] = 255;
                imageData[byteIndex + 3] = 255;
          #endif
            }
        }
    }

    //Convert Flood filled image row data back to UIImage object.

    CGImageRef newCGImage = CGBitmapContextCreateImage(context);

    UIImage *result = [UIImage imageWithCGImage:newCGImage scale:[self scale] orientation:UIImageOrientationUp];

    CGImageRelease(newCGImage);

    CGContextRelease(context);

    free(imageData);

    return result;
}
@catch (NSException *exception)
{
    NSLog(@"Exception : %@", exception);
}
}

   NSUInteger getColorCode (NSUInteger byteIndex, unsigned char *imageData)
  {
    NSUInteger red   = imageData[byteIndex];
    NSUInteger green = imageData[byteIndex + 1];
    NSUInteger blue  = imageData[byteIndex + 2];
    NSUInteger alpha = imageData[byteIndex + 3];
return (red << 24) | (green << 16) | (blue << 8) | alpha;
  // return (red << 32) | (green << 24) | (blue << 16) | alpha;
    }

    bool compareColor (NSUInteger color1, NSUInteger color2, NSInteger tolorance)
    {
if(color1 == color2)
    return true;

NSInteger red1   = ((0xff000000 & color1) >> 24);
NSInteger green1 = ((0x00ff0000 & color1) >> 16);
NSInteger blue1  = ((0x0000ff00 & color1) >> 8);
NSInteger alpha1 =  (0x000000ff & color1);

NSInteger red2   = ((0xff000000 & color2) >> 24);
NSInteger green2 = ((0x00ff0000 & color2) >> 16);
NSInteger blue2  = ((0x0000ff00 & color2) >> 8);
NSInteger alpha2 =  (0x000000ff & color2);

NSInteger diffRed   = labs(red2   - red1);
NSInteger diffGreen = labs(green2 - green1);
NSInteger diffBlue  = labs(blue2  - blue1);
NSInteger diffAlpha = labs(alpha2 - alpha1);

if( diffRed   > tolorance ||
    diffGreen > tolorance ||
    diffBlue  > tolorance ||
    diffAlpha > tolorance  )
{
    return false;
}

return true;
 }


    NSUInteger getColorCodeFromUIColor(UIColor *color, CGBitmapInfo orderMask)
   {
//Convert newColor to RGBA value so we can save it to image.
NSInteger newRed, newGreen, newBlue, newAlpha;

const CGFloat *components = CGColorGetComponents(color.CGColor);

/*
 If you are not getting why I use CGColorGetNumberOfComponents than read following link:
 http://stackoverflow.com/questions/9238743/is-there-an-issue-with-cgcolorgetcomponents
 */

if(CGColorGetNumberOfComponents(color.CGColor) == 2)
{
    newRed   = newGreen = newBlue = components[0] * 255;
    newAlpha = components[1] * 255;
}
else if (CGColorGetNumberOfComponents(color.CGColor) == 4)
{
    if (orderMask == kCGBitmapByteOrder32Little)
    {
        newRed   = components[2] * 255;
        newGreen = components[1] * 255;
        newBlue  = components[0] * 255;
        newAlpha = 255;
    }
    else
    {
        newRed   = components[0] * 255;
        newGreen = components[1] * 255;
        newBlue  = components[2] * 255;
        newAlpha = 255;
    }
}
else
{
    newRed   = newGreen = newBlue = 0;
    newAlpha = 255;
}

NSUInteger ncolor = (newRed << 24) | (newGreen << 16) | (newBlue << 8) | newAlpha;

return ncolor;
   }

 @end

I am getting error same like change only the colour of wall in image. please let me know wt I have do for this ..Or ,, Is there any other ways to Implement painting walls in ios swift?

ios
objective-c
asked on Stack Overflow Sep 17, 2019 by chris • edited Sep 17, 2019 by rmaddy

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0