Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for tint color and saturation #4

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions FXBlurView/FXBlurView.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,7 @@
@property (nonatomic, assign) NSUInteger iterations;
@property (nonatomic, assign) NSTimeInterval updateInterval;
@property (nonatomic, assign) CGFloat blurRadius;
@property (nonatomic, assign) CGFloat backgroundAlpha;
@property (nonatomic, assign) CGFloat saturationDeltaFactor;

@end
81 changes: 76 additions & 5 deletions FXBlurView/FXBlurView.m
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

@implementation UIImage (FXBlurView)

- (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)iterations
- (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)iterations overlayColor:(UIColor *)overlayColor saturationDelta:(CGFloat)saturationDelta
{
//image must be nonzero size
if (floorf(self.size.width) * floorf(self.size.height) <= 0.0f) return self;
Expand Down Expand Up @@ -77,6 +77,23 @@ - (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)itera
buffer2.data = temp;
}

if (saturationDelta != 0) {
CGFloat s = saturationDelta;
CGFloat floatingPointSaturationMatrix[] = {
0.0722 + 0.9278 * s, 0.0722 - 0.0722 * s, 0.0722 - 0.0722 * s, 0,
0.7152 - 0.7152 * s, 0.7152 + 0.2848 * s, 0.7152 - 0.7152 * s, 0,
0.2126 - 0.2126 * s, 0.2126 - 0.2126 * s, 0.2126 + 0.7873 * s, 0,
0, 0, 0, 1,
};
const int32_t divisor = 256;
NSUInteger matrixSize = sizeof(floatingPointSaturationMatrix)/sizeof(floatingPointSaturationMatrix[0]);
int16_t saturationMatrix[matrixSize];
for (NSUInteger i = 0; i < matrixSize; ++i) {
saturationMatrix[i] = (int16_t)roundf(floatingPointSaturationMatrix[i] * divisor);
}
vImageMatrixMultiply_ARGB8888(&buffer1, &buffer2, saturationMatrix, divisor, NULL, NULL, kvImageNoFlags);
}

//free buffers
free(buffer2.data);
free(tempBuffer);
Expand All @@ -86,8 +103,16 @@ - (UIImage *)blurredImageWithRadius:(CGFloat)radius iterations:(NSUInteger)itera
8, buffer1.rowBytes, CGImageGetColorSpace(imageRef),
CGImageGetBitmapInfo(imageRef));

if (overlayColor) {
CGContextSaveGState(ctx);
CGContextSetFillColorWithColor(ctx, overlayColor.CGColor);
CGContextFillRect(ctx, CGRectMake(0, 0, self.size.width, self.size.height));
CGContextRestoreGState(ctx);
}

//create image from context
imageRef = CGBitmapContextCreateImage(ctx);

UIImage *image = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation];
CGImageRelease(imageRef);
CGContextRelease(ctx);
Expand All @@ -107,6 +132,9 @@ @interface FXBlurView ()
@property (nonatomic, assign) BOOL iterationsSet;
@property (nonatomic, assign) BOOL blurRadiusSet;
@property (nonatomic, assign) BOOL dynamicSet;
@property (nonatomic, assign) BOOL saturationDeltaSet;
@property (nonatomic, assign) BOOL backgroundAlphaSet;
@property (nonatomic, copy) UIColor *overlayColor;

@end

Expand Down Expand Up @@ -134,6 +162,8 @@ - (void)setUp
if (!_iterationsSet) _iterations = 3;
if (!_blurRadiusSet) _blurRadius = 40.0f;
if (!_dynamicSet) _dynamic = YES;
if (!_saturationDeltaSet) _saturationDeltaFactor = 0;
if (!_backgroundAlpha) _backgroundAlpha = 0;

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(updateAsynchronously)
Expand Down Expand Up @@ -165,6 +195,21 @@ - (void)dealloc
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)setSaturationDeltaFactor:(CGFloat)saturationDeltaFactor
{
_saturationDeltaSet = YES;
_saturationDeltaFactor = saturationDeltaFactor;
[self setNeedsDisplay];
}

- (void)setBackgroundAlpha:(CGFloat)backgroundAlpha
{
_backgroundAlphaSet = YES;
_backgroundAlpha = backgroundAlpha;
self.overlayColor = nil;
[self setNeedsDisplay];
}

- (void)setIterations:(NSUInteger)iterations
{
_iterationsSet = YES;
Expand All @@ -186,13 +231,39 @@ - (void)setDynamic:(BOOL)dynamic
[self updateAsynchronously];
}

- (UIColor *)overlayColor
{
if (!_overlayColor) {

int componentCount = CGColorGetNumberOfComponents(self.backgroundColor.CGColor);
if (componentCount == 2)
{
CGFloat b;
if ([self.backgroundColor getWhite:&b alpha:NULL])
{
self.overlayColor = [UIColor colorWithWhite:b alpha:self.backgroundAlpha];
}
}
else
{
CGFloat r, g, b;
if ([self.backgroundColor getRed:&r green:&g blue:&b alpha:NULL])
{
self.overlayColor = [UIColor colorWithRed:r green:g blue:b alpha:self.backgroundAlpha];
}
}
}

return _overlayColor;
}

- (void)willMoveToSuperview:(UIView *)superview
{
[super willMoveToSuperview:superview];
if (superview)
{
UIImage *snapshot = [self snapshotOfSuperview:superview];
UIImage *blurredImage = [snapshot blurredImageWithRadius:self.blurRadius iterations:self.iterations];
UIImage *blurredImage = [snapshot blurredImageWithRadius:self.blurRadius iterations:self.iterations overlayColor:[self overlayColor] saturationDelta:self.saturationDeltaFactor];
self.layer.contents = (id)blurredImage.CGImage;
}
}
Expand All @@ -217,7 +288,7 @@ - (void)displayLayer:(CALayer *)layer
self.hidden = YES;
UIImage *snapshot = [self snapshotOfSuperview:self.superview];
self.hidden = wasHidden;
UIImage *blurredImage = [snapshot blurredImageWithRadius:self.blurRadius iterations:self.iterations];
UIImage *blurredImage = [snapshot blurredImageWithRadius:self.blurRadius iterations:self.iterations overlayColor:[self overlayColor] saturationDelta:self.saturationDeltaFactor];
self.layer.contents = (id)blurredImage.CGImage;
}
}
Expand Down Expand Up @@ -245,7 +316,7 @@ - (void)updateAsynchronously
self.updating = YES;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{

UIImage *blurredImage = [snapshot blurredImageWithRadius:self.blurRadius iterations:self.iterations];
UIImage *blurredImage = [snapshot blurredImageWithRadius:self.blurRadius iterations:self.iterations overlayColor:[self overlayColor] saturationDelta:self.saturationDeltaFactor];
dispatch_sync(dispatch_get_main_queue(), ^{

self.layer.contents = (id)blurredImage.CGImage;
Expand All @@ -258,7 +329,7 @@ - (void)updateAsynchronously
else
{
[self performSelectorOnMainThread:@selector(updateAsynchronously) withObject:nil
waitUntilDone:NO modes:@[NSDefaultRunLoopMode, UITrackingRunLoopMode]];
waitUntilDone:NO modes:@[NSDefaultRunLoopMode, UITrackingRunLoopMode]];
}
});
});
Expand Down