一. GPUImage 结构的介绍及根柢运用

1.GPUImage 的介绍

GPUImage是依据OpenGL ES的一套图画、视频处理开源结构,它里边供给了许多的滤镜,运用者能够经过这些滤镜的组合结束很好的作用,一起也很方便在原有基础上结束自界说的滤镜。对于大规模并行操作(如处理图画或实时视频帧),GPU具有比CPU更明显的功用优势。而 GPUImage 悉数滤镜是依据OpenGL Shader结束的,所以滤镜作用、图画处理是在GPU上实行的,处理功率比较高,在iPhone4及其以上手机,giti轮胎能够做到实时流转的作用。而且它躲藏了Objective-COpenGL ES API交互的复杂性。现在市面上的图画视频处理App,95%以上在运用GPUImage,所以学习它的运用及原理仍是很有必要的。objective c语法GPUImage 一起支elementanimation撑iOS跟Andorid途径,地址:iOS版别 Android版别 也支撑 Swift版别,本文首要介绍它的 OC 版别,中心类的功用以及原理跟 Andorid 版别是相通的。
iOS开发者运用办法:直接 CocaPods 集成:

pod 'GPUImage'

首要objective case来看下它的根柢结构图:iOS滤镜那些事儿 | 创作者训练营第二期

从这张图中咱们能够看到GPUelementaryImage的几个中开源阅览心类:GPU开源软件ImageOutput GPUImageFilte开源众包r GPUImageInput 协议 GPUImageFrameBuffer,接下来咱们重点阐明这几个类。

2.中心功用类阐明

GPUImageOutput

GPUImageOutput 是悉数滤镜输入源的基类,也便是滤镜链的起点,先看下他的继承联络:

iOS滤镜那些事儿 | 创作者训练营第二期
分别阐明一下这几种类型:

  • GPUImagePicture

经过图片来初始化开源软件,实开源阅览app下载装置质上是先将图片转化为 CGImageRef,然后将 CGImageRef 转化为纹路。

  • GPUImageVideoCamera:经过相机来初始化,本质是封装了AVCaptur开源矿工eVideoDataOutput来获取持续的视频流数据输出,在代理办法captureOutput:didOutputSampleBuffer:froobjective casemConnection:拿到 CMSampleBufferRef,elements翻译将其转化为纹路的进程。GPUImageStillCamera是 GPUImageVideoCamera 的子类,能够用它来完opengl怎样装置与装备毕摄影功用。
  • GPUImageUIElementgit指令:能够经过 UIView 或许 CALayer 来初始化。opengl和directx这个类能够用来结束在视频上增加文字水印的功用。
  • GPU开源我国ImageTextureInput:经过现已存在的纹路来初始化.
  • GPUImobjective caseageRawDataInputelementui:经过二objective complement进制数据初始化elementui,然后将二进制数据转化为纹路.
  • GPUImageMovie:经过本地的视频来初始化。首要经过 AVAssetReader 来逐帧读取视频,然后将帧数据转化为纹路gitlab
  • GPUImageFilter:比较特别,它既继承自 GPUImageOutput,又遵从element是什么牌子协议 GPUImageInput 协议,所以它既能够作为开源滤镜链的源头,又能够把烘托的纹路输出给遵从 GPUImageInput 协议的类。是滤镜的中心,后边会独自介绍。
中心功用与办法openglskia

梦想一下,一github永久回家地址个滤镜链的源头能做什么呢:

  1. 需求产出一个烘托政策,这个需求烘托的政策便是GPUImagelementtypeeFrameBuffer.几个关于frameBuffer的办法:
- (GitGPUImageFramebuffer *)framebuffe开源rForOutput开源阅览app下载装置;

这个办法能够获得开源我国当时正在烘托的frameBuffer

- (void)removeOutputFramebuffer;

这个办法用来移除当时烘objective clauses是什么意思中文托的frameBuffer

- (void)setobjective correlativeInputFramebufferForTarget:(id&lgithub永久回家地址t;GPUImageInput>)target atIndex:(NSInteger)inputTextureIndex;

这个办法的调用发生在当时output烘托结束后,需求奉告下一个receiver能够开始烘托的时分,把当时Output的Fram开源阅览app下载装置eBuffer传递给下一个Input,让它能够运elementary用这个FrameBuffer的作用进行烘托。

  1. Target的增加以及处理,用来生成整个FilterChelement-plusain.

GPUImageOutput 已然作为一个滤镜的源头,相对应的就得有接受者接受openglskia它输出element-plus的 FrameBuffer ,这些接受者便是Target,而且有可能有多个接受者。处理这些target的首要办法:

- (void)addTarget:(id<GPUImageInput>)newTarget;
- (void)addTarget:(id<GPUImageInput>)newTarget atTextureLocation:(NSInteger)开源textureLocation;

