簡體   English   中英

有效地檢測僅觸摸UIImageView的非透明像素

[英]Detect touches only on non-transparent pixels of UIImageView, efficiently

您如何有效地檢測僅在UIImageView非透明像素上的觸摸?

考慮下面的圖像,與UIImageView顯示。 目標是僅在觸摸發生在圖像的非透明(在這種情況下為黑色)區域時使手勢識別器響應。

在此輸入圖像描述

思路

  • 覆蓋hitTest:withEvent:pointInside:withEvent: ,盡管這種方法可能非常低效,因為這些方法在觸摸事件期間被多次調用。
  • 檢查單個像素是否透明可能會產生意外結果,因為手指大於一個像素。 檢查命中點周圍的像素圓形區域,或嘗試找到朝向邊緣的透明路徑可能會更好。

獎金

  • 區分圖像的外部和內部透明像素會很好。 在該示例中,零內的透明像素也應被視為有效。
  • 如果圖像有變換會發生什么?
  • 圖像處理可以硬件加速嗎?

這是我的快速實現:(基於檢索UIImage的像素alpha值

- (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 ms。 它沒有內部空間,可能不是最佳的。

在github上,您可以找到Ole Begemann的一個項目,項目擴展了UIButton ,使其僅檢測按鈕圖像不透明的觸摸。

由於UIButtonUIView的子類,因此將其調整為UIImageView應該很簡單。

希望這可以幫助。

好吧,如果你需要真的很快,你需要預先計算面具。

以下是如何提取它:

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個點就足夠了。

同時檢測內部像素:另一個預先計算步驟 - 您需要找到蒙版的凸包。 您可以使用“Graham掃描”算法http://softsurfer.com/Archive/algorithm_0109/algorithm_0109.htm執行此操作。然后填充蒙版中的該區域,或者保存多邊形並使用多邊形點測試。

最后,如果圖像有變換,則需要將點坐標從屏幕空間轉換為圖像空間,然后您可以檢查預先計算的蒙版。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM