iOS开发CoreGraphics核心图形框架之二——深入理解图形上下文
  TEZNKK3IfmPf 15天前 19 0
ios

一、引言

      在上一篇博客中,介绍了有关CGPath绘制路径的相关方法,其中在View视图的drawRect方法中,已经使用过上下文将Path路径绘制到当前视图上,上一篇博客只是抛砖引玉,本片博客将更深入的介绍下有关上下文的更多内容。

iOS开发CoreGraphics核心图形框架之一——CGPath的应用

二、关于图形上下文Graphics Context

      GraphicsContext对于开发者来说是完全透明的,开发者不需要关心其实现,也不需要关心其绘制方式,开发者只需要将要绘制的内容传递给图形上下文,由图形上下文来将内容绘制到对应的目标上。这个目标可以是视图,窗口,打印机,PDF文档或者位图对象。需要注意,绘制的顺序在CoreGraphics框架中十分重要,如果后绘制的内容和先绘制的内容有位置冲突,后绘制的内容将覆盖先绘制的内容。

    特定的上下文用于将内容绘制到特定的输出源上,CoreGraphics中提供如下几种图形上下文:

1.位图图形上下文:位图图形上下文用于将RGB图像,GMYK图像或者黑白图像绘制到一个位图(bitmap)对象中。

2.PDF图形上下文:PDF图形上下文可以帮助开发者创建PDF文件,将内容绘制进PDF文件中,其与位图上下文最大的区别在于PDF数据可以保存多页图像。

3.窗口上下文:用于OS系统中的窗口绘制。

4.图层上下文:用于将内容绘制在Layer图层上。

5.打印上下文:使用Mac打印功能时,此上下文用于将内容绘制在打印输出源上。

三、在UIKit框架中操作图形上下文

    在UIKit框架中有一个UIGraphics头文件,其中封装了许多对当前图形上下文进行操作的方法。首先任何UIView和其子类的视图控件都有一个drawRect方法,当视图将要被绘制时会调用这个方法,在drawRect方法中开发者可以获取到当前视图的图形上下文,通过这个图形上下文可以对视图进行自定义的绘制。UIGraphics头文件中定义的如下方法可以对当前的图形上下文进行操作:

//这个方法用于获取当前的图形上下文
UIKIT_EXTERN CGContextRef __nullable UIGraphicsGetCurrentContext(void) CF_RETURNS_NOT_RETAINED;
//这个方法用于将某个图形上下文对象压入栈中 使其变为当前的图形上下文
UIKIT_EXTERN void UIGraphicsPushContext(CGContextRef context);
//这个方法用于将当前的图形上下文出栈 当前的图形上下文始终是栈顶的图形上下文
UIKIT_EXTERN void UIGraphicsPopContext(void);

需要注意,上面的UIGraphicsPushContext()与UIGraphicsPopContext()方法常用于切换当前的图形上下文。

//下面这两个方法用于向当前的图形上下文中填充矩形 
UIKIT_EXTERN void UIRectFillUsingBlendMode(CGRect rect, CGBlendMode blendMode);
UIKIT_EXTERN void UIRectFill(CGRect rect);
//下面这两个方法用于向当前的图形上下文中绘制矩形边框
UIKIT_EXTERN void UIRectFrameUsingBlendMode(CGRect rect, CGBlendMode blendMode);
UIKIT_EXTERN void UIRectFrame(CGRect rect);
//这个方法用于裁剪当前的图形上下文的绘制区域
UIKIT_EXTERN void UIRectClip(CGRect rect);

上面方法中的CGBlendMode参数用于设置图像的混合模式,意义列举如下:

typedef CF_ENUM (int32_t, CGBlendMode) {
//在背景图像之上绘制原图像
kCGBlendModeNormal,
//将背景与原图像进行混合
kCGBlendModeMultiply,
//将背景与原图像进行逆向混合
kCGBlendModeScreen,
//覆盖原图像 同时保持背景阴影
kCGBlendModeOverlay,
//进行灰度复合
kCGBlendModeDarken,
//进行亮度复合
kCGBlendModeLighten,
//复合时 黑色不进行复合
kCGBlendModeColorDodge,
//复合时 白色不进行复合
kCGBlendModeColorBurn,
//复合时 根据黑白色值比例进行复合
kCGBlendModeSoftLight,
kCGBlendModeHardLight,
//复合时 将原图像中有关背景图像的色值去除
kCGBlendModeDifference,
//与kCGBlendModeDifference类似 对比度更低
kCGBlendModeExclusion,
//使用原图像的色调与饱和度
kCGBlendModeHue,
//同kCGBlendModeHue 纯灰度的区域不产生变化
kCGBlendModeSaturation,
//同kCGBlendModeHue 保留灰度等级
kCGBlendModeColor,
//与kCGBlendModeHue效果相反
kCGBlendModeLuminosity,

//下面这些枚举定义了MacOS中图像复合的计算方式
//R 结果
//S 原图像
//D 背景图像
//Ra Sa Da为带透明alpha通道

kCGBlendModeClear, /* R = 0 */
kCGBlendModeCopy, /* R = S */
kCGBlendModeSourceIn, /* R = S*Da */
kCGBlendModeSourceOut, /* R = S*(1 - Da) */
kCGBlendModeSourceAtop, /* R = S*Da + D*(1 - Sa) */
kCGBlendModeDestinationOver, /* R = S*(1 - Da) + D */
kCGBlendModeDestinationIn, /* R = D*Sa */
kCGBlendModeDestinationOut, /* R = D*(1 - Sa) */
kCGBlendModeDestinationAtop, /* R = S*(1 - Da) + D*Sa */
kCGBlendModeXOR, /* R = S*(1 - Da) + D*(1 - Sa) */
kCGBlendModePlusDarker, /* R = MAX(0, (1 - D) + (1 - S)) */
kCGBlendModePlusLighter /* R = MIN(1, S + D) */
};

