2013-10-05 2 views
0

Я хочу сделать выборочную маскировку между двумя изображениями в iOS, подобную функции маски в Blender. Есть два изображения 1 и 2 (с размерами до одинаковых размеров). Первоначально только изображение 1 будет видимым, но где бы пользователь ни коснулся какой-либо области изображения1, он становится прозрачным, а изображение 2 становится видимым в этих регионах.Маскирование двух изображений

Я создал маску-изображение, используя основную графику с движением касания. Это, по сути, полное черное изображение с белыми участками, где я касался. Альфа устанавливается равной 1.0. Я могу использовать это изображение в качестве маски и делать все необходимое, внедряя свои собственные методы обработки изображений, которые будут перебирать каждый пиксель, проверять его и устанавливать соответствующие значения. Теперь этот метод будет называться внутри touch touch, поэтому мой метод может замедлить весь процесс (особенно для 8-мегапиксельных изображений).

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

код у меня до сих пор:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    mouseSwiped = YES; 

    UITouch *touch = [touches anyObject]; 
    CGPoint currentPoint = [touch locationInView:staticBG]; 

    UIGraphicsBeginImageContext(staticBG.frame.size); 
    [maskView.image drawInRect:CGRectMake(0, 0, maskView.frame.size.width, maskView.frame.size.height)]; 

    CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound); 
    CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 20.0); 
    CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 1.0, 1.0, 0.0); 
    CGContextBeginPath(UIGraphicsGetCurrentContext()); 
    CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y); 
    CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y); 
    CGContextStrokePath(UIGraphicsGetCurrentContext()); 

    maskView.image = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    lastPoint = currentPoint; 
    mouseMoved++; 
    if (mouseMoved == 10) 
     mouseMoved = 0; 

    staticBG.image = [self maskImage:staticBG.image withMask:maskView.image]; 
    //maskView.hidden = NO; 
} 

- (UIImage*) maskImage:(UIImage *)baseImage withMask:(UIImage *)maskImage 
{ 
    CGImageRef imgRef = [baseImage CGImage]; 
    CGImageRef maskRef = [maskImage CGImage]; 
    CGImageRef actualMask = CGImageMaskCreate(CGImageGetWidth(maskRef), 
              CGImageGetHeight(maskRef), 
              CGImageGetBitsPerComponent(maskRef), 
              CGImageGetBitsPerPixel(maskRef), 
              CGImageGetBytesPerRow(maskRef), 
              CGImageGetDataProvider(maskRef), NULL, false); 
    CGImageRef masked = CGImageCreateWithMask(imgRef, actualMask); 
    return [UIImage imageWithCGImage:masked]; 
} 

Метод maskImage не работает, так как создает изображение маски в зависимости от значения альфа. Я прошел по этой ссылке: Creating Mask from Path, но я не могу понять ответ.

ответ

0

Прежде всего, я расскажу кое-что, что, надеюсь, вы уже знаете.

  • маскировочные работы, принимая только значения альфа.
  • создание изображения с основной графикой при каждом касании. Очень красивый накладный & вы должны попытаться избежать или использовать какой-либо другой способ делать что-то.
  • попробуйте использовать статическое изображение маски.

Я хотел бы предложить вам взглянуть на это с перевернутой точки зрения.

т. Е. Вместо того, чтобы пытаться сделать отверстие в верхнем изображении, пытаясь просмотреть снизу, почему бы не поместить нижнее изображение сверху & замаскируйте нижнее изображение так, чтобы оно отображало сенсорную точку пользователя, закрывающую вид сверху при определенных частей. ?

Я сделал пример для вас, чтобы получить представление здесь>http://goo.gl/Zlu31T

удачи & делать отправлять обратно, если что-то не понятно. Я верю, что есть намного лучший и оптимизированный способ сделать это. "_"

+0

Ya вашей реализация достаточно быстро в режиме реального времени, но вы можете дать мне какие-либо идеи о сохранении пути, я имею в виду предположит, я начну с середины и идите по диагонали сверху, тогда я хочу увидеть изображение логотипа яблока по всему пути, а не конкретный круг вокруг точки касания. – Soumyajit

+0

Я сделал свой запрос гораздо более понятным здесь: http://stackoverflow.com/questions/19218422/rgbstroke-image-pixels-instead-of-color-ios Пожалуйста, смотрите. – Soumyajit

+0

Когда у вас есть изображение с вашего CGPath, установите свойство содержимого слоя маски, как я сделал в примере. 'masklayer.contents = (__bridge id) (imagefromCGPath.CGImage); bottomimage.layer.mask = masklayer; ' Чтобы проверить производительность, вы должны запустить это на реальном устройстве. Имейте в виду, что операции ЦП выполняются быстрее на симуляторе, в то время как операции графического процессора работают очень медленно на симуляторе, так как симулятор должен создавать программный код графического процессора, поэтому операции графического процессора выполняются намного быстрее на реальном устройстве. – nsuinteger

0

Поскольку вы делаете это в режиме реального времени, я предлагаю вам подделать его во время редактирования, и если вам нужно будет выводить изображение позже, вы можете замаскировать его по-настоящему, поскольку это может занять некоторое время (не так много, просто не достаточно быстро, чтобы делать это в режиме реального времени). И при подделке я хочу поставить изображение1 в качестве фона, а поверх него положить скрытое изображение2. Как только пользователь коснется точки, установите границы изображения2 UIImageView на CGRect rect= CGRectMake(touch.x - desiredRect.size.width/2, touch.y - desiredRect.size.height/2, desiredRect.size.width, desiredRect.size.height); и сделайте его видимым. desiredRect будет частью изображения2, которое вы хотите показать. При поднятии пальца вы можете просто скрыть изображение2 UIImageView, чтобы изображение1 было полностью видимым. Это самый быстрый способ, который я мог бы подумать прямо сейчас, если ваша цель - не выводить изображение в тот самый момент.

+0

Этот метод кажется интересным. Я попробую и вернусь к вам. Интересно, что у многих приложений есть функция маскирования с помощью пользователя, я думал, что может быть какой-то прямой способ сделать это (или, может быть, люди делают это с помощью шейдеров openGL в реальном времени) – Soumyajit

+0

То же самое здесь, может быть, мой вопрос не совсем ясен, но Я хочу, чтобы изменения выполнялись постоянно на самом изображении, и если я нарисую путь, обратное изображение будет видимым по всему пути. Если я протираю весь imageView пальцем, то переднее изображение должно быть полностью исчезло, а обратное изображение будет полностью видимым. – Soumyajit

+0

http://stackoverflow.com/questions/19218422/rgbstroke-image-pixels-instead-of-color-ios – Soumyajit

0

Используйте этот код, это поможет для маскировки два UIImages

CGSize newSize = CGSizeMake(320, 377); 
       UIGraphicsBeginImageContext(newSize); 

      // Use existing opacity as is 
      [ backGroundImageView.image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)]; 
      // Apply supplied opacity 
      [self.drawImage.image drawInRect:CGRectMake(0,0,newSize.width,newSize.height) blendMode:kCGBlendModeNormal alpha:0.8]; 

      UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); 

      UIGraphicsEndImageContext(); 

      imageData = UIImagePNGRepresentation(newImage); 
+0

Я пробовал этот метод с небольшим изменением blendMode: kCGBlendModeColorMultiply все еще его занимает много времени – Soumyajit

Смежные вопросы