这两个addTagithub永久回家地址rget办法的作用都是将下一个结束了GPUImageInput协议的政策增加到FilterChain当中来.objective clauses是什么意思一旦增加到滤镜链后,在当时Outpugit教程t烘托结束后就会收到奉告,然后进行下一步的处理。

- (NSArrayobjective c言语*)targets;

每个Output都能够增加objective clauses是什么意思中文多个targeelement是什么牌子t,这个办法能够获取到当时Output悉数的target.element-plus

- (void)开源矿工removeTarget:(id<GPUImageInput>)targetToRemove;
- (void)removeAllTargets;

这两个办法的作用是将某一个或许悉数的target都移出FilterChain。当一个target被移出FilterChain之后,它将不会再收到任何git指令当时Output烘托结束的奉告。

  1. 获取开源阅览当时的GPUImageOutput对FrameBuffer的处理作用
- (CGImageRef)newCGImageFromCurrentlyProcessedOutput;
- (CGIma开源节流geRef)element是什么牌子newCGImageByFilteringCGImageelementtype:(CGImageRef)imageToFilter;
- (UIImage *)image开源阅览FromCurrentFramebuffer;
- (Uopengl三重缓冲IIm开源age *)imageFromopengl怎样晋级CurrentFramebufferWithOrientation:(UIImageOrientation)imageOrientatigithub永久回家地址on;
- (UIImage *)imageByFilteringImage:(UIImage *)imageToFil开源节流ter;
- (CGImageRef)newCGImageByFilteringImage:(UIImage *)imageToFilter;

其中最中心github的办法是newCGImageFromCurrentlyProcessedOutput,根柢上悉数的办法究竟都调用了这个办法。但是GPUImageOutpuopengl版别过低怎样办t并没有为这个办法供给默许的结束,而是供给了一个办法界说。详细的结束在它的两个重要的子类 GPUImageFilter 和 GPUIopengl怎样装置与装备mageFilterGroup 中。而实践上究竟调用的办法都在 GPUImageFiopengl和directxlteobjective c言语r 中结束了.

GPUImageInput协议

GPUImageInput 是一个协议,它界说了一个能够接纳 FrameBuffer 的 receiver 一切必要结束的根柢功用。结束这个协议的类可elements以作为烘托的结束运用。
结束了 GPUImageInput 接口的类:

iOS滤镜那些事儿 | 创作者训练营第二期
opengl和directx这几OpenGL个类进行阐明:

  • GPUImageMovieWriter:封装了 AVAssobjective clausesetWriter,能够逐帧从帧缓存的烘托作用中读取数据,究竟经过 AVAssetWriter 将视频文件保存到指定的途径。
  • GPUImageView:继承自 UIView,经过输入的纹element-plus理,实行一遍烘托流程。咱们一般运用它来呈现烘托作用。
  • GPUImaobjective complementgeTexturopengl是什么意思eOutput:它能够获取到输入的Framebuffer中的纹路政策.
  • GPUImageRawDataOutpElementut:经过 rawBytesForImage 特点,能够获取到当时输入纹路的二进制数据。
中心功用与办法:

能够作为滤镜链的结束。根柢功用首要包含:

  • 接纳 GPUmageOutput 的输出信息;
  • 接纳上一个GPUImageOutput烘托结束开源众包的奉告,而且结束自己的处理;
  1. 接纳openglskiaGPUmageOutput的输出信息对opengl烘托应办法:
- (void)sgit指令etInputFramebuffer:(GPUImag开源阅览eFramobjective correlativeebuffer *)newInputFramebuffer atInopengl烘托gpu怎样设置dex:(NSInteger)textureIndex;
- (NSInteger)nextAvailabelement什么意思中文leTextuobjective correlativereIndGitex;
- (voopengl和directxid)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex;
- (void)setInputRotation:(GPUImageRotaelementarytionMode)newInputRotation atIndex:(NSInteger)textureIndex;

依据这些办法能够看到,GPUImageInput 能够接纳的信息包含上一个Output输出的FopenglskiarameBuffer,FrameBuffer的size以及rotation。这些 textureIndex 都是为了供给个需求多个input的Filter预备的。
2. 接纳GPUImageOutput烘托结束的奉告对应办法:

- (void)elementarynewFrameReadyAtTime:(CMTime)frameTime at开源众包Index:(NSInteger)textureIndex;

上一个 GPUImageOutput 烘托结束后会奉告它悉数的 Target,能够参看下它在GPUIopenglskiamageFilter里边的结束。

GPUImageFrameBuffer

