Core Graphics 之 Bitmap Images and Image Masks (十二)

Bitmap Images and Image Masks

位图图像和图像掩码类似于Quartz中的任何绘图原语。Quartz中的图像和图像掩码都由CGImageRef数据类型表示。正如您将在本章后面看到的,有许多函数可以用来创建图像。其中一些需要数据提供程序或图像源来提供位图数据。其他函数通过复制映像或对映像应用操作从现有映像创建映像。无论您如何在Quartz中创建位图图像,您都可以根据图形上下文绘制图像。请记住,位图图像是具有特定分辨率的位的数组。如果您将位图图像绘制到与分辨率无关的图形上下文(比如PDF图形上下文),那么位图会受到创建它的分辨率的限制。
有一种创建Quartz图像掩码的方法——通过调用CGImageMaskCreate函数。您将看到如何在创建图像掩码时创建一个掩码。应用图像掩码并不是绘制掩码的唯一方法。这些部分用颜色对图像进行屏蔽,用图像掩码对图像进行屏蔽,通过剪切上下文对图像进行屏蔽,讨论了Quartz中可用的所有屏蔽方法。

About Bitmap Images and Image Masks

位图图像(或采样图像)是像素阵列(或采样)。每个像素代表图像中的一个点。JPEG、TIFF和PNG图形文件是位图图像的示例。应用程序图标是位图图像。位图图像被限制为矩形。但是使用alpha组件,它们可以呈现出各种形状,可以旋转和裁剪,如图11-1所示。


屏幕快照 2018-08-28 上午9.57.34.png

位图中的每个示例在指定的颜色空间中包含一个或多个颜色组件,外加一个指定alpha值以表示透明度的附加组件。每个组件可以从1到32位。在Mac OS X中,Quartz还支持浮点组件。Mac OS X和iOS中支持的格式描述为“位图图形上下文支持的像素格式”。ColorSync为位图图像提供了颜色空间支持。

Quartz还支持图像掩码。图像掩码是位图,指定要绘制的区域,但不指定颜色。实际上,图像掩码充当模板,指定在页面上放置颜色的位置。Quartz使用当前填充颜色来绘制图像掩码。图像掩码的深度可以是1到8位。

Bitmap Image Information

Quartz支持各种各样的图像格式,并且具有几种流行格式的内置知识。在iOS中,这些格式包括JPEG、GIF、PNG、TIF、ICO、GMP、XBM和CUR。您提供给CGImageCreate函数的图像数据必须以每个像素为间隔,而不是以每个扫描行为基础。Quartz不支持平面数据。

本节描述与位图图像相关的信息。当您创建和使用Quartz映像(使用CGImageRef数据类型)时,您将看到一些Quartz映像创建函数需要您指定所有这些信息,而其他函数则需要这些信息的子集。您提供的内容取决于用于位图数据的编码,以及位图表示的是图像还是图像掩码。
注意:为了在处理原始图像数据时获得最佳性能,请使用vImage框架。您可以使用vImageBuffer_InitWithCGImage函数从CGImageRef引用中导入图像数据到vImage。有关详细信息,请参阅加速发行说明。
Quartz在创建位图图像(CGImageRef)时使用以下信息:
1、位图数据源,可以是Quartz数据提供程序或Quartz图像源。Quartz 2D中的数据管理描述了这两种功能,并讨论了提供位图数据源的功能。
2、可选的解码阵列(解码阵列)。
3、一个插值设置,它是一个布尔值,指定在调整图像大小时Quartz是否应该应用插值算法。
4、指定如何映射位于图形上下文的目标颜色空间中的颜色的呈现意图。此信息不需要用于图像掩码。有关更多信息,请参见设置呈现意图。
5、图像尺寸
6、像素格式,包括每个组件的位、每个像素的位和每行的字节(像素格式)。
对于图像,颜色空间和位图布局(颜色空间和位图布局)信息来描述alpha的位置和位7、图是否使用浮点值。图像掩码不需要这些信息。

Decode Array

