Skip to content

Instantly share code, notes, and snippets.

@ahti
Created January 28, 2014 05:55
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save ahti/8662879 to your computer and use it in GitHub Desktop.
Save ahti/8662879 to your computer and use it in GitHub Desktop.
GPUImage iOS 7 Blur Effect Filter

GPUImageiOSImageEffect

This is a GPUImage filter designed to match the blur effect with dark/light overlay as seen in Apple's UIImageEffects sample application.

It works like the built-in GPUImageiOSBlurFilter, but adds a blend with a color on top. It matches Apples filters pretty closely but not perfectly.

#import "GPUImageFilterGroup.h"
@class GPUImageSaturationFilter;
@class GPUImageGaussianBlurFilter;
@class GPUImageSolidColorGenerator;
@class GPUImageAlphaBlendFilter;
typedef enum {
GPUImageIOSImageEffectTypeLight,
GPUImageIOSImageEffectTypeExtraLight,
GPUImageIOSImageEffectTypeDark
} GPUImageIOSImageEffectType;
@interface GPUImageiOSImageEffect : GPUImageFilterGroup
{
GPUImageSaturationFilter *saturationFilter;
GPUImageGaussianBlurFilter *blurFilter;
GPUImageSolidColorGenerator *colorGenerator;
GPUImageAlphaBlendFilter *blendFilter;
}
/** A radius in pixels to use for the blur, with a default of 12.0. This adjusts the sigma variable in the Gaussian distribution function.
*/
@property (readwrite, nonatomic) CGFloat blurRadiusInPixels;
/** Saturation ranges from 0.0 (fully desaturated) to 2.0 (max saturation), with 0.8 as the normal level
*/
@property (readwrite, nonatomic) CGFloat saturation;
/** The degree to which to downsample, then upsample the incoming image to minimize computations within the Gaussian blur, default of 4.0
*/
@property (readwrite, nonatomic) CGFloat downsampling;
@property (readwrite, nonatomic) GPUImageIOSImageEffectType effectType;
@end
#import "GPUImageiOSImageEffect.h"
#import "GPUImageSaturationFilter.h"
#import "GPUImageGaussianBlurFilter.h"
#import "GPUImageSolidColorGenerator.h"
#import "GPUImageAlphaBlendFilter.h"
@implementation GPUImageiOSImageEffect
@synthesize blurRadiusInPixels;
@synthesize saturation;
@synthesize downsampling = _downsampling;
#pragma mark -
#pragma mark Initialization and teardown
- (id)init;
{
if (!(self = [super init]))
{
return nil;
}
// First pass: downsample and desaturate
saturationFilter = [[GPUImageSaturationFilter alloc] init];
[self addFilter:saturationFilter];
// Second pass: apply a strong Gaussian blur
blurFilter = [[GPUImageGaussianBlurFilter alloc] init];
[self addFilter:blurFilter];
colorGenerator = [[GPUImageSolidColorGenerator alloc] init];
[self addFilter:colorGenerator];
blendFilter = [[GPUImageAlphaBlendFilter alloc] init];
[self addFilter:blendFilter];
[saturationFilter addTarget:blurFilter];
[blurFilter addTarget:blendFilter];
[colorGenerator addTarget:blendFilter];
self.initialFilters = @[saturationFilter];
self.terminalFilter = blendFilter;
self.blurRadiusInPixels = 12.0;
self.saturation = 1.8;
self.downsampling = 4.0;
self.effectType = GPUImageIOSImageEffectTypeLight;
return self;
}
- (void)setInputSize:(CGSize)newSize atIndex:(NSInteger)textureIndex;
{
if (_downsampling > 1.0)
{
CGSize rotatedSize = [saturationFilter rotatedSize:newSize forIndex:textureIndex];
[saturationFilter forceProcessingAtSize:CGSizeMake(rotatedSize.width / _downsampling, rotatedSize.height / _downsampling)];
[colorGenerator forceProcessingAtSize:rotatedSize];
[blendFilter forceProcessingAtSize:rotatedSize];
}
[super setInputSize:newSize atIndex:textureIndex];
}
#pragma mark -
#pragma mark Accessors
- (void)setEffectType:(GPUImageIOSImageEffectType)effectType
{
_effectType = effectType;
switch (effectType) {
case GPUImageIOSImageEffectTypeLight:
[colorGenerator setColorRed:1 green:1 blue:1 alpha:1];
blendFilter.mix = 0.3;
break;
case GPUImageIOSImageEffectTypeExtraLight:
[colorGenerator setColorRed:0.97 green:0.97 blue:0.97 alpha:1];
blendFilter.mix = 0.82;
break;
case GPUImageIOSImageEffectTypeDark:
[colorGenerator setColorRed:0.11 green:0.11 blue:0.11 alpha:1];
blendFilter.mix = 0.73;
break;
}
}
// From Apple's UIImage+ImageEffects category:
// A description of how to compute the box kernel width from the Gaussian
// radius (aka standard deviation) appears in the SVG spec:
// http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement
//
// For larger values of 's' (s >= 2.0), an approximation can be used: Three
// successive box-blurs build a piece-wise quadratic convolution kernel, which
// approximates the Gaussian kernel to within roughly 3%.
//
// let d = floor(s * 3*sqrt(2*pi)/4 + 0.5)
//
// ... if d is odd, use three box-blurs of size 'd', centered on the output pixel.
- (void)setBlurRadiusInPixels:(CGFloat)newValue;
{
blurFilter.blurRadiusInPixels = newValue;
}
- (CGFloat)blurRadiusInPixels;
{
return blurFilter.blurRadiusInPixels;
}
- (void)setSaturation:(CGFloat)newValue;
{
saturationFilter.saturation = newValue;
}
- (CGFloat)saturation;
{
return saturationFilter.saturation;
}
- (void)setDownsampling:(CGFloat)newValue;
{
_downsampling = newValue;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment