CodeV

7.3-复杂蒙版

图7-2中的蒙版产生的结果比基本的路径剪切复杂得多。 每个灰度蒙版不仅决定了每个像素可以被绘制的位置,还决定了该像素的绘制程度。 由于蒙版元素的范围从白色到黑色,它们的灰度级别描述了像素对最终图像的贡献程度。

图7-2

图7-2灰度蒙版中的层次建立了如何绘制像素。Public domain images courtesy of the National Park Service.

这些蒙版通过更新上下文状态来工作。 使用CGContextCliptoMask()函数将您提供的蒙版映射到当前上下文的矩形中:

1
2
3
4
5
void CGContextClipToMask (
CGContextRef c,
CGRect rect,
CGImageRef mask
};

对于复杂的绘图,请在GState块内执行蒙版。 您可以在蒙版调用时保存并恢复上下文GState以临时应用蒙版。 这使您能够将上下文恢复到其未应用蒙版的条件以进一步绘制任务,如下例所示:

1
2
3
4
PushDraw(^{
ApplyMaskToContext(mask); // See Listing 7-2
[image drawInRect:targetRect];
});

上下文蒙版确定绘制的像素和绘制的程度。 蒙版中的黑色像素完全遮蔽。没有数据可以通过。 白色像素允许所有数据通过。 纯黑色和纯白色之间的灰色级别将相应的Alpha值应用于绘画。 例如,中等灰色绘画时具有50%透明度。 使用黑白蒙版,蒙版数据必须使用灰度级源图像。 (实现此功能还有第二种方法,本章稍后将会看到。)

清单7-2演示了如何将灰度蒙版应用于当前上下文。 此功能通过将蒙版转换为无alpha的灰色空间开始(请参见第3章)。 它计算上下文大小,以便蒙版在整个上下文中被拉伸(参见第1章)。

要应用蒙版,您必须在Quartz空间中,否则蒙版将被倒置应用。 该功能翻转上下文,添加蒙版,然后将上下文翻转回UIKit坐标以适应下一步的绘图命令。 这个flip–apply–flip顺序从上到下应用蒙版,正如你画的一样。

如果您正在寻找灵感,一个简单的“Photoshop蒙版”网络搜索将返回大量预置的黑白蒙版,可以在iOS应用程序中使用。 确保检查个人许可条款,但您会发现许多蒙版已被放置在公共领域,或提供免版税的使用条款。

清单7-2将蒙版应用于上下文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void ApplyMaskToContext(UIImage *mask)
{
if (!mask)
COMPLAIN_AND_BAIL(@"Mask image cannot be nil", nil);
CGContextRef context = UIGraphicsGetCurrentContext();
if (context == NULL) COMPLAIN_AND_BAIL(
@"No context to apply mask to", nil);

// Ensure that mask is grayscale
UIImage *gray = GrayscaleVersionOfImage(mask);

// Determine the context size
CGSize size = CGSizeMake(
CGBitmapContextGetWidth(context),
CGBitmapContextGetHeight(context));
CGFloat scale = [UIScreen mainScreen].scale;
CGSize contextSize = CGSizeMake(
size.width / scale, size.height / scale);

// Update the GState for masking
FlipContextVertically(contextSize);
CGContextClipToMask(context,
SizeMakeRect(contextSize), gray.CGImage);
FlipContextVertically(contextSize);
}

本文翻译自《iOS Drawing Practical UIKit Solutions》作者:Erica Sadun,翻译:Cheng Dong。如果觉得本书不错请购买支持正版:亚马逊购买传送门,本书所有源代码可在GitHub上下载。译者虽然力求做到信,达,雅,但是由于时间仓促加之译者水平十分有限,文中难免会出现不正确,不准确,词不达意,难于理解的地方,还望各位批评指正,共同进步,谢谢。转载请注明出处。