layer.renderInContext 不考虑 layer.mask?

Posted

技术标签:

【中文标题】layer.renderInContext 不考虑 layer.mask?【英文标题】:layer.renderInContext doesn't take layer.mask into account? 【发布时间】:2011-02-04 09:15:27 【问题描述】:

我正在尝试将一些 UIImages 渲染为 1 张可以保存在相册中的单张图像。但是好像 layer.renderInContext 没有考虑图层蒙版?

当前行为:照片保存,我看到了mosaicLayer,没有maskLayer的遮罩效果。

预期行为:照片保存,我在视图中看到了图像,上面还有一个蒙版的镶嵌图层。

我使用下面的代码来屏蔽图像

UIImage *maskImg = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle]
                        pathForResource:@"mask" ofType:@"png"]];

    maskLayer = [[UIImageView alloc] initWithImage:maskImg];
    maskLayer.multipleTouchEnabled = YES;
    maskLayer.userInteractionEnabled = YES;
    UIImageView *mosaicLayer = [[UIImageView alloc] initWithImage:img];
    mosaicLayer.contentMode = UIViewContentModeScaleAspectFill;

    mosaicLayer.frame = [imageView bounds]; 
    mosaicLayer.layer.mask = maskLayer.layer;

    [imageView addSubview:mosaicLayer];

然后我使用这段代码来保存我的合成图像:

UIGraphicsBeginImageContext(imageView.bounds.size);
    [imageView.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *saver = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    UIImageWriteToSavedPhotosAlbum(saver, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);

编辑:这会正确应用掩码

-(IBAction) saveImage  
UIImage * saver = nil;
CGImageRef image = imageView.image.CGImage;

size_t cWidth = CGImageGetWidth(image);
size_t cHeight = CGImageGetHeight(image);
size_t bitsPerComponent = 8; 
size_t bytesPerRow = 4 * cWidth;

//Now we build a Context with those dimensions.
CGContextRef context = CGBitmapContextCreate(nil, cWidth, cHeight, bitsPerComponent, bytesPerRow, CGColorSpaceCreateDeviceRGB(), CGImageGetBitmapInfo(image));

//The location where you draw your image on the context is not always the same location you have in your UIView, 
//this could change and you need to calculate that position according to the scale between you images real size, and the size of the UIImage being show on the UIView. Hence the mod floats...
CGContextDrawImage(context, CGRectMake(0, 0, cWidth,cHeight), image);

float mod = cWidth/(imageView.frame.size.width);
float modTwo = cHeight/(imageView.frame.size.height);

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

CGContextDrawImage(context, CGRectMake(0, 0, cWidth,cHeight), mosaicLayer.image.CGImage);

CGImageRef mergeResult  = CGBitmapContextCreateImage(context);
saver = [[UIImage alloc] initWithCGImage:mergeResult];
CGContextRelease(context);
CGImageRelease(mergeResult);

UIImageWriteToSavedPhotosAlbum(saver, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);

【问题讨论】:

,,我也需要做类似的代码,你能不能给我一些有用的代码。提前致谢 【参考方案1】:

renderInContext: 的文档指出,除其他属性外,mask 在 Mac OS X 10.5 上不受支持。我怀疑它在 ios 上是一样的,即使文档没有这么说。

要解决您的问题,您可能必须将图层分别绘制到图形上下文中,并在图形上下文本身上设置正确的蒙版。

【讨论】:

这里建议?:***.com/questions/2795151/… @Ole 我已经更新了我的问题,我不知道如何正确应用面具。 在绘制第二张图像之前,您必须使用CGContextClipToMask() 将遮罩应用于图形上下文。如果您的蒙版图像不是灰度图像,您可能需要先将其转换为灰度图像,然后才能将其用作CGContextClipToMask() 中的蒙版。有关详细信息,请参阅文档。 是的,我刚刚发现了一个,即使没有看你的答案! :) 剩下的唯一问题是面具没有正确的尺寸和位置。我猜这与蒙版在视图中的位置与上下文不同的事实有关? @Ole,我似乎找不到要绘制的修改因子。我认为这很简单:我应该将位置和比例乘以 (image-size / imageview-size).. 这怎么不正确?

以上是关于layer.renderInContext 不考虑 layer.mask?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift 中截取全屏截图?

如何将 UIView 转换为高分辨率的 UIImage?

为啥GPDB在成本估算中不考虑段数

在重载时为啥不考虑函数的返回类型? [复制]

考虑不平衡的分层抽样分为3组

中缀表达式转后缀并计算(只考虑个位整数,不考虑除0等情况)