解码数组将图像的颜色值映射到其他颜色值,这对于消除图像的饱和度或反转颜色等任务非常有用。数组包含每个颜色组件的一对数字。当Quartz呈现图像时,它应用线性变换将原始组件值映射到与目标颜色空间相适应的指定范围内的相对数字。例如,RGB颜色空间中的图像的decode数组包含6个条目,每个条目对应一个红色、绿色和蓝色组件。

像素格式

像素格式包含以下信息:

每个组件的比特数,也就是像素中每个颜色组件的比特数。对于图像掩码,此值是源像素中重要掩码位的数量。例如,如果源映像是8位掩码,则为每个组件指定8位。
每个像素的比特数,也就是源像素中比特的总数。这个值必须至少是每个组件的比特数乘以每个像素的组件数。
每一行的字节数。图像中每一行的字节数。

Color Spaces and Bitmap Layout

为了确保Quartz正确地解释每个像素的位,您必须指定:

位图是否包含alpha通道。Quartz支持RGB、CMYK和灰色空间。它还支持alpha或透明度,尽管alpha信息在所有位图图像格式中不可用。当alpha分量可用时,它可以位于像素中最重要的位或最不重要的位。
对于具有alpha组件的位图,颜色组件是否已经乘以alpha值。预乘阿尔法描述了一个源颜色,其组成部分已经乘以一个阿尔法值。预乘通过消除每个颜色组件的额外乘法操作,加速了图像的呈现。例如,在RGB颜色空间中,使用预乘alpha绘制图像消除了图像中每个像素的三个乘法运算(红色乘以alpha,绿色乘以alpha,蓝色乘以alpha)。
整数或浮点值的数据格式。
当您使用CGImageCreate函数创建图像时,您将提供一个bitmapInfo参数(类型为CGImageBitmapInfo)来指定位图布局信息。下面的常量指定alpha组件的位置以及颜色组件是否被预乘:
alpha组件存储在每个像素的最小有效位中,例如RGBA。
alpha组件存储在每个像素中最重要的部分,例如ARGB。
alpha组件存储在每个像素的最小有效位中,颜色组件已经被这个alpha值相乘。
kcgimagealphapremultipliedfirst - alpha组件存储在每个像素的最重要的位上,颜色组件已经乘以这个alpha值。
没有alpha组件。如果像素的总大小大于颜色空间中颜色组件数量所需的空间,则忽略最小有效位。
没有alpha组件。如果像素的总大小大于颜色空间中颜色分量数目所需的空间,则忽略最重要的位元。
kCGImageAlphaNone-equivalent kCGImageAlphaNoneSkipLast。
使用常量kCGBitmapFloatComponents表示使用浮点值的位图格式。对于浮点格式,在逻辑上或此常量与前面列表中的适当常量相同。例如,对于使用预乘alpha的每像素128位浮点格式(alpha位于每个像素的最小有效位),您向Quartz提供以下信息:

kCGImageAlphaPremultipliedLast|kCGBitmapFloatComponents

图11-2直观地描述了使用16位或32位整数格式的CMYK和RGB颜色空间中像素是如何表示的。32位整数像素格式每个组件使用8位。16位整数格式每个组件使用5位。Quartz 2D也支持128位浮点像素格式,每个组件使用32位元。图中没有显示128位格式。


屏幕快照 2018-08-28 上午10.03.51.png
Creating Images

表11-1列出了Quartz为创建CGImage对象提供的函数。图像创建函数的选择取决于图像数据的来源。最灵活的函数是CGImageCreate。它从任何类型的位图数据中创建图像。但是,它是最复杂的函数,因为必须指定所有位图信息。要使用此函数,您需要熟悉位图图像信息中讨论的主题。

如果你想创建一个CGImage对象从一个图像文件,它使用一个标准的图像格式如PNG和JPEG,最简单的解决方案是调用函数CGImageSourceCreateWithURL来创建一个图像源,然后调用函数CGImageSourceCreateImageAtIndex来创建一个图像的图像数据在一个特定的索引图像源。如果原始图像文件仅包含一个图像,则提供0作为索引。如果图像文件格式支持包含多个图像的文件,则需要将索引提供给适当的图像,记住索引值从0开始。

