01-iOS 多媒体技术| 图形处理框架简介:Core Animation、Core Graphics、OpenGL ES、Metal、GPUImage等

前言

多媒体技术 包括 视觉图形处理音频视频处理XR技术(AR、VR)等。都是有趣且富有含金量的技术实践方向。

本篇文章是 iOS 视觉图形处理 技术核心框架简介,为我们快速了解 iOS 视觉图形 技术,以便于在项目实战中进行技术选型、为提升自己在图形学上的技术能力指明方向,为后期我们在图形学方面的项目实践在某一个点的深入埋下伏笔。

一、iOS图像处理相关框架汇总

1. 苹果系统自带的框架:

  • 图形界面 UIKit
  • 核心动画 Core Animation
    • 主要在GPU上工作,用于动画效果和图层管理
  • 2D图形绘制和渲染 Core Graphics(Quartz 2D)
    • 主要在CPU上工作,用于2D图形绘制和渲染
  • 图像处理和滤镜 Core Image
    • 主要在GPU上工作,用于图像处理和滤镜效果
  • 图形渲染和计算 Metal
    • 主要在GPU上工作,用于高性能图形渲染和计算
  • 游戏引擎
    • Scene Kit (3D)
    • Sprite Kit (2D)

2. 优秀的第三方库:

  • 滤镜处理 GPUImage
    • 主要在GPU上工作,提供了丰富的图像处理和滤镜功能
  • 计算机视觉 OpenCV
    • 主要在CPU上工作,用于计算机视觉和图像处理
  • 跨平台图形框架 OpenGL ES
    • 主要在GPU上工作,用于实现3D图形渲染和游戏开发

毫无疑问,开发者们接触得最多的框架是以下几个,UIKit、Core Animation,Core Graphic, Core Image。下面简要介绍这几个框架,顺便介绍下GPUImage:

二、UIKit框架

1. UIKit框架简介

UIKit是iOS应用程序开发的基础框架之一,也是iOS开发中的一个核心框架。它提供了一系列的类和组件,通过UIKit,开发者可以快速构建各种界面元素、实现用户交互和动画效果.

UIKit的主要功能和组件:

  • 视图(View):用于构建应用程序的用户界面,包括
    • 基本视图
    • 容器视图
    • 表视图
    • 集合视图
    • ...
  • 控件(Control):提供了各种用户交互控件,如:
    • 按钮、标签、文本框、滑块等
  • 视图控制器(View Controller):用于管理视图的显示和交互,包括:
    • UIViewController、UINavigationController、UITabBarController等。
  • 动画(Animation):提供了动画效果的支持,如:
    • 视图动画、过渡动画、关键帧动画等。
  • 手势识别(Gesture Recognizer): 用于识别和处理用户手势操作,如:
    • 点击、滑动、捏合等。
  • 绘图(Drawing):提供了绘制图形和文本的功能,如:
    • 绘制形状、渲染文本、处理图形上下文等。
        1. 绘制形状:
        • 使用UIBezierPath类可以绘制各种形状,如直线、曲线、矩形、圆角矩形、椭圆等。
        • 通过设置路径的属性(如线宽、颜色、填充等)可以定制绘制效果。
        1. 绘制文本:
        • 使用NSString和NSAttributedString类可以绘制文本内容。
        • 通过UILabel、UITextView等控件可以显示文本内容,也可以通过Core Text框架实现更复杂的文本排版效果。
        1. 绘制图像:
        • 使用UIImage类可以加载和显示图像。
        • 通过UIImageView控件可以显示图像,也可以通过Core Graphics框架实现图像的绘制和处理。
        1. 绘制图形上下文:
        • 使用UIGraphicsBeginImageContextWithOptions函数可以创建一个图形上下文。
        • 在图形上下文中可以进行绘制操作,如绘制形状、文本、图像等。
        • 使用UIGraphicsGetImageFromCurrentImageContext函数可以获取绘制的图像。
        1. 绘制动画:
        • 使用UIView的动画方法(如animateWithDuration:animations:)可以实现简单的视图动画效果。
        • 通过Core Animation框架可以实现更复杂的动画效果,如关键帧动画、过渡动画等。
        1. 绘制路径:
        • 使用UIBezierPath类可以创建和操作路径对象,实现复杂的路径绘制和操作。
        • 通过CAShapeLayer图层可以将路径添加到视图中进行显示。
  • 文本排版(Text Layout):支持文本的排版和显示,包括文本样式、字体、段落样式等。
  • 多任务处理(Multitasking): 支持应用程序在多任务环境下的处理和适配。
      1. 多任务处理模式:
      • 前台模式:应用程序在前台运行,响应用户交互和显示界面。
      • 后台模式:应用程序在后台运行,执行一些特定的任务,如音频播放、位置更新等。
      • 多任务处理:应用程序可以同时执行多个任务,如下载数据、处理网络请求等。
      1. 多任务处理功能:
      • 后台执行任务:通过使用后台任务、后台会话等机制,应用程序可以在后台执行一些任务,如下载、上传数据等。
      • 多线程处理:通过使用GCD(Grand Central Dispatch)和Operation Queue等多线程技术,应用程序可以在多个线程上执行并发任务,提高性能和响应速度。
      • 多任务处理状态管理:应用程序可以通过UIApplication类的状态变化通知来管理多任务处理状态,如进入后台、恢复前台等。
      1. 多任务处理场景:
      • 音频播放:应用程序可以在后台继续播放音频。
      • 位置更新:应用程序可以在后台更新位置信息。
      • 网络请求:应用程序可以在后台执行网络请求和数据下载。
      • 数据处理:应用程序可以在后台处理数据、计算等任务。
  • 其它:
    • 一些类: UIColor(颜色操作)、UIFont和UIScreen(提供字体和屏幕信息)

2. UIKit与Core Graphics的关系:

UIKit的绘图功能主要用于实现简单的图形绘制、文本显示和图像处理,适用于构建基本的用户界面元素和视图效果。
对于更复杂的绘图需求 ,可以结合Core Graphics框架来实现更丰富用户界面和图形效果

以下是UIKit与Core Graphics结合使用的一些常见场景和方法:

  • 1. 绘制自定义视图:
    • 可以通过继承UIView类,并重写drawRect方法,在其中使用Core Graphics绘制自定义的图形、文本或图像。
    • 在drawRect方法中,可以创建UIBezierPath对象、设置绘制属性(如颜色、线宽等),并调用Core Graphics的绘制方法来实现自定义绘制效果。
  • 2. 绘制图形和文本:
    • 使用UIKit提供的控件和视图来构建用户界面,同时可以使用Core Graphics来实现一些特殊的绘制效果,如渐变背景、阴影效果等。
    • 通过Core Graphics的文本绘制功能,可以实现更灵活的文本排版和样式设置。
  • 3. 图形上下文的管理:
    • 可以通过UIGraphicsGetCurrentContext函数获取当前的图形上下文,然后使用Core Graphics在该上下文中进行绘制操作。
    • 在绘制过程中,可以使用UIGraphicsPushContext和UIGraphicsPopContext函数来管理图形上下文的压栈和出栈。
  • 4. 图形动画效果:
    • 可以结合UIKit的动画方法和Core Graphics的绘制功能,实现一些复杂的图形动画效果。
    • 通过UIView的动画方法和Core Graphics的绘制方法结合使用,可以实现视图的平滑过渡和动态效果。
  • 5. 图形处理和滤镜效果:
    • 可以使用Core Graphics对图像进行处理,如裁剪、缩放、旋转等操作。
    • 结合Core Image框架,可以实现更复杂的图像处理和滤镜效果,为用户界面增加更多的视觉效果。

3. 代码示例:

在UIKit中,UIView类本身在绘制时自动创建一个图形环境,即Core Graphics层的CGContext类型,作为当前的图形绘制环境。

在绘制时可以调用 UIGraphicsGetCurrentContext 函数获得当前的图形环境;

3.1 绘制自定义视图|绘制路径:

Objective-C示例:

objc 复制代码
//这段代码就是在UIView的子类中调用 UIGraphicsGetCurrentContext 函数获得当前的图形环境,然后向该图形环境添加路径,最后绘制。
- (void)drawRect:(CGRect)rect {
      //1.获取上下文
      CGContextRef contextRef = UIGraphicsGetCurrentContext();
      //2.描述路径
      UIBezierPath * path = [UIBezierPath bezierPath];
      //起点
      [path moveToPoint:CGPointMake(10, 10)];
      //终点
      [path addLineToPoint:CGPointMake(100, 100)];
      //设置颜色
      [[UIColor whiteColor]setStroke];
      //3.添加路径
      CGContextAddPath(contextRef, path.CGPath);
      //显示路径
      CGContextStrokePath(contextRef);
}
// Objective-C 代码示例:

// CustomView.h
#import <UIKit/UIKit.h>

@interface CustomView : UIView

@end

// CustomView.m
#import "CustomView.h"

@implementation CustomView

- (void)drawRect:(CGRect)rect {
      //1.获取上下文
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 绘制路径
    CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
    CGContextSetLineWidth(context, 2.0);
    CGContextMoveToPoint(context, 50, 50);
    CGContextAddLineToPoint(context, 200, 200);
    CGContextStrokePath(context);
}

@end

Swift示例:

swift 复制代码
// Swift 代码示例
// CustomView.swift
import UIKit

class CustomView: UIView {

    override func draw(_ rect: CGRect) {
        if let context = UIGraphicsGetCurrentContext() {
            let path = UIBezierPath()
            path.move(to: CGPoint(x: 50, y: 50))
            path.addLine(to: CGPoint(x: 150, y: 150))
            path.addArc(withCenter: CGPoint(x: 100, y: 100), radius: 50, startAngle: 0, endAngle: CGFloat(Double.pi * 2), clockwise: true)
            
            context.setStrokeColor(UIColor.red.cgColor)
            context.setLineWidth(2.0)
            
            context.addPath(path.cgPath)
            context.strokePath()
        }
    }
}

3.2 绘制自定义视图|绘制形状、文本等:

Objective-C示例:

objc 复制代码
// CustomView.h
#import <UIKit/UIKit.h>

@interface CustomView : UIView

@end

// CustomView.m
#import "CustomView.h"

@implementation CustomView

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 绘制矩形
    CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
    CGContextFillRect(context, CGRectMake(50, 50, 100, 100));
    
    // 绘制圆形
    CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
    CGContextFillEllipseInRect(context, CGRectMake(150, 150, 50, 50));
    
    // 绘制文本
    NSString *text = @"Hello, Core Graphics!";
    [text drawAtPoint:CGPointMake(50, 200) withAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:16], NSForegroundColorAttributeName: [UIColor greenColor]}];
}

@end

Swift示例:

swift 复制代码
// CustomView.swift
import UIKit

class CustomView: UIView {
    
