一、使用UIImage和CGImage处理图位
可用通过Quartz的图片对象或原始图片数据来创建UIImage。UIImage还提供了一些方法,允许将自身绘制到绘图Context中。
1、显示动画
UIImage支持的各种图片格式:
标签图像文件格式(TIFF) .tiff、.tif
JPEG(Joint Photographic Experts Group)格式 .jpg、.jpeg
GIF(Graphic Interchange Format)格式 .gif
PNG(Portable Network Graphic)格式 .png
Windows位图格式(DIB)格式 .bmp、.BMPf
Windows图标格式 .ico
Windows光标格式 .cur
Window系统位图 .xbm
当系统内存紧张时,UIImage会将图片数据从UIImage对象中清理出去,以节省系统内存,这里的清理行为只是清理UIImage内部存储的图片数据,并不清理UIImage对象本身。当程序使用一个图片数据被清理过的UIImage对象时,该UIImage将会自动从原始的图片文件中加载图片数据。
尽量避免使用UIImage加载过大(如大雨1024 * 1024)的图片
用UIimage来显示静止的图片,通常用一下方法:
+imageNamed:加载指定文件名对应的图片,该方法有缓存机制,用该方法加载的文件不存在,它才会去加载图片文件并缓存它;如果已经缓存过指定图片,该方法直接使用已缓存的图片。
当程序需要频繁加载、卸载图片文件时,不要使用该方法来加载图片
+imageWithContentsOfFile:该方法用于加载指定文件名对应图片。
+imageWithData:该方法用于根据NSData中封装的图片数据来创建图片。
+imageWithData:scale:该方法用于根据NSData中封装的图片数据来创建图片,并按指定缩放因子对图片进行缩放。
+imageWithCGImage:该方法用于根据指定的CGImageRef对象来创建UIImage。
+imageWithCGImage:scale:orientation:该方法用于根据指定的CGImageRef对象来创建UIImage,按照指定scale来对图片进行缩放,按照orientation参数对图片进行旋转、镜像等。
+animatedImageNamed:duration:根据指定图片名来加载一系列图片
+animatedImageWithImages:duration:传入一个每个对象都是UIImage对象的数组,作为多张动画图片。
2、CGImage与CGImageRef
UIImage虽然可以加载、显示各种格式的位图,甚至可以同时加载图片、并依次播放多张图片形成动画,但是它不能对图片进行缩放、旋转,不能截取指定区域等,这些功能可借助Quartz2D的CGImageRef来实现。
UIImage与CGImageRef可以相互转换。CGImageRef只是一个指针类型。
二、Quartz2D绘图
使用Quartz2D绘图的关键步骤有两步:获取CGContextRef;调用CGContextRef方法进行绘图。
1、Quartz2D提供的绘图函数:
CGContextClearRect(CGContectRef c, CGRect rect) //擦除指定区域绘制图形
CGContextDrawPath(CGContextRef _Nullable c, CGPathDrawingMode mode) //使用指定模式绘制当前CGContextRef所包含的路径。第二个参数支持KCGPathFill、kCGPathEOFill、kCGPathStroke、kCGPathFillStroke、kCGPathEOFillStroke等枚举值
CGContextEOFillPath(CGContextRef _Nullable c) //使用奇偶规则来填充该路径的区域,奇偶规则是指:如果某个点被路径包围了奇数次,name系统绘制该点;如果是偶数次则不绘制
CGContextFillPath(CGContextRef _Nullable c)//填充CGContextRef所包含的路径包围的区域
CGContextFillRect(CGContextRef _Nullable c, CGRect rect)//填充rect所代表的矩形
CGContextFillRects(CGContextRef _Nullable c, const CGRect * _Nullable rects, size_t count)//填充多个矩形
CGContextFillEllipseInRect(CGContextRef _Nullable c, CGRect rect)//填充rect矩形的内切椭圆区域
CGContextStrokePath(CGContextRef _Nullable c)//使用当前CGContextRef设置的线宽绘制路径
CGContextStrokeRect(CGContextRef _Nullable c, CGRect rect)//使用当前CGContextRef设置的绘制矩形框
CGContextStrokeRectWithWidth(CGContextRef _Nullable c, CGRect rect, CGFloat width)//使用指定线宽绘制矩形
CGContextReplacePathWithStrokedPath(CGContextRef _Nullable c)//使用绘制当前路径时覆盖的区域作为当前CGContextRef中的新路径。
CGContextStrokeEllipseInRect(CGContextRef _Nullable c, CGRect rect)//使用当前CGContextRef设置的线宽绘制rect矩形的内切圆
CGContextStrokeLineSegments(CGContextRef _Nullable c, const CGPoint * _Nullable points, size_t count)//使用当前CGContextRef设置的线宽绘制多条线段。
2、设置绘图属性的相关函数
CGContextSaveGState(CGContextRef _Nullable c)//保存CGContextRef当前的绘图状态,方便以后恢复该状态
CGContextRestoreGState(CGContextRef _Nullable c)//把CGContextRef的状态恢复到最近一次保存时的状态
CGContextGetInterpolationQuality(CGContextRef _Nullable c)//获取当前CGContextRef在放大图片的插值质量
CGContextSetInterpolationQuality(CGContextRef _Nullable c, CGInterpolationQuality quality)//设置当前CGContextRef在放大图片的插值质量
CGContextSetLineCap(CGContextRef _Nullable c, CGLineCap cap)//设置线段端点的绘制形状。
CGContextSetLineDash(CGContextRef _Nullable c, CGFloat phase, const CGFloat * _Nullable lengths, size_t count)//绘制边框时所用的点线模式
CGContextSetLineJoin(CGContextRef _Nullable c, CGLineJoin join)//设置线条连接点的风格
CGContextSetLineWidth(CGContextRef _Nullable c, CGFloat width)//设置绘制直线、边框时的线宽
CGContextSetMiterLimit(CGContextRef _Nullable c, CGFloat limit)//把连接点风格设置为meter风格时,该函数用于控制锐角箭头的长度
CGContextSetPatternPhase(CGContextRef _Nullable c, CGSize phase)//设置该CGContextRef采用位图填充的相位
CGContextSetFillPattern(CGContextRef _Nullable c, CGPatternRef _Nullable pattern, const CGFloat * _Nullable components)//设置该CGContextRef使用位图填充
CGContextSetShouldAntialias(CGContextRef _Nullable c, bool shouldAntialias)//设置该CGContextRef是否应该抗锯齿
CGContextSetStrokePattern(CGContextRef _Nullable c, CGPatternRef _Nullable pattern, const CGFloat * _Nullable components)//设置该CGContextRef使用位图绘制线条、边框
CGContextSetBlendMode(CGContextRef _Nullable c, CGBlendMode mode)//设置CGContextRef的叠加模式。
CGContextSetAllowsAntialiasing(CGContextRef _Nullable c, bool allowsAntialiasing)//设置该CGContextRef是否允许抗锯齿
CGContextSetAllowsFontSmoothing(CGContextRef _Nullable c, bool allowsFontSmoothing)//设置该CGContextRef是否允许光滑字体
CGContextSetShouldSmoothFonts(CGContextRef _Nullable c, bool shouldSmoothFonts)//设置该CGContextRef是否应该光滑字体
CGContextSetAlpha(CGContextRef _Nullable c, CGFloat alpha)//设置全局透明度
CGContextSetCMYKFillColor(CGContextRef _Nullable c, CGFloat cyan, CGFloat magenta, CGFloat yellow, CGFloat black, CGFloat alpha)//使用CMYK颜色模式来设置该CGContextRef的填充颜色
CGContextSetCMYKStrokeColor(CGContextRef _Nullable c, CGFloat cyan, CGFloat magenta, CGFloat yellow, CGFloat black, CGFloat alpha)//使用CMYK颜色模式来设置该CGContextRef的线条颜色
CGContextSetFillColorWithColor(CGContextRef _Nullable c, CGColorRef _Nullable color)//使用指定颜色来实现该CGContextRef的填充颜色
CGContextSetShadowWithColor(CGContextRef _Nullable c, CGSize offset, CGFloat blur, CGColorRef _Nullable color)//使用指定颜色来实现该CGContextRef的线条颜色
CGContextSetGrayFillColor(CGContextRef _Nullable c, CGFloat gray, CGFloat alpha)//使用灰色来实现该CGContextRef的填充颜色
CGContextSetGrayStrokeColor(CGContextRef _Nullable c, CGFloat gray, CGFloat alpha)//使用灰色来实现该CGContextRef的线条颜色
CGContextSetRGBFillColor(CGContextRef _Nullable c, CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha)//使用RGB颜色来实现该CGContextRef的填充颜色
CGContextSetRGBStrokeColor(CGContextRef _Nullable c, CGFloat red, CGFloat green, CGFloat blue, CGFloat alpha)//使用RGB颜色来实现该CGContextRef的线条颜色
CGContextSetShadow(<#CGContextRef _Nullable c#>, <#CGSize offset#>, <#CGFloat blur#>)////设置阴影在x、y轴上的偏移,以及模糊度
CGContextSetShadowWithColor(<#CGContextRef _Nullable c#>, <#CGSize offset#>, <#CGFloat blur#>, <#CGColorRef _Nullable color#>)//设置阴影在x、y轴上的偏移,以及模糊度和阴影的颜色
3、点线模式绘制
CGContextSetLineDash(CGContextRef _Nullable c, CGFloat phase, const CGFloat * _Nullable lengths, size_t count)//点线模式绘制
4、绘制文本
CGContextGetTextMatrix(CGContextRef _Nullable c)获取当前对文本执行变换的变换矩阵
CGContextGetTextPosition(CGContextRef _Nullable c) 获取当前文本绘制位置
CGContextSetCharacterSpacing(CGContextRef _Nullable c, CGFloat spacing)设置绘制文本的字符间距
CGContextSetFont(CGContextRef _Nullable c, CGFontRef _Nullable font)设置绘制文本字体
CGContextSetFontSize(CGContextRef _Nullable c, CGFloat size)设置绘制文本字体大小
CGContextSetTextDrawingMode(CGContextRef _Nullable c, CGTextDrawingMode mode)设置绘制文本的绘制模式
CGContextSetTextMatrix(CGContextRef _Nullable c, CGAffineTransform t)设置对将要绘制的文本执行指定的变换
CGContextSetTextPosition(CGContextRef _Nullable c, CGFloat x, CGFloat y)设置绘制文本的绘制位置
5、设置阴影
CGContextSetShadow(<#CGContextRef _Nullable c#>, <#CGSize offset#>, <#CGFloat blur#>)//设置阴影在X、Y轴上的偏移,并设置阴影模糊程度
CGContextSetShadowWithColor(<#CGContextRef _Nullable c#>, <#CGSize offset#>, <#CGFloat blur#>, <#CGColorRef _Nullable color#>)//设置阴影在X、Y轴上的偏移,并设置阴影模糊程度,设置阴影颜色
6、路径使用
CGContextBeginPath(CGContextRef _Nullable c)开始定义路径
CGContextClosePath(CGContextRef _Nullable c)关闭当前定义路径
CGContextAddArc(CGContextRef _Nullable c, CGFloat x, CGFloat y, CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise)向当前路径添加一段圆弧
CGContextAddArcToPoint(CGContextRef _Nullable c, CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2, CGFloat radius)向当前路径添加一段圆弧
CGContextAddCurveToPoint(CGContextRef _Nullable c, CGFloat cp1x, CGFloat cp1y, CGFloat cp2x, CGFloat cp2y, CGFloat x, CGFloat y)向当前路径添加一段贝济埃曲线
CGContextAddLines(CGContextRef _Nullable c, const CGPoint * _Nullable points, size_t count)向当前路径添加多条线段
CGContextAddLineToPoint(CGContextRef _Nullable c, CGFloat x, CGFloat y)向当前路径结束点连接到(x,y)点
CGContextAddQuadCurveToPoint(CGContextRef _Nullable c, CGFloat cpx, CGFloat cpy, CGFloat x, CGFloat y)向当前路径添加一条二次曲线
CGContextAddRect(CGContextRef _Nullable c, CGRect rect)向当前路径添加一个矩形
CGContextAddRects(CGContextRef _Nullable c, const CGRect * _Nullable rects, size_t count)向当前路径添加多个矩形
CGContextMoveToPoint(CGContextRef _Nullable c, CGFloat x, CGFloat y)向当前路径结束点移动到(x,y)点
CGContextAddEllipseInRect(CGContextRef _Nullable c, CGRect rect)向当前路径添加一个椭圆
CGContextCopyPath(CGContextRef _Nullable c)复制当前路径
CGContextAddPath(CGContextRef _Nullable c, CGPathRef _Nullable path)向当前路径添加已有的路径
CGContextIsPathEmpty(CGContextRef _Nullable c)判断CGContextRef包含的路径是否为空
CGContextGetPathCurrentPoint(CGContextRef _Nullable c)返回CGContextRef包涵路径的当前点
CGContextGetPathBoundingBox(CGContextRef _Nullable c)返回CGContextRef完整包围的所有路径的最小矩形
CGContextPathContainsPoint(CGContextRef _Nullable c, CGPoint point, CGPathDrawingMode mode)CGContextRef包含的路径按指定绘制模式进行绘制时,是否需要绘制point点
7、绘制曲线
CGContextAddCurveToPoint()添加贝济埃曲线
CGContextAddQuadCurveToPoint()添加二次曲线
8、内存中绘图
步骤1:调用UIGraphicsBeginImageContext(CGSize size)准备绘图环境
步骤2:调用UIGraphicsGetCurrentContext()获取绘图CGContextRef
步骤3:使用前面介绍的几何图形、路径等函数进行绘图
步骤4:调用UIGraphicsGetImageFromCurrentImageContext()函数获取当前绘制图形,返回一个UIImage对象
步骤5:调用UIGraphicsEndImageContext()结束绘图,关闭绘图环境
UIRectFill(CGRect rect):向当前绘图环境所创建的内存中的图片填充一个矩形
UIRectFillUsingBlendMode(CGRect rect, CGBlendModel blendModel):向当前绘图环境所创建的内存中的图片填充一个矩形,绘制时使用指定的混合模式
UIRectFrame(CGRect rect):向当前绘图环境所创建的内存中的图片绘制一个矩形边框
UIRectFrameUsingBlendMode(CGRect rect, CGBlendModel blendModel):向当前绘图环境所创建的内存中的图片绘制一个矩形边框,绘制时使用指定的混合模式
9、绘制位图
为了绘制位图,UIImage本身提供以下方法:
1、-DrawAtPoint:将该图片本身绘制到当前CGContextRef的指定点,该函数必须传入一个指定点
2、-DrawAtPoint:blendMode:alpha:将该图片本身绘制到当前CGContextRef的指定点,该函数必须传入一个指定点,指定绘制图片的叠加模式和透明度
3、-DrawInRect:将该图片本身绘制到当前CGContextRef的指定区域,必须传入CGRect参数
4、-DrawInRect:blendMode:alpha:将该图片本身绘制到当前CGContextRef的指定区域,必须传入CGRect参数,指定绘制图片的叠加模式和透明度
如果希望对图片执行旋转等变换,则可借助一下函数来绘制图片
1、CGContextDrawImage(CGContextRef c, CGRect rect, CGImageRef Image):将Image绘制到指定Rect区内
2、CGContextDrawTiledImage(CGContextRef c, CGRect rect, CGImageRef image):采用‘平铺’模式将image绘制到指定Rect区域内
如果需要‘挖取’已有图片部分或全部,则可用以下函数:
1、CGImageCreatCopy(CGImageRef image):创建image图片副本
2、CGImageCreatWithImageInRect(CGImageRef image, CGRect rect):挖取image中指定区域rect
三、图形变换
1、坐标变换
CGContextTranslateCTM(CGContextRef _Nullable c, CGFloat tx, CGFloat ty):平移坐标系统
CGContextScaleCTM(CGContextRef _Nullable c, CGFloat sx, CGFloat sy)缩放坐标系统
CGContextRotateCTM(CGContextRef _Nullable c, CGFloat angle)旋转坐标系统
CGContextSaveGState(CGContextRef _Nullable c)保存当前绘图状态
CGContextRestoreGState(CGContextRef _Nullable c)恢复之前保存的绘图状态
2、矩阵变换
CGContextConcatCTM(CGContextRef _Nullable c, CGAffineTransform transform)使用transform变换矩阵对CGContextRef的坐标系执行变换,通过矩阵可以对坐标系统执行任意变换。
CGContextGetCTM(CGContextRef _Nullable c)获取CGContextRef的变换矩阵
CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty)创建进行位移变换的变换矩阵
CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy)创建进行缩放变换的变换矩阵。
CGAffineTransformMakeRotation(CGFloat angle)创建进行旋转变换的变换矩阵
CGAffineTransformMake(CGFloat a, CGFloat b, CGFloat c, CGFloat d, CGFloat tx, CGFloat ty)自定义变换矩阵执行变换
对已有矩阵进行额外变换
CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty)对已有变换矩阵t额外增加位移变换
CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy)对已有变换矩阵t额外增加缩放变换
CGAffineTransformRotate(CGAffineTransform t, CGFloat angle)对已有变换矩阵t额外增加旋转变换
CGAffineTransformInvert(CGAffineTransform t)对已有变换矩阵t进行反转
CGAffineTransformConcat(CGAffineTransform t1, CGAffineTransform t2)将两个变换矩阵进行叠加
对点、矩形等几何形状进行变换
CGPointApplyAffineTransform(CGPoint point, CGAffineTransform t)对指定CGpoint执行变换,函数返回坐标变换后的CGpoint
CGSizeApplyAffineTransform(CGSize size, CGAffineTransform t)对指定CGSize执行变换,函数返回坐标变换后的CGSize
CGRectApplyAffineTransform(CGRect rect, CGAffineTransform t)对指定CGRect执行变换,函数返回坐标变换后的CGRect
3、控制叠加模式
CGContextSetBlendMode(CGContextRef _Nullable c, CGBlendMode mode)设置CGContextRef绘图环境的叠加模式
UIRectFillUsingBlendMode(CGRect rect, CGBlendMode blendMode)
UIRectFrameUsingBlendMode(CGRect rect, CGBlendMode blendMode)
4、处理填充
CGContextDrawLinearGradient(CGContextRef _Nullable c, CGGradientRef _Nullable gradient, CGPoint startPoint, CGPoint endPoint, CGGradientDrawingOptions options)设置线性渐变填充,gradient代表渐变对象,startPoint线性渐变起点,endPoint线性渐变结束点,options支持kCGGradientDrawsBeforeStartLocation(扩展填充起点之前的区域)或者kCGGradientDrawsAfterEndLocation(扩充填充结束点之后的区域)
CGContextDrawRadialGradient(CGContextRef _Nullable c, CGGradientRef _Nullable gradient, CGPoint startCenter, CGFloat startRadius, CGPoint endCenter, CGFloat endRadius, CGGradientDrawingOptions options)设置圆形渐变填充,gradient渐变对象,startCenter参数设置起始点的圆心,startRadius参数设置起始点半径,endCenter参数设置结束圆圆心,endRadius参数设置结束圆半径,options支持kCGGradientDrawsBeforeStartLocation(扩展填充起点之前的区域)或者kCGGradientDrawsAfterEndLocation(扩充填充结束点之后的区域)
CGGradientCreateWithColorComponents(CGColorSpaceRef _Nullable space, const CGFloat * _Nullable components, const CGFloat * _Nullable locations, size_t count)space指定颜色变换空间,CGFloat用于根据不同颜色空间设置多种颜色,locations指定各颜色点分布位置,count指定该渐变包含多少种颜色
Quartz 2D允许采用两种方式来填充:
使用CGColorCreateWithPattern()函数创建代表填充的CGColorRef,接下来使用颜色填充指定区域或绘制边框
首先创建CGPatternRef:(代表模式填充的引用),接下来绘制时调用CGContextSetFillPattern()或CGContextSetStrokePattern()函数设置填充或绘制边框的模式
1、创建代表模式填充的颜色
》定义绘制填充的回调函数,该函数通过CGContextRef执行任意绘制,但必须遵守void函数名(void *info,CGContextRef context)的签名
》使用前面创建的函数创建CGPatternCallbacks结构体数据
》以CGPatternCallbacks结构体作为参数,调用CGPatternCreate()函数创建CGPatternRef。
》调用CGColorSpaceCreatePattern()函数用于模式填充颜色空间。该函数返回CGColorSpaceRef
》以前面创建的CGPatternRef、CGColorSpaceRef为参数,调用CGColorCreateWithPattern()函数创建一个代表模式填充的颜色:CGColorRef。
2、使用CGPatternRef设置模式填充
程序无需创建代表模式填充的UIColorRef,只需创建代表模式填充的CGPatternRef,然后在绘制时使用CGContextSetFillPattern()或CGContextSetStrokePattern()函数设置使用模式进行填充或绘制路径即可
使用CGPatternRef设置模式填充步骤如下:
》定义绘制填充的回调函数,该函数必须遵守void函数名(void *info,CGContextRef context)的签名。该函数可通过CGContextRef参数执行绘制-但只绘制形状,无需指定颜色
》使用前面创建的函数创建CGPatternCallbacks结构体
》以CGPatternCallbacks结构体作为参数,调用CGPatternCreate()函数创建CGPatternRef。
》绘制时调用CGContextSetFillColorSpaces()函数设置使用模式填充的颜色空间
》绘制时调用CGContextSetFillPattern()或CGContextSetStrokePattern()函数设置使用指定的模式执行填充或绘制
四、滤镜
Core Image的三个核心API:
1、CIContext:它是Core Image处理的核心API,所有图片的处理都是在它的管理下完成的。
2、CIFilter:它代表过滤器。所有的过滤器都由该CIFilter代表,在创建CIFilter时传入不同参数即可创建不同类型的过滤器。
3、CIImage:代表Core Image过滤器处理的图片,CIFilter过滤器的输入图片、输出图片都由该CIImage代表。程序可通过UIImage、图片文件或像素数据来创建CIImage。
1、创建CIContext:
》基于CPU的CIContext、基于OpenGL优化的CIContext
2、创建CIFilter过滤器。
3、创建CIImage对象,该CIImage将要作为过滤器的源图片。
4、调用CIFilter的[filter setValue:beginImage forKey:@“inputImage”]方法为inputImage属性赋值,该属性用于指定该过滤器将要处理的源图片。
5、根据需要,为不同的过滤器设置不同过滤参数。
6、调用CIFilter的outputImage属性获取过滤器处理后的图片,返回的时CIImage对象。
7、调用CIContext的不同方法将CIImage转换为CGImageRef,或者将该CIImage绘制到指定区域
五、动画
1、Core Animation动画基础
Core Animation是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍。Core Animation动画使用CALayer来创建用户界面。
Core Animation动画在单独的线程中完成,不会阻塞主线程。
Core Animation动画只会重绘界面上变化部分(局部刷新)
Core Animation动画的核心是CALayer。
CAAnimation是所有动画类的基类,它实现了CAMedia Timing协议,提供了动画的持续时间、速度和重复计数等。
CATransition:CAAnimation的子类,CATransition可通过预置的过度效果来控制CALayer层的过度动画。
CAPropertyAnimation:CAAnimation的子类,代表属性动画,可通过+animationWithKeyPath:类方法来创建属性动画实例,该方法需要制定一个CALayer支持动画的属性,然后通过它的子类(CABasicAnimation、CAKeyframeAnimation)控制CALayer的动画属性慢慢改变,即可实现CALayer动画。
CABasicAnimation:CAPropertyAnimation的子类,简单控制CALayer层属性慢慢改变,从而实现动画效果。
CAKeyframeAnimation:CAPropertyAnimation的子类,支持关键帧的属性动画,该动画最大的特点在于可通过values属性指定多个关键帧,通过关键帧可以指定动画各个阶段的关键值。
CAAnimtaionGroup:CAAnimation的子类,用于多个动画组合在一起执行。
CAAnimation提供了以下方法和属性:
1、BOOL removedOnCompletion;该属性指定该动画完成时是否从目标CALayer上删除该动画。
2、timingFunction;该属性指定一个CAMedia TimingFunction对象,该对象负责控制动画变化步长。
3、- (void)animationDidStart:(CAAnimation *)aim:动画开始时将会调用该方法
4、- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag:动画结束时调用该方法。