Обнаружение альфа-канала на преобразованном изображении в UIImageView - PullRequest
3 голосов
/ 05 января 2012

Я использую эту функцию, чтобы определить, соответствует ли точка касания UIImageView прозрачному пикселю или нет.

-(BOOL)isTransparency:(CGPoint)point
{
    CGImageRef cgim = self.image.CGImage;

    unsigned char pixel[1] = {0};

    point.x = (point.x / (self.frame.size.width / CGImageGetWidth(cgim)));
    point.y = (point.y / (self.frame.size.height / CGImageGetHeight(cgim)));


    CGContextRef context = CGBitmapContextCreate(pixel, 
                                                 1, 1, 8, 1, NULL,
                                                 kCGImageAlphaOnly);

    CGContextSetBlendMode(context, kCGBlendModeCopy);

    CGContextDrawImage(context, CGRectMake(-point.x, 
                                           -(self.image.size.height - point.y), 
                                           CGImageGetWidth(cgim), 
                                           CGImageGetHeight(cgim)), 
                       cgim);

    CGContextRelease(context);

    CGFloat alpha = pixel[0]/255.0;

    return alpha < 0.01;

}

Работает нормально, если преобразование UIImageView не изменено.Но когда пользователь поворачивает изображение, матрица преобразования изменяется, этот код возвращает изображение в исходное положение, не соответствующее положению преобразованного изображения, и я получаю ложные результаты.

У меня вопрос, как я могуопределить, прозрачен ли пиксель изображения UIImageView при его повороте?

Спасибо.

РЕДАКТИРОВАТЬ: -Версия 1.1-

Привет.Спасибо за ответ.Я изменил код, и теперь эта версия все еще работает как предыдущая версия:

-(BOOL)isTransparency:(CGPoint)point
{
    CGImageRef cgim = self.image.CGImage;

    NSLog(@"Image Size W:%lu H:%lu",CGImageGetWidth(cgim),CGImageGetHeight(cgim));

    unsigned char pixel[1] = {0};

    point.x = (point.x / (self.frame.size.width / CGImageGetWidth(cgim)));
    point.y = (point.y / (self.frame.size.height / CGImageGetHeight(cgim)));


    CGContextRef context = CGBitmapContextCreate(pixel, 
                                                 1, 1, 8, 1, NULL,
                                                 kCGImageAlphaOnly);

    CGContextSetBlendMode(context, kCGBlendModeCopy);

    CGContextTranslateCTM(context, self.image.size.width * 0.5f, self.image.size.height * 0.5f);
    CGContextConcatCTM(context, self.transform);
    //CGContextScaleCTM(context, [self currentPercent]/100, [self currentPercent]/100);
    //CGContextRotateCTM(context, atan2f(self.transform.b, self.transform.a));
    CGContextTranslateCTM(context, -self.image.size.width * 0.5f, -self.image.size.height * 0.5f);

    CGContextDrawImage(context, CGRectMake(-point.x, 
                                           -(self.image.size.height - point.y), 
                                           self.image.size.width, 
                                           self.image.size.height), 
                       cgim);

    CGContextRelease(context);

    CGFloat alpha = pixel[0]/255.0;

    NSLog(@"Is Transparent: %d",alpha < 0.01);

    return alpha < 0.01;

}

Я попытался с несколькими функциями повернуть и масштабировать исходное изображение до текущего поворота и размера без успеха.: (

Любая помощь, пожалуйста?

РЕДАКТИРОВАТЬ: Версия 1.2

Я нашел обходной путь для решения этой проблемы. Я решил создать контекст сразмер равен размеру экрана и рисует только затронутый объект, в соответствии с текущей матрицей преобразования.

После этого я создаю растровое изображение для этого контекста, где изображение рисуется правильно, и передаю изображение в функцию, которая работает толькос не преобразованными изображениями.

В результате все работает хорошо. Я не знаю, является ли это оптимальным способом, но работает.

Вот код:

-(BOOL)isTransparency:(CGPoint)point
{
    UIGraphicsBeginImageContext(self.superview.bounds.size);
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSaveGState(context);

    CGContextSetBlendMode(context, kCGBlendModeCopy);

    CGContextTranslateCTM(context, [self center].x, [self center].y);
    CGContextConcatCTM(context, [self transform]);
    CGContextTranslateCTM(context,
                          -[self bounds].size.width * [[self layer] anchorPoint].x,
                          -[self bounds].size.height * [[self layer] anchorPoint].y);

    [[self image] drawInRect:[self bounds]];

    CGContextRestoreGState(context);

    CGImageRef image = CGBitmapContextCreateImage(context);

    CGImageRef viewImage = image;

    return [self isTransparentPixel:point image:image];

}

Эта функция создает изображение с размером суперпредставления (в моем случае это всегда полноэкранный режим) и получает в качестве параметра точку касания в системе координат UIKit из родительского представления.

-(BOOL)isTransparentPixel:(CGPoint)point image:(CGImageRef)cgim
{
    NSLog(@"Image Size W:%lu H:%lu",CGImageGetWidth(cgim),CGImageGetHeight(cgim));

    unsigned char pixel[1] = {0};

    CGContextRef context = CGBitmapContextCreate(pixel, 
                                                 1, 1, 8, 1, NULL,
                                                 kCGImageAlphaOnly);

    CGContextSetBlendMode(context, kCGBlendModeCopy);

    CGContextDrawImage(context, CGRectMake(-point.x, 
                                           -(self.superview.frame.size.height - point.y), 
                                           CGImageGetWidth(cgim), 
                                           CGImageGetHeight(cgim)), 
                       cgim);

    CGContextRelease(context);

    CGFloat alpha = pixel[0]/255.0;

    return alpha < 0.01;

}

Эта функция обнаруживаетальфа-канал данного пикселя в данном изображении.

Спасибо за все.

1 Ответ

2 голосов
/ 08 января 2012

Примените преобразование из представления вашего изображения к вашему CGContext с помощью функции, такой как CGContextConcatCTM (), перед рисованием вашего изображения.

...