GPUImageFrame开源矿工Buffer 供给了在 GPUImageelement是什么牌子Output 和 GPUImageInput 进行gitee数据传递的gitlab前言。在整个烘托流程中,GPUImageFrameBuffer作为一个枢objective clause什么意思纽,将各个不同的元素串联起来;每个GPUImageFrameBuffer 都有一个自己的OpenGL Texture,每个 GPUImaelementtypegeOutput 都会输出一个 GPUImageFrameBuffer 政策,而每个 GPUImagegithubInput都结束了一个setInputgiteeFramebuffer:atIndex:办法,来接纳上一个Output处理完的纹路.

  • GPUImageFrameelementaryBuffer 的获取逻辑,是由GPUImageFrameBufferCache 进行处理的,需求时从BufferCache中获取,运用结束后,被BufferCache回收。Fraobjective clausesmeBuffer 的创立跟存储是需求消耗资源的,所以 GPUImage 为了尽量削减资源的消耗,会将运用结束的 FrameBgiteeuffer 存储在缓存中,每次经过 输入的纹路size 跟 TextureOptions 作为 key 从hash map 中获取。
GPUImageFilt开源er

GPUImageFilter 是整个GPUImage结构的中心,GPUImage所内置的100多种滤镜作用都继承于此类。例如咱们常常用到的一些滤开源软件镜:

  • GPUImageBrightnessFilter:亮度调整滤镜
  • GPUImageExpoobjective clausessureFilter:曝光调整滤镜
  • GPUImageContrastFilOpenGLter:对比度调整滤镜
  • GPUImageSaturationFilter:饱和度调整滤镜
  • GPUImageWhiteBalanceFilter:白平衡调整objective c言语滤镜
  • GPUImageColorInvertopengl版别过低怎样办Filter:回转图画的颜色
  • GPUImageCropFilter:将图画裁elementui剪到特定区域
  • GPUImageGaussianBlurFilter:可变半径高斯模糊
  • GPopengl是什么意思UImageSketchFilter:素描滤镜
  • GPUImageToonFilter:卡通作用
  • GPUImageDissolveBlendFilteobjective caser:两个图画的混合
  • GPUIelementarymageFilterPipeline : 链式组合滤镜

中心功用与办法:
  1. GPUImageFilter是giti是什么牌子GPUIobjective casemageOutput的子类,但是一起它也结束了GPUImelementary是什么意思ageInput协议。因而,它包含了一个Input和Output的悉数功用。既它能够接受一个element什么意思中文待烘托政策,烘托结束后持续传递给giti是什么牌子下一个结束G开源阅览PUImageInputobjective c言语协议的接受者。详细的办法调用咱们开源软件在下一末节的 滤镜底层源码剖析中elementary阐明。

  2. 供给依据不同的极点上色器(VertexShader)与片元上色器(F开源节流是什么意思是什么ragmentShader)来初始化烘托程序(GLProgram)的办法,但是整个烘托进程github永久回家地址是相同的,因而这个进程都被objective clause什么意思封装到了基类中;

- (id)initWithVertexShaderFromString:(NSString *)vertexShaderString fgithub中文官网网页ragmentShaderFromString:(NSString *)fragmentShaderString;
- (id)initWithFragmentShaderFromString:(NSString *)fragmentShaderString;
- (id)inielements翻译tWithFragmentShaderFromFile:(NSString *)fragmentShaderFilename;

这儿简单介绍一下这几个OPenGL的术语

  • VertexShader:极点上色器,OPenGL 接纳用户传递的几许数据(极点信息和几许图元),这些objective clauses是什么意思数据经过极点上色器后能够确认图形的形状以及方位。极点上色Git器是 OPenGL 烘托进程的第一个objective clauses上色element什么意思中文器。
  • 光栅化:opengles3.1扩展包是将图形的立体方位转换成在屏幕上闪现的像素片元的进程;
  • FragmentSh开源节流ader:对光栅化的像素点进行上色就要运用片元上色器。它是OPenGL烘托进程的究竟一个上色器。
  • GLProgrobjective clause什么意思am: OpenGL ES的program的面向政策封装,包含了VertexShader,FragmentShader的加载,program的link以及对attribute和uniform的获取和处理.

这儿首要是一些依据不同的上element什么意思中文色器进行创立Program的办法。

  1. 作为基类供给给子类能够进行掩盖giti轮胎的办法。

用一句话来总结GPUImageFilter的作用:便是用来接纳源图画(FrameBuffer),经过自界说开源众包的极点、片元上色器来烘托新的图画,并在制作结束后奉告照顾链的下一个政策。

3.GPUImage滤镜的运用

咱们先来看它的使用作用
iOS滤镜那些事儿 | 创作者训练营第二期iOS滤镜那些事儿 | 创作者训练营第二期

(1) 为图片增加滤镜

直接上代码:

   /**初始化滤镜源头*/
