iOS圖形處理概論:OpenGL ES,Metal,Core Graphics,Core Image,GPUImage,OpenCV等

前言

對於剛接觸iOS圖形相關框架的小白,有一些圖形框架在字面上和功能上很是容易混淆。這裏旨在總結一下各類框架,區分它們的概念和功能,以做往後進一步細分學習的指引。於是,本文並不會針對具體框架做詳解,只做區分引導,讀者可自行選擇方向繼續深造。爲此,筆者總結了一張各類框架關係圖,以下所示:php

iOS圖形處理相關概念集合

總的來講,iOS與圖形圖像處理相關的框架都在這裏了:html

    1. 界面圖形框架 -- UIKit
    1. 核心動畫框架 -- Core Animation
    1. 蘋果封裝的圖形框架 -- Core Graphics & Quartz 2D
    1. 傳統跨平臺圖形框架 -- OpenGL ES
    1. 蘋果最新力推的圖形框架 -- Metal
    1. 適合圖片的蘋果濾鏡框架 -- Core Image
    1. 適合視頻的第三方濾鏡方案 -- GPUImage
    1. 遊戲引擎 -- Scene Kit (3D) 和 Sprite Kit (2D)
    1. 計算機視覺在iOS的應用 -- OpenCV for iOS

1. 界面圖形框架 -- UIKit

UIKit

UIKit是一組Objective-C API,爲線條圖形、Quartz圖像和顏色操做提供Objective-C 封裝,並提供2D繪製、圖像處理及用戶接口級別的動畫。ios

UIKit包括UIBezierPath(繪製線、角度、橢圓及其它圖形)、UIImage(顯示圖像)、UIColor(顏色操做)、UIFont和UIScreen(提供字體和屏幕信息)等類以及在位圖圖形環境、PDF圖形環境上進行繪製和 操做的功能等, 也提供對標準視圖的支持,也提供對打印功能的支持。git

UIKit與Core Graphics的關係

在UIKit中,UIView類自己在繪製時自動建立一個圖形環境,即Core Graphics層的CGContext類型,做爲當前的圖形繪製環境。在繪製時能夠調用 UIGraphicsGetCurrentContext 函數得到當前的圖形環境,例如:github

- (void)drawRect:(CGRect)rect {
    // Drawing code
    NSLog(@"%s",__func__);
    //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);
    
}
複製代碼

這段代碼就是在UIView的子類中調用 UIGraphicsGetCurrentContext 函數得到當前的圖形環境,而後向該圖形環境添加路徑,最後繪製。算法

2. 核心動畫框架 -- Core Animation

Core Animation

Core Animation 是一套Objective-C API,實現了一個高性能的複合引擎,並提供一個簡單易用的編程接口,給用戶UI添加平滑運動和動態反饋能力。編程

Core Animation 是 UIKit 實現動畫和變換的基礎,也負責視圖的複合功能。使用Core Animation能夠實現定製動畫和細粒度的動畫控制,建立複雜的、支持動畫和變換的layered 2D視圖。安全

Core Animation 不屬於繪製系統,但它是以硬件複合和操做顯示內容的基礎設施。這個基礎設施的核心是layer對象,用來管理和操做顯示內容。在 iOS 中 每個視圖都對應Core Animation的一個層對象,與視圖同樣,層之間也組織爲層關係樹。一個層捕獲視圖內容爲一個被圖像硬件容易操做的位圖。在多數應用中層做爲管理視圖的方式使用,但也能夠建立獨立的層到一個層關係樹中來顯示視圖不夠支持的顯示內容。bash

OpenGL ES的內容也能夠與Core Animation內容進行集成。網絡

爲了使用Core Animation實現動畫,能夠修改 層的屬性值 來觸發一個action對象的執行,不一樣的action對象實現不一樣的動畫。

Core Animatio相關基類及子類