如果您已经将内容绘制到位图图形上下文,并且希望将该绘制捕获到CGImage对象,请调用函数CGBitmapContextCreateImage。

有几个函数是对现有图像进行操作的实用程序,可以复制、创建缩略图,也可以从较大图像的一部分创建图像。无论如何创建CGImage对象,都使用CGContextDrawImage函数将图像绘制到图形上下文。请记住,CGImage对象是不可变的。当您不再需要CGImage对象时,通过调用CGImageRelease函数来释放它。


屏幕快照 2018-08-28 上午10.07.20.png

接下来的部分将讨论如何创建:

现有图像的子图像
位图图形上下文中的图像
你可以参考这些资源获得更多信息:

Quartz 2D中的数据管理讨论了如何读写图像数据。
CGImage Reference、CGImageSource Reference和CGBitmapContext Reference,以进一步了解表11-1中列出的函数及其参数。

Creating an Image From Part of a Larger Image

CGImageCreateWithImageInRect函数允许从现有的Quartz映像创建子映像。图11-3展示了通过提供指定字母“A”位置的矩形从较大的图像中提取包含字母“A”的图像。


屏幕快照 2018-08-28 上午10.07.14.png

函数CGImageCreateWithImageInRect返回的图像保留对原始图像的引用,这意味着您可以在调用该函数后释放原始图像。

图11-4显示了提取图像的一部分以创建另一个图像的另一个示例。在这种情况下,公鸡的头从更大的图像中提取出来,然后绘制到一个比子图像大的矩形,有效地放大了图像。

清单11-1显示了创建并绘制子映像的代码。函数CGContextDrawImage将公鸡的头部吸引到的矩形具有的维数是所提取子图像维数的两倍。清单是一个代码片段。您需要声明适当的变量,创建rooster映像,并处理rooster映像和rooster head子映像。因为代码是一个片段,所以它没有显示如何创建绘制图像的图形上下文。你可以使用任何你喜欢的图形上下文。有关如何创建图形上下文的示例,请参阅图形上下文。


屏幕快照 2018-08-28 上午10.08.57.png

Listing 11-1 Code that creates a subimage and draws it enlarged

myImageArea = CGRectMake (rooster_head_x_origin, rooster_head_y_origin,
                            myWidth, myHeight);
mySubimage = CGImageCreateWithImageInRect (myRoosterImage, myImageArea);
myRect = CGRectMake(0, 0, myWidth*2, myHeight*2);
CGContextDrawImage(context, myRect, mySubimage);
Creating an Image from a Bitmap Graphics Context

要从现有的位图图形上下文创建图像,您可以调用下面的函数CGBitmapContextCreateImage:

CGImageRef myImage;
myImage = CGBitmapContextCreateImage (myBitmapContext);

函数返回的CGImage对象是通过复制操作创建的。因此,对位图图形上下文的任何后续更改都不会影响返回的CGImage对象的内容。在某些情况下,复制操作实际上遵循写时复制的语义,因此只有在修改位图图形上下文中的基础数据时,才会发生实际的位的物理副本。您可能希望使用生成的图像并在向位图图形上下文执行额外绘图之前释放它,以便避免实际的数据副本。

例如一个演示如何创建位图图形上下文的示例,该示例设置位图图形上下文。

Creating an Image Mask

Quartz位图图像掩模的使用方式与艺术家使用丝网印刷相同。位图图像掩码决定颜色的传输方式,而不是使用哪种颜色。图像掩码中的每个样例值都指定当前填充颜色在特定位置被掩码的数量。示例值指定掩码的不透明度。较大的值表示更大的不透明度,并指定Quartz颜料较少的位置。你可以把样本值看成是一个逆alpha值。值1是透明的,0是不透明的。