GPUImagePictu开源阅览re *imagePic = [[GPUImagePicture alloc] initWithImage:[element什么意思中文UIImage imageNameelement什么意思中文d:@"picOne.jpg"]]elementary;
/**创立滤镜*/
GPUImageGaussianBlurFilter *GitgaussianBlur = [[GPUImageGaussianBlurFilter alloc] init];
gau开源软件ssianBlur.blurRadiusInPixels = 10;
/**添element是什么牌子加接受者,即target*/
[imagePic addTarget:gaussi开源软件anBlur];
/**增加frameBUffer 计数防止被移除*/
[gaussianBluobjective c言语r useNextFrameForImageCapture];
/elements翻译**开始处理图片*/
[imagePic processImage]开源我国;
/**依据frameBuffer 获取图片*/
self.showImageView.image = [gaussianBlur imageFromCurrentFramebuffer];
流程阐明:
  • 运用图片初始化滤镜源头GPUImagePict开源是什么意思ure
  • 初始化滤镜作用GPUImageGaussianBlurFilter
  • 为当时滤镜源增加接纳者Target addTarget
  • useNextFrameForImageCapture:办法是防止帧缓存被移除,假设不调用这个办法会导致Framebuffer被移除,然后导致Crashelementary
  • 依据滤镜的烘托作用FrameBuffer导出图片[gaussianBlur imageFromCurrentFramebufelementsfer]
(2) 摄像头捕获视频流增加滤镜

中心代码:

- (void)setupCamera
{
//videoCamera
self.gpuVideoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPreset640x480 cameraPosition:AVCaptureDevicePositionBackobjective clauses是什么意思];
self.gpuVideoCamera.outputImageOrientatioopengl怎样晋级n = [[UIApplication sharedApplication] statusBarOrientation];
//Gopengl烘托gpu怎样设置PUImageView填充办法
self.gpuImageView.fillMode = kGPUImageFelementuiillModePre开源众包serveAspectRatioAndFill开源软件;objective c言语
//空白作用
GPgithub中文官网网页UImageFilter *clearFiltegithub永久回家地址r = [[开源众包GPUImageFilter alloc] ini开源t];
[sgiti是什么牌子elf.gpuVideoCamera addTarget:clearFilter];
[clearFilter addTargetgitee:self.gpuImagit教程geView];
//Start camera capturing, 里边封装的是AVFoundation的session的startRunning
[self.gpuVideoCamera startCameraCapt开源是什么意思ure];
}
#pragma mark - Action && Notification
- (IBAction)originalBtnDown:(id)sender {
/**先移除target*/
[s开源是什么意思elf.gpuVideoCamera removeAllTargets];
//空白作用
GPUImageFiltelementser *clearFilter = [[GPUImageFilter alloc] init];
[self.gpuVideoCamera addTarget:clearFilter];
[clearFilter addTarget:self.gpuImageView];
}
(3) 混合滤镜的运用

中心代码:

    GPUImageView *filterView = [[GPUopengl烘托gpu怎样设置ImageView alloc] initWiopengl和directxthFropengl烘托ame:self.view.frame];
filterView.center = self.view.center;
filterView.fillMode = kGPUImageFillModePrelement是什么牌子eserveAspectRatioAndFill;
[self.view addSubview:filterView];
/*初始化混合滤镜*/
filter = [[GPUImageDissolveBlendFilter alobjective clause什么意思loc] init];
/*Element设置滤镜elements翻译混合度*/
[(GPUImageDissgit教程olveBlendFilter *)filter setMix:0.5];
/*elementtype初始化视频输出源*/
NSURL *sampleURL = [[NSBundle mainBundle] URLForResopengl怎样装置与装备ource:@"IMG_4278" withExteobjective casension:@"MOV"];
movieFile = [[GPUelementary是什么意思ImageMovie alloc] initWithURL:OpenGLsampleURL];
movieFile.runBenchmark = Yopengles3.1扩展包ES;
movieFile.playAtActualSpeed = YES;
/*初始化摄像头输出源*/
videoCamera = [[GPUIgit教程mageVideoCamera alloc] initWithSessionPreset:AVCaptobjective c语法ureSessionPreset640x480 cameraPosition:AVCaptureDevicePositionBack];
videoCamera.out开源我国putImageOgitlabrientation = UIInterfaceOrientationPortrait;
NSString *pathToMovie = [NSHomeDirectory() stringByAppendingPathCopengl怎样晋级omponent:@"Docgit指令uments/Movie.m4vobjective c基础教程"];
unlinobjective clauses是什么意思k([pathToMovie UTF8elementary是什么意思String]);
NSURL *movieURL = [NSURelementsL fileURLWithPath:pathToMovie];
//开源矿工初始化接受者
movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:movieURL size:CGSizeMake(480.opengl怎样晋级0, 640.0)];
GPUImageFilter* progressFilter = [[GPUImageFilter alloc] init];
[movieFile addTarget:progresOpenGLsFilter];
//设置输出方向
[progressFilter setInputRoobjective clausestation:kGPUImag开源软件eRotateRight atIndex:0];
// 照顾链
[progressFilter addTarget:fiopengl版别过低怎样办lter];
[videoCamera addTarget:filter];
//设置音源
movieWriter.elementaryshouldPassthroobjective clauses是什么意思ughAudio = YES;
movieFile.audioEncodingTarget = movieWriter;
[movieFile enableopengl是什么意思SynchronielementaryzelementtypeedEncodingUsingMovieWriter:movieWriter];
// 闪现到界面opengl烘托
[filteGitr addTarget:filterView];
//增加到接纳者
[filter addTarget:movieobjective clauses是什么意思中文Writeobjective c基础教程r];
[videoCameopengl怎样装置与装备ra startCameraCapture];
[movieWrielements翻译ter startRe开源是什么意思cording];
[movieFile startProcessing];
/*写入结束后保存视频*/
__weak typeof(self) weakSelf = self;
[movieWriter setCompletionBlock:^{
_opengl版别过低怎样办_strong typeof(self) strongSelfelement什么意思中文 = weakSelf;
[strongSelf->filter removeTarget:strongSelf->movieWriter];开源是什么意思
[strongSelf-&objective c语法gt;movieWriter finishRecording];
/*依据movieU开源节流RL保存视频到本地*/
// ...
}];
流程阐明:
  • 混合滤的中心是GPUImageDi开源是什么意思ssolveBlendFilter的运用,它继承自GPUImageTwoInputElementFilter,它需求有两个输入源
  • 初始化两个输入源GPUImageVideoCameraGPUImageMovie
  • 增加输入源到DissolveBlendFilterobjective complement
  • 增加filter到输出数据源GPUImageobjective clause什么意思MovieWriter
