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为当处理结束执行的操作。

完整代码

  1. #import <UIKit/UIKit.h>
  2. #import "GPUImageOutput.h"
  3.  
  4. @interface GPUImagePicture : GPUImageOutput
  5. {
  6. CGSize pixelSizeOfImage;
  7. BOOL hasProcessedImage;
  8.  
  9. dispatch_semaphore_t imageUpdateSemaphore;
  10. }
  11.  
  12. // Initialization and teardown
  13. - (id)initWithURL:(NSURL *)url;
  14. - (id)initWithImage:(UIImage *)newImageSource;
  15. - (id)initWithCGImage:(CGImageRef)newImageSource;
  16. - (id)initWithImage:(UIImage *)newImageSource smoothlyScaleOutput:(BOOL)smoothlyScaleOutput;
  17. - (id)initWithCGImage:(CGImageRef)newImageSource smoothlyScaleOutput:(BOOL)smoothlyScaleOutput;
  18.  
  19. // Image rendering
  20. - (void)processImage;
  21. - (CGSize)outputImageSize;
  22.  
  23. /**
  24. * Process image with all targets and filters asynchronously
  25. * The completion handler is called after processing finished in the
  26. * GPU's dispatch queue - and only if this method did not return NO.
  27. *
  28. * @returns NO if resource is blocked and processing is discarded, YES otherwise
  29. */
  30. - (BOOL)processImageWithCompletionHandler:(void (^)(void))completion;
  31. - (void)processImageUpToFilter:(GPUImageOutput<GPUImageInput> *)finalFilterInChain withCompletionHandler:(void (^)(UIImage *processedImage))block;
  32.  
  33. @end
  1. #import "GPUImagePicture.h"
  2.  
  3. @implementation GPUImagePicture
  4.  
  5. #pragma mark -
  6. #pragma mark Initialization and teardown
  7.  
  8. - (id)initWithURL:(NSURL *)url;
  9. {
  10. NSData *imageData = [[NSData alloc] initWithContentsOfURL:url];
  11.  
  12. if (!(self = [self initWithData:imageData]))
  13. {
  14. return nil;
  15. }
  16.  
  17. return self;
  18. }
  19.  
  20. - (id)initWithData:(NSData *)imageData;
  21. {
  22. UIImage *inputImage = [[UIImage alloc] initWithData:imageData];
  23.  
  24. if (!(self = [self initWithImage:inputImage]))
  25. {
  26. return nil;
  27. }
  28.  
  29. return self;
  30. }
  31.  
  32. - (id)initWithImage:(UIImage *)newImageSource;
  33. {
  34. if (!(self = [self initWithImage:newImageSource smoothlyScaleOutput:NO]))
  35. {
  36. return nil;
  37. }
  38.  
  39. return self;
  40. }
  41.  
  42. - (id)initWithCGImage:(CGImageRef)newImageSource;
  43. {
  44. if (!(self = [self initWithCGImage:newImageSource smoothlyScaleOutput:NO]))
  45. {
  46. return nil;
  47. }
  48. return self;
  49. }
  50.  
  51. - (id)initWithImage:(UIImage *)newImageSource smoothlyScaleOutput:(BOOL)smoothlyScaleOutput;
  52. {
  53. return [self initWithCGImage:[newImageSource CGImage] smoothlyScaleOutput:smoothlyScaleOutput];
  54. }
  55.  
  56. - (id)initWithCGImage:(CGImageRef)newImageSource smoothlyScaleOutput:(BOOL)smoothlyScaleOutput;
  57. {
  58. if (!(self = [super init]))
  59. {
  60. return nil;
  61. }
  62.  
  63. hasProcessedImage = NO;
  64. self.shouldSmoothlyScaleOutput = smoothlyScaleOutput;
  65. imageUpdateSemaphore = dispatch_semaphore_create();
  66. dispatch_semaphore_signal(imageUpdateSemaphore);
  67.  
  68. // TODO: Dispatch this whole thing asynchronously to move image loading off main thread
  69. CGFloat widthOfImage = CGImageGetWidth(newImageSource);
  70. CGFloat heightOfImage = CGImageGetHeight(newImageSource);
  71.  
  72. // If passed an empty image reference, CGContextDrawImage will fail in future versions of the SDK.
  73. NSAssert( widthOfImage > && heightOfImage > , @"Passed image must not be empty - it should be at least 1px tall and wide");
  74.  
  75. pixelSizeOfImage = CGSizeMake(widthOfImage, heightOfImage);
  76. CGSize pixelSizeToUseForTexture = pixelSizeOfImage;
  77.  
  78. BOOL shouldRedrawUsingCoreGraphics = NO;
  79.  
  80. // For now, deal with images larger than the maximum texture size by resizing to be within that limit
  81. CGSize scaledImageSizeToFitOnGPU = [GPUImageContext sizeThatFitsWithinATextureForSize:pixelSizeOfImage];
  82. if (!CGSizeEqualToSize(scaledImageSizeToFitOnGPU, pixelSizeOfImage))
  83. {
  84. pixelSizeOfImage = scaledImageSizeToFitOnGPU;
  85. pixelSizeToUseForTexture = pixelSizeOfImage;
  86. shouldRedrawUsingCoreGraphics = YES;
  87. }
  88.  
  89. if (self.shouldSmoothlyScaleOutput)
  90. {
  91. // 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
  92. CGFloat powerClosestToWidth = ceil(log2(pixelSizeOfImage.width));
  93. CGFloat powerClosestToHeight = ceil(log2(pixelSizeOfImage.height));
  94.  
  95. pixelSizeToUseForTexture = CGSizeMake(pow(2.0, powerClosestToWidth), pow(2.0, powerClosestToHeight));
  96.  
  97. shouldRedrawUsingCoreGraphics = YES;
  98. }
  99.  
  100. GLubyte *imageData = NULL;
  101. CFDataRef dataFromImageDataProvider = NULL;
  102. GLenum format = GL_BGRA;
  103.  
  104. if (!shouldRedrawUsingCoreGraphics) {
  105. /* Check that the memory layout is compatible with GL, as we cannot use glPixelStore to
  106. * tell GL about the memory layout with GLES.
  107. */
  108. if (CGImageGetBytesPerRow(newImageSource) != CGImageGetWidth(newImageSource) * ||
  109. CGImageGetBitsPerPixel(newImageSource) != ||
  110. CGImageGetBitsPerComponent(newImageSource) != )
  111. {
  112. shouldRedrawUsingCoreGraphics = YES;
  113. } else {
  114. /* Check that the bitmap pixel format is compatible with GL */
  115. CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(newImageSource);
  116. if ((bitmapInfo & kCGBitmapFloatComponents) != ) {
  117. /* We don't support float components for use directly in GL */
  118. shouldRedrawUsingCoreGraphics = YES;
  119. } else {
  120. CGBitmapInfo byteOrderInfo = bitmapInfo & kCGBitmapByteOrderMask;
  121. if (byteOrderInfo == kCGBitmapByteOrder32Little) {
  122. /* Little endian, for alpha-first we can use this bitmap directly in GL */
  123. CGImageAlphaInfo alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask;
  124. if (alphaInfo != kCGImageAlphaPremultipliedFirst && alphaInfo != kCGImageAlphaFirst &&
  125. alphaInfo != kCGImageAlphaNoneSkipFirst) {
  126. shouldRedrawUsingCoreGraphics = YES;
  127. }
  128. } else if (byteOrderInfo == kCGBitmapByteOrderDefault || byteOrderInfo == kCGBitmapByteOrder32Big) {
  129. /* Big endian, for alpha-last we can use this bitmap directly in GL */
  130. CGImageAlphaInfo alphaInfo = bitmapInfo & kCGBitmapAlphaInfoMask;
  131. if (alphaInfo != kCGImageAlphaPremultipliedLast && alphaInfo != kCGImageAlphaLast &&
  132. alphaInfo != kCGImageAlphaNoneSkipLast) {
  133. shouldRedrawUsingCoreGraphics = YES;
  134. } else {
  135. /* Can access directly using GL_RGBA pixel format */
  136. format = GL_RGBA;
  137. }
  138. }
  139. }
  140. }
  141. }
  142.  
  143. // CFAbsoluteTime elapsedTime, startTime = CFAbsoluteTimeGetCurrent();
  144.  
  145. if (shouldRedrawUsingCoreGraphics)
  146. {
  147. // For resized or incompatible image: redraw
  148. imageData = (GLubyte *) calloc(, (int)pixelSizeToUseForTexture.width * (int)pixelSizeToUseForTexture.height * );
  149.  
  150. CGColorSpaceRef genericRGBColorspace = CGColorSpaceCreateDeviceRGB();
  151.  
  152. CGContextRef imageContext = CGBitmapContextCreate(imageData, (size_t)pixelSizeToUseForTexture.width, (size_t)pixelSizeToUseForTexture.height, , (size_t)pixelSizeToUseForTexture.width * , genericRGBColorspace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
  153. // CGContextSetBlendMode(imageContext, kCGBlendModeCopy); // From Technical Q&A QA1708: http://developer.apple.com/library/ios/#qa/qa1708/_index.html
  154. CGContextDrawImage(imageContext, CGRectMake(0.0, 0.0, pixelSizeToUseForTexture.width, pixelSizeToUseForTexture.height), newImageSource);
  155. CGContextRelease(imageContext);
  156. CGColorSpaceRelease(genericRGBColorspace);
  157. }
  158. else
  159. {
  160. // Access the raw image bytes directly
  161. dataFromImageDataProvider = CGDataProviderCopyData(CGImageGetDataProvider(newImageSource));
  162. imageData = (GLubyte *)CFDataGetBytePtr(dataFromImageDataProvider);
  163. }
  164.  
  165. // elapsedTime = (CFAbsoluteTimeGetCurrent() - startTime) * 1000.0;
  166. // NSLog(@"Core Graphics drawing time: %f", elapsedTime);
  167.  
  168. // CGFloat currentRedTotal = 0.0f, currentGreenTotal = 0.0f, currentBlueTotal = 0.0f, currentAlphaTotal = 0.0f;
  169. // NSUInteger totalNumberOfPixels = round(pixelSizeToUseForTexture.width * pixelSizeToUseForTexture.height);
  170. //
  171. // for (NSUInteger currentPixel = 0; currentPixel < totalNumberOfPixels; currentPixel++)
  172. // {
  173. // currentBlueTotal += (CGFloat)imageData[(currentPixel * 4)] / 255.0f;
  174. // currentGreenTotal += (CGFloat)imageData[(currentPixel * 4) + 1] / 255.0f;
  175. // currentRedTotal += (CGFloat)imageData[(currentPixel * 4 + 2)] / 255.0f;
  176. // currentAlphaTotal += (CGFloat)imageData[(currentPixel * 4) + 3] / 255.0f;
  177. // }
  178. //
  179. // 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);
  180.  
  181. runSynchronouslyOnVideoProcessingQueue(^{
  182. [GPUImageContext useImageProcessingContext];
  183.  
  184. outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:pixelSizeToUseForTexture onlyTexture:YES];
  185. [outputFramebuffer disableReferenceCounting];
  186.  
  187. glBindTexture(GL_TEXTURE_2D, [outputFramebuffer texture]);
  188. if (self.shouldSmoothlyScaleOutput)
  189. {
  190. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
  191. }
  192. // no need to use self.outputTextureOptions here since pictures need this texture formats and type
  193. glTexImage2D(GL_TEXTURE_2D, , GL_RGBA, (int)pixelSizeToUseForTexture.width, (int)pixelSizeToUseForTexture.height, , format, GL_UNSIGNED_BYTE, imageData);
  194.  
  195. if (self.shouldSmoothlyScaleOutput)
  196. {
  197. glGenerateMipmap(GL_TEXTURE_2D);
  198. }
  199. glBindTexture(GL_TEXTURE_2D, );
  200. });
  201.  
  202. if (shouldRedrawUsingCoreGraphics)
  203. {
  204. free(imageData);
  205. }
  206. else
  207. {
  208. if (dataFromImageDataProvider)
  209. {
  210. CFRelease(dataFromImageDataProvider);
  211. }
  212. }
  213.  
  214. return self;
  215. }
  216.  
  217. // ARC forbids explicit message send of 'release'; since iOS 6 even for dispatch_release() calls: stripping it out in that case is required.
  218. - (void)dealloc;
  219. {
  220. [outputFramebuffer enableReferenceCounting];
  221. [outputFramebuffer unlock];
  222.  
  223. #if !OS_OBJECT_USE_OBJC
  224. if (imageUpdateSemaphore != NULL)
  225. {
  226. dispatch_release(imageUpdateSemaphore);
  227. }
  228. #endif
  229. }
  230.  
  231. #pragma mark -
  232. #pragma mark Image rendering
  233.  
  234. - (void)removeAllTargets;
  235. {
  236. [super removeAllTargets];
  237. hasProcessedImage = NO;
  238. }
  239.  
  240. - (void)processImage;
  241. {
  242. [self processImageWithCompletionHandler:nil];
  243. }
  244.  
  245. - (BOOL)processImageWithCompletionHandler:(void (^)(void))completion;
  246. {
  247. hasProcessedImage = YES;
  248.  
  249. // dispatch_semaphore_wait(imageUpdateSemaphore, DISPATCH_TIME_FOREVER);
  250.  
  251. if (dispatch_semaphore_wait(imageUpdateSemaphore, DISPATCH_TIME_NOW) != )
  252. {
  253. return NO;
  254. }
  255.  
  256. runAsynchronouslyOnVideoProcessingQueue(^{
  257. for (id<GPUImageInput> currentTarget in targets)
  258. {
  259. NSInteger indexOfObject = [targets indexOfObject:currentTarget];
  260. NSInteger textureIndexOfTarget = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue];
  261.  
  262. [currentTarget setCurrentlyReceivingMonochromeInput:NO];
  263. [currentTarget setInputSize:pixelSizeOfImage atIndex:textureIndexOfTarget];
  264. [currentTarget setInputFramebuffer:outputFramebuffer atIndex:textureIndexOfTarget];
  265. [currentTarget newFrameReadyAtTime:kCMTimeIndefinite atIndex:textureIndexOfTarget];
  266. }
  267.  
  268. dispatch_semaphore_signal(imageUpdateSemaphore);
  269.  
  270. if (completion != nil) {
  271. completion();
  272. }
  273. });
  274.  
  275. return YES;
  276. }
  277.  
  278. - (void)processImageUpToFilter:(GPUImageOutput<GPUImageInput> *)finalFilterInChain withCompletionHandler:(void (^)(UIImage *processedImage))block;
  279. {
  280. [finalFilterInChain useNextFrameForImageCapture];
  281. [self processImageWithCompletionHandler:^{
  282. UIImage *imageFromFilter = [finalFilterInChain imageFromCurrentFramebuffer];
  283. block(imageFromFilter);
  284. }];
  285. }
  286.  
  287. - (CGSize)outputImageSize;
  288. {
  289. return pixelSizeOfImage;
  290. }
  291.  
  292. - (void)addTarget:(id<GPUImageInput>)newTarget atTextureLocation:(NSInteger)textureLocation;
  293. {
  294. [super addTarget:newTarget atTextureLocation:textureLocation];
  295.  
  296. if (hasProcessedImage)
  297. {
  298. [newTarget setInputSize:pixelSizeOfImage atIndex:textureLocation];
  299. [newTarget newFrameReadyAtTime:kCMTimeIndefinite atIndex:textureLocation];
  300. }
  301. }
  302.  
  303. @end