    override func draw(_ rect: CGRect) {
        if let context = UIGraphicsGetCurrentContext() {
            // 绘制矩形
            context.setFillColor(UIColor.blue.cgColor)
            context.fill(CGRect(x: 50, y: 50, width: 100, height: 100))
            
            // 绘制圆形
            context.setFillColor(UIColor.red.cgColor)
            context.fillEllipse(in: CGRect(x: 150, y: 150, width: 50, height: 50))
            
            // 绘制文本
            let text = "Hello, Core Graphics!"
            let attributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16), NSAttributedString.Key.foregroundColor: UIColor.green]
            text.draw(at: CGPoint(x: 50, y: 200), withAttributes: attributes)
        }
    }
}

3.3 创建自定义按钮:

Objective-C示例:

objc 复制代码
// Objective-C示例:
// CustomButton.h
#import <UIKit/UIKit.h>

@interface CustomButton : UIButton

@end

// CustomButton.m
#import "CustomButton.h"

@implementation CustomButton

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 绘制背景
    CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
    CGContextFillRect(context, rect);
    
    // 绘制边框
    CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
    CGContextStrokeRect(context, rect);
    
    // 绘制文本
    NSString *text = @"Custom Button";
    NSDictionary *attributes = @{ NSFontAttributeName: [UIFont systemFontOfSize:16.0], NSForegroundColorAttributeName: [UIColor whiteColor] };
    CGSize textSize = [text sizeWithAttributes:attributes];
    CGPoint textOrigin = CGPointMake((CGRectGetWidth(rect) - textSize.width) / 2, (CGRectGetHeight(rect) - textSize.height) / 2);
    [text drawAtPoint:textOrigin withAttributes:attributes];
}

@end

Swift示例:

swift 复制代码
// Swift示例:
// CustomButton.swift
import UIKit

class CustomButton: UIButton {
    
    override func draw(_ rect: CGRect) {
        if let context = UIGraphicsGetCurrentContext() {
            // 绘制背景
            context.setFillColor(UIColor.blue.cgColor)
            context.fill(rect)
            
            // 绘制边框
            context.setStrokeColor(UIColor.white.cgColor)
            context.stroke(rect)
            
            // 绘制文本
            let text = "Custom Button"
            let attributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16.0), NSAttributedString.Key.foregroundColor: UIColor.white]
            let textSize = text.size(withAttributes: attributes)
            let textOrigin = CGPoint(x: (rect.width - textSize.width) / 2, y: (rect.height - textSize.height) / 2)
            text.draw(at: textOrigin, withAttributes: attributes)
        }
    }
}

3.4 绘制图像和文本:

Objective-C示例:

objc 复制代码
// Objective-C示例:
// 在UIView的drawRect方法中结合Core Graphics绘制图像和文本

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 绘制图像
    UIImage *image = [UIImage imageNamed:@"exampleImage"];
    CGContextDrawImage(context, CGRectMake(20, 20, 100, 100), image.CGImage);
    
    // 添加滤镜效果
    CGContextSetBlendMode(context, kCGBlendModeMultiply);
    CGContextSetAlpha(context, 0.5);
    
    // 绘制文本
    NSString *text = @"Hello, World!";
    [text drawAtPoint:CGPointMake(20, 150) withAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:16], NSForegroundColorAttributeName: [UIColor redColor]}];
}

Swift示例:

swift 复制代码
// Swift示例:
// 在UIView的draw方法中结合Core Graphics绘制图像和文本

override func draw(_ rect: CGRect) {
    if let context = UIGraphicsGetCurrentContext() {
        // 绘制图像
        if let image = UIImage(named: "exampleImage") {
            context.draw(image.cgImage!, in: CGRect(x: 20, y: 20, width: 100, height: 100))
        }
        
        // 添加滤镜效果
        context.setBlendMode(.multiply)
        context.setAlpha(0.5)
        
        // 绘制文本
        let text = "Hello, World!"
        let attributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16), NSAttributedString.Key.foregroundColor: UIColor.red]
        text.draw(at: CGPoint(x: 20, y: 150), withAttributes: attributes)
    }
}

3.5 绘制动画效果:

Objective-C示例:

objc 复制代码
// Objective-C示例:
#import <UIKit/UIKit.h>

@interface CustomView : UIView

@end

@implementation CustomView

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 绘制路径
    CGContextSetStrokeColorWithColor(context, [UIColor.redColor CGColor]);
    CGContextSetLineWidth(context, 2.0);
    CGContextMoveToPoint(context, 50, 50);
    CGContextAddLineToPoint(context, 200, 200);
    CGContextStrokePath(context);
    
    // 创建路径动画
    CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
    pathAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(50, 50)];
    pathAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(200, 200)];
    pathAnimation.duration = 2.0;
    
    // 添加动画
    [self.layer addAnimation:pathAnimation forKey:@"position"];
}

@end

Swift示例:

swift 复制代码
// Swift示例:
import UIKit

class CustomView: UIView {
    
    override func draw(_ rect: CGRect) {
        if let context = UIGraphicsGetCurrentContext() {
            // 绘制路径
            context.setStrokeColor(UIColor.red.cgColor)
            context.setLineWidth(2.0)
            context.move(to: CGPoint(x: 50, y: 50))
            context.addLine(to: CGPoint(x: 200, y: 200))
            context.strokePath()
            
            // 创建路径动画
            let pathAnimation = CABasicAnimation(keyPath: "position")
            pathAnimation.fromValue = CGPoint(x: 50, y: 50)
            pathAnimation.toValue = CGPoint(x: 200, y: 200)
            pathAnimation.duration = 2.0
            
            // 添加动画
            layer.add(pathAnimation, forKey: "position")
        }
    }
}

3.6 绘制图形上下文:

Objective-C示例:

objc 复制代码
// Objective-C示例:
- (UIImage *)drawCustomImage {
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(200, 200), NO, 0.0);
    
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 绘制矩形
    CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
    CGContextFillRect(context, CGRectMake(50, 50, 100, 100));
    
    // 绘制文本
    NSString *text = @"Hello, Core Graphics!";
    [text drawAtPoint:CGPointMake(20, 20) withAttributes:@{NSFontAttributeName: [UIFont systemFontOfSize:16], NSForegroundColorAttributeName: [UIColor redColor]}];
    
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return image;
}

Swift示例:

swift 复制代码
// Swift示例:
func drawCustomImage() -> UIImage? {
    UIGraphicsBeginImageContextWithOptions(CGSize(width: 200, height: 200), false, 0.0)
    
    if let context = UIGraphicsGetCurrentContext() {
        // 绘制矩形
        context.setFillColor(UIColor.blue.cgColor)
        context.fill(CGRect(x: 50, y: 50, width: 100, height: 100))
        
        // 绘制文本
        let text = "Hello, Core Graphics!"
        let attributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16), NSAttributedString.Key.foregroundColor: UIColor.red]
        text.draw(at: CGPoint(x: 20, y: 20), withAttributes: attributes)
        
        if let image = UIGraphicsGetImageFromCurrentImageContext() {
            UIGraphicsEndImageContext()
            return image
        }
    }
    
    return nil
}

三、 Core Animation 框架

1. 主要特点和功能

Core Animation框架是iOS和macOS平台上用于实现动画效果和图层管理的核心框架。

它提供了一套强大的API,用于创建、组合和管理图层,实现各种动画效果和视觉效果。以下是Core Animation框架的一些主要特点和功能:

    1. 图层(CALayer)与图层管理:
    • CALayer是Core Animation框架的核心,用于管理视图的显示和动画效果。
      • CALayer提供了丰富的属性和方法,用于控制视图的外观、位置、大小等。
      • CALayer负责视图的渲染、布局、动画等操作,是视图的可视化表示。
    1. 动画(CAAnimation):
    • CAAnimation是Core Animation框架中用于实现动画效果的基类。
    • 可以通过设置动画的属性和持续时间来实现各种动画效果。
    • CAAnimation包括:
      • 基础动画(CABasicAnimation)
      • 关键帧动画(CAKeyframeAnimation)
      • 过渡动画(CATransition)等类型。
    1. 图层组合:
    • 可以通过图层组合和图层树的方式来管理和组织视图的层级关系。
    • 可以创建复杂的图层结构,实现多层次的视图组合和效果叠加。
    1. 隐式动画:
    • Core Animation框架支持隐式动画,即通过改变图层的属性值来自动触发动画效果。
    • 可以通过设置图层的属性值来实现简单的动画效果,无需显式创建动画对象。
    1. 图层渲染:
    • Core Animation框架利用GPU硬件加速来实现图层的渲染和动画效果。
    • 可以实现流畅的动画效果和高性能的图层渲染。
    1. 交互效果:
    • Core Animation框架支持用户交互效果,如手势识别、点击事件等。
    • 可以通过手势识别和事件处理来实现交互式的动画效果。

2. 核心类介绍

Core Animation框架中的核心类主要包括以下几个:

    1. CALayer:
    • CALayer是Core Animation框架中的核心类,用于管理视图的显示和动画效果。
    • CALayer负责视图的渲染、布局、动画等操作,是视图的可视化表示。
    • CALayer提供了丰富的属性和方法,用于控制视图的外观、位置、大小等。
    1. CAAnimation:
    • CAAnimation是Core Animation框架中用于实现动画效果的基类。
    • CAAnimation包括基础动画(CABasicAnimation)、关键帧动画(CAKeyframeAnimation)、过渡动画(CATransition)等类型。
    • 开发者可以通过CAAnimation来创建各种动画效果,如平移、旋转、缩放等。
    1. CATransform3D:
    • CATransform3D是Core Animation框架中用于实现3D变换的类。
    • CATransform3D可以实现视图的平移、旋转、缩放等3D变换效果。
    • 开发者可以通过CATransform3D来创建复杂的3D变换效果,实现炫酷的视觉效果。
    1. CAEmitterLayer:
    • CAEmitterLayer是Core Animation框架中用于实现粒子效果的类。
    • CAEmitterLayer可以创建和管理粒子系统,实现雪花、火焰、烟雾等效果。
    • 开发者可以通过CAEmitterLayer来实现丰富的粒子效果,为应用程序增加动感和生动性。
    1. CAShapeLayer:
    • CAShapeLayer是Core Animation框架中用于绘制形状的类。
    • CAShapeLayer可以创建和管理各种形状,如矩形、圆角矩形、椭圆等。
    • 开发者可以通过CAShapeLayer来实现复杂的形状绘制和路径动画效果。

3. 代码示例

3.1 动画

Objective-C示例:

objc 复制代码
// Objective-C示例:
// 创建基础动画(CABasicAnimation)
CABasicAnimation *basicAnimation = [CABasicAnimation animationWithKeyPath:@"position"];
basicAnimation.fromValue = [NSValue valueWithCGPoint:CGPointMake(100, 100)];
basicAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(200, 200)];
basicAnimation.duration = 1.0;

// 创建关键帧动画(CAKeyframeAnimation)
CAKeyframeAnimation *keyframeAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];
keyframeAnimation.values = @[@0, @(M_PI_2), @0];
keyframeAnimation.duration = 1.0;

// 创建过渡动画(CATransition)
CATransition *transition = [CATransition animation];
transition.type = kCATransitionFade;
transition.duration = 1.0;