(4) 为视频增加giti水印

中心代码:

    GPUImageView *filterView = [[GPUImageView alloc] initWithFrame:self.vobjective clauses是什么意思iew.frame];
self.view = filobjective caseterView;
// 混合滤镜初始化
filter = [[GPUImageDissolveBlendFilter alloc] init];
//混合度
[(GPUImageDOpenGLissolveBlendFilter *)filter setMix:0.5];
// 本地视频播映源
NSURL *sampleUobjective correlativeRL = [[NSBundle mainBundle] URLForResource:@"IMG_4278" withEgitixtension:@"MOV"];
AVAsset *asset =elementanimation [AVAsset assetWithURL:sampleelementary是什么意思Ugiti是什么牌子RL];
CGSize size = self.view.bounds.size;
//设置moive源头
mogithubvieFile = [[GPUImageMovigithube alloc] initWithAssElementet:asset];
movieFileelementui.runBenchopengl三重缓冲mark = YES;giti是什么牌子
movieFile.playAtActuopengl怎样装置与装备alSpeed = YES;
// 水印
UILabel *label = [[UILabel alloc] initWithFrame:Cobjective clausesGRectMake开源节流是什么意思是什么(100, 100, 100, 100)git指令];
label.text = @"我是水印";
lgiti轮胎abel.font = [UIFont systemFontOfSize:30];
label.tegit指令xtColor = [UIColor redColor];
[label sizeToFit];
UIImageopengl三重缓冲 *image = [UIImageElement imageNameopengl三重缓冲d:@"watermark.png"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:imaobjective clauses是什么意思ge];
UIView *subView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)];
subView.backgroundColor = [UIColor clearColor];
imageView.center = CGPoingithubtMake(giti是什么牌子subView.bounds.size.width / 2, subView.bounds.si开源是什么意思ze.height / 2);
[subViobjective caseew addSubview:imageVelement是什么牌子iew];
[subView addSubview:label];
//设置UI源头
GPUImaopengl是什么意思geUIElement *uielelementsement = [[GPUImageUIElement alloc] initWithView:subVgithub永久回家地址iew];
//开源节流是什么意思是什么GPUImageTranobjective clauses是什么意思中文sfopengl烘托ormFilter 动画的filter
NSString *pathToMovie = [NSHoobjective clauses是什么意思中文meDirectory() strgithub中文官网网页ingByAppendingPathComponent:@"Documents/Movie.m4v"];
unlink([pathToMovie UTF8String]);
NSURL *movieURL = [NSURL fileURLWithPath:pathToMovie];
//初始化接受者
movieWriter = [[GPUImageMovieWriter alloc] initWithMovieURL:elementanimationmobjective complementovieURL size:CGSielement什么意思中文zeMake(480.0, 640.0)]opengles3.1扩展包;
//为调整视频方向增加一个空白滤镜
GPUI开源矿工mageFilter* progressFilter = [[GPUImageFilter alloc] init];
[movieFile addTarget:progressFilter];
//设置方向
[progressFiltegitlabr setInputelementanimationRotation:kGPUImageRotateRight atIndex:0];
[progressFilter addTarget:filter];
[uielement addTarget:filter];
movieWriter.shouldPassthroughAudio = YES;
movieFilObjective-Ce.audioEncod开源代码网站githubingTarget = movieWriter;
[movieFile enableSynchronizedEncodingUsingMovieWriter:movieWriter];
// 闪现到界面
[filter addTarget:filt开源众包erView];
[filter addTarget:movieWriter];
//开始记elementui载
[movieWriter startRecording];
[movieFile startProcessing];
__weak typeof(self) weakS开源阅览elf = self;
//每一帧处理结束 大约30帧/秒
[progressFilter setFrameProcessingCompletiopengl怎样晋级onBlock:^(GPUImageOutput *output, CMTime time){
CGRecgithubt frame = imageView.frame;
frame.origin.x += 1;
frame.origin.y += 1;
imageView.frame = frame;
//更新UIElement
[uielement updateWithTimestamp:time];
}];
[moviobjective clause什么意思eWriter setCompletionBlock:^{
__strong typeof(self) strongSelf = weakSelf;
[strongSelf->filter removeTopengl怎样晋级arget:strongSe开源阅览app下载装置lf->movieWriter];
[strongSelf->movieWriter finishRecording];
/*依据movieURL保存视频到本地*/
// ...
}];
流程阐明:
  • 混合滤镜的中心是GPUImageOpenGLDissolveBlendFilter的运用,它继承自GPUImageTwoInputFilter,它需求有两个输入源
  • 初始elementtype化两个输入源GPUImageVideoCameraGPUImageUIElement
  • 其他同上
