【问题标题】:Masking two images屏蔽两个图像
【发布时间】:2013-10-12 07:06:41
【问题描述】:

我想在 iOS 中的两个图像之间进行选择性遮罩,类似于 Blender 中的遮罩功能。有两个图像 1 和 2(调整为相同的尺寸)。最初只有图像 1 可见,但无论用户在哪里触摸 image1 上的任何区域,它都会变得透明,而图像 2 在这些区域中变得可见。

我使用带有触摸移动的核心图形创建了一个类似蒙版的图像。它基本上是一个全黑的图像,在我触摸的任何地方都有白色部分。 alpha 始终设置为 1.0。我可以将此图像用作掩码,并通过实现我自己的图像处理方法来完成必要的工作,这些方法将遍历每个像素,检查并设置相应的值。现在这个方法将在 touch move 内部调用,所以我的方法可能会减慢整个过程(特别是对于 8MP 相机图像)。

我想知道如何使用 Quartz Core 或 Core Graphics 来实现这一点,它们的效率足以在大图像中运行。

到目前为止我的代码:

- (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 方法不起作用,因为它会根据 alpha 值创建掩码图像。 我浏览了这个链接:Creating Mask from Path,但我无法理解答案。

【问题讨论】:

    标签: ios objective-c image masking


    【解决方案1】:

    首先我要提一些我希望你已经知道的事情。

    • 屏蔽仅通过获取 alpha 值起作用。
    • 在每次 touchMove 时创建带有核心图形的图像是一项相当大的开销,您应该尽量避免或使用其他方法。
    • 尝试使用静态蒙版图像。

    我想建议你从一个倒置的角度来看待这个问题。

    ie 与其尝试在顶部图像上打一个洞来尝试查看底部,不如将底部图像放在顶部并遮盖底部图像,以便显示用户的触摸点覆盖特定部分的顶部视图. ?

    我已经做了一个例子让你在这里得到一个想法>http://goo.gl/Zlu31T

    祝你好运,如果有任何不清楚的地方请回帖。我确实相信有更好和优化的方法来做到这一点。 “_”

    【讨论】:

    • 是的,您的实时实现速度足够快,但是您能给我关于保存路径的任何想法吗?我的意思是,假设我从中间开始并沿对角线顶部走,然后我想查看苹果徽标图像通过整个路径,而不是围绕触摸点的特定圆圈。
    • 我在这里让我的查询更加清晰:stackoverflow.com/questions/19218422/… 请看一下..
    • 当您从 CGPath 获得图像时,设置为蒙版层的内容属性,就像我在示例中所做的那样。 masklayer.contents = (__bridge id)(imagefromCGPath.CGImage); bottomimage.layer.mask = masklayer; 要检查性能,您必须在真实设备上运行它。请记住,CPU 操作在模拟器上运行得更快,而 GPU 操作在模拟器上运行得非常慢,因为模拟器必须创建基于软件的 GPU 代码,因此 GPU 操作在真实设备上运行得更快。
    【解决方案2】:

    因为你是实时做的,所以建议你在编辑的时候假装它,如果你以后需要输出图像,你可以把它蒙版,因为它可能需要一些时间(不多,只是速度不够快,无法实时完成)。通过伪装,我的意思是将 image1 作为背景,并在其上放置隐藏的 image2。用户触摸该点后,将 image2 UIImageView 的边界设置为 CGRect rect= CGRectMake(touch.x - desiredRect.size.width/2, touch.y - desiredRect.size.height/2, desiredRect.size.width, desiredRect.size.height); 并使其可见。 desiredRect 将是您要显示的 image2 的一部分。抬起手指后,您可以隐藏 image2 UIImageView,以便 image1 完全可见。如果您的目标不是在那一刻输出图像,这是我现在能想到的最快方法。

    【讨论】:

    • 这个方法看起来很有趣。我会尝试一下并回复你。有趣的是,许多应用程序都有这种用户驱动的遮罩功能,我认为可能有一些直接的方法来做到这一点(或者人们可能正在通过 openGL 着色器实时做到这一点)
    • 同样的事情,也许我的问题并不完全清楚,但我希望对图像本身进行永久更改,如果我绘制路径,则背面图像将在整个路径中可见。如果我用手指摩擦整个 imageView,那么前面的图像应该完全消失,后面的图像完全可见。
    【解决方案3】:

    使用此代码将有助于屏蔽两个 UIImage

    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);
    

    【讨论】:

    • 我尝试了这个方法,稍微改变一下 blendMode:kCGBlendModeColorMultiply 仍然需要很多时间
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-02
    • 1970-01-01
    • 1970-01-01
    • 2020-02-15
    • 1970-01-01
    相关资源
    最近更新 更多