Core Animation 提供了一下一組應用能夠採用的類來提供對不一樣動畫類型的支持:

  • CAAnimation 是一個抽象公共基類,CAAnimation採用CAMediaTiming 和CAAction協議爲動畫提供時間(如週期、速度、重複次數等)和action行爲(啓動、中止等)。
  • CAPropertyAnimation 是 CAAnimation的抽象子類,爲動畫提供一個由一個key路徑規定的層屬性的支持;
  • CABasicAnimation 是CAPropertyAnimation的具體子類,爲一個層屬性提供簡單插入能力。
  • CAKeyframeAnimation 也是CAPropertyAnimation的具體子類,提供key幀動畫支持。

3. 蘋果封裝的圖形框架 -- Core Graphics & Quartz 2D

Core Graphics

Core Graphics是一套C-based API, 支持向量圖形,線、形狀、圖案、路徑、剃度、位圖圖像和pdf 內容的繪製。

Quartz 2D

Quartz 2D是Core Graphics中的2D 繪製呈現引擎。Quartz是資源和設備無關的,提供路徑繪製,anti-aliased呈現,剃度填充圖案,圖像,透明繪製和透明層、遮蔽和陰影、顏色管理,座標轉換,字體、offscreen呈現、pdf文檔建立、顯示和分析等功能。

Quartz 2D可以與全部的圖形和動畫技術(如Core Animation, OpenGL ES, 和 UIKit 等)一塊兒使用。

Quartz 2D採用paint模式進行繪製。

圖形環境Context

Quartz 2D中使用的圖形環境也由一個類CGContext表示。

在Quartz 2D中能夠把一個圖形環境做爲一個繪製目標。當使用Quartz 2D進行繪製時,全部設備特定的特性被包含在你使用的特定類型的圖形環境中,所以經過給相同的圖像操做函數提供不一樣的圖像環境你就可以畫相同的圖像到不一樣的設備上,所以作到了圖像繪製的設備無關性。

圖形環境Context是個比較抽象的東西,它不只僅是一個能夠繪製的圖層,還包含爲當前圖層設置的參數,如陰影,線條粗細,繪製模式等。能夠類比成一個新建的Photoshop圖層以及當前筆觸,顏色等配置。

對於移動平臺,有三種常見的圖形環境Context:

  • 位圖上下文(A bitmap graphics context):通常用於繪製圖片或者自定義控件。

    • View Graphics Context: 由UIView自動建立,你重寫UIView drawRect方法時,你的內容會畫在這個上下文上。
    • Bitmap Graphics Context: 繪製在該上下文的內容會以點陣形式存儲在一塊內存中。簡單說,就是爲圖片開闢一塊內存,而後在裏面畫東西,上下文幫你把圖片內存抽象成一個Context(圖層)了。
  • PDF上下文(A PDF graphics context):用於生成pdf文件。

  • 圖層上下文(A layer context):用於離屏繪製( offscreen drawing)。

Quartz 2D提供的主要類包括:
  • CGContext:表示一個圖形環境;
  • CGPath:使用向量圖形來建立路徑,並可以填充和stroke;
  • CGImage:用來表示位圖;
  • CGLayer:用來表示一個可以用於重複繪製和offscreen繪製的繪製層;
  • CGPattern:用來表示Pattern,用於重複繪製;
  • CGShading和 CGGradient:用於繪製剃度;
  • CGColor 和 CGColorSpace;用來進行顏色和顏色空間管理;
  • CGFont, 用於繪製文本;
  • CGPDFContentStream、CGPDFScanner、CGPDFPage、CGPDFObject,CGPDFStream, CGPDFString等用來進行pdf文件的建立、解析和顯示。

4. 傳統跨平臺圖形框架 -- OpenGL ES

OpenGL ES

OpenGL ES是一套多功能開放標準的用於嵌入系統的C-based的圖形庫,用於2D和3D數據的可視化。OpenGL被設計用來轉換一組圖形調用功能到底層圖形硬件(GPU),由GPU執行圖形命令,用來實現複雜的圖形操做和運算,從而可以高性能、高幀率利用GPU提供的2D和3D繪製能力。