(5) 滤镜组的运用

中心代码

    //创立摄像头视图
GPU开源阅览app下载装置ImageView *filterView = [[GPUImageView aobjective caselloc]initWithFrame:self.view.bounds];elementui
//闪现办法充满整个边框
filterView.fillMode = kGPUImagGiteFillModePreservobjective clauses是什么意思eAspectRatioAndFill;
[self.vobjective clausesiew addSubview:filterView];
//初始化滤镜源
seGitlf.stillCamera = [[GPUImagegitiStopenglskiaillCamera alloc]initWithSessionPreset:AVCaptureSessionPgiti轮胎resetPhotopengl版别过低怎样办o cameraPosition:AVCaptureDevicePositionBack];
//输出图画旋转办法
self.stillCamera.outputImageOropengl是什么意思ientation = UIInterfaceOrientationPortrait;
//反色滤镜
GPUImageColorInvertgiti轮胎Filter *filter1 = [[GPUImageColorInvertFilter alloc]init];
//浮开源节流雕滤镜
GPUImageEmbossFilter *filter2 = [[GPUImageEmboobjective correlativessFilter alloc]init];
//GPelementuiUImageToonFilter *filter3 = [[GPgithub中文官网网页UImageToonFilter alloc] init];
GPUImageF开源ilterGroelement什么意思中文up *groupFilter = [[GPUImageFilterGroup alloc]init];
[groupFilter addFilter:filter1];
[groupFilter addFilter:filter2];
//[groupFilter addFilter:filter3];
[fopengl三重缓冲iltegiteer1 addTarobjective caseggiti轮胎et:filter2];
//[elementanimationfiltergit教程2 addTarget:filter3];
//elements翻译界说了一个变量来保存filter-ch开源阅览app下载装置ain上的究竟一个filter,后边保存图片时调用的办法里要用到。
self.lastFilter = filter2;
//设置第一个滤镜
groupFilter.initialFilters = @[filter1];
/opengl怎样装置与装备/设置究竟一个滤镜
groupFilter.teopengles3.1扩展包rminalFilter = filter2;
[self.stillobjective c基础教程Camera addTarge开源我国t:groupFilter];
[groupFilter addTarget:filterView];
//处理第一帧黑屏,音频缓冲区是在视频缓冲区之前写入的。
[self.stillCamera addAudioInputsAn开源是什么意思dOutputs];
[elementsself.view bringSubviewToFront:self.catchBtn];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)objective clauses是什么意思), dispatch_get_opengl三重缓冲main_queue(), ^{
//开始捕捉
[self.stillCamera startCObjective-CameraCapture];
});
流程阐明:
  • 混合giti是什么牌子滤的中心是GPUImageFOpenGLilterGroup的运用
  • 初始化多个滤镜而且增加到滤镜组
  • 设置Group的第一个以及究竟一个滤镜
  • 输出

二. GPUIObjective-Cmage 底层源码剖析

1.滤镜链加载流程剖析objective clauses是什么意思中文

objective c言语过上面的Demo比方咱们能够剖析滤镜链的运用element是什么牌子流程:

iOS滤镜那些事儿 | 创作者训练营第二期

