learning-ios
learning-ios

Reputation: 61

How to add a GPUImageAlphaBlendFilter to GPUImageFilterGroup

I am working on a project that requires a group of effects.

I am successfully using filterGroup as per the example in the FilterShowcase as follows:

filter = [[GPUImageFilterGroup alloc] init];

GPUImageSepiaFilter *sepiaFilter = [[GPUImageSepiaFilter alloc] init];
[(GPUImageFilterGroup *)filter addFilter:sepiaFilter];

GPUImagePixellateFilter *pixellateFilter = [[GPUImagePixellateFilter alloc] init];
[(GPUImageFilterGroup *)filter addFilter:pixellateFilter];

[sepiaFilter addTarget:pixellateFilter];
[(GPUImageFilterGroup *)filter setInitialFilters:[NSArray arrayWithObject:sepiaFilter]];
[(GPUImageFilterGroup *)filter setTerminalFilter:pixellateFilter]; code here

But now I would like to add a new filter to the group like GPUIMAGE_HARRISCORNERDETECTION this filter also requires a blend.

Here is the filter initialization:

filter = [[GPUImageHarrisCornerDetectionFilter alloc] init];
[(GPUImageHarrisCornerDetectionFilter *)filter setThreshold:0.20];     

and then it requires the blending as follows:

GPUImageCrosshairGenerator *crosshairGenerator = [[GPUImageCrosshairGenerator alloc] init];
crosshairGenerator.crosshairWidth = 15.0;
[crosshairGenerator forceProcessingAtSize:CGSizeMake(480.0, 640.0)];

[(GPUImageHarrisCornerDetectionFilter *)filter setCornersDetectedBlock:^(GLfloat* cornerArray, NSUInteger cornersDetected, CMTime frameTime) {
    [crosshairGenerator renderCrosshairsFromArray:cornerArray count:cornersDetected frameTime:frameTime];
}];

GPUImageAlphaBlendFilter *blendFilter = [[GPUImageAlphaBlendFilter alloc] init];
[blendFilter forceProcessingAtSize:CGSizeMake(480.0, 640.0)];
GPUImageGammaFilter *gammaFilter = [[GPUImageGammaFilter alloc] init];
[videoCamera addTarget:gammaFilter];
[gammaFilter addTarget:blendFilter];

[crosshairGenerator addTarget:blendFilter];

[blendFilter addTarget:filterView];

Is there a way to add the GPUImageCrosshairGenerator, GPUImageAlphaBlendFilter, & GPUImageGammaFilter to the filter group?

Thank you

More specific detail follows:

=============================================

Code that works based on FilterShowcase example: The test class GPUImageDrawTriangleTest simply draws random triangles over the live video source

self.title = @"DRAWING TRIANGLES TESTING";

triangleFilter = [[GPUImageDrawTriangleTest alloc] init];
[((GPUImageDrawTriangleTest *)particleFilter) setDrawColorRed:1.0 green:0.0 blue:1.0];

filter = [[GPUImageContrastFilter alloc] init];

__unsafe_unretained GPUImageDrawTriangleTest *weakGPUImageTestCust = (GPUImageDrawTriangleTest *)triangleFilter;

[filter  setFrameProcessingCompletionBlock:^(GPUImageOutput * filter, CMTime frameTime){
    [weakGPUImageTestCust update:frameTime];
}];

blendingFilters = TRUE;

blendFilter = nil;
blendFilter = [[GPUImageAlphaBlendFilter alloc] init];
[blendFilter forceProcessingAtSize:CGSizeMake(640.0, 480.0)];

GPUImageGammaFilter *gammaFilter = [[GPUImageGammaFilter alloc] init];

[videoCamera addTarget:gammaFilter];
[gammaFilter addTarget:blendFilter];

blendFilter.mix = 1.0;

[triangleFilter  addTarget:blendFilter];
[filter  addTarget:blendFilter];

[blendFilter addTarget:filterView];

[filter  addTarget:filterView];

[videoCamera addTarget:filter];

