【问题标题】:How to detect when the non-transparent part of an UIImage is in contact with another non-transparent part of an UIImage如何检测 UIImage 的非透明部分何时与 UIImage 的另一个非透明部分接触
【发布时间】:2014-05-11 09:18:04
【问题描述】:

我在完成一些我认为会容易得多的事情时遇到了麻烦。每当 UIImage 中图片的非透明部分接触到 UIImage 中包含的图像的另一个非透明部分时,我都会尝试运行一个方法。我提供了一个示例来帮助进一步解释我的问题。

如上图所示,我有两个三角形,它们都在 UIImage 中。三角形都是PNG图片。只有三角形是可见的,因为背景已变得透明。两个 UIImage 都在 UIImageView 内。我希望能够在三角形的可见部分接触到另一个三角形的可见部分时运行一个方法。有人可以帮帮我吗?

【问题讨论】:

  • 这听起来非常复杂,但您可以使用CGRectIntersectsRect 来近似这个过程
  • 在取交点后,使用 alpha 通道透明度将一张图像与另一张图像遮罩,并检查是否有任何不透明的像素。复杂且昂贵,但我怀疑有任何简单的方法可以做到这一点。

标签: ios objective-c uiimageview uiimage


【解决方案1】:

该问题的强力解决方案是为每个图像创建一个包含bools 的二维数组,其中每个数组条目对于不透明像素是true,对于透明像素是false。如果CGRectIntersectsRect 返回真(表示可能发生碰撞),则代码扫描两个数组(根据相对位置使用适当的偏移量)以检查实际碰撞。这变得复杂,并且是计算密集型的。

蛮力方法的一种替代方法是使用 OpenGLES 来完成所有工作。这仍然是一个蛮力解决方案,但它将工作卸载到 GPU,这在这些事情上要好得多。我不是 OpenGLES 方面的专家,所以我将把细节留给其他人。

第二种选择是对问题进行限制,使其更容易解决。例如,给定两个三角形 A 和 B,只有当 A 的一个顶点包含在 B 的区域内,或者 B 的一个顶点在 A 中时,才会发生碰撞。这个问题可以使用 UIBezierPath 类来解决在目标-C。 UIBezierPath 可用于创建三角形形状的路径。然后可以使用 UIBezierPath 的containsPoint: 方法来检查对面三角形的顶点是否包含在目标三角形的区域内。

总而言之,解决方案是为每个对象添加一个 UIBezierPath 属性。初始化 UIBezierPath 以近似对象的形状。如果CGRectIntersectsRect 表示可能发生碰撞,则使用containsPoint: 方法检查一个对象的顶点是否包含在另一个对象的区域中。

【讨论】:

    【解决方案2】:

    我所做的是:

    • 计算图像 A 中非 alpha 像素的数量
    • 对图像 B 做了同样的事情
    • 将 A + B 图像合并为一个图像:C
    • 比较得到的像素数

    如果合并后像素数量减少,那么我们就成功了。

    如果 (C.count 我们成功了

    + (int)countPoints:(UIImage *)img
    {
    
        CGImageRef cgImage = img.CGImage;
        NSUInteger width = img.size.width;
        NSUInteger height = img.size.height;
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    
        size_t bitsPerComponent = 8;
        size_t bytesPerPixel    = 1;
        size_t bytesPerRow      = width * bitsPerComponent * bytesPerPixel;
        size_t dataSize         = bytesPerRow * height;
    
        unsigned char *bitmapData = malloc(dataSize);
        memset(bitmapData, 0, dataSize);
    
        CGContextRef bitmap = CGBitmapContextCreate(bitmapData, width, height, bitsPerComponent, width, NULL,(CGBitmapInfo)kCGImageAlphaOnly);
    
        CGColorSpaceRelease(colorSpace);
    
        CGContextTranslateCTM(bitmap, 0, img.size.height);
        CGContextScaleCTM(bitmap, 1.0, -1.0);
    
        CGContextDrawImage(bitmap, CGRectMake(0, 0, width, height), cgImage);
    
        int p = 0;
        int i = 0;
        while (i < width * height) {
    
            if (bitmapData[i] > 0) {
                p++;
            }
            i++;
        }
    
        free(bitmapData);
        bitmapData = NULL;
        CGContextRelease(bitmap);
        bitmap = NULL;
    
        //NSLog(@"points: %d",p);
    
        return p;
    }
    + (UIImage *)marge:(UIImage *)imageA withImage:(UIImage *)imageB {
    
        CGSize itemSize = CGSizeMake(imageA.size.width,  imageB.size.width);
        UIGraphicsBeginImageContext(itemSize);
    
        CGRect rect = CGRectMake(0,
                                 0,
                                 itemSize.width,
                                 itemSize.height);
        [imageA drawInRect:rect];
        [imageB drawInRect:rect];
    
        UIImage *overlappedImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        return overlappedImage;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-10
      • 1970-01-01
      • 2011-10-15
      • 1970-01-01
      • 2020-05-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多