接下来我github们以图片增加滤镜的比方剖析GPUImage的滤镜办法调用流程:

  • 运用图片初始化opengl是什么意思滤镜源头GPUImagePicture,调用办法:
- (id)initWithImage:(UIImage *)newImageSource;

这个办法里边又会调用

outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:pixelSizeToUseForTexture onlyTexture:YES];

这个办法最首要的作用element什么意思中文是依据图片的大小去GPUImageFramebufferCache中去获取一块 FrameBuffer,也便是outputFraopengl三重缓冲mebuffer

  • 滤镜的初始化,github永久回家地址依据其objective clause什么意思时自己的极点上色器以及片元上色器初始化滤镜,以及创立OPenGL ES的烘托程序 GLProgramobjective complement
  • 为滤镜源增加Target:- (void)addTarget:(id<GPUImageInput>)newTarget;. 在这个办法里边会调用

[seobjective clauses是什么意思lf sobjective clause什么意思etInputFramebufferForTarget:nopengl和directxewTarget atIndex:textureLocation];
究竟会调用[target setInputFramebuffer:[self framebufferForOutput] atIndex:iobjective clause什么意思nputTextureIndex];办法.这个办法最首要giti是什么牌子的作用是把当时Ogithub永久回家地址utput的输出 Framebuffer 传递给接受者.

  • - (void)useNextFrameFo开源rImageCapture;设置成员变量usingNextFrameForImageCapture = YES代表着输出的作用会被用于获取图画,所以在烘托的中心方giti轮胎
- (void)renderToTextureWithVertiobjective c语法ces:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)github永久回家地址textureCoordinates;

outputFramebuffer加锁,由于默许情况下,当下一个input烘托结束之后,就会开释这个 FrameBuffer。假设你需求对当时的Filobjective c言语ter的输出进行截图的话,则需求保留住这个 FrameBuffer。

  • 接下来调用方opengl怎样装置与装备[imagePiobjective complementc processI开源阅览app下载装置mage];: 开始进入滤elementary镜处objective case理流程,接着调用办法-(BOOL)processImageWithCompletionHandler:(elementtypevoid (^)(void))completion;在这个办法内部调用了Target的两个办法,进行OutputFrameBuffer的烘托与向下传递.
 [currentTarget setInputFramebuffer:outputFramebuffer atIndex:textureIndexOfTarget];
[currentTarget newFrameReadyAtTime:kCMTimeIndefinite atIndex:textuopengl是什么意思reIndexOfTargetgithub永久回家地址];

第一个办法的作用是获取从上个Output传递过来的 Framebuffer,并进行加锁操作。
第二个办法的效objective complement果是运用自身GLProgram进行烘托,而且调用- (void)informTargetsAboutNewFrameAtTime:(CMTime)frameTime;objective c基础教程把烘托作用向下一个结束GPUImageIobjective clauses是什么意思npgiti是什么牌子ut协议的滤镜传递。

  • [gausopengl烘托sianBlur imaobjective clauses是什么意思中文geFromCurrentFraobjective c基础教程mebuffer]; 办法:依据 Framebuffer 获取图片,里边调用- (CGImageRef)newCGImageFromCurreobjective clause什么意思ntlyPro开源阅览celement什么意思中文essedOutput 办法,结束图片获取以及开释GCD信号量。
if (dispatch_semaphoreopengl烘托_wait(imageCaptureSemopengl烘托aphore, convertedTimeout) != 0)
{
return N开源是什么意思ULL;
}

这儿信号量的作用是等待烘托结束。结束后走下面的获取图片流程。整个的办法调用流opengl烘托gpu怎样设置程能够参看下面的图片:

iOS滤镜那些事儿 | 创作者训练营第二期

2.滤镜烘托流程剖析

烘托开源我国是整个GPUImageFilter 的中心,在初始化办法中结束了OpenGL ES Program的创立好而且link成功了之后,咱们就能够运用这个Prgithubogram进行烘托了。整个烘托的进程发生在- (void)rendgithub中文官网网页erToTextureWithVerticgithub永久回家地址es:textureCoordinateelement是什么牌子s:中。咱们也借着解析这个办法来了解一下OpenGL ES的烘托进程:

  • [GPUImageContext setActiveShade开源rProgram:figithub中文官网网页ltobjective correlativeerProgram];: 将初始化后得到Progrobjective c言语m 上下文设置为默许的context,而且激活。调用的GPUImageContext办法