// 动画的组合
CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
animationGroup.animations = @[basicAnimation, keyframeAnimation, transition];
animationGroup.duration = 2.0;

// 将动画添加到视图的图层上
CALayer *layer = [CALayer layer];
[layer addAnimation:animationGroup forKey:@"animationGroup"];

Swift示例:

swift 复制代码
// Swift示例:
// 创建基础动画(CABasicAnimation)
let basicAnimation = CABasicAnimation(keyPath: "position")
basicAnimation.fromValue = CGPoint(x: 100, y: 100)
basicAnimation.toValue = CGPoint(x: 200, y: 200)
basicAnimation.duration = 1.0

// 创建关键帧动画(CAKeyframeAnimation)
let keyframeAnimation = CAKeyframeAnimation(keyPath: "transform.rotation")
keyframeAnimation.values = [0, .pi/2, 0]
keyframeAnimation.duration = 1.0

// 创建过渡动画(CATransition)
let transition = CATransition()
transition.type = .fade
transition.duration = 1.0

// 动画的组合
let animationGroup = CAAnimationGroup()
animationGroup.animations = [basicAnimation, keyframeAnimation, transition]
animationGroup.duration = 2.0

// 将动画添加到视图的图层上
let layer = CALayer()
layer.add(animationGroup, forKey: "animationGroup")

3.2 图层组合

Objective-C示例:

objc 复制代码
// Objective-C示例:
CALayer *parentLayer = [CALayer layer];
parentLayer.frame = CGRectMake(50, 50, 200, 200);
parentLayer.backgroundColor = [UIColor blueColor].CGColor;

CALayer *childLayer1 = [CALayer layer];
childLayer1.frame = CGRectMake(20, 20, 100, 100);
childLayer1.backgroundColor = [UIColor redColor].CGColor;

CALayer *childLayer2 = [CALayer layer];
childLayer2.frame = CGRectMake(50, 50, 100, 100);
childLayer2.backgroundColor = [UIColor greenColor].CGColor;

[parentLayer addSublayer:childLayer1];
[parentLayer addSublayer:childLayer2];

[self.view.layer addSublayer:parentLayer];

Swift示例:

swift 复制代码
// Swift示例:
let parentLayer = CALayer()
parentLayer.frame = CGRect(x: 50, y: 50, width: 200, height: 200)
parentLayer.backgroundColor = UIColor.blue.cgColor

let childLayer1 = CALayer()
childLayer1.frame = CGRect(x: 20, y: 20, width: 100, height: 100)
childLayer1.backgroundColor = UIColor.red.cgColor

let childLayer2 = CALayer()
childLayer2.frame = CGRect(x: 50, y: 50, width: 100, height: 100)
childLayer2.backgroundColor = UIColor.green.cgColor

parentLayer.addSublayer(childLayer1)
parentLayer.addSublayer(childLayer2)

view.layer.addSublayer(parentLayer)

3.3 隐式动画

Objective-C示例:

objc 复制代码
// Objective-C示例:
CALayer *layer = [CALayer layer];
layer.frame = CGRectMake(50, 50, 100, 100);
layer.backgroundColor = [UIColor blueColor].CGColor;

// 隐式动画:改变图层的位置属性
[CATransaction begin];
[CATransaction setAnimationDuration:1.0];
layer.position = CGPointMake(150, 150);
[CATransaction commit];

Swift示例:

swift 复制代码
// Swift示例:
let layer = CALayer()
layer.frame = CGRect(x: 50, y: 50, width: 100, height: 100)
layer.backgroundColor = UIColor.blue.cgColor

// 隐式动画:改变图层的位置属性
CATransaction.begin()
CATransaction.setAnimationDuration(1.0)
layer.position = CGPoint(x: 150, y: 150)
CATransaction.commit()

3.4 图层渲染

Objective-C示例:

objc 复制代码
// Objective-C示例:
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>

@interface ViewController : UIViewController

@property (nonatomic, strong) CALayer *customLayer;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 创建自定义图层
    self.customLayer = [CALayer layer];
    self.customLayer.frame = CGRectMake(50, 50, 100, 100);
    self.customLayer.backgroundColor = [UIColor blueColor].CGColor;
    
    // 添加图层到视图
    [self.view.layer addSublayer:self.customLayer];
    
    // 创建基础动画
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
    animation.fromValue = [NSValue valueWithCGPoint:self.customLayer.position];
    animation.toValue = [NSValue valueWithCGPoint:CGPointMake(200, 200)];
    animation.duration = 1.0;
    
    // 添加动画到图层
    [self.customLayer addAnimation:animation forKey:@"position"];
}

@end

Swift示例:

swift 复制代码
// Swift示例:
import UIKit

class ViewController: UIViewController {
    
    var customLayer: CALayer!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 创建自定义图层
        customLayer = CALayer()
        customLayer.frame = CGRect(x: 50, y: 50, width: 100, height: 100)
        customLayer.backgroundColor = UIColor.blue.cgColor
        
        // 添加图层到视图
        view.layer.addSublayer(customLayer)
        
        // 创建基础动画
        let animation = CABasicAnimation(keyPath: "position")
        animation.fromValue = customLayer.position
        animation.toValue = CGPoint(x: 200, y: 200)
        animation.duration = 1.0
        
        // 添加动画到图层
        customLayer.add(animation, forKey: "position")
    }
}

3.5 交互效果

Objective-C示例:

objc 复制代码
// Objective-C示例:
#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>

@interface ViewController ()

@property (nonatomic, strong) CALayer *animationLayer;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.animationLayer = [CALayer layer];
    self.animationLayer.backgroundColor = [UIColor blueColor].CGColor;
    self.animationLayer.frame = CGRectMake(50, 50, 100, 100);
    [self.view.layer addSublayer:self.animationLayer];
    
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
    [self.view addGestureRecognizer:tapGesture];
}

- (void)handleTap:(UITapGestureRecognizer *)gesture {
    CGPoint location = [gesture locationInView:self.view];
    
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
    animation.toValue = [NSValue valueWithCGPoint:location];
    animation.duration = 0.5;
    
    [self.animationLayer addAnimation:animation forKey:@"position"];
}

@end

Swift示例:

swift 复制代码
// Swift示例:
import UIKit

class ViewController: UIViewController {

    var animationLayer: CALayer!

    override func viewDidLoad() {
        super.viewDidLoad()

        animationLayer = CALayer()
        animationLayer.backgroundColor = UIColor.blue.cgColor
        animationLayer.frame = CGRect(x: 50, y: 50, width: 100, height: 100)
        view.layer.addSublayer(animationLayer)

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
        view.addGestureRecognizer(tapGesture)
    }

    @objc func handleTap(_ gesture: UITapGestureRecognizer) {
        let location = gesture.location(in: view)

        let animation = CABasicAnimation(keyPath: "position")
        animation.toValue = location
        animation.duration = 0.5

        animationLayer.add(animation, forKey: "position")
    }
}
  • Core Animation 是常用的框架之一。它比 UIKit 和 AppKit 更底层。正如我们所知,UIView底下封装了一层CALayer树,Core Animation 层是真正的渲染层,我们之所以能在屏幕上看到内容,真正的渲染工作是在 Core Animation 层进行的。
  • Core Animation 是一套Objective-C API,实现了一个高性能的复合引擎,并提供一个简单易用的编程接口,给用户UI添加平滑运动和动态反馈能力。
  • Core Animation 是 UIKit 实现动画和变换的基础,也负责视图的复合功能。使用Core Animation可以实现定制动画和细粒度的动画控制,创建复杂的、支持动画和变换的layered 2D视图
  • OpenGL ES的内容也可以与Core Animation内容进行集成。
  • 为了使用Core Animation实现动画,可以修改 层的属性值 来触发一个action对象的执行,不同的action对象实现不同的动画。Core Animation 提供了一组基类及子类,提供对不同动画类型的支持:
    • CAAnimation 是一个抽象公共基类,CAAnimation采用CAMediaTiming 和CAAction协议为动画提供时间(如周期、速度、重复次数等)和action行为(启动、停止等)。
    • CAPropertyAnimation 是 CAAnimation的抽象子类,为动画提供一个由一个key路径规定的层属性的支持;
    • CABasicAnimation 是CAPropertyAnimation的具体子类,为一个层属性提供简单插入能力。
    • CAKeyframeAnimation 也是CAPropertyAnimation的具体子类,提供key帧动画支持。

四、 Core Graphics & Quartz 2D

1. 主要特点和功能

Core Graphics(Quartz 2D)是iOS和macOS平台上的2D绘图引擎,它是一套C-based API ,用于实现图形绘制图像处理文本渲染等功能。

以下是Core Graphics & Quartz 2D的详细介绍:

    1. 绘图功能:
    • 绘图上下文:
      • Core Graphics使用绘图上下文(Graphics Context)来进行绘制操作,可以是基于位图的上下文、PDF上下文等。
    • Core Graphics提供了丰富的绘图功能,包括:
      • 绘制形状(直线、矩形、椭圆等)
      • 绘制路径(自定义路径、曲线路径等)
      • 绘制图像(位图图像、矢量图像等)
      • ...
    • 开发者可以在不同类型的上下文中进行绘制操作,创建自定义的绘图效果,实现各种绘图需求
    1. 图像处理:
    • Core Graphics支持图像的加载绘制裁剪变换合成渲染 等操作 实现图像的特效和优化
    1. 文本渲染:
    • Core Graphics提供了文本渲染功能,可以渲染文本内容,可以控制文本样式排版布局等实现文本的自定义渲染。
    1. 图形上下文:
    • Core Graphics使用图形上下文(Graphics Context)来管理绘图环境的状态和属性。
    • 通过设置图形上下文的属性来控制绘图效果,如颜色、线宽、填充模式等。
    1. 颜色和渲染:
    • Core Graphics支持颜色管理和渲染操作,可以设置填充颜色描边颜色渐变色等。
    1. 图形变换:
    • Core Graphics提供了图形变换的功能,可以实现平移旋转缩放等变换操作。
    1. 坐标系:
    • Core Graphics使用笛卡尔坐标系,原点在左下角,x轴向右延伸,y轴向上延伸。
    • 开发者可以通过坐标变换来实现坐标系的转换和调整,实现复杂的绘图效果和布局。
    1. 性能优化:
    • Core Graphics利用GPU硬件加速 来实现图形渲染和处理,提高绘图效率和性能
    • 开发者可以通过合理使用Core Graphics的API和功能来优化绘图性能,实现流畅的图形绘制和处理
    1. 其它
    • Core Graphics(使用Quartz 2D引擎)
      • 当开发者需要在运行时创建图像时,可以使用 Core Graphics 去绘制,运行时实时计算绘制一系列图像帧来实现动画。
      • 与之相对的是运行前创建图像(例如从磁盘中或内存中已经创建好的UIImage图像)
    • Quartz 2D
      • Quartz 2D是Core Graphics中的2D 绘制呈现引擎。
      • Quartz 2D能够与所有的图形和动画技术(如Core Animation, OpenGL ES, 和 UIKit 等)一起使用。Quartz 2D采用paint模式进行绘制。

