洪水填充渐变

时间:2016-11-20 04:47:17

标签: ios gradient flood-fill

我正在尝试用渐变填充UIImage。我已经实现了这个纯色。我尝试使用UIColor colorWithPatternImage进行填充,但它会用奇怪的颜色填充图像。有人可以指出我正确的方向。这是我用于填充洪水的方法

    - (UIImage *) floodFillFromPoint:(CGPoint)startPoint withColor:(UIColor *)newColor andTolerance:(int)tolerance
 {

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

    CGImageRef imageRef = [self CGImage];

    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);

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

    NSUInteger bytesPerPixel = CGImageGetBitsPerPixel(imageRef) / 8;
    NSUInteger bytesPerRow = CGImageGetBytesPerRow(imageRef);
    NSUInteger bitsPerComponent = CGImageGetBitsPerComponent(imageRef);

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

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

    //Get color at start point
    unsigned int byteIndex = (bytesPerRow * startPoint.y) + startPoint.x * bytesPerPixel;

    unsigned int ocolor = getColorCode(byteIndex, imageData);

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

    const CGFloat *components = CGColorGetComponents(newColor.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(newColor.CGColor) == 2)
    {
        newRed   = newGreen = newBlue = components[0] * 255;
        newAlpha = components[1];
    }
    else if (CGColorGetNumberOfComponents(newColor.CGColor) == 4)
    {
        newRed   = components[0] * 255;
        newGreen = components[1] * 255;
        newBlue  = components[2] * 255;
        newAlpha = 255;
    }

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

    /*
        We are using stack to store point.
        Stack is implemented by LinkList.
        To incress speed I have used NSMutableData insted of NSMutableArray.
        To see Detail Of This implementation visit following leink.
        http://iwantmyreal.name/blog/2012/09/29/a-faster-array-in-objective-c/
    */

    LinkedListStack *points = [[LinkedListStack alloc] initWithCapacity:500 incrementSize:500 andMultiplier:height];

    int x = startPoint.x;
    int y = 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)
    */

    unsigned int color;
    BOOL spanLeft,spanRight;

    while ([points popFront:&x andY:&y] != INVALID_NODE_CONTENT)
    {


       /* if (spanRight) {
            newRed = newRed-1;
            newBlue  = newBlue+1;
        }

        if (spanLeft) {
            newBlue = newBlue-1;
            newRed  = newRed+1;
        }*/

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

        color = getColorCode(byteIndex, imageData);

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

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

                color = getColorCode(byteIndex, imageData);
            }
        }

        y++;

        spanLeft = spanRight = NO;

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

        color = getColorCode(byteIndex, imageData);

        while (y < height && compareColor(ocolor, color, tolerance) )
        {
           // NSLog(@"compareColor");
            //Change old color with newColor RGBA value
          /*  if (compareColor(ncolor, color, tolerance)) {
                newRed = 255;
                newGreen = 255;
                newBlue = 255;
                newAlpha = 0;
            }*/

            imageData[byteIndex + 0] = newRed;
            imageData[byteIndex + 1] = newGreen;
            imageData[byteIndex + 2] = newBlue;
            imageData[byteIndex + 3] = newAlpha;

            if(x > 0)
            {
                byteIndex = (bytesPerRow * y) + (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;
                }
            }

            if(x < width - 1)
            {
                byteIndex = (bytesPerRow * y) + (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;
                }
            }

            y++;

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

                color = getColorCode(byteIndex, imageData);
            }
        }
    }

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

    CGImageRef newCGImage = CGBitmapContextCreateImage(context);

    UIImage *result = [UIImage imageWithCGImage:newCGImage];

    CGImageRelease(newCGImage);

    CGContextRelease(context);

    free(imageData);

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

}

这是我用于渐变

的洪水填充
filledImage = [_imageView.image floodFillFromPoint:CGPointMake((touchPoint.x*ScaleFactor)/_zoomScrollview.zoomScale,( touchPoint.y*ScaleFactor)/_zoomScrollview.zoomScale) withColor:[UIColor colorWithPatternImage:[UIImage imageNamed:@"color-book.png"]] andTolerance:5.0 ];

这是我正在使用的渐变图像:

Here is the gradient image i am using

但是显示出像这样奇怪的颜色

Gradient Applied Image

我正在制作一本着色书app.so它看起来应该像应用渐变后在任何着色书应用上看起来一样。 谁能告诉我问题在哪里或我该怎么做才能解决它?

0 个答案:

没有答案