首页 > 学院 > 开发设计 > 正文

GPUImageAPI文档之GPUImageOutput类

2019-11-14 17:55:04
字体:
来源:转载
供稿:网友

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

  方法

  - (void)setInputFramebufferForTarget:(id<GPUImageInput>)target atIndex:(NSInteger)inputTextureIndex

  说明:用于设置指定纹理的输入帧缓冲区的尺寸

  参数:target是具体的对象,它接受了GPUImageInput的协议,例如:当我们使用[GPUImageLookupFilter]滤镜时,target就是一个GPUImageLookupFilter的实例。

  

  

  - (void)addTarget:(id<GPUImageInput>)newTarget atTextureLocation:(NSInteger)textureLocation

   说明:添加target

  

  

  - (void)removeTarget:(id<GPUImageInput>)targetToRemove

   说明:删除指定的target

 

  - (void)removeAllTargets

  说明:删除所有target

  

  - (UIImage *)imageFromCurrentFramebufferWithOrientation:(UIImageOrientation)imageOrientation

  说明:从帧缓冲区中取回对象,打印在屏幕中。

  参数:imageOrientation时当前设备的手持方向

  

  - (CGImageRef)newCGImageByFilteringCGImage:(CGImageRef)imageToFilter

  说明:使用一张静态图片做滤镜纹理

完整代码

