且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

GPUImage动画高斯模糊滤镜

更新时间:2023-02-26 19:24:07

有趣的问题.***的选择是在您的范围内以几个模糊比例预先计算和渲染CGImage,然后使用两个堆叠的UIImageView,最上面的一个显示模糊副本,但部分透明.例如,如果以1、2、3,…,10的半径渲染了模糊的图像,并且想要显示3.7,则在底部显示图像3,在顶部显示图像4,不透明度为70%.

interesting question. Your best bet is to pre-compute and render CGImages at a couple of blur scales in your range, then use two stacked UIImageViews, with the one on top showing the blurrier copy but partially transparent. For example, if you rendered blurred at radiuses 1,2,3,…,10, and you wanted to show 3.7, you'd show image 3 on the bottom and image 4 on the top, at 70% opacity.

// Created in answer to Nikhil Varma's question at http://***.com/questions/18804668/gpuimage-animated-gaussian-blur-filter
#import "GPUImage.h"
#define BLUR_STEP 2.
@interface AHViewController : UIViewController

@property (weak, nonatomic) IBOutlet UIImageView *imageView2;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@property (nonatomic) CGFloat blurRadius;
@property (nonatomic, strong) UIImage *image;
@property (nonatomic, strong) GPUImageGaussianBlurFilter *blurFilter;
@property (nonatomic, strong) NSCache *blurredImageCache;
@property (nonatomic, strong) dispatch_queue_t blurQueue;
@property (nonatomic, strong) NSMutableSet *blurAmountsBeingRendered;
@end

@implementation AHViewController

-(void)viewDidLoad {
    [super viewDidLoad];
    self.image = [UIImage imageNamed:@"ph.jpg"];
    self.blurFilter = [GPUImageGaussianBlurFilter new];
    self.blurredImageCache = [NSCache new];
    self.blurQueue = dispatch_queue_create("Image Blur Queue", DISPATCH_QUEUE_SERIAL);
    self.blurAmountsBeingRendered = [NSMutableSet set];
    self.blurRadius = 1.0;
}
- (IBAction)sliderDidMove:(UISlider *)sender {
    self.blurRadius = 10 * sender.value;
}
-(void)setBlurRadius:(CGFloat)blurRadius {
    _blurRadius = blurRadius;
    CGFloat smaller = self.blurRadius - fmodf(self.blurRadius, BLUR_STEP);
    [self asyncGenerateImageWithBlurAmount:smaller];
    CGFloat larger = smaller + BLUR_STEP;
    [self asyncGenerateImageWithBlurAmount:larger];

}
-(UIImage *)cachedImageWithBlurAmount:(CGFloat)blur {
    return [self.blurredImageCache objectForKey:@(blur)];
}
-(void)asyncGenerateImageWithBlurAmount:(CGFloat)blur {
    // This image is already available.
    if([self.blurredImageCache objectForKey:@(blur)]) {
        [self imageIsAvailableWithBlur:blur];
        return;
    }
    // There's already a render going on for this. Just return.
    if([self.blurAmountsBeingRendered containsObject:@(blur)])
        return;

    // Start a render
    [self.blurAmountsBeingRendered addObject:@(blur)];
    dispatch_async(self.blurQueue, ^{
        self.blurFilter.blurSize = blur;
        UIImage *result = [self.blurFilter imageByFilteringImage:self.image];
        [self.blurredImageCache setObject:result forKey:@(blur)];
        [self.blurAmountsBeingRendered removeObject:@(blur)];
        dispatch_async(dispatch_get_main_queue(), ^{
            [self imageIsAvailableWithBlur:blur];
        });
    });
}

-(void)imageIsAvailableWithBlur:(CGFloat)blurAmount {
    CGFloat smaller = self.blurRadius - fmodf(self.blurRadius, BLUR_STEP);
    CGFloat larger = smaller + BLUR_STEP;

    UIImage *sharperImage = [self cachedImageWithBlurAmount:smaller];
    UIImage *blurrier = [self cachedImageWithBlurAmount:larger];
    if(sharperImage && blurrier) {
        if(![self.imageView.image isEqual:sharperImage])
            self.imageView.image = sharperImage;
        if(![self.imageView2.image isEqual:blurrier]) {
            self.imageView2.image = blurrier;
        }
        self.imageView2.alpha = (self.blurRadius - smaller) / BLUR_STEP;
    }
}


@end