2. 核心类介绍

Core Graphics(Quartz 2D)框架中的核心类主要包括以下几个:

    1. CGContext:
    • CGContext是Core Graphics中的绘图上下文用于执行绘图操作和渲染图形
    • CGContext提供了绘制路径、图像、文本等的功能,是实现图形绘制的核心类。
    1. CGPath:
    • CGPath是Core Graphics中表示路径的类,用于创建和管理路径对象
    • CGPath可以包含直线曲线矩形椭圆等形状,用于定义绘制的轮廓和形状
    • CGPath能够被填充和stroke
    1. CGImage:
    • CGImage是Core Graphics中表示图像的类,用于加载、创建和处理位图图像
    • CGImage可以从文件、数据或其他来源创建,用于图像的绘制和处理。
    1. CGColor:
    • CGColor是Core Graphics中表示颜色的类,用于定义绘制和填充的颜色
    • CGColor可以表示RGB、RGBA、灰度等颜色空间,用于设置绘制和填充的颜色值。
    • CGColorCGColorSpace;用来进行颜色和颜色空间管理;
    1. CGGradient:
    • CGGradient是Core Graphics中表示渐变的类,用于创建和管理颜色渐变效果
    • CGGradient可以定义线性渐变径向渐变等效果,用于实现丰富的颜色渐变效果。
    • CGShadingCGGradient:用于绘制剃度;
    1. CTFont:
    • CTFont是Core Text框架中表示字体的类,用于处理文本的字体和排版
    • CTFont可以设置字体的样式大小粗细等属性,用于文本的渲染和显示。
  • 其他常用类:

    • CGLayer:用来表示一个能够用于重复绘制和offscreen绘制的绘制层;
    • CGPattern:用来表示Pattern,用于重复绘制;
    • CGPDFContentStreamCGPDFScannerCGPDFPageCGPDFObject,CGPDFStream, CGPDFString 等用来进行pdf文件的创建、解析和显示

3. 代码示例

3.1 绘图功能|绘制形状(直线、曲线、矩形、椭圆等)

Objective-C示例:

objc 复制代码
// Objective-C示例:
#import <UIKit/UIKit.h>

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 绘制直线
    CGContextMoveToPoint(context, 50, 50);
    CGContextAddLineToPoint(context, 150, 150);
    CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
    CGContextStrokePath(context);
    
    // 绘制曲线
    CGContextMoveToPoint(context, 50, 100);
    CGContextAddQuadCurveToPoint(context, 100, 50, 150, 100);
    CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
    CGContextStrokePath(context);
    
    // 绘制矩形
    CGContextAddRect(context, CGRectMake(50, 150, 100, 50));
    CGContextSetFillColorWithColor(context, [UIColor greenColor].CGColor);
    CGContextFillPath(context);
    
    // 绘制椭圆
    CGContextAddEllipseInRect(context, CGRectMake(50, 200, 100, 50));
    CGContextSetStrokeColorWithColor(context, [UIColor purpleColor].CGColor);
    CGContextStrokePath(context);
}

Swift示例:

swift 复制代码
// Swift示例:
override func draw(_ rect: CGRect) {
    if let context = UIGraphicsGetCurrentContext() {
        // 绘制直线
        context.move(to: CGPoint(x: 50, y: 50))
        context.addLine(to: CGPoint(x: 150, y: 150))
        context.setStrokeColor(UIColor.red.cgColor)
        context.strokePath()
        
        // 绘制曲线
        context.move(to: CGPoint(x: 50, y: 100))
        context.addQuadCurve(to: CGPoint(x: 150, y: 100), control: CGPoint(x: 100, y: 50))
        context.setStrokeColor(UIColor.blue.cgColor)
        context.strokePath()
        
        // 绘制矩形
        context.addRect(CGRect(x: 50, y: 150, width: 100, height: 50))
        context.setFillColor(UIColor.green.cgColor)
        context.fillPath()
        
        // 绘制椭圆
        context.addEllipse(in: CGRect(x: 50, y: 200, width: 100, height: 50))
        context.setStrokeColor(UIColor.purple.cgColor)
        context.strokePath()
    }
}

3.2 绘图功能|绘制路径(自定义路径、曲线路径等)

Objective-C示例:

objc 复制代码
// Objective-C示例:
#import <UIKit/UIKit.h>

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 绘制自定义路径
    CGContextMoveToPoint(context, 50, 50);
    CGContextAddLineToPoint(context, 150, 50);
    CGContextAddLineToPoint(context, 100, 100);
    CGContextClosePath(context);
    
    // 绘制曲线路径
    CGContextMoveToPoint(context, 50, 150);
    CGContextAddQuadCurveToPoint(context, 100, 200, 150, 150);
    
    // 设置路径样式
    CGContextSetLineWidth(context, 2.0);
    CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
    
    // 绘制路径
    CGContextDrawPath(context, kCGPathFillStroke);
}

Swift示例:

swift 复制代码
// Swift示例:
override func draw(_ rect: CGRect) {
    if let context = UIGraphicsGetCurrentContext() {
        // 绘制自定义路径
        context.move(to: CGPoint(x: 50, y: 50))
        context.addLine(to: CGPoint(x: 150, y: 50))
        context.addLine(to: CGPoint(x: 100, y: 100))
        context.closePath()
        
        // 绘制曲线路径
        context.move(to: CGPoint(x: 50, y: 150))
        context.addQuadCurve(to: CGPoint(x: 150, y: 150), control: CGPoint(x: 100, y: 200))
        
        // 设置路径样式
        context.setLineWidth(2.0)
        context.setStrokeColor(UIColor.blue.cgColor)
        
        // 绘制路径
        context.drawPath(using: .fillStroke)
    }
}

3.3 绘图功能|绘制图像(位图图像、矢量图像等)

Objective-C示例:

objc 复制代码
// Objective-C示例:
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 创建绘图上下文
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(200, 200), NO, 0.0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 绘制矩形
    CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
    CGContextFillRect(context, CGRectMake(50, 50, 100, 100));
    
    // 绘制图像
    UIImage *image = [UIImage imageNamed:@"exampleImage"];
    [image drawInRect:CGRectMake(20, 20, 50, 50)];
    
    // 获取绘制的图像
    UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    // 显示绘制的图像
    UIImageView *imageView = [[UIImageView alloc] initWithImage:resultImage];
    [self.view addSubview:imageView];
}

@end

Swift示例:

swift 复制代码
// Swift示例:
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 创建绘图上下文
        UIGraphicsBeginImageContextWithOptions(CGSize(width: 200, height: 200), false, 0.0)
        if let context = UIGraphicsGetCurrentContext() {
            // 绘制矩形
            context.setFillColor(UIColor.blue.cgColor)
            context.fill(CGRect(x: 50, y: 50, width: 100, height: 100))
            
            // 绘制图像
            if let image = UIImage(named: "exampleImage") {
                image.draw(in: CGRect(x: 20, y: 20, width: 50, height: 50))
            }
            
            // 获取绘制的图像
            if let resultImage = UIGraphicsGetImageFromCurrentImageContext() {
                UIGraphicsEndImageContext()
                
                // 显示绘制的图像
                let imageView = UIImageView(image: resultImage)
                imageView.frame = CGRect(x: 100, y: 100, width: 200, height: 200)
                view.addSubview(imageView)
            }
        }
    }
}

3.4 图像处理|加载绘制裁剪变换合成渲染

Objective-C示例:

objc 复制代码
// Objective-C示例:
#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) UIImageView *imageView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIImage *originalImage = [UIImage imageNamed:@"original_image"];
    
    // 创建绘图上下文
    UIGraphicsBeginImageContextWithOptions(originalImage.size, NO, 0.0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 绘制原始图像
    [originalImage drawInRect:CGRectMake(0, 0, originalImage.size.width, originalImage.size.height)];
    
    // 裁剪图像
    CGContextClipToRect(context, CGRectMake(0, 0, originalImage.size.width / 2, originalImage.size.height));
    
    // 创建变换矩阵
    CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI_4);
    CGContextConcatCTM(context, transform);
    
    // 绘制变换后的图像
    UIImage *transformedImage = UIGraphicsGetImageFromCurrentImageContext();
    
    // 合成图像
    UIImage *compositeImage = [UIImage imageNamed:@"overlay_image"];
    [compositeImage drawInRect:CGRectMake(0, 0, originalImage.size.width, originalImage.size.height) blendMode:kCGBlendModeNormal alpha:0.5];
    
    // 渲染图像
    self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, originalImage.size.width, originalImage.size.height)];
    self.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
    [self.view addSubview:self.imageView];
    
    UIGraphicsEndImageContext();
}

@end

Swift示例:

swift 复制代码
// Swift示例:
import UIKit

class ViewController: UIViewController {

    var imageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

        if let originalImage = UIImage(named: "original_image") {
            // 创建绘图上下文
            UIGraphicsBeginImageContextWithOptions(originalImage.size, false, 0.0)
            if let context = UIGraphicsGetCurrentContext() {
                // 绘制原始图像
                originalImage.draw(in: CGRect(x: 0, y: 0, width: originalImage.size.width, height: originalImage.size.height))

                // 裁剪图像
                context.clip(to: CGRect(x: 0, y: 0, width: originalImage.size.width / 2, height: originalImage.size.height))

                // 创建变换矩阵
                let transform = CGAffineTransform(rotationAngle: CGFloat.pi / 4)
                context.concatenate(transform)

                // 绘制变换后的图像
                let transformedImage = UIGraphicsGetImageFromCurrentImageContext()

                // 合成图像
                if let compositeImage = UIImage(named: "overlay_image") {
                    compositeImage.draw(in: CGRect(x: 0, y: 0, width: originalImage.size.width, height: originalImage.size.height), blendMode: .normal, alpha: 0.5)
                }

                // 渲染图像
                imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: originalImage.size.width, height: originalImage.size.height))
                imageView.image = UIGraphicsGetImageFromCurrentImageContext()
                view.addSubview(imageView)

                UIGraphicsEndImageContext()
            }
        }
    }
}

3.5 文本渲染|渲染文本内容,控制文本样式、排版布局

Objective-C示例:

objc 复制代码
// Objective-C示例:
#import <UIKit/UIKit.h>

- (void)drawTextWithCustomStyle {
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    NSString *text = @"Hello, Core Graphics!";
    UIFont *font = [UIFont systemFontOfSize:16];
    UIColor *textColor = [UIColor redColor];
    
    NSDictionary *attributes = @{NSFontAttributeName: font, NSForegroundColorAttributeName: textColor};
    
    CGSize textSize = [text sizeWithAttributes:attributes];
    CGRect textRect = CGRectMake(50, 50, textSize.width, textSize.height);
    
    [text drawInRect:textRect withAttributes:attributes];
}

Swift示例:

swift 复制代码
// Swift示例:
import UIKit

