2D обнаружение столкновения на уровне пикселей между UIImages - PullRequest
1 голос
/ 22 октября 2011

Я пытаюсь закодировать метод, который обнаруживает, когда сталкиваются два UIImage, принимая во внимание только непрозрачные пиксели. Просто чтобы быть понятным, метод, который возвращает TRUE, когда пиксель с его альфа-компонентом больше 0 в UIImageView перекрывается с пикселем, а его альфа-компонент больше 0 в другом UIImageView.

Метод должен выглядеть примерно так:

- (void)checkCollisionBetweenImage:(UIImage *)img1 inFrame:(CGRect)frame1 andImage:(UIImage *)img2 inFrame:(CGRect)frame2;

Таким образом, он получает оба изображения для проверки с независимой передачей кадра, так как позиции координат должны быть преобразованы для соответствия (UIImageView.frame не подойдет).

[ОБНОВЛЕНИЕ 1] Я обновлю фрагмент кода, который использовал в предыдущем вопросе, который я задал, однако этот код не всегда работает. Я предполагаю, что проблема заключается в том, что используемые UIImages не обязательно находятся в одном и том же суперпредставлении.

Обнаружение столкновения / перекрытия пикселей между двумя изображениями

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 = malloc(canvasRect.size.width * canvasRect.size.height * 4 * bitsPerComponent);
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++)
{
    int8_t alpha = rawData[byteIndex + 3];
    if (alpha > 64) 
    {
        NSLog(@"collided in byte: %d", i);
        free(rawData);
        return YES;
    }
    byteIndex += 4;
}

free(rawData);

return NO;

[ОБНОВЛЕНИЕ 2] Я использовал другую строку, предположительно необходимую перед рисованием маскированного изображения.

CGContextSetBlendMode(context, kCGBlendModeCopy);

Все еще не работает. Любопытно, что я проверял альфа-значения, обнаруженные при столкновении, и они являются случайными числами. Это любопытно, потому что изображения, которые я использую, имеют только полную непрозрачность или полную прозрачность, ничего между ними.

Ответы [ 2 ]

0 голосов
/ 22 октября 2011

Хмм ... Ваша проблема в том, что ваши изображения имеют белые квадраты позади, и вы не хотите, чтобы белые прямоугольники сталкивались, но вы хотите, чтобы изображения внутри них сталкивались? Что ж... Я не думаю, что вы можете проверить столкновение на основе цветов. Вам нужно скачать программное обеспечение для редактирования изображений (например, gimp) и обрезать белый фон.

0 голосов
/ 22 октября 2011

Проверка на фактическое пересечение кадра -> дает вам прямоугольник. Проверьте каждый пиксель в одном из изображений в прямоугольнике на альфа> 0. Если это так, то преобразуйте текущую координату в другое изображение, а затем, если альфа этого пикселя> 0, у вас есть попадание. Повторяйте, пока прямоугольник не будет сделан. Остановитесь рано, если у вас есть удар.

...