下面这些方法用于操作位图图形上下文:

//这个方法会创建一个位图图形上下文 并将其push进图形上下文栈中 size参数设置图像的大小
UIKIT_EXTERN void UIGraphicsBeginImageContext(CGSize size);
//方法同上,其中opaque参数设置是否为不透明的 scale设置缩放因子
UIKIT_EXTERN void UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale) NS_AVAILABLE_IOS(4_0);
//这个方法用于将当前的位图图形上下文内容画成UIImage对象
UIKIT_EXTERN UIImage* __nullable UIGraphicsGetImageFromCurrentImageContext(void);
//结束位图图形上下文的编辑 会POP出栈
UIKIT_EXTERN void UIGraphicsEndImageContext(void);

我们可以通过代码来画一个简单的UIImage图像,示例如下:

- (void)viewDidLoad {
[super viewDidLoad];
//创建位图图形上下文 设置大小为200*200
UIGraphicsBeginImageContext(CGSizeMake(200, 200));
//获取到当前图形上下文
CGContextRef ref = UIGraphicsGetCurrentContext();
//裁剪其进行绘制的尺寸为100*100
UIRectClip(CGRectMake(0, 0, 100, 100));
//设置线条颜色
[[UIColor redColor] setStroke];
//设置填充颜色
[[UIColor grayColor] setFill];
//设置边框宽度
CGContextSetLineWidth(ref, 10);
//进行填充
UIRectFill(CGRectMake(0, 0, 100, 100));
//进行边框绘制
UIRectFrame(CGRectMake(0, 0, 200, 200));
//拿到UIImage实例
UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
//结束位图上下文编辑
UIGraphicsEndImageContext();
//将UIImage展示到界面上
UIImageView * imageView = [[UIImageView alloc]initWithImage:image];
imageView.contentMode = UIViewContentModeCenter;
imageView.frame = CGRectMake(100, 100, 200, 200);
[self.view addSubview:imageView];
}

效果如下图所示:

iOS开发CoreGraphics核心图形框架之二——深入理解图形上下文

//这个方法用于创建一个PDF图形上下文 将其入栈 作为当前的图形上下文  
/*
其中path为PDF文件写入的路径
bounds为PDF文档的尺寸
decumentInfo地点为设置PDF文档信息 后面会介绍
*/
UIKIT_EXTERN BOOL UIGraphicsBeginPDFContextToFile(NSString *path, CGRect bounds, NSDictionary * __nullable documentInfo) NS_AVAILABLE_IOS(3_2);
//这个方法用于穿件一个PDF图形上下文 但是将PDF内容写成Data数据 参数意义同上
UIKIT_EXTERN void UIGraphicsBeginPDFContextToData(NSMutableData *data, CGRect bounds, NSDictionary * __nullable documentInfo) NS_AVAILABLE_IOS(3_2);
//结束PDF图形上下文的编辑 将其出栈
UIKIT_EXTERN void UIGraphicsEndPDFContext(void) NS_AVAILABLE_IOS(3_2);
//这个方法用于将当前的PDF图形上下文新开一页内容
UIKIT_EXTERN void UIGraphicsBeginPDFPage(void) NS_AVAILABLE_IOS(3_2);
//同上
UIKIT_EXTERN void UIGraphicsBeginPDFPageWithInfo(CGRect bounds, NSDictionary * __nullable pageInfo) NS_AVAILABLE_IOS(3_2);
//返回当前PDF图形上下文所在页的尺寸
UIKIT_EXTERN CGRect UIGraphicsGetPDFContextBounds(void) NS_AVAILABLE_IOS(3_2);
//向PDF文档中的某个区域添加链接
UIKIT_EXTERN void UIGraphicsSetPDFContextURLForRect(NSURL *url, CGRect rect) NS_AVAILABLE_IOS(3_2);
//向PDF文档中的某个区域添加一个跳转目标 使其滚动到某点
UIKIT_EXTERN void UIGraphicsAddPDFContextDestinationAtPoint(NSString *name, CGPoint point) NS_AVAILABLE_IOS(3_2);
//向PDF文档中的某个区域添加一个跳转目标 使其滚动到某个区域
UIKIT_EXTERN void UIGraphicsSetPDFContextDestinationForRect(NSString *name, CGRect rect) NS_AVAILABLE_IOS(3_2);
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 15天前 0

暂无评论

推荐阅读
  TEZNKK3IfmPf   2024年03月22日   86   0   0 ios
  TEZNKK3IfmPf   2023年11月15日   21   0   0 ios
  TEZNKK3IfmPf   2024年03月30日   22   0   0 ios
TEZNKK3IfmPf