func drawTextWithCustomStyle() {
    if let context = UIGraphicsGetCurrentContext() {
        let text = "Hello, Core Graphics!"
        let font = UIFont.systemFont(ofSize: 16)
        let textColor = UIColor.red
        
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.alignment = .center
        
        let attributes: [NSAttributedString.Key: Any] = [
            .font: font,
            .foregroundColor: textColor,
            .paragraphStyle: paragraphStyle
        ]
        
        let textSize = text.size(withAttributes: attributes)
        let textRect = CGRect(x: 50, y: 50, width: textSize.width, height: textSize.height)
        
        text.draw(in: textRect, withAttributes: attributes)
    }
}

3.6 图形上下文|绘图 颜色、线宽、填充模式

Objective-C示例:

objc 复制代码
// Objective-C示例:
- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 设置绘图颜色
    CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
    CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
    
    // 设置线宽
    CGContextSetLineWidth(context, 2.0);
    
    // 绘制矩形
    CGContextAddRect(context, CGRectMake(50, 50, 100, 100));
    
    // 填充矩形
    CGContextFillPath(context);
}

Swift示例:

swift 复制代码
// Swift示例:
override func draw(_ rect: CGRect) {
    if let context = UIGraphicsGetCurrentContext() {
        // 设置绘图颜色
        context.setFillColor(UIColor.blue.cgColor)
        context.setStrokeColor(UIColor.red.cgColor)
        
        // 设置线宽
        context.setLineWidth(2.0)
        
        // 绘制矩形
        context.addRect(CGRect(x: 50, y: 50, width: 100, height: 100))
        
        // 填充矩形
        context.fillPath()
    }
}

3.7 颜色和渲染|填充颜色描边颜色渐变色

Objective-C示例:

objc 复制代码
// Objective-C示例:
- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 填充颜色
    CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
    CGContextFillRect(context, rect);
    
    // 描边颜色
    CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
    CGContextStrokeRect(context, CGRectMake(50, 50, 100, 100));
    
    // 创建渐变色
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGFloat locations[] = {0.0, 1.0};
    NSArray *colors = @[(id)[UIColor redColor].CGColor, (id)[UIColor blueColor].CGColor];
    CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations);
    
    // 绘制渐变色
    CGContextDrawLinearGradient(context, gradient, CGPointMake(0, 0), CGPointMake(0, CGRectGetHeight(rect)), kCGGradientDrawsBeforeStartLocation);
    
    CGGradientRelease(gradient);
    CGColorSpaceRelease(colorSpace);
}

Swift示例:

swift 复制代码
// Swift示例:
override func draw(_ rect: CGRect) {
    if let context = UIGraphicsGetCurrentContext() {
        // 填充颜色
        context.setFillColor(UIColor.blue.cgColor)
        context.fill(rect)
        
        // 描边颜色
        context.setStrokeColor(UIColor.red.cgColor)
        context.stroke(CGRect(x: 50, y: 50, width: 100, height: 100))
        
        // 创建渐变色
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let locations: [CGFloat] = [0.0, 1.0]
        if let gradient = CGGradient(colorsSpace: colorSpace, colors: [UIColor.red.cgColor, UIColor.blue.cgColor] as CFArray, locations: locations) {
            // 绘制渐变色
            context.drawLinearGradient(gradient, start: CGPoint(x: 0, y: 0), end: CGPoint(x: 0, y: rect.height), options: [])
        }
    }
}

3.8 图形变换|平移、旋转、缩放

Objective-C示例:

objc 复制代码
// Objective-C示例:
#import <UIKit/UIKit.h>

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 平移
    CGContextTranslateCTM(context, 50, 50);
    
    // 旋转
    CGContextRotateCTM(context, M_PI_4); // 45度
    
    // 缩放
    CGContextScaleCTM(context, 1.5, 1.5);
    
    // 绘制一个矩形
    CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
    CGContextFillRect(context, CGRectMake(0, 0, 100, 100));
}

Swift示例:

swift 复制代码
// Swift示例:
override func draw(_ rect: CGRect) {
    if let context = UIGraphicsGetCurrentContext() {
        // 平移
        context.translateBy(x: 50, y: 50)
        
        // 旋转
        context.rotate(by: CGFloat.pi / 4) // 45度
        
        // 缩放
        context.scaleBy(x: 1.5, y: 1.5)
        
        // 绘制一个矩形
        context.setFillColor(UIColor.blue.cgColor)
        context.fill(CGRect(x: 0, y: 0, width: 100, height: 100))
    }
}

3.9 性能优化

Objective-C示例:

objc 复制代码
// Objective-C示例:
- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 设置绘制属性,如颜色、线宽等
    CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
    CGContextSetLineWidth(context, 2.0);
    
    // 性能优化:禁止图形上下文的自动平滑处理
    CGContextSetAllowsAntialiasing(context, NO);
     // 性能优化:设置图形上下文的属性
    CGContextSetShouldAntialias(context, YES); // 开启抗锯齿
    CGContextSetAllowsAntialiasing(context, YES); // 允许抗锯齿
    CGContextSetInterpolationQuality(context, kCGInterpolationHigh); // 设置插值质量为高
    
    
    // 绘制大量图形
    for (int i = 0; i < 1000; i++) {
        CGContextMoveToPoint(context, i, 0);
        CGContextAddLineToPoint(context, i, 100);
    }
    
    // 执行绘制
    CGContextStrokePath(context);
}

Swift示例:

swift 复制代码
// Swift示例:
override func draw(_ rect: CGRect) {
    if let context = UIGraphicsGetCurrentContext() {
        // 设置绘制属性,如颜色、线宽等
        context.setStrokeColor(UIColor.red.cgColor)
        context.setLineWidth(2.0)
        
        // 性能优化:禁止图形上下文的自动平滑处理
        context.setAllowsAntialiasing(false)
         // 性能优化:设置图形上下文的属性
        context.setShouldAntialias(true) // 开启抗锯齿
        context.setAllowsAntialiasing(true) // 允许抗锯齿
        context.setInterpolationQuality(.high) // 设置插值质量为高
        
        // 绘制大量图形
        for i in 0..<1000 {
            context.move(to: CGPoint(x: i, y: 0))
            context.addLine(to: CGPoint(x: i, y: 100))
        }
        
        // 执行绘制
        context.strokePath()
    }
}

五、Core Image

Core Image是苹果提供的图像处理框架,主要用于实现图像处理滤镜应用图像分析等功能。以下是Core Image的核心要点:

