user3143098
user3143098

Reputation: 217

Accesing a single pixels alpha in an UIImageView

I'm trying to make that detects for collision ignoring transparent area. I have all of it done but a function that returns wether or not a single pixel in a UIImageView is transparent or not. Currently putting together some posts from here I have:

- (BOOL)IsPixelNonTransparentFromImage:(UIImage*)image atX:(int)x andY:(int)y {
    CGImageRef imageRef = [image CGImage];
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    unsigned char *rawData = (unsigned char*) calloc(height * width * 4, sizeof(unsigned char));
    NSUInteger bytesPerPixel = 4;
    NSUInteger bytesPerRow = bytesPerPixel * width;
    NSUInteger bitsPerComponent = 8;
    CGContextRef context = CGBitmapContextCreate(rawData, width, height,
                                             bitsPerComponent, bytesPerRow, colorSpace,
                                             kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
    CGContextRelease(context);
    NSUInteger byteIndex = (bytesPerRow * y) + x * bytesPerPixel;
    CGFloat alpha = (rawData[byteIndex + 3] * 1.0)/255.0;
    free(rawData);
    return alpha > 0.0;
}

Not only does this not work for me but also I'm pretty sure there is a more sleek solution for just finding one pixel. Any help would be appreciated.

Upvotes: 2

Views: 42

Answers (1)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 727077

Here is code that should detect alpha of a single pixel:

- (BOOL)IsPixelNonTransparentFromImage:(UIImage*)image atX:(int)x andY:(int)y {
    unsigned char pixel[1] = { 0 };
    CGContextRef context = CGBitmapContextCreate(pixel, 1, 1, 8, 1, NULL, (CGBitmapInfo)kCGImageAlphaOnly);
    UIGraphicsPushContext(context);
    [image drawAtPoint:CGPointMake(-x, -y)];
    UIGraphicsPopContext();
    CGContextRelease(context);
    return pixel[0] != 0;
}

The idea is to draw the image into a context that is one pixel by one pixel at the offset of (-x, -y), so that the point at (x, y) gets "drawn" into the single pixel of the bitmap context that we create. This avoids dynamic allocation and rendering the whole picture to speed up the processing. kCGImageAlphaOnly is used to capture only the alpha channel of the picture.

Here is a program to test this code:

UIImage *image = [UIImage imageNamed:@"BlueCircle.png"];
NSLog(@"%@", [NSValue valueWithCGSize:image.size]);
for (int y = 0 ; y < image.size.height ; y++) {
    NSMutableString *buf = [NSMutableString string];
    for (int x = 0 ; x < image.size.width ; x++) {
        [buf appendFormat:@"%c", [self IsPixelNonTransparentFromImage:image atX:x andY:y] ? '*' : '-'];
    }
    NSLog(@"%@", buf);
}

Here is a link to the BlueCircle.png image that I used for testing.

When this code runs, I get this printout in the log:

2015-04-15 20:15:55.213[10456:620425] ---------************---------
2015-04-15 20:15:55.213[10456:620425] -------****************-------
2015-04-15 20:15:55.214[10456:620425] ------******************------
2015-04-15 20:15:55.214[10456:620425] ----**********************----
2015-04-15 20:15:55.215[10456:620425] ---************************---
2015-04-15 20:15:55.216[10456:620425] ---************************---
2015-04-15 20:15:55.216[10456:620425] --**************************--
2015-04-15 20:15:55.217[10456:620425] -****************************-
2015-04-15 20:15:55.217[10456:620425] -****************************-
2015-04-15 20:15:55.218[10456:620425] ******************************
2015-04-15 20:15:55.219[10456:620425] ******************************
2015-04-15 20:15:55.219[10456:620425] ******************************
2015-04-15 20:15:55.220[10456:620425] ******************************
2015-04-15 20:15:55.278[10456:620425] ******************************
2015-04-15 20:15:55.279[10456:620425] ******************************
2015-04-15 20:15:55.279[10456:620425] ******************************
2015-04-15 20:15:55.280[10456:620425] ******************************
2015-04-15 20:15:55.280[10456:620425] ******************************
2015-04-15 20:15:55.281[10456:620425] ******************************
2015-04-15 20:15:55.281[10456:620425] ******************************
2015-04-15 20:15:55.282[10456:620425] ******************************
2015-04-15 20:15:55.282[10456:620425] -****************************-
2015-04-15 20:15:55.283[10456:620425] -****************************-
2015-04-15 20:15:55.283[10456:620425] --**************************--
2015-04-15 20:15:55.284[10456:620425] ---************************---
2015-04-15 20:15:55.284[10456:620425] ---************************---
2015-04-15 20:15:55.330[10456:620425] ----**********************----
2015-04-15 20:15:55.331[10456:620425] ------******************------
2015-04-15 20:15:55.331[10456:620425] -------****************-------
2015-04-15 20:15:55.332[10456:620425] ---------************---------

Upvotes: 2

Related Questions