1
votes

Hey guys at Stackoverflow!

I need your help within my code. I wrote a little application which blurs the camera in real time.

For this I used the GPUImage framework from Brad Larson (Thanks to Brad Larson)!

Now I want to remove the blur from the camera with an animation. This animation should have a duration of 2 seconds. So I've set up my code to remove the filter from my camera like this:

-(IBAction)BtnPressed:(id)sender {
    [UIView animateWithDuration: 2
                     animations:^{
                         [(GPUImageTiltShiftFilter *)filter setBlurSize:0.0];
                     }];
}

As far as I know the code should work. However, I run the application and push the button, but the filter was not removed within two seconds.

It was removed in less than one second, which means that the code above doesn't work. I tried to put some code to change the alpha with an animation, like this:

-(IBAction)BtnPressed:(id)sender {
    [UIView animateWithDuration: 2
                     animations:^{
                        fstBtn.alpha = 0.0;
                     }];
}

This code worked very well with a duration of two seconds. I can't see a solution for this. I really would appreciate your help.

Thanks in advance,

Noah

1
Loved the way question was asked !!!Nikhil Manapure

1 Answers

2
votes

The difference is [UIView animateWithDuration...] is call for animating UIView's properties, internally using CoreAnimation.

GPUImage filters are not UIViews and you cannot therefore animate any of its properties using UIView animation mechanism.

In order to animate "unblurring" of GPUImage filter, I recommend you to create repeating NSTimer and on each "tick" of timer, lower the filters property (blurSize in your case) a little until it is 0. Once it is zero, invalidate timer, remove the filter from the camera and maybe from all variables and let it dealloc.

Im using this approach and works fine.


You can take a look at my animation methods. I'm using both of those are working fine. They are pretty enough commented, but please don't expect me to give you step by step explanation of the code as it would take a lot of time

- (void)blurIn
{
    if (_bluringTimer) {
        NSLog(@"WARNING: already blurring");
        return;
    }

    //  Blur filter is not yet active
    if ([[self.blurFilter targets] count] == 0) {

        self.blurFilter.blurSize = 0.0f;

        //  Add blur filter to the output
        [self.activeFilter removeTarget:self.gpuImageView];
        [self.activeFilter addTarget:self.blurFilter];

        [self.blurFilter addTarget:self.gpuImageView];
    }

    //  Start timer
    //  Blur animation is faked using timer and in(/de)credementing the filter size
    _bluringTimer = [NSTimer timerWithTimeInterval:0.1
                                            target:self
                                          selector:@selector(blurTimerStep:)
                                          userInfo:@(YES)
                                           repeats:YES];

    [[NSRunLoop mainRunLoop] addTimer:_bluringTimer forMode:NSRunLoopCommonModes];

    NSLog(@"Blur start");
}

- (void)blurOut
{
    if (_bluringTimer) {
        NSLog(@"WARNING: already blurring");
        return;
    }

    _bluringTimer = [NSTimer timerWithTimeInterval:0.05
                                            target:self
                                          selector:@selector(blurTimerStep:)
                                          userInfo:@(NO)
                                           repeats:YES];

    [[NSRunLoop mainRunLoop] addTimer:_bluringTimer forMode:NSRunLoopCommonModes];
}

/**
        One step of blurring timer. This method takes care of incrementing / decrementing blur size of blur filter
        @param timer Timer calling this method
 */
- (void)blurTimerStep:(NSTimer *)timer

{
    static NSInteger Step;

    BOOL blurringIn = [[timer userInfo] boolValue];

    //  Blurring settings
    static NSTimeInterval BlurringDuration = 0.4;
    static CGFloat MaxBlur = 3.0f;

    CGFloat bluringStepsCount = BlurringDuration / timer.timeInterval;
    CGFloat blurSizeStep = MaxBlur/bluringStepsCount;

    //  Make step in blurring
    self.blurFilter.blurSize += (blurringIn ? blurSizeStep : -blurSizeStep);

    Step++;

    if (Step > bluringStepsCount) {
        [_bluringTimer invalidate];
        _bluringTimer = nil;
        Step = 0;

        //  If blurring out, when its done, remove the blur filter from the filters chain
        if (!blurringIn) {
            //  Reset filters chain (remove blur)
            [self.activeFilter removeTarget:self.blurFilter];
            [self.blurFilter removeAllTargets];
            [self.activeFilter addTarget:self.gpuImageView];

            self.blurFilter = nil;
            NSLog(@"Blur filter removed");
        }
    }
}