Oleksandr Matrosov
Oleksandr Matrosov

Reputation: 27187

Verify pixel with coord (iOS)

In my view I have few subviews. This is UIImageView.

Each UIImageView contain image with alpha chanel.

This is an image: enter image description here

I use this method below for detecting my touch in location view:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{   

    UITouch *touch = [[event allTouches] anyObject];
    CGPoint touchLocation = [touch locationInView:self.view];

    NSArray *views = [self.view subviews];

    for (UIView *v in views) {
        if([v isKindOfClass:[Piece class]]){
            if (CGRectContainsPoint(v.frame, touchLocation) && ((Piece *)v).snapped == FALSE) { 

                UITouch* touchInPiece = [touches anyObject]; 
                CGPoint point = [touchInPiece locationInView:(Piece *)v];
                BOOL solidColor = [self verifyAlphaPixelImage:(Piece *)v atX:point.x atY:point.y];

                if (solidColor) {                    
                    dragging = YES;
                    oldX = touchLocation.x;
                    oldY = touchLocation.y;
                    piece = (Piece *)v;
                    [self.view bringSubviewToFront:piece];
                    break;
                }              

            }
        }
    }
}

and this method for verify alpha pixel

- (BOOL)verifyAlphaPixelImage:(Piece *)image atX:(int)x atY:(int)y{

    CGImageRef imageRef = [image.image CGImage];
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    unsigned char *rawData = malloc(height * width * 4);
    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);    
    // Now your rawData contains the image data in the RGBA8888 pixel format.
    int byteIndex = (bytesPerRow * y) + x * bytesPerPixel;
    //    CGFloat red   = (rawData[byteIndex]     ) ;
    //    CGFloat green = (rawData[byteIndex + 1] ) ;
    //    CGFloat blue  = (rawData[byteIndex + 2] ) ;
    CGFloat alpha = (rawData[byteIndex + 3] ) ;   
    NSLog(@"%f", alpha);
    free(rawData);    
    if(alpha==255.0) return NO;
    else return YES;



}

If alpha pixel founded I need to touch other UIImageView below UIImageView that I have tapp's before.

For example if I have stacked UIImageView and I touch on first:

now I should verify first UIImageView

if I touched on alpha pixel - > I should move to next UIImageView with this coord and verify it for alpha pixel too.

If second 3th, 4th or 5th have not alpha pixel with my coord I should select this UIImageView.

For now I verify my pixel - but my method return wrong value.

Upvotes: 0

Views: 360

Answers (1)

Cowirrie
Cowirrie

Reputation: 7226

  1. At the discussion for How to get pixel data from a UIImage (Cocoa Touch) or CGImage (Core Graphics)?, there's a correction to the routine you're using. Use calloc instead of malloc, or you'll start getting arbitrary results.
  2. If your Piece class ever scales images, you will need to scale its x and y inputs by the scale the image is being displayed at.
  3. The touchesBegan method oddly looks at some other view it contains, not itself. Is there a reason for this? What class is touchesBegan in?
  4. Subviews are stored in drawing order from back to front, so when you iterate through subviews, you'll look at (and potentially select) the rearmost object first. Iterate from the last element of subviews towards the front instead.
  5. Even after this works, it will be very inefficient, rendering every Piece image every time the user taps. You'll ultimately want to cache the pixel data for every Piece for rapid lookup.

Upvotes: 1

Related Questions