GPUImage API 文档之GPUImagePicture类
GPUImagePicture类静态图像处理操作,它可以是需要处理的静态图像,也可以是一张作为纹理使用的图片,调用向它发送processImage消息,进行图像滤镜处理。
方法
- (id)initWithURL:(NSURL *)url
说明:使用指定url的图片来初始化GPUImagePicture
- (id)initWithImage:(UIImage *)newImageSource
说明:使用指定的UIImage对象来初始化GPUImagePicture
- (id)initWithCGImage:(CGImageRef)newImageSource
说明:使用指定的CGImageRef对象来初始化GPUImagePicture
- (id)initWithImage:(UIImage *)newImageSource smoothlyScaleOutput:(BOOL)smoothlyScaleOutput
说明:使用指定的UIImage对象来初始化GPUImagePicture,是否按比例调整输入图像的尺寸
- (void)processImage
说明:进行图像处理实际操作。
- (BOOL)processImageWithCompletionHandler:(void (^)(void))completion
说明:进行图像处理实际的操作,completion为当处理结束执行的操作。
完整代码
#import <UIKit/UIKit.h>
#import "GPUImageOutput.h" @interface GPUImagePicture : GPUImageOutput
{
CGSize pixelSizeOfImage;
BOOL hasProcessedImage; dispatch_semaphore_t imageUpdateSemaphore;
} // Initialization and teardown
- (id)initWithURL:(NSURL *)url;
- (id)initWithImage:(UIImage *)newImageSource;
- (id)initWithCGImage:(CGImageRef)newImageSource;
- (id)initWithImage:(UIImage *)newImageSource smoothlyScaleOutput:(BOOL)smoothlyScaleOutput;
- (id)initWithCGImage:(CGImageRef)newImageSource smoothlyScaleOutput:(BOOL)smoothlyScaleOutput; // Image rendering
- (void)processImage;
- (CGSize)outputImageSize; /**
* Process image with all targets and filters asynchronously
* The completion handler is called after processing finished in the
* GPU's dispatch queue - and only if this method did not return NO.
*
* @returns NO if resource is blocked and processing is discarded, YES otherwise
*/
- (BOOL)processImageWithCompletionHandler:(void (^)(void))completion;
- (void)processImageUpToFilter:(GPUImageOutput<GPUImageInput> *)finalFilterInChain withCompletionHandler:(void (^)(UIImage *processedImage))block; @end
#import "GPUImagePicture.h" @implementation GPUImagePicture #pragma mark -
#pragma mark Initialization and teardown - (id)initWithURL:(NSURL *)url;
{
NSData *imageData = [[NSData alloc] initWithContentsOfURL:url]; if (!(self = [self initWithData:imageData]))
{
return nil;
} return self;
} - (id)initWithData:(NSData *)imageData;
{
UIImage *inputImage = [[UIImage alloc] initWithData:imageData]; if (!(self = [self initWithImage:inputImage]))
{
return nil;
} return self;
} - (id)initWithImage:(UIImage *)newImageSource;
{
if (!(self = [self initWithImage:newImageSource smoothlyScaleOutput:NO]))
{
return nil;
} return self;
} - (id)initWithCGImage:(CGImageRef)newImageSource;
{
if (!(self = [self initWithCGImage:newImageSource smoothlyScaleOutput:NO]))
{
return nil;
}
return self;
} - (id)initWithImage:(UIImage *)newImageSource smoothlyScaleOutput:(BOOL)smoothlyScaleOutput;
{
return [self initWithCGImage:[newImageSource CGImage] smoothlyScaleOutput:smoothlyScaleOutput];
} - (id)initWithCGImage:(CGImageRef)newImageSource smoothlyScaleOutput:(BOOL)smoothlyScaleOutput;
{
if (!(self = [super init]))
{
return nil;
} hasProcessedImage = NO;
self.shouldSmoothlyScaleOutput = smoothlyScaleOutput;
imageUpdateSemaphore = dispatch_semaphore_create();
dispatch_semaphore_signal(imageUpdateSemaphore); // TODO: Dispatch this whole thing asynchronously to move image loading off main thread
CGFloat widthOfImage = CGImageGetWidth(newImageSource);
CGFloat heightOfImage = CGImageGetHeight(newImageSource); // If passed an empty image reference, CGContextDrawImage will fail in future versions of the SDK.
NSAssert( widthOfImage > && heightOfImage > , @"Passed image must not be empty - it should be at least 1px tall and wide"); pixelSizeOfImage = CGSizeMake(widthOfImage, heightOfImage);
CGSize pixelSizeToUseForTexture = pixelSizeOfImage; BOOL shouldRedrawUsingCoreGraphics = NO; // For now, deal with images larger than the maximum texture size by resizing to be within that limit
CGSize scaledImageSizeToFitOnGPU = [GPUImageContext sizeThatFitsWithinATextureForSize:pixelSizeOfImage];
if (!CGSizeEqualToSize(scaledImageSizeToFitOnGPU, pixelSizeOfImage))
{
pixelSizeOfImage = scaledImageSizeToFitOnGPU;
pixelSizeToUseForTexture = pixelSizeOfImage;
shouldRedrawUsingCoreGraphics = YES;
} if (self.shouldSmoothlyScaleOutput)
{
// In order to use mipmaps, you need to provide power-of-two textures, so convert to the next largest power of two and stretch to fill
CGFloat powerClosestToWidth = ceil(log2(pixelSizeOfImage.width));
CGFloat powerClosestToHeight = ceil(log2(pixelSizeOfImage.height)); pixelSizeToUseForTexture = CGSizeMake(pow(2.0, powerClosestToWidth), pow(2.0, powerClosestToHeight)); shouldRedrawUsingCoreGraphics = YES;
} GLubyte *imageData = NULL;
CFDataRef dataFromImageDataProvider = NULL;
GLenum format = GL_BGRA; if (!shouldRedrawUsingCoreGraphics) {
/* Check that the memory layout is compatible with GL, as we cannot use glPixelStore to
* tell GL about the memory layout with GLES.
*/
if (CGImageGetBytesPerRow(newImageSource) != CGImageGetWidth(newImageSource) * ||
CGImageGetBitsPerPixel(newImageSource) != ||
CGImageGetBitsPerComponent(newImageSource) != )
{
shouldRedrawUsingCoreGraphics = YES;
} else {
/* Check that the bitmap pixel format is compatible with GL */
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(newImageSource);
if ((bitmapInfo & kCGBitmapFloatComponents) != ) {
/* We don't support float components for use directly in GL */
shouldRedrawUsingCoreGraphics = YES;
} else {
CGBitmapInfo byteOrderInfo = bitmapInfo & kCGBitmapByteOrderMask;
if (byteOrderInfo == kCGBitmapByteOrder32Little) {
/* Little endian, for alpha-first we can use this bitmap directly in GL */
CGImageAlphaInfo alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask;
if (alphaInfo != kCGImageAlphaPremultipliedFirst && alphaInfo != kCGImageAlphaFirst &&
alphaInfo != kCGImageAlphaNoneSkipFirst) {
shouldRedrawUsingCoreGraphics = YES;
}
} else if (byteOrderInfo == kCGBitmapByteOrderDefault || byteOrderInfo == kCGBitmapByteOrder32Big) {
/* Big endian, for alpha-last we can use this bitmap directly in GL */
CGImageAlphaInfo alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask;
if (alphaInfo != kCGImageAlphaPremultipliedLast && alphaInfo != kCGImageAlphaLast &&
alphaInfo != kCGImageAlphaNoneSkipLast) {
shouldRedrawUsingCoreGraphics = YES;
} else {
/* Can access directly using GL_RGBA pixel format */
format = GL_RGBA;
}
}
}
}
} // CFAbsoluteTime elapsedTime, startTime = CFAbsoluteTimeGetCurrent(); if (shouldRedrawUsingCoreGraphics)
{
// For resized or incompatible image: redraw
imageData = (GLubyte *) calloc(, (int)pixelSizeToUseForTexture.width * (int)pixelSizeToUseForTexture.height * ); CGColorSpaceRef genericRGBColorspace = CGColorSpaceCreateDeviceRGB(); CGContextRef imageContext = CGBitmapContextCreate(imageData, (size_t)pixelSizeToUseForTexture.width, (size_t)pixelSizeToUseForTexture.height, , (size_t)pixelSizeToUseForTexture.width * , genericRGBColorspace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
// CGContextSetBlendMode(imageContext, kCGBlendModeCopy); // From Technical Q&A QA1708: http://developer.apple.com/library/ios/#qa/qa1708/_index.html
CGContextDrawImage(imageContext, CGRectMake(0.0, 0.0, pixelSizeToUseForTexture.width, pixelSizeToUseForTexture.height), newImageSource);
CGContextRelease(imageContext);
CGColorSpaceRelease(genericRGBColorspace);
}
else
{
// Access the raw image bytes directly
dataFromImageDataProvider = CGDataProviderCopyData(CGImageGetDataProvider(newImageSource));
imageData = (GLubyte *)CFDataGetBytePtr(dataFromImageDataProvider);
} // elapsedTime = (CFAbsoluteTimeGetCurrent() - startTime) * 1000.0;
// NSLog(@"Core Graphics drawing time: %f", elapsedTime); // CGFloat currentRedTotal = 0.0f, currentGreenTotal = 0.0f, currentBlueTotal = 0.0f, currentAlphaTotal = 0.0f;
// NSUInteger totalNumberOfPixels = round(pixelSizeToUseForTexture.width * pixelSizeToUseForTexture.height);
//
// for (NSUInteger currentPixel = 0; currentPixel < totalNumberOfPixels; currentPixel++)
// {
// currentBlueTotal += (CGFloat)imageData[(currentPixel * 4)] / 255.0f;
// currentGreenTotal += (CGFloat)imageData[(currentPixel * 4) + 1] / 255.0f;
// currentRedTotal += (CGFloat)imageData[(currentPixel * 4 + 2)] / 255.0f;
// currentAlphaTotal += (CGFloat)imageData[(currentPixel * 4) + 3] / 255.0f;
// }
//
// NSLog(@"Debug, average input image red: %f, green: %f, blue: %f, alpha: %f", currentRedTotal / (CGFloat)totalNumberOfPixels, currentGreenTotal / (CGFloat)totalNumberOfPixels, currentBlueTotal / (CGFloat)totalNumberOfPixels, currentAlphaTotal / (CGFloat)totalNumberOfPixels); runSynchronouslyOnVideoProcessingQueue(^{
[GPUImageContext useImageProcessingContext]; outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:pixelSizeToUseForTexture onlyTexture:YES];
[outputFramebuffer disableReferenceCounting]; glBindTexture(GL_TEXTURE_2D, [outputFramebuffer texture]);
if (self.shouldSmoothlyScaleOutput)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
}
// no need to use self.outputTextureOptions here since pictures need this texture formats and type
glTexImage2D(GL_TEXTURE_2D, , GL_RGBA, (int)pixelSizeToUseForTexture.width, (int)pixelSizeToUseForTexture.height, , format, GL_UNSIGNED_BYTE, imageData); if (self.shouldSmoothlyScaleOutput)
{
glGenerateMipmap(GL_TEXTURE_2D);
}
glBindTexture(GL_TEXTURE_2D, );
}); if (shouldRedrawUsingCoreGraphics)
{
free(imageData);
}
else
{
if (dataFromImageDataProvider)
{
CFRelease(dataFromImageDataProvider);
}
} return self;
} // ARC forbids explicit message send of 'release'; since iOS 6 even for dispatch_release() calls: stripping it out in that case is required.
- (void)dealloc;
{
[outputFramebuffer enableReferenceCounting];
[outputFramebuffer unlock]; #if !OS_OBJECT_USE_OBJC
if (imageUpdateSemaphore != NULL)
{
dispatch_release(imageUpdateSemaphore);
}
#endif
} #pragma mark -
#pragma mark Image rendering - (void)removeAllTargets;
{
[super removeAllTargets];
hasProcessedImage = NO;
} - (void)processImage;
{
[self processImageWithCompletionHandler:nil];
} - (BOOL)processImageWithCompletionHandler:(void (^)(void))completion;
{
hasProcessedImage = YES; // dispatch_semaphore_wait(imageUpdateSemaphore, DISPATCH_TIME_FOREVER); if (dispatch_semaphore_wait(imageUpdateSemaphore, DISPATCH_TIME_NOW) != )
{
return NO;
} runAsynchronouslyOnVideoProcessingQueue(^{
for (id<GPUImageInput> currentTarget in targets)
{
NSInteger indexOfObject = [targets indexOfObject:currentTarget];
NSInteger textureIndexOfTarget = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue]; [currentTarget setCurrentlyReceivingMonochromeInput:NO];
[currentTarget setInputSize:pixelSizeOfImage atIndex:textureIndexOfTarget];
[currentTarget setInputFramebuffer:outputFramebuffer atIndex:textureIndexOfTarget];
[currentTarget newFrameReadyAtTime:kCMTimeIndefinite atIndex:textureIndexOfTarget];
} dispatch_semaphore_signal(imageUpdateSemaphore); if (completion != nil) {
completion();
}
}); return YES;
} - (void)processImageUpToFilter:(GPUImageOutput<GPUImageInput> *)finalFilterInChain withCompletionHandler:(void (^)(UIImage *processedImage))block;
{
[finalFilterInChain useNextFrameForImageCapture];
[self processImageWithCompletionHandler:^{
UIImage *imageFromFilter = [finalFilterInChain imageFromCurrentFramebuffer];
block(imageFromFilter);
}];
} - (CGSize)outputImageSize;
{
return pixelSizeOfImage;
} - (void)addTarget:(id<GPUImageInput>)newTarget atTextureLocation:(NSInteger)textureLocation;
{
[super addTarget:newTarget atTextureLocation:textureLocation]; if (hasProcessedImage)
{
[newTarget setInputSize:pixelSizeOfImage atIndex:textureLocation];
[newTarget newFrameReadyAtTime:kCMTimeIndefinite atIndex:textureLocation];
}
} @end
GPUImage API 文档之GPUImagePicture类的更多相关文章
- GPUImage API 文档之GPUImageFilter类
		