OpenGL ES規範自己不定義繪製表面和繪製窗口,所以ios爲了使用它必須提供和建立一個OpenGL ES 的呈現環境,建立和配置存儲繪製命令結果的framebuffer 及建立和配置一個或多個呈現目標。

EAGL

在 iOS中使用EAGL提供的EAGLContext類 來實現和提供一個呈現環境,用來保持OpenGL ES使用到的硬件狀態。 EAGL是一個Objective-C API,提供使OpenGL ES與Core Animation和UIKIT集成的接口。

在調用任何OpenGL ES 功能以前必須首先初始化一個EAGLContext 對象。每個IOS應用的每個線程都有一個當前context,在調用OpenGL ES函數時,使用或改變此context中的狀態。

EAGLContext 的類方法setCurrentContext: 用來設置當前線程的當前context。EAGLContext 的類方法currentContext 返回當前線程的當前context。在切換相同線程的兩個上下文以前,必須調用glFlush函數來確保先前已提交的命令被提交到圖形硬件中。

GLKit

能夠採用不一樣的方式使用OpenGL ES以便呈現OpenGL ES內容到不一樣的目標:GLKit和CAEAGLLayer。

爲了建立全屏幕的視圖或使OpenGL ES內容與UIKit視圖集成,可使用GLKit。在使用GLKit時,GLKit提供的類GLKView類自己實現呈現目標及建立和維護一個framebuffer。

GLKit是一組Objective-C 類,爲使用OpenGL ES 提供一個面向對象接口,用來簡化OpenGL ES應用的開發。

CAEAGLLayer

爲了使OpenGL ES內容做爲一個Core Animation層的部份內容時,可使用CAEAGLLayer 做爲呈現目標,並須要另外建立framebuffer以及本身實現和控制整個繪製流程。

GLKit支持四個3D應用開發的關鍵領域:

1) GLKView 和GLKViewController類提供一個標準的OpenGL ES視圖和相關聯的呈現循環。GLKView能夠做爲OpenGL ES內容的呈現目標,GLKViewController提供內容呈現的控制和動畫。視圖管理和維護一個framebuffer,應用只需在framebuffer進行繪畫便可。

2)GLKTextureLoader 爲應用提供從IOS支持的各類圖像格式的源自動加載紋理圖像到OpenGL ES 圖像環境的方式,並可以進行適當的轉換,並支持同步和異步加載方式。

3)數學運算庫,提供向量、矩陣、四元數的實現和矩陣堆棧操做等OpenGL ES 1.1功能。

4)Effect效果類提供標準的公共着色效果的實現。可以配置效果和相關的頂點數據,而後建立和加載適當的着色器。GLKit 包括三個可配置着色效果類:GLKBaseEffect實現OpenGL ES 1.1規範中的關鍵的燈光和材料模式, GLKSkyboxEffect提供一個skybox效果的實現, GLKReflectionMapEffect 在GLKBaseEffect基礎上包括反射映射支持。

5. 蘋果最新力推的圖形框架 -- Metal

Metal框架支持GPU硬件加速、高級3D圖形渲染以及大數據並行運算。且提供了先進而精簡的API來確保框架的細粒度(fine-grain),而且在組織架構、程序處理、圖形呈現、運算指令以及指令相關數據資源的管理上都支持底層控制。其核心目的是儘量的減小CPU開銷,而將運行時產生的大部分負載交由GPU承擔

編寫基於底層圖形 API 的渲染引擎時,除了 Metal 之外的其餘選擇還有 OpenGL 和 OpenGL ES。OpenGL 不只支持包括 OSX,Windows,Linux 和 Android 在內的幾乎全部平臺,還有大量的教程,書籍和最佳實踐指南等資料。目前,Metal 的資源很是有限,而且僅限於搭載了 64 位處理器的 iPhone 和 iPad。但另一方面,由於 OpenGL 的限制,其性能與 Metal 相比並不佔優點,畢竟後者是專門用來解決這些問題的。

若是想要一個 iOS 上高性能的並行計算庫,答案很是簡單。Metal 是惟一的選擇。OpenGL 在 iOS 上是私有框架,而 Core Image (使用了 OpenGL) 對這樣的任務來講既不夠強大又不夠靈活。