GPUImage API 文档之GPUImagePicture类的更多相关文章

  1. GPUImage API 文档之GPUImageFilter类

    GPUImageFilter类 方法 - (id)initWithVertexShaderFromString:(NSString *)vertexShaderString fragmentShade ...

  2. GPUImage API 文档之GPUImageOutput类

    GPUImageOutput类将静态图像纹理上传到OpenGL ES中,然后使用这些纹理去处理进程链中的下一个对象.它的子类可以获得滤镜处理后的图片功能.[本文讲的很少,由于有许多地方不清楚,以后会更 ...

  3. GPUImage API文档之GPUImageContext类

    GPUImageContext类,提供OpenGL ES基本环境,我们一般不会用到,所以讲的很简单. 属性 @property(readonly, nonatomic) dispatch_queue_ ...

  4. GPUImage API文档之GPUImageFramebufferCache类

    GPUImageFramebufferCache类负责管理GPUImageFramebuffer对象,是一个GPUImageFramebuffer对象的缓存. 方法 - (GPUImageFrameb ...

  5. GPUImage API文档之GPUImageFramebuffer类

    GPUImageFramebuffer类用于管理帧缓冲对象,负责帧缓冲对象的创建和销毁,读取帧缓冲内容 属性 @property(readonly) CGSize size 说明:只读属性,在实现中, ...

  6. GPUImage API文档之GLProgram类

    GLProgram是GPUImage中代表openGL ES 中的program,具有glprogram功能. 属性 @property(readwrite, nonatomic) BOOL init ...

  7. GPUImage API文档之GPUImageInput协议

    GPUImageInput协议主要包含一些输入需要渲染目标的操作. - (void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)t ...

  8. 通过API文档查询Math类的方法,打印出近似圆,只要给定不同半径,圆的大小就会随之发生改变

    package question; import java.util.Scanner; import java.lang.Math; public class MathTest { /** * 未搞懂 ...

  9. Java,面试题,简历,Linux,大数据,常用开发工具类,API文档,电子书,各种思维导图资源,百度网盘资源,BBS论坛系统 ERP管理系统 OA办公自动化管理系统 车辆管理系统 各种后台管理系统

    Java,面试题,简历,Linux,大数据,常用开发工具类,API文档,电子书,各种思维导图资源,百度网盘资源BBS论坛系统 ERP管理系统 OA办公自动化管理系统 车辆管理系统 家庭理财系统 各种后 ...

随机推荐

  1. STM32 Seminar 2007 -- Timer

  2. AIX 与Linux 中crontab 介绍

    AIX 与Linux 中crontab 用法相似,先介绍Linux 中的Crontab 用法,再后介绍AIX 与Linux 的不同之处.   一.Crontab 介绍 crontab命令的功能是在一定 ...

  3. MyEclipse10安装Log4E插件

    一. Log4E插件下载 下载地址:http://log4e.jayefem.de/content/view/3/2/ 二.安装Log4E插件 将下载下来的压缩包解压缩,如下图所示: 解压缩生成的[d ...

  4. [Mac入门]如何在Mac下显示Finder中的所有文件

    在Unix下工作,你可能需要处理一些“特殊“文件或文件夹,例如/usr,/bin, etcf,或一些"dot files"(如.bash_profile).但是Linux/Unix ...

  5. 为Qemu aarch32添加BeautifulSoup4模块

    环境 Qemu:2.8.0 开发板:vexpress-ca9   概述 上一篇博文已经可以让我们的开发板可以成功的ping通百度了,据说Python的网络功能也很强大,而Beautiful Soup是 ...

  6. springMVC helloworld入门

    一.SpringMVC概述与基本原理 spring Web MVC是一种基于Java的实现了Web MVC设计模式的请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将web层进行职责解耦 ...

  7. Scala从零開始:使用Intellij IDEA写hello world

    引言 在之前的文章中,我们介绍了怎样使用Scala IDE也就是eclipse中集成的Scala开发插件来进行Scala语言程序的开发,在使用了一段时间之后,发现eclipse对Scala的支持并非非 ...

  8. 从零开始写一个发送h264的rtsp服务器(下)

    转自:http://blog.csdn.net/jychen105/article/details/47012099 一.H264是如何通过rtsp发送的 简单来说,H264就是通过打包到rtp协议的 ...

  9. MySQL中进行树状所有子节点的查询 . mysql根据父id 查询所有的子id

    在Oracle 中我们知道有一个 Hierarchical Queries 通过CONNECT BY 我们可以方便的查了所有当前节点下的所有子节点.但很遗憾,在MySQL的目前版本中还没有对应的功能. ...

  10. spring 5.0.1.RELEASE官方任然不支持velocity(平台升级)

    官方说明: Dear Spring community, It is my pleasure to announce that Spring Framework 5.0.1 is available ...