不使用图像掩码如何裁剪图像?

4
我正在尝试在我的iPhone应用程序中添加一个功能,允许用户录制屏幕。为此,我使用了一个名为ScreenCaptureView的开源类,通过renderInContext:方法编译主视图的一系列屏幕截图。然而,这种方法忽略了关键的掩码CALayer,这对我的应用程序非常重要。
编辑: 我需要一种记录屏幕并包括掩码的方法。虽然这个问题特别要求创建一种图像掩码的假象,但我愿意采取任何其他修改来成功记录屏幕。
应用描述: 在应用中,我拍照并通过动画化下巴区域的位置来创造一个移动嘴巴的效果,如下所示。

enter image description here enter image description here

目前,我将整个脸作为一个CALayer,下巴区域作为一个单独的CALayer。为了制作下巴层,我使用CGPath从完整的脸部遮罩下巴区域。(该路径是不规则的形状,必须是动态的)。

enter image description here

- (CALayer *)getChinLayerFromPic:(UIImage *)pic frame:(CGRect)frame {


    CGMutablePathRef mPath = CGPathCreateMutable();
    CGPathMoveToPoint(mPath, NULL, p0.x, p0.y);
    CGPoint midpt = CGPointMake( (p2.x + p0.x)/2, (p2.y+ p0.y)/2);
    CGPoint c1 = CGPointMake(2*v1.x - midpt.x, 2*v1.y - midpt.y); //control points
    CGPoint c2 = CGPointMake(2*v2.x - midpt.x, 2*v2.y - midpt.y);

    CGPathAddQuadCurveToPoint(mPath, NULL, c1.x, c1.y, p2.x, p2.y);
    CGPathAddQuadCurveToPoint(mPath, NULL, c2.x, c2.y, p0.x, p0.y);

    CALayer *chin = [CALayer layer];
    CAShapeLayer *chinMask = [CAShapeLayer layer];
    chin.frame = frame;
    chin.contents = (id)[pic CGImageWithProperOrientation];
    chinMask.path = mPath;
    chin.mask = chinMask;
    CGPathRelease(mPath);
    return chin;

}

我会将下巴层通过路径动画进行动画化。
如前所述,renderInContext:方法忽略掩码,并返回整个脸部的图像,而不仅仅是下巴。是否有任何方法可以创造一种下巴遮罩的错觉?如果可能的话,我想使用CALayers,因为它对于动画最方便。然而,我也愿意接受任何想法,包括其他捕捉视频的方法。谢谢。
编辑:我正在将裁剪的下巴转换成UIImage,然后将该新图像设置为图层内容,而不是直接对图层进行遮罩处理。但是,裁剪区域与指定的路径相反。
 CALayer *chin = [CALayer layer];
 chin.frame = frame;   
 CGImageRef imageRef = [pic CGImage];
 CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);
 int targetWidth = frame.size.width;
 int targetHeight = frame.size.height;
 CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);

 CGContextRef bitmap = CGBitmapContextCreate(NULL, targetWidth, targetHeight, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);
    CGContextAddPath(bitmap, mPath);
    CGContextClip(bitmap);
    CGContextDrawImage(bitmap, CGRectMake(0, 0, targetWidth, targetHeight), imageRef);
    CGImageRef ref = CGBitmapContextCreateImage(bitmap);
    UIImage *chinPic = [UIImage imageWithCGImage:ref];
    chin.contents = (id)[chinPic CGImageWithProperOrientation];
4个回答

0

你有没有尝试看一下layer.renderInContext不考虑layer.mask的情况??

特别是(注意坐标翻转):

//Make the drawing right with coordinate switch
CGContextTranslateCTM(context, 0, cHeight);
CGContextScaleCTM(context, 1.0, -1.0);

CGContextClipToMask(context, CGRectMake(maskLayer.frame.origin.x * mod, maskLayer.frame.origin.y * modTwo, maskLayer.frame.size.width * mod,maskLayer.frame.size.height * modTwo), maskLayer.image.CGImage);

//Reverse the coordinate switch
CGAffineTransform ctm = CGContextGetCTM(context);
ctm = CGAffineTransformInvert(ctm);
CGContextConcatCTM(context, ctm);

0

我建议你单独绘制每个部分(无需使用遮罩),包括没有下巴的脸和下巴,两者都带有透明像素边缘,然后只需将下巴绘制并移动到你的路径上..

如果这对你没有帮助,请告诉我,谢谢。


我最初有一个“没有下巴”的图层和一个“下巴”图层,但是我遇到了一些问题,所以我决定按照我的当前方式来做。 - Mahir
我在图像绘制方面有点缺乏经验。您能详细说明一下使用 alpha 像素进行绘制的含义吗? - Mahir
好的,您可以使用绘图功能在对象上绘制想要的一切,比如说您正在使用一个jpanel并在其上绘制图像,必须注意alpha像素,因为它们在过程中可能会丢失,因为它们没有rgb值。 您将不得不用argb来绘制它们(抱歉我现在不在家,无法参考我的旧项目文件),我希望这个链接能帮助您使用alpha映射绘制图像:http://docs.oracle.com/javase/tutorial/2d/images/drawimage.html - CME64
我注意到链接是针对Java的。我正在使用Objective-C。 - Mahir
哦,我以为你在用Java,可能是我昏睡了。我会为你检查的,但是相同的概念应该适用。 - CME64

0
如果你只是想捕捉屏幕,那么使用像这样的程序会更加容易。

http://www.airsquirrels.com/reflector/

该程序通过AirPlay将您的设备连接到计算机,然后在计算机上记录流。这个特定的程序内置了屏幕录制功能,非常方便。我认为您可以使用试用版进行最多10分钟的录制。


这是供用户记录屏幕的,不是我。 - Mahir

0
为什么不将下巴的CALayer绘制成单独的CGImage,并使用它创建一个新的UIImage呢? 然后,您可以将此CGImage添加到单独的UIImageView中,例如使用PanGestureRecognizer移动它。

我可以从普通的CALayer创建图像,但是当有蒙版时就不行了,因为这种方法涉及到renderInContext方法。有没有一种不同的绘制图层的方法可以考虑蒙版? - Mahir
你不能在不使用CALayers的情况下在CGContext中进行遮罩吗? 就像以下答案中所述: https://dev59.com/kGHVa4cB1Zd3GeqPigK9 - Bersaelor
我成功地获得了一个裁剪后的图像,但我认为我忽略了坐标系的变化,因为裁剪后的路径在屏幕的垂直方向上翻转并且位于相反的一侧。我已经在上面添加了我的代码。 - Mahir
这些东西中的图像方向很棘手;)尝试使用答案中的代码:https://dev59.com/YnM_5IYBdhLWcg3wt1k0 - Bersaelor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接