6. 適合圖片的蘋果濾鏡框架 -- Core Image

Core Image 是 iOS5 新加入到 iOS 平臺的一個圖像處理框架,提供了強大高效的圖像處理功能, 用來對基於像素的圖像進行操做與分析, 內置了不少強大的濾鏡(Filter) (目前數量超過了180種), 這些Filter 提供了各類各樣的效果, 而且還能夠經過 濾鏡鏈 將各類效果的 Filter疊加 起來造成強大的自定義效果。

一個 濾鏡 是一個對象,有不少輸入和輸出,並執行一些變換。例如,模糊濾鏡可能須要輸入圖像和一個模糊半徑來產生適當的模糊後的輸出圖像。

一個 濾鏡鏈 是一個連接在一塊兒的濾鏡網絡,使得一個濾鏡的輸出能夠是另外一個濾鏡的輸入。以這種方式,能夠實現精心製做的效果。

iOS8 以後更是支持自定義 CIFilter,能夠定製知足業務需求的複雜效果。

Core Image 的 API 主要就是三類:

  • CIImage 保存圖像數據的類,能夠經過UIImage,圖像文件或者像素數據來建立,包括未處理的像素數據。
  • CIFilter 表示應用的濾鏡,這個框架中對圖片屬性進行細節處理的類。它對全部的像素進行操做,用一些鍵-值設置來決定具體操做的程度。
  • CIContext 表示上下文,如 Core Graphics 以及 Core Data 中的上下文用於處理繪製渲染以及處理託管對象同樣,Core Image 的上下文也是實現對圖像處理的具體對象。能夠從其中取得圖片的信息。

Core Image 的另一個優點,就是能夠根據需求選擇 CPU 或者 GPU 來處理。

// 建立基於 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];
複製代碼

7. 適合視頻的第三方濾鏡方案 -- GPUImage

GPUImage 優點: 最低支持 iOS 4.0,iOS 5.0 以後就支持自定義濾鏡。 在低端機型上,GPUImage 有更好的表現。(這個我沒用真正的設備對比過,GPUImage 的主頁上是這麼說的) GPUImage 在視頻處理上有更好的表現。 GPUImage 的代碼完成公開,實現透明。 能夠根據本身的業務需求,定製更加複雜的管線操做。可定製程度高。

8. 遊戲引擎 -- Scene Kit (3D) 和 Sprite Kit (2D)

對於尋找遊戲引擎的開發者來講,Metal 不是最佳選擇。蘋果官方的的 Scene Kit (3D) 和 Sprite Kit (2D) 是更好的選擇。這些 API 提供了包括物理模擬在內的更高級別的遊戲引擎。

另外還有功能更全面的 3D 引擎,例如 Epic 的 Unreal Engine 或 Unity,兩者都是跨平臺的。使用這些引擎,你無需直接使用 Metal 的 API,就能夠從 Metal 中獲益。

2D渲染 -- SpriteKit

SpriteKit 讓開發者能夠開發高性能、省電節能的 2D 遊戲。在 iOS 8 中,咱們新添了多項加強功能,這將使 2D 遊戲體驗更加精彩。這些新技術有助於使遊戲角色的動做更加天然,並讓開發者能夠更輕鬆地在遊戲中加入力場、檢測碰撞和生成新的燈光效果。

3D渲染 -- SceneKit

SceneKit 專爲休閒 3D 遊戲而設計,可以讓開發者渲染 3D 遊戲場景。SceneKit 內置了物理引擎、粒子發生器和各類易用工具,能夠輕鬆快捷地爲 3D 物體編寫動做。不只如此,它還與 SpriteKit 徹底集成,因此開發者能夠直接在 3D 遊戲中加入 SpriteKit 的素材。

9. 計算機視覺在iOS的應用 -- OpenCV for iOS