Based on the FilterShowcase example and the template of the GPUImageUnsharpMaskFilter group I created GPUImageParticleGroupTest

#import "GPUImageParticleGroupTest.h"

#import "GPUImageFilter.h"
#import "GPUImageGammaFilter.h"
#import "GPUImageDrawTriangleTest.h"
#import "GPUImageContrastFilter.h"
#import "GPUImageAlphaBlendFilter.h"

#import "GPUImageDrawTriangleTest.h"

@implementation GPUImageParticleGroupTest
    - (id)init;
{
    if (!(self = [super init]))
    {
        return nil;
    }

    contrastFilter = [[GPUImageContrastFilter alloc] init];
    [self addFilter:contrastFilter];

    gammaFilter = [[GPUImageGammaFilter alloc] init];
    [self addFilter:gammaFilter];

    triangleFilter = [[GPUImageDrawTriangleTest alloc] init];
    [((GPUImageDrawTriangleTest *)triangleFilter) setDrawColorRed:1.0 green:0.0 blue:1.0];

    //[self addFilter:triangleFilter];

    __unsafe_unretained GPUImageDrawTriangleTest *weakGPUImageTestCust = (GPUImageDrawTriangleTest *)triangleFilter;

    [ contrastFilter  setFrameProcessingCompletionBlock:^(GPUImageOutput * contrastfilter, CMTime frameTime){
        [weakGPUImageTestCust update:frameTime];
    }];

    theblendFilter = [[GPUImageAlphaBlendFilter alloc] init];
    theblendFilter.mix = 1.0;
    [self addFilter:theblendFilter];

    [gammaFilter addTarget:theblendFilter  atTextureLocation:1];

    [triangleFilter  addTarget:theblendFilter  atTextureLocation:1];

    [contrastFilter  addTarget:theblendFilter  atTextureLocation:1];


    self.initialFilters = [NSArray arrayWithObjects:contrastFilter,gammaFilter, nil];
    self.terminalFilter = theblendFilter;

    return self;
}
@end

The intent is that when this group class was instantiated as follows:

filter=  [[GPUImageParticleGroupTest alloc] init];
[filter addTarget:filterView];
[videoCamera addTarget:filter];

I would get the same result and have the same random triangles drawn over live video. The app does not crash but I no longer get any live video or triangles.

Where did I go wrong?

Upvotes: 0

Views: 2445

Answers (1)

Brad Larson
Brad Larson

Reputation: 170309

When dealing with a GPUImageFilterGroup that needs to blend the input image with something generated inside the group, there's only one other thing you need to deal with, and that's making sure targets get added to the blend in the right order.

Look at the GPUImageUnsharpMaskFilter as an example. It takes in input frames to that group, passes them through a blur filter, and then blends the output of that blur filter with the input image. To set this up, it uses the following code:

// First pass: apply a variable Gaussian blur
blurFilter = [[GPUImageGaussianBlurFilter alloc] init];
[self addFilter:blurFilter];

// Second pass: combine the blurred image with the original sharp one
unsharpMaskFilter = [[GPUImageTwoInputFilter alloc] initWithFragmentShaderFromString:kGPUImageUnsharpMaskFragmentShaderString];
[self addFilter:unsharpMaskFilter];

// Texture location 0 needs to be the sharp image for both the blur and the second stage processing
[blurFilter addTarget:unsharpMaskFilter atTextureLocation:1];

self.initialFilters = [NSArray arrayWithObjects:blurFilter, unsharpMaskFilter, nil];
self.terminalFilter = unsharpMaskFilter;

The one new method used here is -addTarget:atTextureLocation:, which makes sure that the input image is added as the first input for both the blur filter and the later blend. Also note that there are two initialFilters for this group, to make sure the input image goes to those two filters.

You'd need to do something similar with the above code, feeding input into the Harris corner detector as well as your blend. It should be reasonably straightforward to do based on the code you already have from the FilterShowcase example and the template of the GPUImageUnsharpMaskFilter group.

Upvotes: 1

Related Questions