1. 主要特点和功能

    1. 滤镜(Filter):
    • Core Image提供了丰富的滤镜效果,如模糊锐化色彩调整边缘检测等。
    • 开发者可以通过Core Image的滤镜功能对图像进行处理和增强。
    • iOS 8 之后 引入 CIFilter,Core Image从此支持自定义滤镜的创建和应用,实现个性化的图像处理效果。
    1. 图像处理链(Image Processing Pipeline):
    • Core Image使用图像处理链来处理图像,包括输入图像滤镜效果和输出图像
    • 开发者可以构建自定义的图像处理链,实现复杂的图像处理流程。
    1. 图像分析(Image Analysis):
    • Core Image支持图像分析功能,如人脸检测特征识别颜色识别物体识别等。
    • 开发者可以利用Core Image进行图像分析,提取图像中的信息和特征
    1. Metal性能优化:
    • Core Image可以与Metal框架结合,利用GPU硬件加速来提高图像处理的性能。
    • 开发者可以通过Metal框架优化Core Image的性能,实现高效的图像处理和滤镜效果。
    1. 图像格式转换(Image Format Conversion):
    • Core Image支持图像格式的转换和处理,如颜色空间转换像素格式转换等。
    • 开发者可以使用Core Image进行图像格式的转换和处理,满足不同的图像处理需求。
    1. 实时预览(Real-time Preview):
    • Core Image提供实时预览功能,可以在应用程序中实时显示滤镜效果的预览。
    • 开发者可以通过Core Image实现实时的滤镜预览,方便用户调整和查看效果。
    1. 其它
    • Core Image 与 Core Graphics 恰恰相反

      • Core Graphics 用于在运行时创建图像
      • 而 Core Image 是用来处理已经创建的图像的。
    • Core Image 是 iOS5 新加入到 iOS 平台的一个图像处理框架,提供了强大高效的图像处理功能, 用来对基于像素的图像进行操作与分析, 内置了很多强大的滤镜(Filter) (目前数量超过了180种), 这些Filter 提供了各种各样的效果, 并且还可以通过 滤镜链 将各种效果的 Filter叠加 起来形成强大的自定义效果。

      • iOS8 之后更是支持自定义 CIFilter,可以定制满足业务需求的复杂效果。
    • Core Image 的优点在于十分高效。大部分情况下,它会在 GPU 中完成工作,但如果 GPU 忙,会使用 CPU 进行处理。如果设备支持 Metal,那么会使用 Metal 处理。这些操作会在底层完成,Apple 的工程师们已经帮助开发者们完成这些操作了。

      • 例如他可以根据需求选择 CPU 或者 GPU 来处理。
      objc 复制代码
        // 创建基于 CPU 的 CIContext 对象 (默认是基于 GPU,CPU 需要额外设置参数)
        context = [CIContext contextWithOptions: [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:kCIContextUseSoftwareRenderer]];
        // 创建基于 GPU 的 CIContext 对象
        context = [CIContext contextWithOptions: nil];
        // 创建基于 GPU 的 CIContext 对象
        EAGLContext *eaglctx = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
        context = [CIContext contextWithEAGLContext:eaglctx];
       ```  

2. 核心类介绍

    1. CIImage:
    • CIImage是Core Image框架中表示图像数据的类,可以用来表示图像数据源
    • CIImage可以从各种来源创建,如UIImage、CGImage、NSData、图像文件或者像素数据等,用于输入到Core Image的滤镜中进行处理。
    1. CIFilter:
    • CIFilter是Core Image框架中的滤镜类,用于实现各种图像处理和滤镜效果。
    • CIFilter包含了各种内置的滤镜效果,也可以自定义滤镜来实现特定的图像处理需求。
    • 这个框架中对图片属性进行细节处理的类。它对所有的像素进行操作,用一些键-值设置来决定具体操作的程度。
    1. CIContext:
    • CIContext是Core Image框架中的上下文类,用于管理图像处理的环境和输出。
    • CIContext可以指定渲染目标(如屏幕、图像文件)、渲染选项(如颜色空间、缩放比例)等参数。
    1. CIFeature:
    • CIFeature是Core Image框架中的特征类,用于检测图像中的特征和对象。
    • CIFeature可以用于人脸检测、文本识别、条形码识别等应用场景。
    1. CIColor:
    • CIColor是Core Image框架中的颜色类,用于表示颜色信息。
    • CIColor可以用来创建颜色对象,设置滤镜效果中的颜色参数。
    1. CIVector:
    • CIVector是Core Image框架中的向量类,用于表示多维向量数据。
    • CIVector可以用来设置滤镜效果中的向量参数,如位置、大小等。
  • Core Image 的 API 主要就是三类:

    • CIContext 表示上下文,如 Core Graphics 以及 Core Data 中的上下文用于处理绘制渲染以及处理托管对象一样,Core Image 的上下文也是实现对图像处理的具体对象。可以从其中取得图片的信息。

3. 代码示例

3.1 滤镜|模糊、锐化、色彩调整、边缘检测 和 自定义滤镜

Objective-C示例:

objc 复制代码
// Objective-C示例:
#import <UIKit/UIKit.h>
#import <CoreImage/CoreImage.h>

// 模糊处理
UIImage *applyBlurFilter(UIImage *image) {
    CIImage *ciImage = [[CIImage alloc] initWithImage:image];
    CIFilter *filter = [CIFilter filterWithName:@"CIGaussianBlur"];
    [filter setValue:ciImage forKey:kCIInputImageKey];
    [filter setValue:@10 forKey:kCIInputRadiusKey];
    CIImage *outputImage = [filter outputImage];
    
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef cgImage = [context createCGImage:outputImage fromRect:outputImage.extent];
    UIImage *resultImage = [UIImage imageWithCGImage:cgImage];
    CGImageRelease(cgImage);
    
    return resultImage;
}

// 锐化处理
UIImage *applySharpenFilter(UIImage *image) {
    CIImage *ciImage = [[CIImage alloc] initWithImage:image];
    CIFilter *filter = [CIFilter filterWithName:@"CISharpenLuminance"];
    [filter setValue:ciImage forKey:kCIInputImageKey];
    [filter setValue:@0.5 forKey:kCIInputSharpnessKey];
    CIImage *outputImage = [filter outputImage];
    
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef cgImage = [context createCGImage:outputImage fromRect:outputImage.extent];
    UIImage *resultImage = [UIImage imageWithCGImage:cgImage];
    CGImageRelease(cgImage);
    
    return resultImage;
}

// 色彩调整
UIImage *applyColorAdjustmentFilter(UIImage *image) {
    CIImage *ciImage = [[CIImage alloc] initWithImage:image];
    CIFilter *filter = [CIFilter filterWithName:@"CIColorControls"];
    [filter setValue:ciImage forKey:kCIInputImageKey];
    [filter setValue:@1.2 forKey:kCIInputContrastKey];
    [filter setValue:@0.5 forKey:kCIInputBrightnessKey];
    [filter setValue:@0.8 forKey:kCIInputSaturationKey];
    CIImage *outputImage = [filter outputImage];
    
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef cgImage = [context createCGImage:outputImage fromRect:outputImage.extent];
    UIImage *resultImage = [UIImage imageWithCGImage:cgImage];
    CGImageRelease(cgImage);
    
    return resultImage;
}

// 边缘检测
UIImage *applyEdgeDetectionFilter(UIImage *image) {
    CIImage *ciImage = [[CIImage alloc] initWithImage:image];
    CIFilter *filter = [CIFilter filterWithName:@"CIEdges"];
    [filter setValue:ciImage forKey:kCIInputImageKey];
    CIImage *outputImage = [filter outputImage];
    
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef cgImage = [context createCGImage:outputImage fromRect:outputImage.extent];
    UIImage *resultImage = [UIImage imageWithCGImage:cgImage];
    CGImageRelease(cgImage);
    
    return resultImage;
}

// 自定义滤镜
UIImage *applyCustomFilter(UIImage *image) {
    CIImage *ciImage = [[CIImage alloc] initWithImage:image];
    
    // 自定义滤镜
    CIFilter *filter = [CIFilter filterWithName:@"CIColorMatrix"];
    [filter setValue:ciImage forKey:kCIInputImageKey];
    
    // 设置自定义参数
    CIVector *RVector = [CIVector vectorWithX:1 Y:0 Z:0 W:0];
    CIVector *GVector = [CIVector vectorWithX:0 Y:1 Z:0 W:0];
    CIVector *BVector = [CIVector vectorWithX:0 Y:0 Z:1 W:0];
    CIVector *AVector = [CIVector vectorWithX:0 Y:0 Z:0 W:1];
    [filter setValue:RVector forKey:@"inputRVector"];
    [filter setValue:GVector forKey:@"inputGVector"];
    [filter setValue:BVector forKey:@"inputBVector"];
    [filter setValue:AVector forKey:@"inputAVector"];
    
    CIImage *outputImage = [filter outputImage];
    
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef cgImage = [context createCGImage:outputImage fromRect:outputImage.extent];
    UIImage *resultImage = [UIImage imageWithCGImage

Swift示例:

swift 复制代码
import UIKit
import CoreImage

// 图像处理类
class ImageProcessor {
    
    // 应用模糊滤镜
    func applyBlurFilter(to image: UIImage) -> UIImage? {
        if let ciImage = CIImage(image: image) {
            let filter = CIFilter(name: "CIGaussianBlur")
            filter?.setValue(ciImage, forKey: kCIInputImageKey)
            filter?.setValue(5.0, forKey: kCIInputRadiusKey)
            
            if let outputImage = filter?.outputImage {
                let context = CIContext()
                if let cgImage = context.createCGImage(outputImage, from: outputImage.extent) {
                    return UIImage(cgImage: cgImage)
                }
            }
        }
        return nil
    }
    
    // 应用锐化滤镜
    func applySharpenFilter(to image: UIImage) -> UIImage? {
        if let ciImage = CIImage(image: image) {
            let filter = CIFilter(name: "CISharpenLuminance")
            filter?.setValue(ciImage, forKey: kCIInputImageKey)
            filter?.setValue(0.5, forKey: kCIInputSharpnessKey)
            
            if let outputImage = filter?.outputImage {
                let context = CIContext()
                if let cgImage = context.createCGImage(outputImage, from: outputImage.extent) {
                    return UIImage(cgImage: cgImage)
                }
            }
        }
        return nil
    }
    
    // 应用色彩调整滤镜
    func applyColorAdjustmentFilter(to image: UIImage) -> UIImage? {
        if let ciImage = CIImage(image: image) {
            let filter = CIFilter(name: "CIColorControls")
            filter?.setValue(ciImage, forKey: kCIInputImageKey)
            filter?.setValue(1.2, forKey: kCIInputContrastKey)
            filter?.setValue(0.8, forKey: kCIInputBrightnessKey)
            filter?.setValue(0.5, forKey: kCIInputSaturationKey)
            
            if let outputImage = filter?.outputImage {
                let context = CIContext()
                if let cgImage = context.createCGImage(outputImage, from: outputImage.extent) {
                    return UIImage(cgImage: cgImage)
                }
            }
        }
        return nil
    }
    
    // 应用边缘检测滤镜
    func applyEdgeDetectionFilter(to image: UIImage) -> UIImage? {
        if let ciImage = CIImage(image: image) {
            let filter = CIFilter(name: "CIEdges")
            filter?.setValue(ciImage, forKey: kCIInputImageKey)
            
            if let outputImage = filter?.outputImage {
                let context = CIContext()
                if let cgImage = context.createCGImage(outputImage, from: outputImage.extent) {
                    return UIImage(cgImage: cgImage)
                }
            }
        }
        return nil
    }
    
    // 应用自定义滤镜
    func applyCustomFilter(to image: UIImage) -> UIImage? {
        if let ciImage = CIImage(image: image) {
            // 自定义滤镜:将图像转为灰度图
            let filter = CIFilter(name: "CIPhotoEffectMono")
            filter?.setValue(ciImage, forKey: kCIInputImageKey)
            
            if let outputImage = filter?.outputImage {
                let context = CIContext()
                if let cgImage = context.createCGImage(outputImage, from: outputImage.extent) {
                    return UIImage(cgImage: cgImage)
                }
            }
        }
        return nil
    }
}

// 使用示例
let image = UIImage(named: "example.jpg")!
let processor = ImageProcessor()

let blurredImage = processor.applyBlurFilter(to: image)
let sharpenedImage = processor.applySharpenFilter(to: image)
let colorAdjustedImage = processor.applyColorAdjustmentFilter(to: image)
let edgeDetectedImage = processor.applyEdgeDetectionFilter(to: image)
let customFilteredImage = processor.applyCustomFilter(to: image)

3.1 图像处理链|输入图像、滤镜效果、和输出图像

Objective-C示例:

objc 复制代码
// Objective-C示例:
#import <UIKit/UIKit.h>
#import <CoreImage/CoreImage.h>

UIImage *applyFilterToImage(UIImage *inputImage) {
    CIImage *ciImage = [[CIImage alloc] initWithImage:inputImage];
    
    CIFilter *filter = [CIFilter filterWithName:@"CIPhotoEffectMono"];
    [filter setValue:ciImage forKey:kCIInputImageKey];
    
    CIImage *outputImage = [filter outputImage];
    
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef cgImage = [context createCGImage:outputImage fromRect:outputImage.extent];
    
    UIImage *filteredImage = [UIImage imageWithCGImage:cgImage];
    CGImageRelease(cgImage);
    
    return filteredImage;
}

Swift示例:

swift 复制代码
// Swift示例:
import UIKit
import CoreImage

func applyFilterToImage(inputImage: UIImage) -> UIImage? {
    if let ciImage = CIImage(image: inputImage) {
        let filter = CIFilter(name: "CIPhotoEffectMono")
        filter?.setValue(ciImage, forKey: kCIInputImageKey)
        
        if let outputImage = filter?.outputImage {
            let context = CIContext(options: nil)
            if let cgImage = context.createCGImage(outputImage, from: outputImage.extent) {
                let filteredImage = UIImage(cgImage: cgImage)
                return filteredImage
            }
        }
    }
    return nil
}

3.1 图像分析|人脸检测、特征识别、颜色识别、物体识别

Objective-C示例:

objc 复制代码
// Objective-C示例:
#import <UIKit/UIKit.h>
#import <CoreImage/CoreImage.h>

- (void)analyzeImage:(UIImage *)image {
    CIImage *ciImage = [[CIImage alloc] initWithImage:image];
    
    // 人脸检测
    NSDictionary *options = @{CIDetectorAccuracy: CIDetectorAccuracyHigh};
    CIDetector *faceDetector = [CIDetector detectorOfType:CIDetectorTypeFace context:nil options:options];
    NSArray *faces = [faceDetector featuresInImage:ciImage];
    for (CIFaceFeature *faceFeature in faces) {
        NSLog(@"Detected face at %@", NSStringFromCGRect(faceFeature.bounds));
    }
    
    // 特征识别
    NSDictionary *featureOptions = @{CIDetectorImageOrientation: @(1)};
    CIDetector *featureDetector = [CIDetector detectorOfType:CIDetectorTypeQRCode context:nil options:featureOptions];
    NSArray *features = [featureDetector featuresInImage:ciImage];
    for (CIQRCodeFeature *feature in features) {
        NSLog(@"Detected QR code with message: %@", feature.messageString);
    }
    
    // 颜色识别
    CIColor *averageColor = [ciImage valueForKey:@"inputImage"];
    NSLog(@"Average color of the image: %@", averageColor);
    
    // 物体识别
    NSDictionary *objectOptions = @{CIDetectorAccuracy: CIDetectorAccuracyHigh};
    CIDetector *objectDetector = [CIDetector detectorOfType:CIDetectorTypeRectangle context:nil options:objectOptions];
    NSArray *objects = [objectDetector featuresInImage:ciImage];
    for (CIRectangleFeature *objectFeature in objects) {
        NSLog(@"Detected object at %@", NSStringFromCGRect(objectFeature.bounds));
    }
}

Swift示例:

swift 复制代码
import UIKit
import CoreImage

class ImageAnalysis {
    
    func analyzeImage(image: UIImage) {
        if let ciImage = CIImage(image: image) {
            let context = CIContext()
            
            // 人脸检测
            let faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: context, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])
            let faces = faceDetector?.features(in: ciImage)
            for face in faces as! [CIFaceFeature] {
                print("Face bounds: \(face.bounds)")
                if face.hasLeftEyePosition {
                    print("Left eye position: \(face.leftEyePosition)")
                }
                if face.hasRightEyePosition {
                    print("Right eye position: \(face.rightEyePosition)")
                }
            }
            
            // 特征识别
            let featureDetector = CIDetector(ofType: CIDetectorTypeRectangle, context: context, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])
            let features = featureDetector?.features(in: ciImage)
            for feature in features as! [CIRectangleFeature] {
                print("Feature bounds: \(feature.bounds)")
            }
            
            // 颜色识别
            let colorDetector = CIDetector(ofType: CIDetectorTypeColor, context: context, options: nil)
            let colors = colorDetector?.features(in: ciImage)
            for color in colors as! [CIColorFeature] {
                print("Detected color: \(color.color)")
            }
            
            // 物体识别
            let objectDetector = CIDetector(ofType: CIDetectorTypeQRCode, context: context, options: nil)
            let objects = objectDetector?.features(in: ciImage)
            for object in objects as! [CIQRCodeFeature] {
                print("Detected QR code: \(object.messageString ?? "")")
            }
        }
    }
}

// 使用示例
let image = UIImage(named: "sampleImage")
let imageAnalysis = ImageAnalysis()
imageAnalysis.analyzeImage(image: image)

3.1 Metal性能优化

Objective-C示例:

objc 复制代码
// Objective-C示例:
#import <Metal/Metal.h>
#import <MetalKit/MetalKit.h>
#import <CoreImage/CoreImage.h>

// 创建Metal设备和CIContext
id<MTLDevice> device = MTLCreateSystemDefaultDevice();
CIContext *ciContext = [CIContext contextWithMTLDevice:device];

// 创建Metal纹理
MTKView *metalView = [[MTKView alloc] initWithFrame:CGRectZero device:device];
id<MTLTexture> metalTexture = metalView.currentDrawable.texture;

// 创建CIImage
CIImage *ciImage = [CIImage imageWithMTLTexture:metalTexture options:nil];

// 创建滤镜
CIFilter *filter = [CIFilter filterWithName:@"CIColorControls"];
[filter setValue:ciImage forKey:kCIInputImageKey];
[filter setValue:@(1.2) forKey:kCIInputContrastKey];

// 渲染并显示结果
CIImage *outputImage = [filter outputImage];
[ciContext render:outputImage toMTLTexture:metalTexture commandBuffer:nil bounds:outputImage.extent colorSpace:outputImage.colorSpace];

Swift示例:

swift 复制代码
// Swift示例:
import Metal
import MetalKit
import CoreImage

// 创建Metal设备和CIContext
let device = MTLCreateSystemDefaultDevice()
let ciContext = CIContext(mtlDevice: device!)

// 创建Metal纹理
let metalView = MTKView(frame: CGRect.zero, device: device)
let metalTexture = metalView.currentDrawable?.texture

// 创建CIImage
let ciImage = CIImage(mtlTexture: metalTexture!, options: nil)

// 创建滤镜
let filter = CIFilter(name: "CIColorControls")
filter?.setValue(ciImage, forKey: kCIInputImageKey)
filter?.setValue(1.2, forKey: kCIInputContrastKey)

// 渲染并显示结果
if let outputImage = filter?.outputImage {
    ciContext.render(outputImage, to: metalTexture!, commandBuffer: nil, bounds: outputImage.extent, colorSpace: outputImage.colorSpace)
}

3.1 实时预览

Objective-C示例:

objc 复制代码
// Objective-C示例:
#import <UIKit/UIKit.h>
#import <CoreImage/CoreImage.h>

@interface ViewController : UIViewController <AVCaptureVideoDataOutputSampleBufferDelegate>

@property (nonatomic, strong) AVCaptureSession *captureSession;
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;
@property (nonatomic, strong) CIContext *ciContext;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.captureSession = [[AVCaptureSession alloc] init];
    AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    
    NSError *error = nil;
    AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];
    
    if (videoInput) {
        [self.captureSession addInput:videoInput];
        
        AVCaptureVideoDataOutput *videoOutput = [[AVCaptureVideoDataOutput alloc] init];
        [videoOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];
        [self.captureSession addOutput:videoOutput];
        
        self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];
        self.previewLayer.frame = self.view.bounds;
        [self.view.layer addSublayer:self.previewLayer];
        
        [self.captureSession startRunning];
        
        self.ciContext = [CIContext contextWithOptions:nil];
    } else {
        NSLog(@"Error setting up video input: %@", error);
    }
}

- (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
    CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pixelBuffer];
    
    // 应用滤镜
    CIFilter *filter = [CIFilter filterWithName:@"CIColorControls"];
    [filter setValue:ciImage forKey:kCIInputImageKey];
    [filter setValue:@(1.2) forKey:kCIInputContrastKey];
    
    CIImage *outputImage = [filter outputImage];
    
    // 渲染到预览层
    [self.ciContext render:outputImage toCVPixelBuffer:pixelBuffer];
}

@end

Swift示例:

swift 复制代码
// Swift示例:
import UIKit
import AVFoundation

class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate {
    
    var captureSession: AVCaptureSession!
    var previewLayer: AVCaptureVideoPreviewLayer!
    var ciContext: CIContext!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        captureSession = AVCaptureSession()
        guard let videoDevice = AVCaptureDevice.default(for: .video),
              let videoInput = try? AVCaptureDeviceInput(device: videoDevice) else {
            return
        }
        
        if captureSession.canAddInput(videoInput) {
            captureSession.addInput(videoInput)
            
            let videoOutput = AVCaptureVideoDataOutput()
            videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue.main)
            captureSession.addOutput(videoOutput)
            
            previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
            previewLayer.frame = view.bounds
            view.layer.addSublayer(previewLayer)
            
            captureSession.startRunning()
            
            ciContext = CIContext()
        }
    }
    
    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
        let ciImage = CIImage(cvPixelBuffer: pixelBuffer)
        
        // 应用滤镜
        let filter = CIFilter(name: "CIColorControls")
        filter?.setValue(ciImage, forKey: kCIInputImageKey)
        filter?.setValue(1.2, forKey: kCIInputContrastKey)
        
        if let outputImage = filter?.outputImage {
            // 渲染到预览层
            ciContext.render(outputImage, to: pixelBuffer)
        }
    }
}

六、Metal

1. 主要特点和功能

Metal是苹果公司推出的图形和计算框架,主要用于实现高性能的图形渲染和通用计算任务。以下是Metal框架的主要特点和功能:

    1. 低级别接口:
    • Metal提供了直接访问GPU的低级别接口,相比OpenGL和OpenCL等传统图形和计算框架更加高效。
    • 开发者可以更加精细地控制图形渲染和计算流程,实现更高性能的图形处理和计算任务。
    1. 高性能图形渲染:
    • Metal通过利用GPU的并行处理能力,实现高性能的图形渲染和效果处理。
    • Metal支持现代图形渲染技术,如着色器编程纹理映射光照效果渲染三维场景等,可以实现复杂的图形渲染效果。
    1. 通用计算:
    • Metal不仅用于图形渲染,还可以用于通用计算任务,如机器学习图像处理物理模拟等。
    • Metal提供了计算着色器和计算管线,支持GPU加速的通用计算,提高计算任务的效率和速度。
    1. 着色器编程:
    • Metal使用着色器(Shader)来控制图形渲染和计算过程。
    • 开发者可以使用Metal Shading Language(MSL)编写着色器代码,实现定制化的图形效果计算逻辑
    1. 命令缓冲区:
    • Metal使用命令缓冲区(Command Buffer)来管理GPU命令的提交和执行。
    • 开发者可以创建和提交命令缓冲区,控制GPU的操作流程,实现高效的图形渲染和计算任务。
    1. 资源管理:
    • Metal提供了资源管理功能,用于管理GPU资源如缓冲区、纹理等。
    • 开发者可以创建和管理各种GPU资源,优化资源的使用和共享,提高图形渲染和计算的效率。
    1. 多线程并发:
    • Metal框架支持多线程并发,可以在多个线程上同时执行图形渲染和计算任务。
    • 开发者可以利用Metal的多线程特性实现并行处理,提高应用程序的性能和响应速度。
    1. 内存管理:
    • Metal提供了高效的内存管理机制,可以管理GPU资源和缓冲区的分配和释放。
    • Metal的内存管理功能可以帮助开发者优化内存使用,避免内存泄漏和性能下降。
    1. 跨平台支持:
    • Metal框架不仅支持iOS和macOS平台,还可以在tvOS上使用,实现跨平台的图形渲染和计算功能。
    • Metal提供了一致的API和功能,方便开发者在不同平台上实现统一的图形处理和计算任务

2. 核心类介绍

以下是Metal框架中一些核心类的介绍:

    1. MTLDevice:
    • MTLDevice是Metal框架中表示GPU设备的类,用于创建Metal对象和管理GPU资源。
    • 开发者可以通过MTLDevice创建其他Metal对象,如缓冲区、纹理等。
    1. MTLCommandQueue:
    • MTLCommandQueue是Metal框架中的命令队列类,用于提交和执行GPU命令。
    • 开发者可以将命令添加到MTLCommandQueue中,然后由GPU执行这些命令。
    1. MTLRenderPipelineState:
    • MTLRenderPipelineState是Metal框架中的渲染管线状态类,用于配置图形渲染管线。
    • 开发者可以通过MTLRenderPipelineState设置渲染管线的各个阶段,如顶点着色器、片元着色器等。
    1. MTLBuffer:
    • MTLBuffer是Metal框架中表示缓冲区的类,用于存储数据和传递给GPU。
    • 开发者可以创建MTLBuffer对象来传递顶点数据、纹理数据等到GPU进行处理。
    1. MTLTexture:
    • MTLTexture是Metal框架中表示纹理的类,用于存储和处理图像数据。
    • 开发者可以创建MTLTexture对象来加载纹理数据,用于图像处理和渲染。
    1. MTLComputePipelineState:
    • MTLComputePipelineState是Metal框架中的计算管线状态类,用于配置计算任务。
    • 开发者可以通过MTLComputePipelineState设置计算任务的各个阶段,如计算内核函数等。
    • Metal框架提供了直接访问GPU的能力,可以实现高性能的图形渲染和计算任务。通过这些核心类,开发者可以利用Metal框架实现复杂的图形渲染、计算任务和图形效果,为应用程序提供更加流畅和高性能的图形处理能力。

3. 代码示例

通过后期的文章篇幅展开介绍...

七、GPUImage

1. 主要特点和功能

GPUImage是一个基于OpenGL ES 2.0的开源图像处理框架,支持GPU加速,用于实现图像和视频处理的功能 以下是GPUImage框架的主要特点和功能:

    1. 滤镜(Filters):
    • GPUImage提供了大量的滤镜效果,如色彩调整模糊锐化边缘检测 等。
    • 开发者可以通过GPUImage提供的滤镜效果对图像视频进行实时处理
    • 定制滤镜(Custom Filters):开发者可以通过编写自定义滤镜来扩展GPUImage的功能和效果,通过组合各种图像处理操作来创建个性化的滤镜效果,满足特定的处理需求。
    1. 处理链(Processing Chain):
    • GPUImage支持链式处理图像和视频数据,可以将多个滤镜效果串联起来,实现复杂的处理流程,同时保持高效的处理速度
    • 每个处理步骤都可以添加不同的滤镜效果。
    • 开发者可以自定义处理链,实现复杂的图像处理流程。
    1. 实时相机(Camera):
    • GPUImage提供了相机类,可以直接从摄像头捕获实时图像数据、视频流。
    • 开发者可以利用GPUImage的相机类实现实时滤镜效果和实时图像处理。
    1. 纹理(Textures):
    • GPUImage使用OpenGL纹理来处理图像数据,提高处理效率和性能。
    • 开发者可以利用GPUImage的纹理处理功能实现高效的图像处理和渲染。
    1. 实时处理(Real-time Processing):
    • GPUImage支持实时处理图像和视频流,可以在实时视频流中应用滤镜效果实现实时的图像处理和增强
    • 开发者可以利用GPUImage实现实时的图像处理效果,为应用程序增加更多的视觉吸引力
    1. 跨平台支持:
    • GPUImage不仅支持iOS平台,还支持Android平台和桌面平台,可以实现跨平台的图像处理应用开发。
    1. 易用性:
    • GPUImage提供了简洁易用的API和文档,使开发者能够快速上手并实现各种图像处理需求,降低开发成本和复杂度。
    1. GPU加速:
    • GPUImage利用GPU的并行计算能力来加速图像处理和滤镜效果的计算,提高处理速度和效率。

2. 核心类和协议介绍

核心类:

    1. GPUImageOutput:
    • GPUImageOutput是所有输出类的基类,用于处理图像数据的输出。
    • 其子类包括GPUImageFilter、GPUImagePicture等,用于实现不同的图像处理功能。
    1. GPUImageFilter:
    • GPUImageFilter是图像滤镜的基类,用于实现各种图像处理滤镜效果。
    • 开发者可以通过GPUImageFilter及其子类来应用各种滤镜效果,如模糊、锐化、色彩调整等。
    1. GPUImagePicture:
    • GPUImagePicture用于将静态图像加载到GPU中进行处理。
    • 可以通过GPUImagePicture加载UIImage或CGImage等静态图像数据,并传递给滤镜进行处理。
    1. GPUImageFramebuffer:
    • GPUImageFramebuffer用于在GPU中存储图像数据的帧缓冲区。
    • GPUImage处理图像数据时会使用帧缓冲区来存储中间结果,提高处理效率。
    1. GPUImageMovieWriter:
    • GPUImageMovieWriter是用于将视频数据写入文件的类。
    • GPUImageMovieWriter实现了GPUImageInput和GPUImageTextureOutput协议,可以接收图像数据并将处理后的视频数据写入文件。

协议:

    1. GPUImageInput:
    • GPUImageInput是输入类的协议,定义了接收图像数据的方法。
    • 所有需要接收图像数据的类都需要实现GPUImageInput协议,以便接收和处理图像数据。
    1. GPUImageTextureOutput:
    • GPUImageTextureOutput是输出纹理的协议,用于输出处理后的纹理数据。
    • 实现了GPUImageTextureOutput协议的类可以将处理后的纹理数据输出到其他地方,如屏幕、纹理等。

3. 代码示例

通过后期的文章篇幅展开介绍...

八、OpenGL ES

1. 主要特点和功能

OpenGL ES(OpenGL for Embedded Systems)是一种用于嵌入式系统的轻量级版本的OpenGL图形库,常用于移动设备和嵌入式系统中的图形渲染。以下是OpenGL ES的核心要点:

    1. 跨平台性:
    • OpenGL ES是跨平台的图形API,可以在多种移动设备和嵌入式系统上使用,如iOS、Android、嵌入式Linux等。
    1. 硬件加速:
    • OpenGL ES利用GPU硬件加速进行图形渲染,提供高性能的图形处理能力,适合移动设备和嵌入式系统的资源限制环境。
    1. 上下文管理:
    • OpenGL ES使用上下文(Context)来管理图形状态和资源,包括着色器程序纹理缓冲区等。
    • 开发者需要创建和管理OpenGL ES上下文,以便进行图形渲染和操作。
    1. 图形渲染:
    • OpenGL ES支持各种图形渲染功能,包括顶点处理片元处理纹理映射着色器编程等,可以实现各种复杂的图形效果。
    • 着色器编程:
      • OpenGL ES使用着色器(Shader)来定义图形渲染的计算过程,包括顶点着色器片元着色器
      • 开发者可以编写自定义的着色器程序,用于实现各种图形效果和渲染算法。
    • 纹理映射:
      • OpenGL ES支持纹理映射(Texture Mapping),用于将纹理映射到几何图形表面,实现丰富的纹理效果和贴图功能。
      • 开发者可以加载纹理数据并将其映射到几何图形上,实现丰富的纹理效果。
    1. 缓冲区对象:
    • OpenGL ES使用缓冲区对象(Buffer Object),包括顶点缓冲区索引缓冲区等来存储顶点数据索引数据等。
    • 开发者可以创建和管理缓冲区对象,存储和传递图形数据,提供给GPU进行图形渲染
    1. 深度测试和混合:
    • OpenGL ES支持深度测试和混合功能,可以实现透明效果深度排序等,提高图形渲染的真实感和逼真度。
    • 多重采样抗锯齿:
    • OpenGL ES支持多重采样抗锯齿(MSAA),可以减少图形渲染中的锯齿现象,提高图形质量。
    1. 光照和材质:
    • OpenGL ES支持光照和材质(Lighting and Material),用于模拟光照效果和物体表面的材质特性
    • 开发者可以通过设置光照参数和材质属性来实现逼真的光照效果。
    1. 渲染管线:
    • OpenGL ES使用渲染管线(Rendering Pipeline)来处理图形渲染过程,包括顶点处理、几何处理、光栅化等阶段。
    • 开发者可以配置渲染管线的各个阶段,以实现定制的图形渲染效果。

2. 核心类介绍

    1. GLKView:
    • GLKView是OpenGL ES框架中用于显示OpenGL内容的视图类。
    • GLKView提供了一个方便的方式来在iOS应用中显示OpenGL渲染的内容。
    1. GLKViewController:
    • GLKViewController是OpenGL ES框架中的视图控制器类,用于管理OpenGL渲染和视图的交互。
    • GLKViewController可以处理渲染循环、用户交互等任务,简化OpenGL ES应用程序的开发。
    1. GLKBaseEffect:
    • GLKBaseEffect是OpenGL ES框架中的基本效果类,用于实现简单的渲染效果。
    • GLKBaseEffect提供了一些基本的渲染效果,如颜色、光照、纹理等。
    1. GLKTextureLoader:
    • GLKTextureLoader是OpenGL ES框架中的纹理加载器类,用于加载和管理纹理数据。
    • GLKTextureLoader可以从文件、内存等来源加载纹理数据,方便在OpenGL ES应用中使用纹理。
    1. GLKMath:
    • GLKMath是OpenGL ES框架中的数学库,用于处理矩阵、向量等数学运算。
    • GLKMath提供了一些常用的数学函数和数据结构,方便在OpenGL ES应用中进行数学计算。

3. 代码示例

通过后期的文章篇幅展开介绍...

九、ARKit和Metal框架

在iOS开发中,使用ARKit框架 可以进行 AR开发,使用ARKit+Metal可以进行VR开发。本文主要针对官方自带的图形界面处理框架和比较流行的GPUImage框架进行简单介绍。暂不对AR、VR等相关技术展开讨论

十、Open CV、SpriteKit、Sence Kit

在iOS开发中,使用SpriteKit框架、Sence Kit框架 可以进行 2D、3D游戏开发。使用OpenCV可以进行计算机视觉处理开发。本文主要针对官方自带的图形界面处理框架和比较流行的GPUImage框架进行简单介绍。暂不对游戏、计算机视觉等相关技术展开讨论

总结

本文主要针对官方自带的图形界面处理框架和比较流行视频图层处理框架进行简单介绍:

  • 系统自带框架
    • UIKit
    • Core Graphics
    • Core Image
    • Core Animation
    • Metal
  • 流行的第三方框架
    • GPUImage
    • OpenGL ES

后面会有几篇文章针对这几大块,进行更详细的介绍

本文尚未讨论

  • ARKit和Metal框架进行 XR开发(AR、VR)
  • Open CV 计算机视觉开发
  • SpriteKit、Sence Kit 游戏开发 若后面有时间,会进行简单的了解,给自己一个知识储备

系列文章

  • [01-iOS 多媒体技术| 图形处理框架简介:Core Animation、Core Graphics、OpenGL ES、Metal、GPUImage等](#01-iOS 多媒体技术| 图形处理框架简介:Core Animation、Core Graphics、OpenGL ES、Metal、GPUImage等 "#")
相关推荐
键盘敲没电7 小时前
【iOS】知乎日报总结
学习·ios·objective-c·xcode
安和昂12 小时前
【iOS】UICollectionView的学习
学习·ios·cocoa
二流小码农15 小时前
鸿蒙开发:自定义一个任意位置弹出的Dialog
android·ios·harmonyos
小江村儿的文杰1 天前
UE4 iOS Package的过程与XCode工程中没有游戏Content的原因
macos·ios·ue4·xcode
__WanG2 天前
Flutter将应用打包发布到App Store
前端·flutter·ios
安和昂2 天前
【iOS】bug调试技巧
ios·bug·cocoa
emperinter2 天前
WordCloudStudio Now Supports AliPay for Subscriptions !
人工智能·macos·ios·信息可视化·中文分词
AirDroid_cn2 天前
iPhone或iPad接收的文件怎么找?怎样删除?
ios·iphone·ipad·文件传输
Swift社区2 天前
在 Swift 中实现字符串分割问题:以字典中的单词构造句子
开发语言·ios·swift
#摩斯先生2 天前
Swift从0开始学习 对象和类 day3
ios·xcode·swift