#import "GPUImageContext.h"#import "GPUImageFramebuffer.h"#if TARGET_ipHONE_SIMULATOR || TARGET_OS_IPHONE#import <UIKit/UIKit.h>#else// For now, just redefine this on the Mactypedef NS_ENUM(NSInteger, UIImageOrientation) {    UIImageOrientationUp,            // default orientation    UIImageOrientationDown,          // 180 deg rotation    UIImageOrientationLeft,          // 90 deg CCW    UIImageOrientationRight,         // 90 deg CW    UIImageOrientationUpMirrored,    // as above but image mirrored along other axis. horizontal flip    UIImageOrientationDownMirrored,  // horizontal flip    UIImageOrientationLeftMirrored,  // vertical flip    UIImageOrientationRightMirrored, // vertical flip};#endifvoid runOnMainQueueWithoutDeadlocking(void (^block)(void));void runSynchronouslyOnVideoPRocessingQueue(void (^block)(void));void runAsynchronouslyOnVideoProcessingQueue(void (^block)(void));void runSynchronouslyOnContextQueue(GPUImageContext *context, void (^block)(void));void runAsynchronouslyOnContextQueue(GPUImageContext *context, void (^block)(void));void reportAvailableMemoryForGPUImage(NSString *tag);@class GPUImageMovieWriter;/** GPUImage's base source object  Images or frames of video are uploaded from source objects, which are subclasses of GPUImageOutput. These include:  - GPUImageVideoCamera (for live video from an iOS camera)  - GPUImageStillCamera (for taking photos with the camera) - GPUImagePicture (for still images) - GPUImageMovie (for movies)  Source objects upload still image frames to OpenGL ES as textures, then hand those textures off to the next objects in the processing chain. */@interface GPUImageOutput : NSObject{    GPUImageFramebuffer *outputFramebuffer;        NSMutableArray *targets, *targetTextureIndices;        CGSize inputTextureSize, cachedMaximumOutputSize, forcedMaximumSize;        BOOL overrideInputSize;        BOOL allTargetsWantMonoChromeData;    BOOL usingNextFrameForImageCapture;}@property(readwrite, nonatomic) BOOL shouldSmoothlyScaleOutput;@property(readwrite, nonatomic) BOOL shouldIgnoreUpdatesToThisTarget;@property(readwrite, nonatomic, retain) GPUImageMovieWriter *audioEncodingTarget;@property(readwrite, nonatomic, unsafe_unretained) id<GPUImageInput> targetToIgnoreForUpdates;@property(nonatomic, copy) void(^frameProcessingCompletionBlock)(GPUImageOutput*, CMTime);@property(nonatomic) BOOL enabled;@property(readwrite, nonatomic) GPUTextureOptions outputTextureOptions;/// @name Managing targets- (void)setInputFramebufferForTarget:(id<GPUImageInput>)target atIndex:(NSInteger)inputTextureIndex;- (GPUImageFramebuffer *)framebufferForOutput;- (void)removeOutputFramebuffer;- (void)notifyTargetsAboutNewOutputTexture;/** Returns an array of the current targets. */- (NSArray*)targets;/** Adds a target to receive notifications when new frames are available.  The target will be asked for its next available texture.  See [GPUImageInput newFrameReadyAtTime:]  @param newTarget Target to be added */- (void)addTarget:(id<GPUImageInput>)newTarget;/** Adds a target to receive notifications when new frames are available.  See [GPUImageInput newFrameReadyAtTime:]  @param newTarget Target to be added */- (void)addTarget:(id<GPUImageInput>)newTarget atTextureLocation:(NSInteger)textureLocation;/** Removes a target. The target will no longer receive notifications when new frames are available.  @param targetToRemove Target to be removed */- (void)removeTarget:(id<GPUImageInput>)targetToRemove;/** Removes all targets. */- (void)removeAllTargets;/// @name Manage the output texture- (void)forceProcessingAtSize:(CGSize)frameSize;- (void)forceProcessingAtSizeRespectingaspectRatio:(CGSize)frameSize;/// @name Still image processing- (void)useNextFrameForImageCapture;- (CGImageRef)newCGImageFromCurrentlyProcessedOutput;- (CGImageRef)newCGImageByFilteringCGImage:(CGImageRef)imageToFilter;// Platform-specific image output methods// If you're trying to use these methods, remember that you need to set -useNextFrameForImageCapture before running -processImage or running video and calling any of these methods, or you will get a nil image#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE- (UIImage *)imageFromCurrentFramebuffer;- (UIImage *)imageFromCurrentFramebufferWithOrientation:(UIImageOrientation)imageOrientation;- (UIImage *)imageByFilteringImage:(UIImage *)imageToFilter;- (CGImageRef)newCGImageByFilteringImage:(UIImage *)imageToFilter;#else- (NSImage *)imageFromCurrentFramebuffer;- (NSImage *)imageFromCurrentFramebufferWithOrientation:(UIImageOrientation)imageOrientation;- (NSImage *)imageByFilteringImage:(NSImage *)imageToFilter;- (CGImageRef)newCGImageByFilteringImage:(NSImage *)imageToFilter;#endif- (BOOL)providesMonochromeOutput;@end
#import "GPUImageOutput.h"#import "GPUImageMovieWriter.h"#import "GPUImagePicture.h"#import <mach/mach.h>void runOnMainQueueWithoutDeadlocking(void (^block)(void)){    if ([NSThread isMainThread])    {        block();    }    else    {        dispatch_sync(dispatch_get_main_queue(), block);    }}void runSynchronouslyOnVideoProcessingQueue(void (^block)(void)){    dispatch_queue_t videoProcessingQueue = [GPUImageContext sharedContextQueue];#if !OS_OBJECT_USE_OBJC#pragma clang diagnostic push#pragma clang diagnostic ignored "-Wdeprecated-declarations"    if (dispatch_get_current_queue() == videoProcessingQueue)#pragma clang diagnostic pop#else    if (dispatch_get_specific([GPUImageContext contextKey]))#endif    {        block();    }else    {        dispatch_sync(videoProcessingQueue, block);    }}void runAsynchronouslyOnVideoProcessingQueue(void (^block)(void)){    dispatch_queue_t videoProcessingQueue = [GPUImageContext sharedContextQueue];    #if !OS_OBJECT_USE_OBJC#pragma clang diagnostic push#pragma clang diagnostic ignored "-Wdeprecated-declarations"    if (dispatch_get_current_queue() == videoProcessingQueue)#pragma clang diagnostic pop#else    if (dispatch_get_specific([GPUImageContext contextKey]))#endif    {        block();    }else    {        dispatch_async(videoProcessingQueue, block);    }}void runSynchronouslyOnContextQueue(GPUImageContext *context, void (^block)(void)){    dispatch_queue_t videoProcessingQueue = [context contextQueue];#if !OS_OBJECT_USE_OBJC#pragma clang diagnostic push#pragma clang diagnostic ignored "-Wdeprecated-declarations"    if (dispatch_get_current_queue() == videoProcessingQueue)#pragma clang diagnostic pop#else        if (dispatch_get_specific([GPUImageContext contextKey]))#endif        {            block();        }else        {            dispatch_sync(videoProcessingQueue, block);        }}void runAsynchronouslyOnContextQueue(GPUImageContext *context, void (^block)(void)){    dispatch_queue_t videoProcessingQueue = [context contextQueue];    #if !OS_OBJECT_USE_OBJC#pragma clang diagnostic push#pragma clang diagnostic ignored "-Wdeprecated-declarations"    if (dispatch_get_current_queue() == videoProcessingQueue)#pragma clang diagnostic pop#else        if (dispatch_get_specific([GPUImageContext contextKey]))#endif        {            block();        }else        {            dispatch_async(videoProcessingQueue, block);        }}void reportAvailableMemoryForGPUImage(NSString *tag) {        if (!tag)        tag = @"Default";        struct task_basic_info info;        mach_msg_type_number_t size = sizeof(info);        kern_return_t kerr = task_info(mach_task_self(),                                                                      TASK_BASIC_INFO,                                                                      (task_info_t)&info,                                                                      &size);        if( kerr == KERN_SUCCESS ) {                NSLog(@"%@ - Memory used: %u", tag, (unsigned int)info.resident_size); //in bytes    } else {                NSLog(@"%@ - Error: %s", tag, mach_error_string(kerr));            }    }@implementation GPUImageOutput@synthesize shouldSmoothlyScaleOutput = _shouldSmoothlyScaleOutput;@synthesize shouldIgnoreUpdatesToThisTarget = _shouldIgnoreUpdatesToThisTarget;@synthesize audioEncodingTarget = _audioEncodingTarget;@synthesize targetToIgnoreForUpdates = _targetToIgnoreForUpdates;@synthesize frameProcessingCompletionBlock = _frameProcessingCompletionBlock;@synthesize enabled = _enabled;@synthesize outputTextureOptions = _outputTextureOptions;#pragma mark -#pragma mark Initialization and teardown- (id)init; {    if (!(self = [super init]))    {        return nil;    }    targets = [[NSMutableArray alloc] init];    targetTextureIndices = [[NSMutableArray alloc] init];    _enabled = YES;    allTargetsWantMonochromeData = YES;    usingNextFrameForImageCapture = NO;        // set default texture options    _outputTextureOptions.minFilter = GL_LINEAR;    _outputTextureOptions.magFilter = GL_LINEAR;    _outputTextureOptions.wrapS = GL_CLAMP_TO_EDGE;    _outputTextureOptions.wrapT = GL_CLAMP_TO_EDGE;    _outputTextureOptions.internalFormat = GL_RGBA;    _outputTextureOptions.format = GL_BGRA;    _outputTextureOptions.type = GL_UNSIGNED_BYTE;    return self;}- (void)dealloc {    [self removeAllTargets];}#pragma mark -#pragma mark Managing targets- (void)setInputFramebufferForTarget:(id<GPUImageInput>)target atIndex:(NSInteger)inputTextureIndex;{    [target setInputFramebuffer:[self framebufferForOutput] atIndex:inputTextureIndex];}- (GPUImageFramebuffer *)framebufferForOutput;{    return outputFramebuffer;}- (void)removeOutputFramebuffer;{    outputFramebuffer = nil;}- (void)notifyTargetsAboutNewOutputTexture;{    for (id<GPUImageInput> currentTarget in targets)    {        NSInteger indexOfObject = [targets indexOfObject:currentTarget];        NSInteger textureIndex = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue];                [self setInputFramebufferForTarget:currentTarget atIndex:textureIndex];    }}- (NSArray*)targets;{    return [NSArray arrayWithArray:targets];}- (void)addTarget:(id<GPUImageInput>)newTarget;{    NSInteger nextAvailableTextureIndex = [newTarget nextAvailableTextureIndex];    [self addTarget:newTarget atTextureLocation:nextAvailableTextureIndex];        if ([newTarget shouldIgnoreUpdatesToThisTarget])    {        _targetToIgnoreForUpdates = newTarget;    }}- (void)addTarget:(id<GPUImageInput>)newTarget atTextureLocation:(NSInteger)textureLocation;{    if([targets containsObject:newTarget])    {        return;    }        cachedMaximumOutputSize = CGSizeZero;    runSynchronouslyOnVideoProcessingQueue(^{        [self setInputFramebufferForTarget:newTarget atIndex:textureLocation];        [targets addObject:newTarget];        [targetTextureIndices addObject:[NSNumber numberWithInteger:textureLocation]];                allTargetsWantMonochromeData = allTargetsWantMonochromeData && [newTarget wantsMonochromeInput];    });}- (void)removeTarget:(id<GPUImageInput>)targetToRemove;{    if(![targets containsObject:targetToRemove])    {        return;    }        if (_targetToIgnoreForUpdates == targetToRemove)    {        _targetToIgnoreForUpdates = nil;    }        cachedMaximumOutputSize = CGSizeZero;        NSInteger indexOfObject = [targets indexOfObject:targetToRemove];    NSInteger textureIndexOfTarget = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue];    runSynchronouslyOnVideoProcessingQueue(^{        [targetToRemove setInputSize:CGSizeZero atIndex:textureIndexOfTarget];        [targetToRemove setInputRotation:kGPUImageNoRotation atIndex:textureIndexOfTarget];        [targetTextureIndices removeObjectAtIndex:indexOfObject];        [targets removeObject:targetToRemove];        [targetToRemove endProcessing];    });}- (void)removeAllTargets;{    cachedMaximumOutputSize = CGSizeZero;    runSynchronouslyOnVideoProcessingQueue(^{        for (id<GPUImageInput> targetToRemove in targets)        {            NSInteger indexOfObject = [targets indexOfObject:targetToRemove];            NSInteger textureIndexOfTarget = [[targetTextureIndices objectAtIndex:indexOfObject] integerValue];                        [targetToRemove setInputSize:CGSizeZero atIndex:textureIndexOfTarget];            [targetToRemove setInputRotation:kGPUImageNoRotation atIndex:textureIndexOfTarget];        }        [targets removeAllObjects];        [targetTextureIndices removeAllObjects];                allTargetsWantMonochromeData = YES;    });}#pragma mark -#pragma mark Manage the output texture- (void)forceProcessingAtSize:(CGSize)frameSize;{    }- (void)forceProcessingAtSizeRespectingAspectRatio:(CGSize)frameSize;{}#pragma mark -#pragma mark Still image processing- (void)useNextFrameForImageCapture;{}- (CGImageRef)newCGImageFromCurrentlyProcessedOutput;{    return nil;}- (CGImageRef)newCGImageByFilteringCGImage:(CGImageRef)imageToFilter;{    GPUImagePicture *stillImageSource = [[GPUImagePicture alloc] initWithCGImage:imageToFilter];        [self useNextFrameForImageCapture];    [stillImageSource addTarget:(id<GPUImageInput>)self];    [stillImageSource processImage];        CGImageRef processedImage = [self newCGImageFromCurrentlyProcessedOutput];        [stillImageSource removeTarget:(id<GPUImageInput>)self];    return processedImage;}- (BOOL)providesMonochromeOutput;{    return NO;}#pragma mark -#pragma mark Platform-specific image output methods#if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE- (UIImage *)imageFromCurrentFramebuffer;{    UIDeviceOrientation deviceOrientation = [[UIDevice currentDevice] orientation];    UIImageOrientation imageOrientation = UIImageOrientationLeft;    switch (deviceOrientation)    {        case UIDeviceOrientationPortrait:            imageOrientation = UIImageOrientationUp;            break;        case UIDeviceOrientationPortraitUpsideDown:            imageOrientation = UIImageOrientationDown;            break;        case UIDeviceOrientationLandscapeLeft:            imageOrientation = UIImageOrientationLeft;            break;        case UIDeviceOrientationLandscapeRight:            imageOrientation = UIImageOrientationRight;            break;        default:            imageOrientation = UIImageOrientationUp;            break;    }        return [self imageFromCurrentFramebufferWithOrientation:imageOrientation];}- (UIImage *)imageFromCurrentFramebufferWithOrientation:(UIImageOrientation)imageOrientation;{    CGImageRef cgImageFromBytes = [self newCGImageFromCurrentlyProcessedOutput];    UIImage *finalImage = [UIImage imageWithCGImage:cgImageFromBytes scale:1.0 orientation:imageOrientation];    CGImageRelease(cgImageFromBytes);        return finalImage;}- (UIImage *)imageByFilteringImage:(UIImage *)imageToFilter;{    CGImageRef image = [self newCGImageByFilteringCGImage:[imageToFilter CGImage]];    UIImage *processedImage = [UIImage imageWithCGImage:image scale:[imageToFilter scale] orientation:[imageToFilter imageOrientation]];    CGImageRelease(image);    return processedImage;}- (CGImageRef)newCGImageByFilteringImage:(UIImage *)imageToFilter{    return [self newCGImageByFilteringCGImage:[imageToFilter CGImage]];}#else- (NSImage *)imageFromCurrentFramebuffer;{    return [self imageFromCurrentFramebufferWithOrientation:UIImageOrientationLeft];}- (NSImage *)imageFromCurrentFramebufferWithOrientation:(UIImageOrientation)imageOrientation;{    CGImageRef cgImageFromBytes = [self newCGImageFromCurrentlyProcessedOutput];    NSImage *finalImage = [[NSImage alloc] initWithCGImage:cgImageFromBytes size:NSZeroSize];    CGImageRelease(cgImageFromBytes);        return finalImage;}- (NSImage *)imageByFilteringImage:(NSImage *)imageToFilter;{    CGImageRef image = [self newCGImageByFilteringCGImage:[imageToFilter CGImageForProposedRect:NULL context:[NSGraphicsContext currentContext] hints:nil]];    NSImage *processedImage = [[NSImage alloc] initWithCGImage:image size:NSZeroSize];    CGImageRelease(image);    return processedImage;}- (CGImageRef)newCGImageByFilteringImage:(NSImage *)imageToFilter{    return [self newCGImageByFilteringCGImage:[imageToFilter CGImageForProposedRect:NULL context:[NSGraphicsContext currentContext] hints:nil]];}#endif#pragma mark -#pragma mark accessors- (void)setAudioEncodingTarget:(GPUImageMovieWriter *)newValue;{        _audioEncodingTarget = newValue;    if( ! _audioEncodingTarget.hasAudioTrack )    {        _audioEncodingTarget.hasAudioTrack = YES;    }}-(void)setOutputTextureOptions:(GPUTextureOptions)outputTextureOptions{    _outputTextureOptions = outputTextureOptions;        if( outputFramebuffer.texture )    {        glBindTexture(GL_TEXTURE_2D,  outputFramebuffer.texture);        //_outputTextureOptions.format        //_outputTextureOptions.internalFormat        //_outputTextureOptions.magFilter        //_outputTextureOptions.minFilter        //_outputTextureOptions.type        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _outputTextureOptions.wrapS);        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _outputTextureOptions.wrapT);        glBindTexture(GL_TEXTURE_2D, 0);    }}@end

 


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表