GPUImage作為iOS相當(dāng)老牌的圖片處理三方庫已經(jīng)有些日子了(2013年發(fā)布第一個(gè)版本)聚磺,至今甚至感覺要離我們慢慢遠(yuǎn)去(2015年更新了最后一個(gè)release)岸军∽可能現(xiàn)在分享這個(gè)稍微有點(diǎn)晚瘟斜,再加上落影大神早已發(fā)布過此類文章冬三,但是還是想從自己的角度來分享一下對(duì)其的理解和想法抖拴。
本文集所有內(nèi)容皆為原創(chuàng)燎字,嚴(yán)禁轉(zhuǎn)載。
? ? ? ? 第一篇有提到想試著翻譯一下GitHub中GPUImage的說明文檔來化解當(dāng)時(shí)剛接觸時(shí)給我留下的不會(huì)用的痛阿宅,結(jié)果發(fā)現(xiàn)網(wǎng)上已有挺多大神完成了一字不差的翻譯工作候衍。那我就選擇從其中挑選重點(diǎn),以個(gè)人理解來解釋說明文檔重點(diǎn)部分的意思家夺。
Overview? ? ? ??
GPUImage可以對(duì)圖片脱柱、攝像頭實(shí)時(shí)影像、視頻添加通過GPU加速的濾鏡和圖像處理效果拉馋。
與iOS5.0上的CoreImage框架比較榨为,GPUImage的優(yōu)勢(shì):可以自定義濾鏡(通過自定義glsl語句來實(shí)現(xiàn))惨好;不足:沒有人臉檢測等此類先進(jìn)技術(shù)(話說現(xiàn)在已經(jīng)相對(duì)不先進(jìn)了吧。随闺。)日川。
如果需要對(duì)圖片或者視頻進(jìn)行大量計(jì)算,那么GPU實(shí)現(xiàn)可以說是首選矩乐,iPhone4上比較快了100倍。
使用GPU處理圖像需要編寫大量代碼才可實(shí)現(xiàn)散罕,作者就先寫了一篇demo(http://www.sunsetlakesoftware.com/2010/10/22/gpu-accelerated-video-processing-mac-and-ios)分歇。之后發(fā)現(xiàn)其實(shí)之間有很多可模版化的內(nèi)容,再結(jié)合具體使用欧漱,最后開發(fā)出了GPUImage职抡。意思就是使用GPUImage可以實(shí)現(xiàn)基于OpenGLES2.0的GPU處理圖像工作并且基本不需涉及OpenGLES2.0的api误甚。
Technical requirements
iOS5+缚甩,ARC窑邦,有攝像頭,...現(xiàn)在已經(jīng)不存在不滿足要求的吧郊丛。
General architecture
這個(gè)在第一篇當(dāng)中已經(jīng)大致說明我自己的理解宾袜,此處就照本翻譯驾窟。
GPUImage是通過OpenGL ES 2.0著色器實(shí)現(xiàn)圖片和視頻的處理計(jì)算,所以會(huì)比CPU更快认轨。并且绅络!在使用過程中不需要涉及復(fù)雜的OpenGLES2.0的api恩急,而是提供封裝好的OC實(shí)現(xiàn)的類和方法即可實(shí)現(xiàn)圖片或視頻的多步驟處理操作、并能導(dǎo)出處理完成的結(jié)果纪蜒。
視頻或圖片載入后會(huì)以GPUImageOutput的一種子類為類型的資源對(duì)象存在衷恭。GPUImage具備的資源類有:GPUImageVideoCamera、GPUImageStillCamera纯续、GPUImagePicture随珠、GPUImageMovie(我記得還有一種:GPUImageRawDataInput灭袁。具體使用之后細(xì)說)。資源對(duì)象會(huì)把圖片或視頻載入到紋理(OpenGLES中的一種存儲(chǔ)圖片信息的具體對(duì)象)窗看,并且把這些紋理傳入具體的處理流程茸歧。
在整個(gè)處理流程鏈中的濾鏡或者說除了輸入源之后的對(duì)象,都需要遵循GPUImageInput協(xié)議显沈,只有這樣才能拿到上一個(gè)步驟處理完成的紋理進(jìn)行相應(yīng)處理软瞎。這些對(duì)象會(huì)經(jīng)過預(yù)先設(shè)置好的所有目標(biāo)對(duì)象中,并且處理過程中可以有多個(gè)分支的存在拉讯,即有多個(gè)下一步驟的路徑涤浇。
總結(jié):通過GPUImage可以創(chuàng)建一個(gè)濾鏡鏈,鏈中可以有多個(gè)分支魔慷,載入所需輸入源后經(jīng)過每個(gè)步驟的處理可得到一個(gè)或者多個(gè)結(jié)果只锭。
Performing common tasks(挑重點(diǎn))
Filtering live video
通過CustomShader.fsh(glsl語句構(gòu)成)文件作為參數(shù)生成的自定義濾鏡customFilter可以作為一個(gè)目標(biāo)(target)添加到從攝像頭獲取到的實(shí)時(shí)影像幀對(duì)象上。最終盖彭,這些經(jīng)過濾鏡處理后的幀內(nèi)容會(huì)顯示在一個(gè)繼承自UIView并且可以把紋理顯示出來的視圖(GPUImageView纹烹,其實(shí)最終是通過它的layer,即CAEAGLLayer對(duì)象來展示)上召边。
接下來提到了一個(gè)重點(diǎn):GPUImageView的fillMode屬性铺呵。源碼中該屬性的每個(gè)枚舉都有簡短的解釋:1.kGPUImageFillModeStretch, ?// Stretch to fill the full view, which may distort the image outside of its normal aspect ratio。拉伸內(nèi)容至填滿整個(gè)視圖隧熙,可能會(huì)照成圖片被不等比拉伸至變形片挂。
2.kGPUImageFillModePreserveAspectRatio,? ? ? ? ? // Maintains the aspect ratio of the source image, adding bars of the specified background color。保持顯示圖片的原比例贞盯,在未鋪滿區(qū)域顯示設(shè)置的背景顏色音念。
3.kGPUImageFillModePreserveAspectRatioAndFill? ? // Maintains the aspect ratio of the source image, zooming in on its center to fill the view。保持顯示圖片的原比例躏敢,等比放大填充整個(gè)視圖并居中顯示闷愤。
這個(gè)fillMode在我實(shí)際項(xiàng)目中給我?guī)砹艘恍├_。所以這里就先簡單翻譯件余,想在之后單獨(dú)針對(duì)GPUImageView的文章中詳細(xì)說明讥脐。
如果想在通過GPUImage錄制視頻時(shí)也把聲音錄進(jìn)去,那么可以設(shè)置GPUImageVideoCamera對(duì)象的audioEncodingTarget屬性啼器。
Capturing and filtering a still photo
這里提到的一點(diǎn)是:在某些設(shè)備上是支持不到2048或者更高像素的攝像頭圖片捕捉旬渠,原因是這些設(shè)備對(duì)紋理大小有相應(yīng)的限制,翻開源碼端壳,可以從繼承自GPUImageOutput的五個(gè)資源類中發(fā)現(xiàn)告丢,初始化資源將信息寫入紋理時(shí),會(huì)做一次資源文件大小的判斷损谦。因?yàn)閷?duì)應(yīng)生成的紋理對(duì)象是根據(jù)資源文件大小來生成的岖免,所以如果過大岳颇,則會(huì)使用當(dāng)前設(shè)備所支持的最大紋理大小來進(jìn)行生成。紋理既然作為一個(gè)編輯過程中實(shí)時(shí)存儲(chǔ)數(shù)據(jù)信息的對(duì)象觅捆,它也是會(huì)占據(jù)相應(yīng)內(nèi)存的赦役,并且在處理過程中,如果紋理過大栅炒,或者說紋理中待處理的信息過多掂摔,也會(huì)給GPU帶來壓力。所以即使在使用GPUImage對(duì)圖片或者視頻進(jìn)行處理的過程中赢赊,同樣需要注意處理資源的大小問題乙漓。
Processing a still image
對(duì)一張靜態(tài)圖片進(jìn)行濾鏡或者其他效果處理可以說是GPUImage的基礎(chǔ)入門操作(我是這么認(rèn)為)。
1.使用GPUImagePicture的初始化方法释移,可以將一張靜態(tài)圖片載入到紋理中叭披。不過GPUImagePicture的初始化方法有好幾個(gè),具體區(qū)別同樣之后再細(xì)說玩讳。
2.可以通過繼承自GPUImageFilter的類的對(duì)象調(diào)用imageFromCurrentFramebuffer方法得到處理后的圖片涩蜘。但如果要使用這種方法導(dǎo)出圖片,則必須要在GPUImagePicture對(duì)象執(zhí)行processImage方法之前執(zhí)行濾鏡對(duì)象的useNextFrameForImageCapture方法熏纯,否則按照GPUImage的源碼來看注定會(huì)crash同诫,控制臺(tái)的提示“Tried to overrelease a framebuffer, did you forget to call -useNextFrameForImageCapture before using -imageFromCurrentFramebuffer?”。
3.另一種導(dǎo)出處理圖片的方法是調(diào)用濾鏡對(duì)象的imageByFilteringImage方法樟澜,入?yún)閁IImage對(duì)象误窖。
Writing a custom filter
GPUImage相比CoreImage另一個(gè)大優(yōu)勢(shì)在于可以自定義濾鏡,通過glsl語言(OpenGL Shading Language秩贰,十分類似C語言的OpenGL著色器語言)實(shí)現(xiàn)霹俺。GPUImage庫中的絕大多數(shù)濾鏡都是通過自定義的glsl語句進(jìn)行對(duì)片段著色器操作,之前也有說過毒费,因?yàn)榇蠖鄶?shù)濾鏡只改變紋理內(nèi)容丙唧,并不會(huì)涉及到如何貼圖,或者說如何展示紋理觅玻。
Filtering and re-encoding a movie
視頻文件通過GPUImageMovie類載入艇棕,GPUImageMovieWriter類導(dǎo)出。需要注意的點(diǎn)有:
1.記錄串塑,或者說處理完成后,需要將GPUImageMovieWriter對(duì)象從上一個(gè)target(一般都為GPUImageFilter對(duì)象)中移除北苟,并且調(diào)用自身的finishRecording方法桩匪。
2.如果在記錄完成前壞了,那之前的處理導(dǎo)出內(nèi)容也沒了友鼻。
Interacting with OpenGL ES
通過GPUImage的GPUImageTextureOutput和GPUImageTextureInput類傻昙,可以從OpenGLES中導(dǎo)入或者導(dǎo)出紋理闺骚。使用這種方式的過程中要注意,待處理的紋理需要通過類似共享群組的東西在GPUImage自身的OpenGLES的context和其他context之間實(shí)現(xiàn)共享妆档。
Built-in filters
GPUImage庫中提供125種左右的內(nèi)建濾鏡僻爽。
這個(gè)我記得網(wǎng)上已經(jīng)有大神對(duì)文檔中有說明的濾鏡做了詳細(xì)的翻譯,之后會(huì)針對(duì)比較常用或者特殊的濾鏡做詳細(xì)說明贾惦,此處就不翻譯了胸梆。
Sample applications
又想起第一次接觸GPUImage時(shí),不看文檔直接download须板,run碰镜,完了完全不知道每個(gè)demo的具體實(shí)現(xiàn)內(nèi)容。所以建議初學(xué)者在接觸到新的三方庫或者源碼時(shí)习瑰,不要急著run绪颖,先看看文檔或者源碼注釋,可能會(huì)更好上手甜奄。
1.SimpleImageFilter:對(duì)一張靜態(tài)圖片進(jìn)行濾鏡操作柠横,保存到disk。
2.SimpleVideoFilter:馬賽克錄像课兄,滑桿可調(diào)整馬賽克顆粒大小牍氛。
3.SimpleVideoFileFilter:對(duì)disk中的視頻文件進(jìn)行虛化處理,并保存為另一個(gè)視頻文件第喳。
4.MultiViewFilterExample:攝像頭實(shí)時(shí)濾鏡效果糜俗,多個(gè)濾鏡疊加,并且其中兩個(gè)是自定義濾鏡曲饱。
5.FilterShowcase:GPUImage內(nèi)建濾鏡的全部展示悠抹,這個(gè)demo中的判斷語句優(yōu)點(diǎn)復(fù)雜。
6.BenchmarkSuite:GPUImage與基于CPU實(shí)現(xiàn)的圖片處理效果以及CoreImage做的處理效率比較扩淀。
7.CubeExample:說明GPUImage與OpenGLES渲染的相互關(guān)系楔敌。給攝像頭獲取到的每一幀內(nèi)容加上sepia(烏賊色效果?)的濾鏡并且顯示在一個(gè)立方體的表面驻谆,可以用手機(jī)旋轉(zhuǎn)立方體卵凑。立方體被渲染成一個(gè)texture-backed(沒懂)的frambuffer對(duì)象,再反饋給GPUImage進(jìn)行馬賽克處理后顯示。
7.ColorObjectTracking:待解釋竭沫。