-->

仅检测上的UIImageView的非透明像素触摸,有效地(Detect touches only o

2019-07-03 16:22发布

你将如何检测只能在非透明像素触摸UIImageView ,有效?

考虑像下面的一个,并显示图像UIImageView 。 我们的目标是是使手势识别器仅当触摸发生在非透明(黑色在这种情况下)的图像的区域响应。

思路

  • 覆盖hitTest:withEvent:pointInside:withEvent: ,虽然这种方法可能是非常低效的,因为这些方法获得的触摸事件中调用多次。
  • 检查如果一个像素是透明的可能会产生意想不到的效果,如手指大于一个像素。 检查周围的命中点像素的圆形区域,或试图找到一个透明的道路走向的边缘可能会更好地工作。

奖金

  • 它会是不错的图像的外周和内透明的像素之间进行区分。 在该实例中,零内部的透明的像素也应视为有效。
  • 如果图像已经变换,会发生什么?
  • 可在图像处理进行硬件加速?

Answer 1:

这是我的快速实施:(基于检索的一个UIImage一个像素的α值 )

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    //Using code from https://stackoverflow.com/questions/1042830/retrieving-a-pixel-alpha-value-for-a-uiimage

    unsigned char pixel[1] = {0};
    CGContextRef context = CGBitmapContextCreate(pixel,
                                                 1, 1, 8, 1, NULL,
                                                 kCGImageAlphaOnly);
    UIGraphicsPushContext(context);
    [image drawAtPoint:CGPointMake(-point.x, -point.y)];
    UIGraphicsPopContext();
    CGContextRelease(context);
    CGFloat alpha = pixel[0]/255.0f;
    BOOL transparent = alpha < 0.01f;

    return !transparent;
}

这是假设该图像是在同一个坐标空间的point 。 如果缩放的推移,你可能要在转换point检查的像素数据之前。

似乎很快上班对我来说。 我约测量。 0.1-0.4毫秒调用此方法。 它不会做的内部空间,而且可能不是最优的。



Answer 2:

在GitHub上,你可以找到一个由OLE Begemann项目延伸UIButton ,使其仅检测触摸其中按钮的图片不是透明的。

由于UIButton是子类UIView ,它适应UIImageView应该直截了当。

希望这可以帮助。



Answer 3:

好吧,如果你需要做的真快,你需要预先计算的面具。

以下是如何提取它:

UIImage *image = [UIImage imageNamed:@"some_image.png"];
NSData *data = (NSData *) CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
unsigned char *pixels = (unsigned char *)[data bytes];
BOOL *mask = (BOOL *)malloc(data.length);
for (int i = 0; i < data.length; i += 4) {
  mask[i >> 2] = pixels[i + 3] == 0xFF; // alpha, I hope
}
// TODO: save mask somewhere

或者你可以使用1x1位图背景的解决方案预先计算的面具。 有一个面具意味着你可以通过任何一点与一个索引内存访问的成本。

作为用于检查大面积大于一个像素 - 我会检查与触摸点中心的圆形像素。 圆上关于16分就足够了。

还检测内像素:另一个预计算一步 - 你需要找到面罩的凸包。 你可以这样做,使用“格雷厄姆扫描”算法http://softsurfer.com/Archive/algorithm_0109/algorithm_0109.htm然后要么填补这一区域的面具,或保存多边形和使用点在多边形测试来代替。

最后,如果图像的变换,你需要转换从屏幕空间的点坐标图像空间,然后你可以检查预先计算的面具。



文章来源: Detect touches only on non-transparent pixels of UIImageView, efficiently