GPUImageOutput -> (GPUImageFilter : GPUImageOutput <GPUImageInput> ) -> (GPUImageFilter : GPUImageOutput <GPUImageInput> ) -> (GPUImageFilter : GPUImageOutput <GPUImageInput> ) -> (GPUImageView <GPUImageInput>)
[[GPUImagePicture alloc] initWithImage:inputImage] 时候会生成一个 outputFramebuffer;
[sourcePicture addTarget:filter1]; -> [sourcePicture setInputFramebufferForTarget:newTarget atIndex:textureLocation]; -> [filter1 setInputFramebuffer:outputFramebuffer atIndex:inputTextureIndex]; 即会把 filter1 添加到 sourcePicture.targets 数组中, 并且设置 filter1.firstInputFramebuffer = sourcePicture.outputFramebuffer
[sourcePicture processImage] 函数的流程
当遍历到的 target 为 GPUImageView 时候, 调用 GPUImageView的newFrameReadyAtTime:atIndex 方法, 在这个方法中, 直接将 inputFramebufferForDisplay的纹理纹绘制到当前的帧缓冲区中,并且将当前的帧缓冲显示到屏幕上;
UIImage *inputImage = [UIImage imageNamed:@"gyy"];
GPUImagePicture *sourcePicture = [[GPUImagePicture alloc] initWithImage:inputImage];
GPUImageBrightnessFilter *filter1 = [[GPUImageBrightnessFilter alloc] init];
GPUImageSepiaFilter *filter2 = [[GPUImageSepiaFilter alloc] init];
[sourcePicture addTarget:filter1];
[filter1 addTarget:filter2];
[filter2 addTarget:self.imageView];
[sourcePicture processImage];
self.valueChanged = ^(UISlider *slider) {
CGFloat midpoint = [(UISlider *)slider value];
filter2.intensity = midpoint;
filter1.brightness = midpoint;
[sourcePicture processImage];
};
GLProgram
GLProgram 是对于 program 的封装就, 这里边包括了 program 的编译, 链接和属性赋值, 注意这里有个initialized 属性, 只有当 programe link 过了,这个 initialized 的值才会为 YES;
GPUImageContext
对于 context 和 context 的各种操作的封装, 包括了 context, shaderProgramCache(字典, 是GLProgram 的缓存, 每次去 program 时, 先去shaderProgramCache中取 ,取到就使用, 没有取到就创建.) framebufferCache(GPUImageFramebufferCache 是对GPUImageFramebuffer 的缓存封装)
GPUImageFramebufferCache
对于 GPUImageFramebuffer 的缓存的封装, 用 texture 的属性和framebuffer 的 size作为 key, GPUImageFramebuffer 作为 value;
GPUImageFramebuffer
对于 framebuffer 的封装. 初始化时候需要传入一个参数 onlyGenerateTexture, 如果 onlyGenerateTexture = YES, 则只是生成一个 framebuffer, 并设置texture 的一些通用属性, 如果 onlyGenerateTexture = NO, 那么, 就会生成 framebuffer 的同时, 会生成一个 texture 纹理, 并且纹理会绑定到生成的 framebuffer 中; 还可以将当前的帧缓冲中的纹理转化为 UIImage; renderTarget (当前帧缓冲区的数据, 转换成 CVPixelBufferRef 的数据)
// - 创建一个 CVPixelBuffer, 将最终的像素数据写到 renderTarget 中 由CVPixelBufferCreate()函数生成了一个CVPixelBufferRef对象,该对象作为像素数据的载体,最终由CVOpenGLESTextureCacheCreateTextureFromImage()函数传递给opengl es
CVReturn err = CVPixelBufferCreate(kCFAllocatorDefault, (int)_size.width, (int)_size.height, kCVPixelFormatType_32BGRA, attrs, &renderTarget);
// - 根据 renderTarget 中的像素数据, 生成一个纹理 id
/* renderTarget像素数据传给opengl es,类似于相当于glTexImage2D(),当 然renderTarget中数据可以是由CVPixelBufferCreate()创建的默认值都是0的像素数据,也可以是具体的像素数据*/
err = CVOpenGLESTextureCacheCreateTextureFromImage (kCFAllocatorDefault, coreVideoTextureCache, renderTarget,
NULL, // texture attributes
GL_TEXTURE_2D,
_textureOptions.internalFormat, // opengl format
(int)_size.width,
(int)_size.height,
_textureOptions.format, // native iOS format
_textureOptions.type,
0,
&renderTexture);
// - 将纹理附加到帧缓存上, 以后获取当前的帧缓冲的纹理, 实际上就是获取使用着色器程序后最终存储在帧缓冲的结果.在 GPUImage 中; glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 会根据 shader 绘制数据到 当前的outputFramebufferCurrent上; 每个 filterCurrent 都是用上一个 filterLast 的 outputFramebufferLast 的 纹理, 作为输入纹理, 然后根据当前的shader 将outputFramebufferLast的纹理绘制到当前的帧缓冲 outputFramebufferCurrent上的;
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _texture, 0);
/** 创建一个帧缓冲的纹理 (和创建普通的纹理对象一样, 只不过最后一个参数不是图片数据, 而是 NULL) */
glTexImage2D(GL_TEXTURE_2D, 0, _textureOptions.internalFormat, (int)_size.width, (int)_size.height, 0, _textureOptions.format, _textureOptions.type, NULL);
GPUImageInput
是一个协议, 遵守这个协议的类代表可以作为源数据的输入, 输入的是 GPUImageFramebuffer
// - 准备下一个要使用的帧
- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex;
// 设置输入的帧缓冲对象以及纹理索引
- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)textureIndex;
GPUImageOutput
表示该类可以作为源数据的输出, 输入出的 GPUImageFramebuffer
关键代码调用流程
// - 从当前的帧缓冲中获取图片
- (UIImage *)imageFromCurrentFramebufferWithOrientation:(UIImageOrientation)imageOrientation;
// - 添加 target
- (void)addTarget:(id<GPUImageInput>)newTarget;
--> - (void)addTarget:(id<GPUImageInput>)newTarget atTextureLocation:(NSInteger)textureLocation;
-->[self setInputFramebufferForTarget:newTarget atIndex:textureLocation];
--> [target setInputFramebuffer:[self framebufferForOutput] atIndex:inputTextureIndex];
GPUImageFilter
继承自 GPUImageOutput 并且遵守 GPUImageInput 协议; 所以 GPUImageFilter 可以作为输入, 也可以作为输出, 这就是链式编程实现的关键
// - 赋值firstInputFramebuffer
- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)textureIndex;
// - 准备下一个要使用的帧
- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex;
// - 生成 outputFramebuffer, 并将 firstInputFramebuffer 的纹理作为输入,结合 shader 绘制到 outputFramebuffer 的帧缓冲中;
--> - (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates
// - 遍历 self.targets, 设置 target.firstInputFramebuffer = outputFramebuffer;然后 调用 target 的 newFrameReadyAtTime:atIndex:方法;
--> - (void)informTargetsAboutNewFrameAtTime:(CMTime)frameTime;
GPUImagePicture
继承自 GPUImageOutput, 封装了静态图片; 将图片转为纹理并且绑定到outputFramebuffer.texture
// - 生成 outputFramebuffer, 将图片数据转为纹理, 绘制到outputFramebuffer的帧缓冲区中.
- (id)initWithCGImage:(CGImageRef)newImageSource smoothlyScaleOutput:(BOOL)smoothlyScaleOutput removePremultiplication:(BOOL)removePremultiplication;
// - 同 GPUImageOutput 的方法调用
- (void)addTarget:(id<GPUImageInput>)newTarget;
// - 处理数据
- (void)processImage;
--> - (BOOL)processImageWithCompletionHandler:(void (^)(void))completion;
// - 同 GPUImageFilter 的 setInputFramebuffer:atIndex: 和 newFrameReadyAtTime:的方法一样
--> [currentTarget setInputFramebuffer:outputFramebuffer atIndex:textureIndexOfTarget];
--> [currentTarget newFrameReadyAtTime:currentTime atIndex:textureIndexOfTarget];
GPUImageUIElement
继承自 GPUImageOutput, 将 view 转为 image 数据;
// - 将 view 转为 image 数据; 生成 outputFramebuffer中, 将图片转为纹理并且绑定到 outputFramebuffer.texture
- (void)update;
// - 调用 target 的 newFrameReadyAtTime:fatIndex:的方法
--> [currentTarget newFrameReadyAtTime:frameTime atIndex:textureIndexOfTarget];
GPUImageRawDataInput 和 GPUImageTextureInput 内部实现和 GPUImagePicture 相似
GPUImageVideoCamera
继承自 GPUImageOutput, 封装了相机的初始化, 视频的捕捉, 每次捕捉到一帧画面, 就将画面绘制到当前的这缓冲区中, 并且将 outputFramebuffer 传递给下一个 target 作为 target 的 firstInputFramebuffer;
// - 捕捉到每帧的数据的回调
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
// - 处理每一帧的视频数据
--> - (void)processVideoSampleBuffer:(CMSampleBufferRef)sampleBuffer;
// - 生成 outputFramebuffer, 并将 帧数据绘制到 outputFramebuffer的 帧缓冲区中
--> - (void)convertYUVToRGBOutput
// - 通知 self.targets 中的 target, 并设置 target.firstInputFramebuffer = self.outputFramebuffer;
--> - (void)updateTargetsForVideoCameraUsingCacheTextureAtWidth:(int)bufferWidth height:(int)bufferHeight time:(CMTime)currentTime;
--> [currentTarget setInputFramebuffer:outputFramebuffer atIndex:textureIndexOfTarget];
--> [currentTarget newFrameReadyAtTime:currentTime atIndex:textureIndexOfTarget];
GPUImageStillCamera
继承自 GPUImageVideoCamera, 封装了拍照的功能;
// - 将 摄像头捕捉到的数据转为 CVImageBufferRef, 之后将 CVImageBufferRef, 传递给父类的 - (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection; 方法, 之后调用 GPUImageOutput 的 - (UIImage *)imageFromCurrentFramebufferWithOrientation:(UIImageOrientation)imageOrientation;方法, 返回一个图片
- (void)capturePhotoProcessedUpToFilter:(GPUImageOutput<GPUImageInput> *)finalFilterInChain withImageOnGPUHandler:(void (^)(NSError *error))block
GPUImageMovie
继承自 GPUImageOutput, 用于给视频添加滤镜, 可以传入 AVAsset 或者 AVPlayerItem; 具体处理视频的实现和 GPUImageVideoCamera 基本相同
GPUImageFilterGroup
继承自 GPUImageOutput, 并且遵守 GPUImageInput 协议
// - 记录所有的 filter
- (void)addFilter:(GPUImageOutput<GPUImageInput> *)newFilter;
// - 给_terminalFilter 设置 _terminalFilter.firstInputFramebuffer = newTarget.outputFramebuffer; 这里需要每次加入一个新的 target 时候, 设置 _terminalFilter = newFilter;
- (void)addTarget:(id<GPUImageInput>)newTarget;
--> [_terminalFilter addTarget:newTarget atTextureLocation:textureLocation];
// - 设置 initialFilters[0].firstInputFramebuffer = newTarget.outputFramebuffer; [picture addTarget:self.myFilterGroup]; 时候内部会调用这个函数;
- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)textureIndex;
--> [initialFilters[0] setInputFramebuffer:newInputFramebuffer atIndex:textureIndex];
// - 调用 initialFilters[0] 的 newFrameReadyAtTime:frameTimeatIndex:函数 来实现链式编程 调用 [picture processImage]; 时候会调用这个函数;
- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex;
--> [initialFilters[0] newFrameReadyAtTime:frameTime atIndex:textureIndex];
GPUImageMovieWriter
遵守 GPUImageInput 协议, 主要用来将捕捉到的视频帧数据保存到本地;
// - firstInputFramebuffer = newInputFramebuffer [filter addTarget:movieWriter]; 时候调用
- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)textureIndex;
// - 采集到的每一帧的数据, 都会调用这个方法
- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex;
// - 调用 createDataFBO, 将 inputFramebufferToUse 的纹理绘制到当前的当前的帧缓冲中;
--> - (void)renderAtInternalSizeUsingFramebuffer:(GPUImageFramebuffer *)inputFramebufferToUse;
// - 生成 framebuffer, 并且将生成的纹理绑定到帧缓冲中; 同时将当前帧缓冲中的数据,生成CVPixelBufferRef;
--> - (void)createDataFBO;
--> 调用 write()这个 block, 将 CVPixelBufferRef 写入到本地;
GPUImageView
遵守 GPUImageInput 协议 用来将绘制的结果显示到屏幕上.
// - inputFramebufferForDisplay = newInputFramebuffer; 保存传入的 framebuffer
- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)textureIndex;
// - 将 inputFramebufferForDisplay 的纹理绘制到当前的纹理缓冲区,并且将绘制的结果显示到屏幕上
- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex;
GPUImageRawDataOutput 和 GPUImageTextureOutput 将输入的帧缓冲转为原始数据或者纹理;
GPUImageTwoInputFilter GPUImageThreeInputFilter GPUImageFourInputFilter 基本相似, 就是在 GPUImageFilter 的基础上 增加了 secondInputFramebuffer, thirdInputFramebuffer, fourthInputFramebuffer, 先是在 setInputFramebuffer:atIndex: 中记录 secondInputFramebuffer, thirdInputFramebuffer, fourthInputFramebuffer, , 然后在 renderToTextureWithVertices:textureCoordinates: 函数中 激活这些 inputFramebuffer 的 texture; 然后将结果绘制到 outputFramebuffer 的帧缓冲区中
// - 关键函数
- (void)setInputFramebuffer:(GPUImageFramebuffer *)newInputFramebuffer atIndex:(NSInteger)textureIndex;
- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates;
GPUImageTwoPassFilter
GPUImageTwoPassFilter 继承自 GPUImageFilter , 这个类多了个 secondOutputFramebuffer 和 secondFilterProgram , 它的作用是 将 firstInputFramebuffer 结合 filterProgram 绘制到 outputFramebuffer 的帧缓冲区中, 然后 结合 secondFilterProgram 和 outputFramebuffer 的纹理, 将最后结果绘制到 secondOutputFramebuffer 中;
// - 关键函数
- (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates;
GPUImageTwoPassTextureSamplingFilter
GPUImage3x3TextureSamplingFilter
GPUImageTwoInputCrossTextureSamplingFilter
GPUImageBuffer
(以上几个看了下源码 没看懂干啥用的, 先留着)
项目地址(加注释)