GPUImageFilter类 方法 - (id)initWithVertexShaderFromString:(NSString *)vertexShaderString fragmentShade ...
 - GPUImage API 文档之GPUImageOutput类
		
GPUImageOutput类将静态图像纹理上传到OpenGL ES中,然后使用这些纹理去处理进程链中的下一个对象.它的子类可以获得滤镜处理后的图片功能.[本文讲的很少,由于有许多地方不清楚,以后会更 ...
 - GPUImage API文档之GPUImageContext类
		
GPUImageContext类,提供OpenGL ES基本环境,我们一般不会用到,所以讲的很简单. 属性 @property(readonly, nonatomic) dispatch_queue_ ...
 - GPUImage API文档之GPUImageFramebufferCache类
		
GPUImageFramebufferCache类负责管理GPUImageFramebuffer对象,是一个GPUImageFramebuffer对象的缓存. 方法 - (GPUImageFrameb ...
 - GPUImage API文档之GPUImageFramebuffer类
		
GPUImageFramebuffer类用于管理帧缓冲对象,负责帧缓冲对象的创建和销毁,读取帧缓冲内容 属性 @property(readonly) CGSize size 说明:只读属性,在实现中, ...
 - GPUImage API文档之GLProgram类
		
GLProgram是GPUImage中代表openGL ES 中的program,具有glprogram功能. 属性 @property(readwrite, nonatomic) BOOL init ...
 - GPUImage API文档之GPUImageInput协议
		
GPUImageInput协议主要包含一些输入需要渲染目标的操作. - (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)t ...
 - 通过API文档查询Math类的方法,打印出近似圆,只要给定不同半径,圆的大小就会随之发生改变
		
package question; import java.util.Scanner; import java.lang.Math; public class MathTest { /** * 未搞懂 ...
 - Java,面试题,简历,Linux,大数据,常用开发工具类,API文档,电子书,各种思维导图资源,百度网盘资源,BBS论坛系统 ERP管理系统 OA办公自动化管理系统 车辆管理系统 各种后台管理系统
		
Java,面试题,简历,Linux,大数据,常用开发工具类,API文档,电子书,各种思维导图资源,百度网盘资源BBS论坛系统 ERP管理系统 OA办公自动化管理系统 车辆管理系统 家庭理财系统 各种后 ...
 
随机推荐
- LDO current regulator for power LED
			
LDO current regulator for power LED Challenge You've got a power LED? Great! Build a flash light! Wh ...
 - [Deepin 15] 安装 Java 8、Git、Firefox、SafeEyes(定时提醒休息工具)
			
一.安装 JDK 8 1.到官网,用 迅雷下载 安装包 (jdk-8u131-linux-x64.tar.gz) 2.解压放到目录 /opt/software/jdk 3.配置环境变量 sudo vi ...
 - Android笔记之 网络http通信
			
0.在认识HTTP前先认识URL 在我们认识HTTP之前,有必要先弄清楚URL的组成,比如: http://www.******.com/china/index.htm 它的含义例如以下: 1. ht ...
 - 在ASP.NET Web API中使用OData的Containment
			
通常情况下,一个OData的EDM(Entity Data Model)在配置的时候定义了,才可以被查询或执行各种操作.比如如下: builder.EntitySet<SomeModel> ...
 - 委托、Lambda表达式、事件系列04,委托链是怎样形成的, 多播委托, 调用委托链方法,委托链异常处理
			
委托是多播委托,我们可以通过"+="把多个方法赋给委托变量,这样就形成了一个委托链.本篇的话题包括:委托链是怎样形成的,如何调用委托链方法,以及委托链异常处理. □ 调用返回类型为 ...
 - SpringMVC和Springboot的区别
			
转自站在浪潮之巅的原文SpringMVC和Springboot的区别(网摘) spring boot 我理解就是把 spring spring mvc spring data jpa 等等的一些常用的 ...
 - mysql time zone时区的错误解决
			
错误提示: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zon ...
 - 清理tomcat服务器缓存
			
据悉,2014年最流行的应用服务器排行榜揭晓Tomcat仍然处于领先位置.41%的部署使用的是Tomcat,和2013年的43%的市场份额数据一 致.下面还是我们的热门选择Jetty和JBoss/Wi ...
 - WebApp分析建模的工具
			
最近Web工程课在学习分析建模工具的内容.这周作业就写我对WebApp建模工具的认识.Web建模工具有很多,但是专门为分析开发的却相对很少.下面介绍在进行分析时可以用的四类工具. UML工具.使用统一 ...
 - GO -- 正则表达式
			
str := "880218end" match, _ := regexp.MatchString("\\d{16}", str) //六位连续的数字 fmt. ...