GPUImage源码解读(九)

GPUImageUIElement

与GPUImagePicture类似可以作为响应链源。与GPUImagePicture不同的是,它的数据不是来自图片,而是来自于UIView或CALayer的渲染结果,类似于对UIView或CALayer截图。GPUImageUIElement继承自GPUImageOutput,从而可以知道它能够作为输出,由于它没有实现GPUImageInput协议,不能处理输入

  • 初始化方法

- (id)initWithView:(UIView *)inputView;
- (id)initWithLayer:(CALayer *)inputLayer;

通过UIView或CALayer进行初始化,初始化的过程中调用 [layer renderInContext:imageContext] 进行渲染,渲染后便生成纹理对象。

// 带时间的更新方法
- (void)updateWithTimestamp:(CMTime)frameTime;
{
[GPUImageContext useImageProcessingContext];
//相素大小
CGSize layerPixelSize = [self layerSizeInPixels];
//创建数据内存空间
GLubyte *imageData = (GLubyte *) calloc(1, (int)layerPixelSize.width * (int)layerPixelSize.height * 4);
//使用RGB模式的颜色空间
CGColorSpaceRef genericRGBColorspace = CGColorSpaceCreateDeviceRGB();
//位图
CGContextRef imageContext = CGBitmapContextCreate(imageData, (int)layerPixelSize.width, (int)layerPixelSize.height, 8, (int)layerPixelSize.width * 4, genericRGBColorspace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
// CGContextRotateCTM(imageContext, M_PI_2);
// 矩形Y轴正方向平移layerPixelSize.height
CGContextTranslateCTM(imageContext, 0.0f, layerPixelSize.height);
CGContextScaleCTM(imageContext, layer.contentsScale, -layer.contentsScale);
// CGContextSetBlendMode(imageContext, kCGBlendModeCopy); // From Technical Q&A QA1708: http://developer.apple.com/library/ios/#qa/qa1708/_index.html
[layer renderInContext:imageContext];
CGContextRelease(imageContext);
CGColorSpaceRelease(genericRGBColorspace);
// TODO: This may not work
outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:layerPixelSize textureOptions:self.outputTextureOptions onlyTexture:YES];
glBindTexture(GL_TEXTURE_2D, [outputFramebuffer texture]);
// no need to use self.outputTextureOptions here, we always need these texture options
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)layerPixelSize.width, (int)layerPixelSize.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, imageData);
//析构数据
free(imageData);
for (id<GPUImageInput> currentTarget in targets)
{
if (currentTarget != self.targetToIgnoreForUpdates)
{
NSInteger indexOfObject = [targets indexOfObject:currentTarget];
NSInteger textureIndexOfTarget = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue];
[currentTarget setInputSize:layerPixelSize atIndex:textureIndexOfTarget];
[currentTarget newFrameReadyAtTime:frameTime atIndex:textureIndexOfTarget];
}
}
}
  • 其它方法

- (CGSize)layerSizeInPixels;
- (void)update;
- (void)updateUsingCurrentTime;
// 获取像素大小
- (CGSize)layerSizeInPixels;
{
CGSize pointSize = layer.bounds.size;
return CGSizeMake(layer.contentsScale * pointSize.width, layer.contentsScale * pointSize.height);
}
// 更新方法
- (void)update;
{
[self updateWithTimestamp:kCMTimeIndefinite];
}