+ (void)setActiveShaderProgram:(GLProgramOpenGL *)shaderProgram;
{
GPUIopengl三重缓冲mageContext *sharedContext = [GPUImageContext sharedImageProcessingConElementtext];
[sharedContext setContextShaderProgram:shaderProgram];
}
  • 获取一个待烘托的GPUImageF开源节流rameBuffer,这个FrameBuffer 会依据输入纹路的尺度(inputTextureSize)以及纹路信息(outputTextureOptions) 去GPUImageFrameBufferCahe中获取。大致流程为:存在符合要求的Framebuffer就回来一个,没有就去创立。
  • 依据usingNextFrameForImageCgiti是什么牌子apture判别giti是什么牌子当时Framebuffer是否用于获取图片giti,假设是则进行加objective complement锁。
 if (usingNextFrameForImageCapture)
{ //将这个outputFrameBuffer进行lock。
[outputFramebuffer lock];
}
  • 将整个FrameBufopengl和directxfer的数据运用backgroundColor进Objective-C行清空:
glClearColor(opengl和directxbackgroundColorRed, backgroundColorGreen, backgroundCol开源代码网站githuborBlue, backgroundColorAlpha);
glClear(GL_COLOR_BUFFEgitiR_BIT);
  • 将上一个Output传递过来的FrameBuffer作为texture用来烘托:
glActiveTex开源节流ture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, [firstInputFramebuffer texture]);
glUnif开源阅览orm1i(filterInputTextureUniform, 2);
  • 将极点的方位信息以及极点的纹路坐标信息作为attrgiti是什么牌子ibutelements翻译e传递给GPU:
glVertexAttobjective caseribPointerobjective c言语(filterPositopengl和directxionAttribute, 2, GL_FLOAT, 0, 0, vertices);
glVertexAttribPointer(filterTextureopengl烘托CoordinategitiAttribute, 2, GL_FLOAT, 0, 0, textureCoordinates);
  • 进行烘托:
glDrawArrays(GL_TRIANGLE_STRIPgitlab, 0, 4);
  • 究竟将上一个GPUImageOutput传递过来的FrameBuffer使命现已结束,对其Git进行解锁开释:
[firstInputFramebuffer unlock];

整个烘托进程结束。

三. 自界说滤镜

1.怎样加载一个自界说滤镜

经过上面的学习咱们知道,elementanimationgithub永久回家地址镜的作用实践是依据不同的极点上色器以及片元上色器来结束的。自界说滤镜实践便是自界说这两种上色器。有两种办法来加载咱们的自界说滤镜

  • 自界说滤镜类,继承自GPUImageFilter,然后用字符串常量办法加载咱们的Shader代码例如:
NSString *const kGPUImageBrightnessFragmentShaderString = SHADER_STRING
(
varying highp vec2 textObjective-CureCoordina开源节流te;
uniform sampler2D inputImageTeopengl三重缓冲xture;
uniform lowp float bropengles3.1扩展包ightness;
void main()
{
lowp vec4 texturelements翻译eColor = texture2D(inputImageTexture, textureCoordinate);
gl_FragColor = vec4((textureColor.rgb + vec3(brightness)), textureColor.w);
}
);

然后依据elementaryGPUImageFilter供给的初始化办法objective clauses是什么意思中文进行加载。

- (id)initWithVertexS开源是什么意思haderFromString:(NSS开源tring *)vertexShaderString fragmentShaderFromString:(NSString *)opengl怎样晋级fragmentShaderString;
- (id)initWithFragmentShaderFromString:(NSString *)fraopenglskiagmentShaderString;
- (id)initWithFragmentShaderFromFile:开源节流(NSStringobjective c言语 *)fragmentShaderFilename;
  • 另一种办法objective clauses是什么意思:假设仅仅自界说FragmentShader,可所以将Shader语句封装为fsh结束的文件,然后调用下面办法进行加载
- (id)initWithFragmentShaderFromFile:(opengl烘托gpu怎样设置NSStriopengl怎样晋级ng *)fragmentShaderFilename;

2. 一些特别的自界说滤镜作用

iOS滤镜那些事儿 | 创作者训练营第二期
一些特别的滤镜作用,比方抖音的滤镜作用(闪白、魂灵出窍、颤抖、缩放、毛刺、昏厥等)能够查看我的GitHub.
关于自界说滤镜部分需求你对OPenGL ES、线性代数以及算法有基础的了解,而且熟悉GLSL上色言语,假设想进一步学习能够参看GLSL的官方快速入门辅导OpenGL ES,咱们这篇文章不在涉及。

四. 总结

这篇文章首要是介绍了GPUImage的运用、滤镜链加载流程、烘托逻辑,还有一些模块未涉及到,比方GLProgram的创立、lOpenGLink进程,GPUImageMovieComposition视频修正模块,滤镜的自objective clauses是什么意思中文界说流程opengl烘托gpu怎样设置等,需求感兴趣的同学自己探求。

1.进一步学习需求掌握的内容

The OpenGL Shading Languageopengl怎样晋级
Gobjective clause什么意思LSL内建的函数介绍

2.一些参看引用

github.com/BradLarson/…
www.khronos.org/opengles/sd…
www.jianshu.com/u/8367278ff…