每个组件的图像掩码是1、2、4或8位。对于一个1位掩码,样本值为1指定了掩码中阻塞当前填充颜色的部分。示例值为0,指定在绘制掩码时显示图形状态的当前填充颜色的掩码部分。你可以把一个1位的面具想象成黑白的;样品要么完全阻挡油漆,要么完全允许油漆。

每个组件有2、4或8位的图像掩码表示灰度值。使用以下公式,每个组件映射到0到1的范围:


屏幕快照 2018-08-28 上午10.11.34.png

例如,4位掩码的值在0到1之间,增量为1/15。0或1的组件值代表了极端-完全块漆和完全允许油漆。0到1之间的值允许使用公式1 - MaskSampleValue进行部分绘制。例如,如果8位掩码的样本值缩放到0.7,颜色就会被绘制成alpha值(1 - 0.7),也就是0.3。

CGImageMaskCreate函数从您提供的位图图像信息中创建一个石英图像掩码,这将在位图图像信息中讨论。用于创建图像掩码的信息与用于创建图像的信息相同,只是不提供颜色空间信息、位图信息常量或呈现意图,如清单11-2中的函数原型所示。
Listing 11-2 The prototype for the function CGImageMaskCreate

CGImageRef CGImageMaskCreate (
        size_t width,
        size_t height,
        size_t bitsPerComponent,
        size_t bitsPerPixel,
        size_t bytesPerRow,
        CGDataProviderRef provider,
        const CGFloat decode[],
        bool shouldInterpolate
);
Masking Images

掩蔽技术可以产生许多有趣的效果,通过控制图像的哪个部分被绘制。您可以:

*对图像应用图像掩码。您还可以使用图像作为掩码来实现与应用图像掩码相反的效果。

*使用颜色来掩盖图像的部分,包括称为色度关键掩蔽的技术。

*将一个图形上下文剪辑到一个图像或图像掩码,当Quartz将内容绘制到剪切上下文时,该掩码有效地屏蔽了一个图像(或任何类型的绘图)。

Masking an Image with an Image Mask

函数CGImageCreateWithMask返回通过对图像应用图像掩码创建的图像。这个函数有两个参数:

要应用掩码的图像。此图像不能是图像掩码或具有与之关联的掩蔽颜色(请参阅用颜色掩蔽图像)。
通过调用函数CGImageMaskCreate创建的图像掩码。提供一个图像而不是一个图像掩码是可能的,但结果却大不相同。请参阅用图像屏蔽图像。
图像掩码的源样本作为一个反alpha值。图像掩模样本值:

等于1块绘制相应的图像样本。
= 0允许在全覆盖范围内绘制相应的图像样本。
大于0和小于1允许用alpha值(1 - S)绘制相应的图像样本。

图11-5显示了使用Quartz图像创建函数之一创建的图像,图11-6显示了使用CGImageMaskCreate函数创建的图像掩码。图11-7显示了调用CGImageCreateWithMask函数将图像掩码应用到图像的结果。


屏幕快照 2018-08-28 上午10.14.26.png

请注意,原始图像中对应于遮罩黑色区域的区域会在生成的图像中显示出来(图11-7)。与面具的白色区域相对应的区域没有被绘制。对应于掩模中灰色区域的区域使用中间alpha值绘制,该值等于1减去图像掩模样本值。


屏幕快照 2018-08-28 上午10.15.05.png
Masking an Image with an Image

您可以使用CGImageCreateWithMask函数用另一个图像来屏蔽一个图像,而不是用图像掩码。这样做的目的是为了达到与用图像掩模掩盖图像相反的效果。不传递使用CGImageMaskCreate函数创建的图像掩码,而是提供一个由Quartz图像创建函数创建的图像。

用作掩码(但不是石英图像掩码)的图像源样本操作为alpha值。图像样本值:

等于1允许绘制相应的图像样本在全覆盖。
等于0块绘制相应的图像样本。
大于0和小于1允许用alpha值S绘制相应的图像样本。

