2011-10-20 18 views
4

透明な領域を持つ画像を含む2つのUIImageViewがあります。両方の画像間の不透明領域が衝突するかどうかを確認する方法はありますか?2つの画像間のピクセル衝突/オーバーラップの検出

ありがとうございました。

[UPDATE] これは私が今まで行ってきたことですが、残念ながらそれはまだ動作していませんが、理由を理解できません。

if (!CGRectIntersectsRect(frame1, frame2)) return NO; 
NSLog(@"OverlapsPixelsInImage:withImage:> Images Intersect"); 

UIImage *img1 = imgView1.image; 
UIImage *img2 = imgView2.image; 
CGImageRef imgRef1 = [img1 CGImage]; 
CGImageRef imgRef2 = [img2 CGImage]; 

float minx = MIN(frame1.origin.x, frame2.origin.x); 
float miny = MIN(frame1.origin.y, frame2.origin.y); 
float maxx = MAX(frame1.origin.x + frame1.size.width, frame2.origin.x + frame2.size.width); 
float maxy = MAX(frame1.origin.y + frame1.size.height, frame2.origin.y + frame2.size.height); 
CGRect canvasRect = CGRectMake(0, 0, maxx - minx, maxy - miny); 

size_t width = floorf(canvasRect.size.width); 
size_t height = floorf(canvasRect.size.height); 

NSUInteger bitsPerComponent = 8; 
NSUInteger bytesPerRow = 4 * width; 
unsigned char *rawData = calloc(width * height, sizeof(*rawData)); 
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

CGContextRef context = CGBitmapContextCreate(rawData, width, height, bitsPerComponent, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast); 

CGColorSpaceRelease(colorSpace); 

CGContextTranslateCTM(context, 0, canvasRect.size.height); 
CGContextScaleCTM(context, 1.0, -1.0); 

CGContextClipToMask(context, CGRectMake(frame2.origin.x - minx, frame2.origin.y - miny, frame2.size.width, frame2.size.height), imgRef2); 
CGContextDrawImage(context, CGRectMake(frame1.origin.x - minx, frame1.origin.y - miny, frame1.size.width, frame1.size.height), imgRef1); 

CGContextRelease(context); 

int byteIndex = 0; 
for (int i = 0; i < width * height; i++) 
{ 
    CGFloat alpha = rawData[byteIndex + 3]; 
    if (alpha > 128) 
    { 
     NSLog(@"collided in byte: %d", i); 
     free(rawData); 
     return YES; 
    } 
    byteIndex += 4; 
} 

free(rawData); 

return NO; 

答えて

1

両方の画像の両方のアルファチャンネルを1つのビットマップコンテキストに描画し、透過ピクセルのデータを調べることができます。 Clipping CGRect to a CGPathclipRectToPath()コードをご覧ください。それは別の問題を解決していますが、アプローチは同じです。コンテキスト内に描画する場合はCGContextFillPath()を使用するのではなく、両方の画像を描画します。ここで

は流れます:

  1. は、あなたが値を見てピクセルを歩くことに
  2. を比較したいすべてのものを描きアルファのみのビットマップコンテキスト(kCGImageAlphaOnly
  3. を作成します。私の例では、それは< 128を "透明"と見なします。完全に透明にしたい場合は、== 0を使用してください。
  4. トランスペアレントピクセルを見つけたら、その列がどの列にあるかをメモするだけです。問題の場合は、YESを返すか、そのデータを使用して別のマスクを作成できます。
+0

このアルゴリズムが衝突を検出する方法はまだわかりません。私がkCGImageAlphaOnlyコンテキストで両方のイメージを描画すると、透過ピクセルと非透明ピクセルが見つかるので、透明ピクセルを探してもそのトリックはできません。 – jglievano

+0

あなたは正しいです。私はあなたがここで画像を簡単にマージして重複を見つけることはできないと信じています(私は透明性を探していました)。しかし、@ logancautrellのアプローチは正しく動作するはずです。リファレンスサンプルを使用して2つのビットマップ配列を作成し、 'X> 0 && Y> 0'の両方を探して歩いてください。 –

+0

おそらくあなたの方法も機能します。 1つのイメージを描いて、他のイメージをマスクすることができます。次に、透明でないピクセルがあれば、衝突があることを意味します。 – jglievano

1

簡単にはできませんが、生のビットマップデータを読み込んでピクセルを歩かなければなりません。