回顧
解析(一)
解析(二)
解析(三)
這次介紹的GPUImageContext
、GPUImageFramebufferCache
和GPUImagePicture
缸濒。
GPUImageContext
GPUImageContext是GPUImage對(duì)OpenGL ES上下文的封裝酵使,添加了GPUImage相關(guān)的上下文驾凶,比如說(shuō)Program的使用緩存浊洞,處理隊(duì)列藻丢,CV紋理緩存等。
1杨帽、屬性介紹
contextQueue
統(tǒng)一處理隊(duì)列
currentShaderProgram
正在使用的program
context
OpenGL ES的上下文
coreVideoTextureCache
CV紋理緩存
framebufferCache
GPUImageBuffer緩存
shaderProgramCache
Program的緩存
shaderProgramUsageHistory
Program的使用歷史
2漓穿、方法介紹
useAsCurrentContext()
在useAsCurrentContext設(shè)置當(dāng)前上下文的時(shí)候,會(huì)先判斷上下文是否是當(dāng)前context注盈,不是再設(shè)置(為了避免上下文切換的性能消耗晃危,即使設(shè)置的上下文是同一個(gè)上下文也會(huì)消耗性能)sizeThatFitsWithinATextureForSize()
會(huì)調(diào)整紋理大小,如果超過(guò)最大的紋理老客,會(huì)調(diào)整為不超過(guò)最大的紋理寬高僚饭。(GLProgram*)programForVertexShaderString:fragmentShaderString:;
shaderProgramCache 是program的緩存,由頂點(diǎn)shader和片元shader字符串拼接起來(lái)做key胧砰。- (void)useSharegroup:(EAGLSharegroup *)sharegroup;
EAGLSharegroup類(lèi)管理一個(gè)或者多個(gè)EAGLContext的OpenGLES資源鳍鸵;這個(gè)是一個(gè)封閉的類(lèi),沒(méi)有開(kāi)發(fā)者API尉间。負(fù)責(zé)管理紋理緩存偿乖、頂點(diǎn)緩存、幀緩存哲嘲、顏色緩存贪薪。(textures, buffers, framebuffers, and render buffers)- (EAGLContext *)context;
返回OpenGL ES2.0的上下文,同時(shí)設(shè)置glDisable(GL_DEPTH_TEST);
撤蚊,圖像處理管道默認(rèn)不允許使用深度緩存古掏。
GPUImageFramebufferCache
GPUImageFramebufferCache是GPUImageFrameBuffer的管理類(lèi)
1、屬性介紹
CacheframebufferCache
緩存字典
framebufferTypeCounts
緩存數(shù)量字典
activeImageCaptureList
正在讀取Image數(shù)據(jù)的GPUImageFrameBuffer列表
framebufferCacheQueue
緩存隊(duì)列
2侦啸、方法介紹
- (NSString *)hashForSize: textureOptions:onlyTexture:;
根據(jù)size槽唾、textureOptions和onlyTexture,創(chuàng)建緩存字符串光涂。
緩存字符串+當(dāng)前緩存數(shù)量形成framebufferCache緩存的key庞萍。
如果找不到framebufferCache對(duì)應(yīng)的數(shù)量,會(huì)創(chuàng)建新的緩存忘闻。- (void)returnFramebufferToCache:;
回收緩存钝计。根據(jù)size、textureOptions和onlyTexture齐佳,創(chuàng)建緩存字符串私恬,緩存字符串+當(dāng)前緩存數(shù)量形成framebufferCache緩存的key。(之所以會(huì)加上數(shù)量炼吴,是因?yàn)榫彺孀址晃ㄒ唬?/p>- (void)addFramebufferToActiveImageCaptureList:;
- (void)removeFramebufferFromActiveImageCaptureList:
這兩個(gè)方法主要用于本鸣,當(dāng)newCGImageFromFramebufferContents()
讀取幀緩存圖像數(shù)據(jù)時(shí),保持GPUImageFramebuffer的引用硅蹦。并且讀取完數(shù)據(jù)后荣德,在dataProviderUnlockCallback()
方法釋放闷煤。
GPUImagePicture
GPUImagePicture是PGUImage的圖像處理類(lèi),繼承GPUImageOutput涮瞻,一般作為響應(yīng)鏈的源頭鲤拿。
1、屬性介紹
pixelSizeOfImage 圖像的像素大小署咽。
hasProcessedImage 圖像是否已處理近顷。
imageUpdateSemaphore 圖像處理的GCD信號(hào)量。
2艇抠、方法介紹
- (id)initWithCGImage:smoothlyScaleOutput:
用源圖像newImageSource和是否采用mipmaps來(lái)初始化GPUImagePicture幕庐。
如果圖像大小超過(guò)OpenGL ES最大紋理寬高久锥,或者使用mipmaps家淤,或者圖像數(shù)據(jù)是浮點(diǎn)型、顏色空間不對(duì)等都會(huì)采用CoreGraphics重新繪制圖像瑟由。
然后通過(guò)glTexImage2D把圖像數(shù)據(jù)發(fā)送給GPU絮重,最后釋放掉CPU的圖像數(shù)據(jù)。- (BOOL)processImageWithCompletionHandler:;
通知targets處理圖像歹苦,并在完成后調(diào)用complete代碼塊青伤。在處理開(kāi)始時(shí),會(huì)標(biāo)記hasProcessedImage為YES殴瘦,并調(diào)用dispatch_semaphore_wait()
狠角,確定上次處理已經(jīng)完成,否則取消這次處理蚪腋。
-
- (void)addTarget: atTextureLocation:;
添加target到響應(yīng)鏈丰歌。如果hasProcessedImage為YES,表示圖像已經(jīng)處理完畢屉凯,直接設(shè)置targets的InputSize立帖,并調(diào)用newFrameReadyAtTime()
通知target。
DEMO
用GPUImagePicture處理源圖像悠砚,用GPUImageTiltShiftFilter處理模糊效果晓勇,用GPUImageView顯示。
效果展示
核心代碼
將GPUImageView設(shè)置為self.view灌旧,根據(jù)face.png绑咱,設(shè)置GPUImagePicture,然后添加GPUImageTiltShiftFilter到響應(yīng)鏈枢泰,再把GPUImageView作為響應(yīng)鏈的終點(diǎn)描融,最后調(diào)用processImage,開(kāi)始處理圖像宗苍。
GPUImageView *primaryView = [[GPUImageView alloc] initWithFrame:self.view.frame];
self.view = primaryView;
UIImage *inputImage = [UIImage imageNamed:@"face.png"];
_sourcePicture = [[GPUImagePicture alloc] initWithImage:inputImage];
_sepiaFilter = [[GPUImageTiltShiftFilter alloc] init];
_sepiaFilter.blurRadiusInPixels = 40.0;
[_sepiaFilter forceProcessingAtSize:primaryView.sizeInPixels];
[_sourcePicture addTarget:_sepiaFilter];
[_sepiaFilter addTarget:primaryView];
[_sourcePicture processImage];
總結(jié)
最近因?yàn)橹辈ビ脩?hù)增長(zhǎng)太快稼稿,忙著優(yōu)化原來(lái)的邏輯薄榛,研讀源代碼的時(shí)間變少。
同時(shí)為了寫(xiě)這篇文章让歼,查了一些關(guān)于圖像資料敞恋,末尾附上。
下一篇文章可能會(huì)介紹今年大火的直播APP的一種速成方案谋右,也可能會(huì)是GPUImageMovie的介紹硬猫。
喜歡的點(diǎn)一下關(guān)注,不迷路改执。
Mipmap紋理技術(shù)是目前解決紋理分辨率與視點(diǎn)距離關(guān)系的最有效途徑,它會(huì)先將圖片壓縮成很多逐漸縮小的圖片,例如一張6464的圖片,會(huì)產(chǎn)生6464,3232,1616,88,44,22,11的7張圖片,當(dāng)屏幕上需要繪制像素點(diǎn)為2020 時(shí)啸蜜,程序只是利用 3232 和 1616 這兩張圖片來(lái)計(jì)算出即將顯示為 2020 大小的一個(gè)圖片,這比單獨(dú)利用 32*32 的那張?jiān)计?jì)算出來(lái)的圖片效果要好得多辈挂,速度也更快.
kCGImageAlphaLast:alpha 分量存儲(chǔ)在每個(gè)像素中的低位衬横,如RGBA。
kCGImageAlphaFirst:alpha 分量存儲(chǔ)在每個(gè)像素中的高位终蒂,如ARGB蜂林。
kCGImageAlphaPremultipliedLast:alpha 分量存儲(chǔ)在每個(gè)像素中的低位,同時(shí)顏色分量已經(jīng)乘以了 alpha 值拇泣。
kCGImageAlphaPremultipliedFirst:alpha 分量存儲(chǔ)在每個(gè)像素中的高位噪叙,同時(shí)顏色分量已經(jīng)乘以了 alpha 值。
kCGImageAlphaNoneSkipLast:沒(méi)有 alpha 分量霉翔。如果像素的總大小大于顏色空間中顏色分量數(shù)目所需要的空間睁蕾,則低位將被忽略。
kCGImageAlphaNoneSkipFirst:沒(méi)有 alpha 分量债朵。如果像素的總大小大于顏色空間中顏色分量數(shù)目所需要的空間子眶,則高位將被忽略。