图11-8显示了调用CGImageCreateWithMask函数将图11-6所示的图像应用于图11-5所示的图像的结果。在本例中,假设图11-6所示的图像是使用石英图像创建函数(如CGImageCreate)创建的。将图11-8与图11-7进行比较,看看相同的样本值在用作图像样本而不是图像掩码样本时是如何达到相反的效果的。

原始图像中对应于图像黑色区域的区域不在生成的图像中绘制(图11-8)。与白色区域相对应的区域被涂上了颜色。与掩模中的灰色区域相对应的区域使用中间alpha值绘制,该值等于掩蔽图像样本值。


屏幕快照 2018-08-28 上午10.16.28.png
Masking an Image with Color

函数CGImageCreateWithMaskingColors通过在提供给函数的图像中屏蔽一种颜色或一系列颜色来创建一个图像。使用这个函数,您可以执行类似于图11-9所示的chroma key屏蔽,或者您可以屏蔽一系列颜色,类似于图11-11、图11-12和图11-13所示。

CGImageCreateWithMaskingColors函数有两个参数:

不是图像掩码的图像,并且不是对另一个图像应用图像掩码或掩码颜色的结果。
一组颜色组件,用于指定要在图像中屏蔽的函数的颜色或颜色范围。
颜色组件数组中的元素数量必须等于图像颜色空间中颜色组件数量的两倍。对于颜色空间中的每个颜色组件,提供一个最小值和一个最大值,指定要蒙版的颜色范围。为了只屏蔽一种颜色,设置最小值等于最大值。颜色组件数组中的值按以下顺序提供:

{min[1], max[1], ... min[N], max[N]}其中N是分量的个数。

如果图像使用整数像素组件,颜色组件数组中的每个值必须在范围[0 ..]2 ^ bitsPerComponent - 1)。如果图像使用浮点像素组件,每个值可以是任何浮点数,该浮点数是有效的颜色组件。

如果图像样本的颜色值在以下范围内,则不绘制:

{c[1], ... c[N]}

where min[i] <= c[i] <= max[i] for 1 <= i <= N

未绘制的样品下面的任何东西,比如当前填充颜色或其他绘图,都可以显示出来。

如图11-10所示,两个老虎的图像使用了一个RGB颜色空间,每个组件有8位。要在此图像中屏蔽一系列颜色,您需要在0到255之间提供最小和最大的颜色组件值。


屏幕快照 2018-08-28 上午10.19.23.png

清单11-3显示了一个代码片段,它设置了一个颜色组件数组,并将数组提供给CGImageCreateWithMaskingColors函数,以实现图11-11所示的结果。
Listing 11-3 Masking light to mid-range brown colors in an image

CGImageRef myColorMaskedImage;
const CGFloat myMaskingColors[6] = {124, 255,  68, 222, 0, 165};
myColorMaskedImage = CGImageCreateWithMaskingColors (image,
                                        myMaskingColors);
CGContextDrawImage (context, myContextRect, myColorMaskedImage);
屏幕快照 2018-08-28 上午10.20.23.png

清单11-4显示了对图11-10所示图像进行操作的另一个代码片段,以获得图11-12所示的结果。这个例子掩盖了更深的颜色范围。
Listing 11-4 Masking shades of brown to black

CGImageRef myMaskedImage;
const CGFloat myMaskingColors[6] = { 0, 124, 0, 68, 0, 0 };
myColorMaskedImage = CGImageCreateWithMaskingColors (image,
                                        myMaskingColors);
CGContextDrawImage (context, myContextRect, myColorMaskedImage);
屏幕快照 2018-08-28 上午10.29.32.png

您可以对图像中的颜色进行遮罩,也可以设置填充颜色,以实现如图11-13所示的效果,其中用填充颜色替换了掩蔽区域。清单11-5显示了生成图11-13所示图像的代码片段。
Listing 11-5 Masking a range of colors and setting a fill color and

CGImageRef myMaskedImage;
const CGFloat myMaskingColors[6] = { 0, 124, 0, 68, 0, 0 };
myColorMaskedImage = CGImageCreateWithMaskingColors (image,
                                        myMaskingColors);
