更新 GPUImageFilterGroup 中的一个过滤器而不重绘所有过滤器
Update one filter in GPUImageFilterGroup without redraw all filters
我使用 GPUImageFilterGroup 对图像应用一些滤镜。所有 filters stable(所有参数不变),但 last filter 是 变量 (某些参数已更改)。
我需要在更改最后一个滤镜后重新绘制图像。
现在我在源 GPUImagePicture 上调用了 processImage,但是这个调用重绘了所有过滤器并且速度太慢了。
如何只重绘组中的最后一个过滤器?
我认为,我应该在绘制最后一个过滤器之前保存帧缓冲区的副本,并且当我更改了最后一个过滤器中的某些参数时,我应该使用保存的帧缓冲区来重绘最后一个过滤器。但是我找不到如何保存帧缓冲区的副本。
我已经通过子类化 GPUImageFilter 和 GPUImageFilterGroup 解决了这个问题。
在 GPUImageFilter 中,我重载了方法
- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex
<...>
[self renderToTextureWithVertices:imageVertices textureCoordinates:[[self class] textureCoordinatesForRotation:inputRotation]];
_bufferCallback(self);
[self informTargetsAboutNewFrameAtTime:frameTime];
<...>
在 GPUImageFilterGroup 中,我重载了方法:
- (void)addFilter:(GPUImageOutput<GPUImageInput> *)newFilter
{
NSParameterAssert([newFilter isKindOfClass: [FAEShiftFilterWithBackOutputBuffer class]]);
if ([newFilter isKindOfClass:[FAEShiftFilterWithBackOutputBuffer class]])
{
__weak typeof(self) selfWeak = self;
[(FAEShiftFilterWithBackOutputBuffer*)newFilter setOutputBufferCallback:^(FAEShiftFilterWithBackOutputBuffer *sender) {
__strong typeof(selfWeak) selfStrong = selfWeak;
if (selfStrong)
{
if (!selfStrong.lastFramebuffer)
{
if ([selfStrong isPreLastFilter:sender])
{
selfStrong.lastFramebuffer = [sender framebufferForOutput];
[selfStrong.lastFramebuffer lock];
}
}
}
}];
}
[super addFilter:newFilter];
}
此方法存储来自 preLast 过滤器的 outputFrameBuffer。
和方法:
- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex
{
if (self.filterCount > 1)
{
if (self.lastFramebuffer)
{
GPUImageFilter* lastFilter = (GPUImageFilter*)self.terminalFilter;
[lastFilter setInputFramebuffer:self.lastFramebuffer atIndex:0];
[lastFilter newFrameReadyAtTime:frameTime atIndex:textureIndex];
}
else
{
[super newFrameReadyAtTime:frameTime atIndex:textureIndex];
}
}
else
{
[super newFrameReadyAtTime:frameTime atIndex:textureIndex];
}
}
我还在 dealloc 和 forceProcessingAtSize 和 forceProcessingAtSizeRespectingAspectRatio 方法中重置了保存的帧缓冲区。
- (void)_clearLastFrameBuffer
{
if (_lastFramebuffer)
{
[_lastFramebuffer unlock];
_lastFramebuffer = nil;
}
}
我使用 GPUImageFilterGroup 对图像应用一些滤镜。所有 filters stable(所有参数不变),但 last filter 是 变量 (某些参数已更改)。
我需要在更改最后一个滤镜后重新绘制图像。
现在我在源 GPUImagePicture 上调用了 processImage,但是这个调用重绘了所有过滤器并且速度太慢了。
如何只重绘组中的最后一个过滤器?
我认为,我应该在绘制最后一个过滤器之前保存帧缓冲区的副本,并且当我更改了最后一个过滤器中的某些参数时,我应该使用保存的帧缓冲区来重绘最后一个过滤器。但是我找不到如何保存帧缓冲区的副本。
我已经通过子类化 GPUImageFilter 和 GPUImageFilterGroup 解决了这个问题。 在 GPUImageFilter 中,我重载了方法
- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex
<...>
[self renderToTextureWithVertices:imageVertices textureCoordinates:[[self class] textureCoordinatesForRotation:inputRotation]];
_bufferCallback(self);
[self informTargetsAboutNewFrameAtTime:frameTime];
<...>
在 GPUImageFilterGroup 中,我重载了方法:
- (void)addFilter:(GPUImageOutput<GPUImageInput> *)newFilter
{
NSParameterAssert([newFilter isKindOfClass: [FAEShiftFilterWithBackOutputBuffer class]]);
if ([newFilter isKindOfClass:[FAEShiftFilterWithBackOutputBuffer class]])
{
__weak typeof(self) selfWeak = self;
[(FAEShiftFilterWithBackOutputBuffer*)newFilter setOutputBufferCallback:^(FAEShiftFilterWithBackOutputBuffer *sender) {
__strong typeof(selfWeak) selfStrong = selfWeak;
if (selfStrong)
{
if (!selfStrong.lastFramebuffer)
{
if ([selfStrong isPreLastFilter:sender])
{
selfStrong.lastFramebuffer = [sender framebufferForOutput];
[selfStrong.lastFramebuffer lock];
}
}
}
}];
}
[super addFilter:newFilter];
}
此方法存储来自 preLast 过滤器的 outputFrameBuffer。 和方法:
- (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex
{
if (self.filterCount > 1)
{
if (self.lastFramebuffer)
{
GPUImageFilter* lastFilter = (GPUImageFilter*)self.terminalFilter;
[lastFilter setInputFramebuffer:self.lastFramebuffer atIndex:0];
[lastFilter newFrameReadyAtTime:frameTime atIndex:textureIndex];
}
else
{
[super newFrameReadyAtTime:frameTime atIndex:textureIndex];
}
}
else
{
[super newFrameReadyAtTime:frameTime atIndex:textureIndex];
}
}
我还在 dealloc 和 forceProcessingAtSize 和 forceProcessingAtSizeRespectingAspectRatio 方法中重置了保存的帧缓冲区。
- (void)_clearLastFrameBuffer
{
if (_lastFramebuffer)
{
[_lastFramebuffer unlock];
_lastFramebuffer = nil;
}
}