OpenCV 的 API 是 C++ 的。它由不一樣的模塊組成,這些模塊中包含範圍極爲普遍的各類方法,從底層的圖像顏色空間轉換到高層的機器學習工具。這裏提供一個入門PDF文檔 下載入口

使用 C++ API 並非絕大多數 iOS 開發者天天都作的事,你須要使用 Objective-C++ 文件來調用 OpenCV 的函數。 也就是說,你不能在 Swift 或者 Objective-C 語言內調用 OpenCV 的函數。 這篇 OpenCV 的 iOS 教程告訴你只要把全部用到 OpenCV 的類的文件後綴名改成 .mm 就好了,包括視圖控制器類也是如此。這麼幹或許能行得通,卻不是什麼好主意。正確的方式是給全部你要在 app 中使用到的 OpenCV 功能寫一層 Objective-C++ 封裝。這些 Objective-C++ 封裝把 OpenCV 的 C++ API 轉化爲安全的 Objective-C API,以方便地在全部 Objective-C 類中使用。

走封裝的路子,你的工程中就能夠只在這些封裝中調用 C++ 代碼,從而避免掉不少讓人頭痛的問題,好比直接改文件後綴名會由於在錯誤的文件中引用了一個 C++ 頭文件而產生難以追蹤的編譯錯誤。

OpenCV 聲明瞭命名空間 cv,所以 OpenCV 的類的前面會有個 cv:: 前綴,就像 cv::Mat、 cv::Algorithm 等等。你也能夠在 .mm 文件中使用 using namespace cv 來避免在一堆類名前使用 cv::前綴。可是,在某些類名前你必須使用命名空間前綴,好比 cv::Rect 和 cv::Point,由於它們會跟定義在 MacTypes.h 中的 Rect 和 Point 相沖突。儘管這只是我的偏好問題,我仍是偏向在任何地方都使用 cv::以保持一致性。

通常講的OpenCV是基於CPU的,相關資料和支持也是最完善的。固然,也有基於GPU模塊,但提供的接口很是坑爹,至關一部分不支持浮點類型(像histogram、integral這類經常使用的都不支持);又如,遇到閾值判斷的地方,就必須傳回cpu處理,由於gpu函數都是並行處理的,每改寫完一個算法模塊,就測試一下運行效率,有的時候是振奮人心,有的時候則是當頭棒喝——比CPU還慢。詳情可參閱 這裏

10. 參考文獻

  • Core Animations

https://www.sohu.com/a/203987045_468740 https://blog.csdn.net/huangznian/article/details/42919221 https://www.jianshu.com/p/446a6b72f981 https://www.jianshu.com/p/439e158b44de

  • Metal

https://juejin.im/post/59ad5d6551882539255b4809 https://www.jianshu.com/p/ce53d0178f20 https://blog.csdn.net/pizi0475/article/details/50232029 https://baike.baidu.com/item/Metal/10917053?fr=aladdin https://zhuanlan.zhihu.com/p/24623380?utm_source=tuicool&utm_medium=referral

  • Core Image

https://objccn.io/issue-21-6/ http://colin1994.github.io/2016/10/21/Core-Image-OverView/?utm_source=tuicool&utm_medium=referral https://blog.csdn.net/jingcheng345413/article/details/54967640 https://www.cnblogs.com/try2do-neo/p/3601546.html

  • Core Graphics

https://www.jianshu.com/p/e7a50dcbe7c8 https://www.jianshu.com/p/55cc1587e618 https://www.jianshu.com/p/494c57f49479 https://my.oschina.net/flyfishbay/blog/1504698

  • OpenCV

https://blog.csdn.net/zhonggaorong/article/details/78191514 http://www.opencv.org.cn/forum.php?mod=viewthread&tid=33549 https://blog.csdn.net/kelvin_yan/article/details/41804357 https://blog.csdn.net/sinat_31135199/article/details/53053188 https://blog.csdn.net/liyuefeilong/article/details/46292339

  • GPUImage

https://blog.csdn.net/fanbird2008/article/details/51707430

  • 其它

https://blog.csdn.net/goohong/article/details/40743883

相關文章
相關標籤/搜索