CGContextSetRGBFillColor (myContext, 0.6373,0.6373, 0, 1);
CGContextFillRect(context, rect);
CGContextDrawImage(context, rect, myColorMaskedImage);
屏幕快照 2018-08-28 上午10.30.42.png
Masking an Image by Clipping the Context

函数CGContextClipToMask将掩码映射到一个矩形中,并与当前图形上下文的剪切区域相交。您提供以下参数:

要剪辑的图形上下文。
应用蒙版的矩形。
通过调用函数CGImageMaskCreate创建的图像掩码。您可以提供图像而不是图像掩码,以达到与提供图像掩码相反的效果。图像必须使用石英图像创建函数创建,但它不能是对另一个图像应用掩码或掩蔽颜色的结果。

产生的剪切区域取决于您是向CGContextClipToMask函数提供图像掩码还是图像。如果您提供了一个图像掩码,您将得到与使用图像掩码对图像进行掩码时所描述的结果类似的结果,但图形上下文是剪切的。如果您提供了一个图像,图形上下文将被裁剪,类似于用图像掩盖图像所描述的内容。

看看图11-14。假设它是通过调用函数CGImageMaskCreate创建的图像掩码,然后将掩码作为参数提供给函数CGContextClipToMask。结果上下文允许绘制到黑色区域,不允许绘制到白色区域,允许绘制到灰色区域,alpha值为1-S,其中S是图像蒙版的样本值。如果您使用CGContextDrawImage函数将图像绘制到修剪后的上下文,您将得到类似于图11-15所示的结果。


屏幕快照 2018-08-28 上午10.31.58.png

当掩蔽图像被当作图像处理时,会得到相反的结果,如图11-16所示。


屏幕快照 2018-08-28 上午10.32.38.png
Using Blend Modes with Images

您可以使用Quartz 2D混合模式(请参阅设置混合模式)来合成两个图像,或将图像与任何已经绘制到图形上下文的内容合成。本节讨论在背景图上合成图像。

在背景上合成图像的一般程序如下:

画的背景。
通过使用混合模式常量调用函数CGContextSetBlendMode来设置混合模式。(混合模式基于PDF参考,第四版,1.5版,Adobe Systems, Inc.)中定义的模式。)
通过调用CGContextDrawImage函数,在背景上绘制要合成的图像。
这段代码片段复合了一个图像背景使用“暗”混合模式:

CGContextSetBlendMode (myContext, kCGBlendModeDarken);
CGContextDrawImage (myContext, myRect, myImage2);

本节的其余部分使用Quartz中可用的每种混合模式来绘制图11-17右侧所示的图像,背景由图左侧所示的绘制矩形所组成。在所有情况下,矩形首先被绘制到图形上下文。然后,通过调用函数CGContextSetBlendMode来设置混合模式,并传递适当的混合模式常量。最后,将跳线的图像绘制到图形上下文。


屏幕快照 2018-08-28 上午10.33.52.png
Normal Blend Mode

普通混合模式在背景图像样本上绘制源图像样本。普通混合模式是Quartz中的默认混合模式。如果您目前正在使用另一种混合模式,并且希望切换到普通混合模式,则只需要显式地设置普通混合模式。可以通过将常量kcgblendmodennormal传递给函数CGContextSetBlendMode来设置普通混合模式,或者使用函数cgcontext - trestoregstate来恢复图形状态(假设之前的图形状态使用普通混合模式)。

图11-18显示了使用普通混合模式将图11-17所示的图像绘制在相同图形所示矩形上的结果。在本例中,图像使用alpha值1.0绘制,因此背景完全被图像遮挡。


屏幕快照 2018-08-28 上午10.37.49.png
Multiply Blend Mode

多重混合模式将源图像样本与背景图像样本相乘。生成的图像中的颜色至少与两个生成的示例颜色一样暗。

通过将常量kcgblendmodemulply传递给函数CGContextSetBlendMode,可以指定多重混合模式。图11-19显示了使用multiblend mode绘制图11-17中矩形的结果。


