developer
2023-05-20 e12c7b4c22df631ebdcd16b2f98fbef8f738f92f
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#import "GPUImageiOSBlurFilter.h"
#import "GPUImageSaturationFilter.h"
#import "GPUImageGaussianBlurFilter.h"
#import "GPUImageLuminanceRangeFilter.h"
 
@implementation GPUImageiOSBlurFilter
 
@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];
    
    // Third pass: upsample and adjust luminance range
    luminanceRangeFilter = [[GPUImageLuminanceRangeFilter alloc] init];
    [self addFilter:luminanceRangeFilter];
        
    [saturationFilter addTarget:blurFilter];
    [blurFilter addTarget:luminanceRangeFilter];
    
    self.initialFilters = [NSArray arrayWithObject:saturationFilter];
    self.terminalFilter = luminanceRangeFilter;
    
    self.blurRadiusInPixels = 12.0;
    self.saturation = 0.8;
    self.downsampling = 4.0;
    self.rangeReductionFactor = 0.6;
 
    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)];
        [luminanceRangeFilter forceProcessingAtSize:rotatedSize];
    }
    
    [super setInputSize:newSize atIndex:textureIndex];
}
 
#pragma mark -
#pragma mark Accessors
 
// 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;
}
 
- (void)setRangeReductionFactor:(CGFloat)rangeReductionFactor
{
    luminanceRangeFilter.rangeReductionFactor = rangeReductionFactor;
}
 
- (CGFloat)rangeReductionFactor
{
    return luminanceRangeFilter.rangeReductionFactor;
}
 
@end