屏幕快照 2018-08-28 上午10.38.33.png
Screen Blend Mode

屏幕混合模式将源图像样本的反方向与背景图像样本的反方向相乘,以获得至少与两个产生的样本颜色一样轻的颜色。

通过将常量kCGBlendModeScreen传递给函数CGContextSetBlendMode,可以指定屏幕混合模式。图11-20显示了使用屏幕混合模式绘制图11-17中所示矩形的结果。


屏幕快照 2018-08-28 上午10.39.24.png
Overlay Blend Mode

叠加混合模式可以使用背景图像样本复制源图像样本,也可以根据背景样本的颜色对源图像样本进行筛选。结果是覆盖现有的图像样本,同时保留背景的高光和阴影。背景颜色与源图像混合以反映背景的明度或暗度。

通过将常量kCGBlendModeOverlay传递给CGContextSetBlendMode函数,可以指定叠加混合模式。图11-21显示了使用叠加混合模式将图11-17所示的图形覆盖在相同图形所示矩形上的结果。


屏幕快照 2018-08-28 上午10.40.16.png
Darken Blend Mode

暗混合模式通过从源图像或背景中选择较暗的样本来创建复合图像样本。比背景图像颜色深的源图像样本替换相应的背景样本。

通过将常量kCGBlendModeDarken传递给函数CGContextSetBlendMode,可以指定混合模式为暗。图11-22显示了使用darken blend模式绘制图11-17中矩形的结果。


屏幕快照 2018-08-28 上午10.41.24.png
Lighten Blend Mode

通过从源图像或背景中选择较轻的样本来创建复合图像样本。比背景图像样本轻的源图像样本替换相应的背景样本。

通过将常量kcgblendmodeliallymode传递给函数CGContextSetBlendMode,您可以指定减轻混合模式。图11-23显示了使用变淡混合模式将图11-17所示的图像绘制在相同图形所示矩形上的结果。


屏幕快照 2018-08-28 上午10.42.04.png
Color Dodge Blend Mode

颜色减淡混合模式照亮背景图像样本,以反映源图像样本。指定黑色的源图像样本值保持不变。

通过将常量kCGBlendModeColorDodge传递给函数CGContextSetBlendMode,可以指定颜色减淡混合模式。图11-24显示了使用颜色减淡混合模式将图11-17所示的图像绘制在相同图形所示矩形上的结果。


屏幕快照 2018-08-28 上午10.42.49.png
Color Burn Blend Mode

颜色烧伤混合模式使背景图像样本变暗以反映源图像样本。指定白色的源图像样本值保持不变。

通过将常量kCGBlendModeColorBurn传递给函数CGContextSetBlendMode,可以指定颜色烧伤混合模式。图11-25显示了使用color burn blend模式绘制图11-17中矩形的结果。


屏幕快照 2018-08-28 上午10.43.34.png
Soft Light Blend Mode

柔和的光混合模式或暗或淡的颜色,取决于源图像样本的颜色。如果源图像的样本颜色小于50%的灰度,背景会变浅,类似于躲避。如果源图像的样本颜色比50%的灰度深,背景会变暗,类似于燃烧。如果源图像的样本颜色等于50%的灰度,背景不会改变。

与纯黑或纯白相等的图像样本会产生较暗或较浅的区域,但不会产生纯黑或纯白。整体效果类似于在源图像上使用漫射聚光灯的效果。

通过将常量kCGBlendModeSoftLight传递给函数CGContextSetBlendMode,可以指定软光混合模式。图11-26显示了使用柔光混合模式在相同的矩形上绘制图11-17所示的图像的结果。


屏幕快照 2018-08-28 上午10.44.49.png
Hard Light Blend Mode

强光混合模式可以是多重或屏幕颜色,取决于源图像样本颜色。如果源图像的样本颜色小于50%的灰色,背景会变亮,类似于筛选。如果源图像的样本颜色比50%的灰度深,背景会变暗,类似于相乘。如果源图像的样本颜色等于50%的灰度,则源图像不会改变。等于纯黑或纯白的图像样本结果是纯黑或纯白。整体效果类似于你通过在源图像上发出强烈的聚光灯而获得的效果。

通过将常量kCGBlendModeHardLight传递给函数CGContextSetBlendMode,可以指定强光混合模式。图11-27显示了使用强光混合模式将图11-17所示的图像绘制在相同图形所示矩形上的结果。


屏幕快照 2018-08-28 上午10.45.39.png
Difference Blend Mode

差分混合模式将源图像样本颜色从背景图像样本颜色中减去,或者相反,这取决于哪个样本的亮度值更大。黑色的源图像样本值不会产生变化;白色反转背景颜色的值。

通过将常量kCGBlendModeDifference传递给函数CGContextSetBlendMode,可以指定差异混合模式。图11-28显示了使用差异混合模式绘制图11-17中所示的图形在相同图形中所示矩形上的结果。


屏幕快照 2018-08-28 上午10.46.27.png
Exclusion Blend Mode

排除混合模式产生一个不同混合模式的低对比度版本。黑色的源图像样本值不会产生变化;白色反转背景颜色的值。

通过将常量kCGBlendModeExclusion传递给函数CGContextSetBlendMode,可以指定排除混合模式。图11-29显示了使用排除混合模式将图11-17所示的图像绘制到相同图中所示矩形上的结果。


屏幕快照 2018-08-28 上午10.47.24.png
Hue Blend Mode

色调混合模式使用背景的亮度和饱和度值与源图像的色调。通过将常量kCGBlendModeHue传递给函数CGContextSetBlendMode,可以指定色调混合模式。图11-30显示了使用色调混合模式将图11-17所示的图像绘制在相同图形所示矩形上的结果。


屏幕快照 2018-08-28 上午10.48.08.png
Saturation Blend Mode

饱和度混合模式使用背景亮度和色调值与源图像的饱和度。纯灰色区域不会产生变化。通过将常量kCGBlendModeSaturation传递给函数CGContextSetBlendMode,可以指定饱和度混合模式。图11-31显示了使用饱和度混合模式将图11-17所示的图像绘制在相同图形所示矩形上的结果。


屏幕快照 2018-08-28 上午10.48.52.png
Color Blend Mode

颜色混合模式使用背景的亮度值和源图像的色调和饱和度值。这种模式保留了图像中的灰度。通过将常量kCGBlendModeColor传递给函数CGContextSetBlendMode,可以指定颜色混合模式。图11-32显示了使用颜色混合模式将图11-17所示的图像绘制在相同图形所示矩形上的结果。


屏幕快照 2018-08-28 上午10.49.42.png
Luminosity Blend Mode

光度混合模式使用背景的色相和饱和度与源图像的亮度来创建与颜色混合模式产生的效果相反的效果。

通过将常数kcgblendmodelescence传递给函数CGContextSetBlendMode,可以指定光度混合模式。图11-33显示了使用光度混合模式将图11-17所示的图像绘制在相同图形所示矩形上的结果。


屏幕快照 2018-08-28 上午10.50.23.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容

  • 位图图像和图像蒙板就像Quartz中的任何图形图元。 Quartz中的图像和图像蒙板都由CGImageRef数据类...
    权宜平和阅读 1,657评论 0 3
  • 在Quartz中位图图像和图像掩模更像是初级的。图像和图像掩模在Quartz中都是CGImageRef 数据类型。...
    雪_晟阅读 684评论 1 3
  • Paths path定义了一个或多个形状或子路径。子路径可以由直线、曲线或两者组成。它可以是打开的路径可以是关闭的...
    Niko_peng阅读 495评论 0 0
  • 路径定义一个或多个形状或子路径。 子路径可以由直线,曲线或两者组成。 它可以打开或关闭。 子路径可以是简单的形状,...
    权宜平和阅读 820评论 0 1
  • Graphics Contexts 图形上下文表示绘图目的地。它包含绘图参数和绘图系统执行任何后续绘图命令所需的所...
    Niko_peng阅读 604评论 0 0