├── .gitignore ├── RCBlurredImageView.gif ├── RCBlurredImageView ├── RCBlurredImageView.h └── RCBlurredImageView.m ├── RCBlurredImageViewTestApp.xcodeproj └── project.pbxproj ├── RCBlurredImageViewTestApp ├── Default-568h@2x.png ├── Default.png ├── Default@2x.png ├── RCAppDelegate.h ├── RCAppDelegate.m ├── RCBlurredImageViewTestApp-Info.plist ├── RCBlurredImageViewTestApp-Prefix.pch ├── RCTestViewController.h ├── RCTestViewController.m ├── en.lproj │ └── InfoPlist.strings ├── main.m ├── test.jpg └── test@2x.jpg └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | *.xcworkspace 13 | !default.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .idea/ 19 | -------------------------------------------------------------------------------- /RCBlurredImageView.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rcameron/RCBlurredImageView/e7e7bec5112661a838f39858b479409ce4a802af/RCBlurredImageView.gif -------------------------------------------------------------------------------- /RCBlurredImageView/RCBlurredImageView.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCBlurredImageView.h 3 | // 4 | // Permission is hereby granted, free of charge, to any person obtaining a copy 5 | // of this software and associated documentation files (the "Software"), to deal 6 | // in the Software without restriction, including without limitation the rights 7 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | // copies of the Software, and to permit persons to whom the Software is 9 | // furnished to do so, subject to the following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included in 12 | // all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | // THE SOFTWARE.Copyright (c) 2013 Rich Cameron. All rights reserved. 21 | // 22 | 23 | #import 24 | 25 | @interface RCBlurredImageView : UIView 26 | 27 | - (id)initWithImage:(UIImage *)image; 28 | 29 | @property (nonatomic, strong) UIImage *image; // default is nil 30 | @property (nonatomic, assign) CGFloat blurIntensity; // default is 0.f 31 | 32 | @property (nonatomic, assign, getter=isUserInteractionEnabled) BOOL userInteractionEnabled; // default is NO 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /RCBlurredImageView/RCBlurredImageView.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCBlurredImageView.m 3 | // 4 | // Created by Rich Cameron on 5/10/13. 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in 14 | // all copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | // THE SOFTWARE.Copyright (c) 2013 Rich Cameron. All rights reserved. 23 | // 24 | 25 | #import "RCBlurredImageView.h" 26 | 27 | @implementation RCBlurredImageView 28 | { 29 | UIImageView *_imageView; 30 | UIImageView *_blurredImageView; 31 | 32 | BOOL _userInteractionEnabled; 33 | } 34 | 35 | //////////////////////////////////////////////////////// 36 | //////////////////////////////////////////////////////// 37 | #pragma mark - Init 38 | //////////////////////////////////////////////////////// 39 | - (id)initWithImage:(UIImage *)image 40 | { 41 | // Make sure we have an image to work with 42 | if (!image) 43 | return nil; 44 | 45 | // Calculate frame size 46 | CGRect frame = (CGRect){CGPointZero, image.size}; 47 | 48 | self = [super initWithFrame:frame]; 49 | 50 | if (!self) 51 | return nil; 52 | 53 | // Pass along parameters 54 | _image = image; 55 | 56 | [self RCBlurredImageView_commonInit]; 57 | 58 | return self; 59 | } 60 | 61 | //////////////////////////////////////////////////////// 62 | - (void)RCBlurredImageView_commonInit 63 | { 64 | // Make sure we're not subclassed 65 | if ([self class] != [RCBlurredImageView class]) 66 | return; 67 | 68 | // Set user interaction to NO 69 | [self setUserInteractionEnabled:NO]; 70 | 71 | // Set up regular image 72 | _imageView = [[UIImageView alloc] initWithImage:_image]; 73 | [self addSubview:_imageView]; 74 | 75 | // Set blurred image 76 | _blurredImageView = [[UIImageView alloc] initWithImage:[self blurredImage]]; 77 | [_blurredImageView setAlpha:0.95f]; 78 | 79 | if (_blurredImageView) 80 | [self addSubview:_blurredImageView]; 81 | 82 | NSLog(@"imageview frame = %@", NSStringFromCGRect(_imageView.frame)); 83 | NSLog(@"blurred frame = %@", NSStringFromCGRect(_blurredImageView.frame)); 84 | } 85 | 86 | 87 | //////////////////////////////////////////////////////// 88 | //////////////////////////////////////////////////////// 89 | #pragma mark - Blur 90 | //////////////////////////////////////////////////////// 91 | /* 92 | ======================== 93 | - (UIImage *)blurredImage 94 | Description: Returns a Gaussian blurred version of _image 95 | ======================== 96 | */ 97 | - (UIImage *)blurredImage 98 | { 99 | // Make sure that we have an image to work with 100 | if (!_image) 101 | return nil; 102 | 103 | // Create context 104 | CIContext *context = [CIContext contextWithOptions:nil]; 105 | 106 | // Create an image 107 | CIImage *image = [CIImage imageWithCGImage:_image.CGImage]; 108 | 109 | // Set up a Gaussian Blur filter 110 | CIFilter *blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"]; 111 | [blurFilter setValue:image forKey:kCIInputImageKey]; 112 | 113 | // Get blurred image out 114 | CIImage *blurredImage = [blurFilter valueForKey:kCIOutputImageKey]; 115 | 116 | // Set up vignette filter 117 | CIFilter *vignetteFilter = [CIFilter filterWithName:@"CIVignette"]; 118 | [vignetteFilter setValue:blurredImage forKey:kCIInputImageKey]; 119 | [vignetteFilter setValue:@(4.f) forKey:@"InputIntensity"]; 120 | 121 | // get vignette & blurred image 122 | CIImage *vignetteImage = [vignetteFilter valueForKey:kCIOutputImageKey]; 123 | 124 | CGFloat scale = [[UIScreen mainScreen] scale]; 125 | CGSize scaledSize = CGSizeMake(_image.size.width * scale, _image.size.height * scale); 126 | CGImageRef imageRef = [context createCGImage:vignetteImage fromRect:(CGRect){CGPointZero, scaledSize}]; 127 | 128 | return [UIImage imageWithCGImage:imageRef scale:[[UIScreen mainScreen] scale] orientation:UIImageOrientationUp]; 129 | } 130 | 131 | /* 132 | ======================== 133 | - (void)setBlurIntensity 134 | Description: Changes the opacity on the blurred image to change intensity 135 | ======================== 136 | */ 137 | - (void)setBlurIntensity:(CGFloat)blurIntensity 138 | { 139 | if (blurIntensity < 0.f) 140 | blurIntensity = 0.f; 141 | else if (blurIntensity > 1.f) 142 | blurIntensity = 1.f; 143 | 144 | _blurIntensity = blurIntensity; 145 | 146 | [_blurredImageView setAlpha:blurIntensity]; 147 | } 148 | 149 | //////////////////////////////////////////////////////// 150 | @end 151 | -------------------------------------------------------------------------------- /RCBlurredImageViewTestApp.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 96EAAF6F173D8EFE00DEB37E /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96EAAF6E173D8EFE00DEB37E /* UIKit.framework */; }; 11 | 96EAAF71173D8EFE00DEB37E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96EAAF70173D8EFE00DEB37E /* Foundation.framework */; }; 12 | 96EAAF73173D8EFE00DEB37E /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96EAAF72173D8EFE00DEB37E /* CoreGraphics.framework */; }; 13 | 96EAAF79173D8EFE00DEB37E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 96EAAF77173D8EFE00DEB37E /* InfoPlist.strings */; }; 14 | 96EAAF7B173D8EFE00DEB37E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 96EAAF7A173D8EFE00DEB37E /* main.m */; }; 15 | 96EAAF7F173D8EFE00DEB37E /* RCAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 96EAAF7E173D8EFE00DEB37E /* RCAppDelegate.m */; }; 16 | 96EAAF81173D8EFE00DEB37E /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 96EAAF80173D8EFE00DEB37E /* Default.png */; }; 17 | 96EAAF83173D8EFE00DEB37E /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 96EAAF82173D8EFE00DEB37E /* Default@2x.png */; }; 18 | 96EAAF85173D8EFF00DEB37E /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 96EAAF84173D8EFF00DEB37E /* Default-568h@2x.png */; }; 19 | 96EAAF8F173D8FE900DEB37E /* RCBlurredImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = 96EAAF8E173D8FE900DEB37E /* RCBlurredImageView.m */; }; 20 | 96EAAF91173D94EB00DEB37E /* CoreImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96EAAF90173D94EB00DEB37E /* CoreImage.framework */; }; 21 | 96EAAF94173D986800DEB37E /* RCTestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 96EAAF93173D986800DEB37E /* RCTestViewController.m */; }; 22 | 96EAAF97173D9A3300DEB37E /* test.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 96EAAF95173D9A3300DEB37E /* test.jpg */; }; 23 | 96EAAF98173D9A3300DEB37E /* test@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 96EAAF96173D9A3300DEB37E /* test@2x.jpg */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 96EAAF6B173D8EFE00DEB37E /* RCBlurredImageViewTestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RCBlurredImageViewTestApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | 96EAAF6E173D8EFE00DEB37E /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 29 | 96EAAF70173D8EFE00DEB37E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 30 | 96EAAF72173D8EFE00DEB37E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 31 | 96EAAF76173D8EFE00DEB37E /* RCBlurredImageViewTestApp-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "RCBlurredImageViewTestApp-Info.plist"; sourceTree = ""; }; 32 | 96EAAF78173D8EFE00DEB37E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 33 | 96EAAF7A173D8EFE00DEB37E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 34 | 96EAAF7C173D8EFE00DEB37E /* RCBlurredImageViewTestApp-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RCBlurredImageViewTestApp-Prefix.pch"; sourceTree = ""; }; 35 | 96EAAF7D173D8EFE00DEB37E /* RCAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCAppDelegate.h; sourceTree = ""; }; 36 | 96EAAF7E173D8EFE00DEB37E /* RCAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RCAppDelegate.m; sourceTree = ""; }; 37 | 96EAAF80173D8EFE00DEB37E /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 38 | 96EAAF82173D8EFE00DEB37E /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 39 | 96EAAF84173D8EFF00DEB37E /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 40 | 96EAAF8D173D8FE900DEB37E /* RCBlurredImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCBlurredImageView.h; sourceTree = ""; }; 41 | 96EAAF8E173D8FE900DEB37E /* RCBlurredImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCBlurredImageView.m; sourceTree = ""; }; 42 | 96EAAF90173D94EB00DEB37E /* CoreImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreImage.framework; path = System/Library/Frameworks/CoreImage.framework; sourceTree = SDKROOT; }; 43 | 96EAAF92173D986800DEB37E /* RCTestViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTestViewController.h; sourceTree = ""; }; 44 | 96EAAF93173D986800DEB37E /* RCTestViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTestViewController.m; sourceTree = ""; }; 45 | 96EAAF95173D9A3300DEB37E /* test.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = test.jpg; sourceTree = ""; }; 46 | 96EAAF96173D9A3300DEB37E /* test@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "test@2x.jpg"; sourceTree = ""; }; 47 | /* End PBXFileReference section */ 48 | 49 | /* Begin PBXFrameworksBuildPhase section */ 50 | 96EAAF68173D8EFE00DEB37E /* Frameworks */ = { 51 | isa = PBXFrameworksBuildPhase; 52 | buildActionMask = 2147483647; 53 | files = ( 54 | 96EAAF91173D94EB00DEB37E /* CoreImage.framework in Frameworks */, 55 | 96EAAF6F173D8EFE00DEB37E /* UIKit.framework in Frameworks */, 56 | 96EAAF71173D8EFE00DEB37E /* Foundation.framework in Frameworks */, 57 | 96EAAF73173D8EFE00DEB37E /* CoreGraphics.framework in Frameworks */, 58 | ); 59 | runOnlyForDeploymentPostprocessing = 0; 60 | }; 61 | /* End PBXFrameworksBuildPhase section */ 62 | 63 | /* Begin PBXGroup section */ 64 | 96EAAF62173D8EFE00DEB37E = { 65 | isa = PBXGroup; 66 | children = ( 67 | 96EAAF8C173D8FBF00DEB37E /* RCBlurredImageView */, 68 | 96EAAF74173D8EFE00DEB37E /* RCBlurredImageViewTestApp */, 69 | 96EAAF6D173D8EFE00DEB37E /* Frameworks */, 70 | 96EAAF6C173D8EFE00DEB37E /* Products */, 71 | ); 72 | sourceTree = ""; 73 | }; 74 | 96EAAF6C173D8EFE00DEB37E /* Products */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | 96EAAF6B173D8EFE00DEB37E /* RCBlurredImageViewTestApp.app */, 78 | ); 79 | name = Products; 80 | sourceTree = ""; 81 | }; 82 | 96EAAF6D173D8EFE00DEB37E /* Frameworks */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | 96EAAF90173D94EB00DEB37E /* CoreImage.framework */, 86 | 96EAAF6E173D8EFE00DEB37E /* UIKit.framework */, 87 | 96EAAF70173D8EFE00DEB37E /* Foundation.framework */, 88 | 96EAAF72173D8EFE00DEB37E /* CoreGraphics.framework */, 89 | ); 90 | name = Frameworks; 91 | sourceTree = ""; 92 | }; 93 | 96EAAF74173D8EFE00DEB37E /* RCBlurredImageViewTestApp */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | 96EAAF95173D9A3300DEB37E /* test.jpg */, 97 | 96EAAF96173D9A3300DEB37E /* test@2x.jpg */, 98 | 96EAAF7D173D8EFE00DEB37E /* RCAppDelegate.h */, 99 | 96EAAF7E173D8EFE00DEB37E /* RCAppDelegate.m */, 100 | 96EAAF92173D986800DEB37E /* RCTestViewController.h */, 101 | 96EAAF93173D986800DEB37E /* RCTestViewController.m */, 102 | 96EAAF75173D8EFE00DEB37E /* Supporting Files */, 103 | ); 104 | path = RCBlurredImageViewTestApp; 105 | sourceTree = ""; 106 | }; 107 | 96EAAF75173D8EFE00DEB37E /* Supporting Files */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 96EAAF76173D8EFE00DEB37E /* RCBlurredImageViewTestApp-Info.plist */, 111 | 96EAAF77173D8EFE00DEB37E /* InfoPlist.strings */, 112 | 96EAAF7A173D8EFE00DEB37E /* main.m */, 113 | 96EAAF7C173D8EFE00DEB37E /* RCBlurredImageViewTestApp-Prefix.pch */, 114 | 96EAAF80173D8EFE00DEB37E /* Default.png */, 115 | 96EAAF82173D8EFE00DEB37E /* Default@2x.png */, 116 | 96EAAF84173D8EFF00DEB37E /* Default-568h@2x.png */, 117 | ); 118 | name = "Supporting Files"; 119 | sourceTree = ""; 120 | }; 121 | 96EAAF8C173D8FBF00DEB37E /* RCBlurredImageView */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 96EAAF8D173D8FE900DEB37E /* RCBlurredImageView.h */, 125 | 96EAAF8E173D8FE900DEB37E /* RCBlurredImageView.m */, 126 | ); 127 | path = RCBlurredImageView; 128 | sourceTree = ""; 129 | }; 130 | /* End PBXGroup section */ 131 | 132 | /* Begin PBXNativeTarget section */ 133 | 96EAAF6A173D8EFE00DEB37E /* RCBlurredImageViewTestApp */ = { 134 | isa = PBXNativeTarget; 135 | buildConfigurationList = 96EAAF88173D8EFF00DEB37E /* Build configuration list for PBXNativeTarget "RCBlurredImageViewTestApp" */; 136 | buildPhases = ( 137 | 96EAAF67173D8EFE00DEB37E /* Sources */, 138 | 96EAAF68173D8EFE00DEB37E /* Frameworks */, 139 | 96EAAF69173D8EFE00DEB37E /* Resources */, 140 | ); 141 | buildRules = ( 142 | ); 143 | dependencies = ( 144 | ); 145 | name = RCBlurredImageViewTestApp; 146 | productName = RCBlurredImageView; 147 | productReference = 96EAAF6B173D8EFE00DEB37E /* RCBlurredImageViewTestApp.app */; 148 | productType = "com.apple.product-type.application"; 149 | }; 150 | /* End PBXNativeTarget section */ 151 | 152 | /* Begin PBXProject section */ 153 | 96EAAF63173D8EFE00DEB37E /* Project object */ = { 154 | isa = PBXProject; 155 | attributes = { 156 | CLASSPREFIX = RC; 157 | LastUpgradeCheck = 0460; 158 | ORGANIZATIONNAME = "Rich Cameron"; 159 | }; 160 | buildConfigurationList = 96EAAF66173D8EFE00DEB37E /* Build configuration list for PBXProject "RCBlurredImageViewTestApp" */; 161 | compatibilityVersion = "Xcode 3.2"; 162 | developmentRegion = English; 163 | hasScannedForEncodings = 0; 164 | knownRegions = ( 165 | en, 166 | ); 167 | mainGroup = 96EAAF62173D8EFE00DEB37E; 168 | productRefGroup = 96EAAF6C173D8EFE00DEB37E /* Products */; 169 | projectDirPath = ""; 170 | projectRoot = ""; 171 | targets = ( 172 | 96EAAF6A173D8EFE00DEB37E /* RCBlurredImageViewTestApp */, 173 | ); 174 | }; 175 | /* End PBXProject section */ 176 | 177 | /* Begin PBXResourcesBuildPhase section */ 178 | 96EAAF69173D8EFE00DEB37E /* Resources */ = { 179 | isa = PBXResourcesBuildPhase; 180 | buildActionMask = 2147483647; 181 | files = ( 182 | 96EAAF79173D8EFE00DEB37E /* InfoPlist.strings in Resources */, 183 | 96EAAF81173D8EFE00DEB37E /* Default.png in Resources */, 184 | 96EAAF83173D8EFE00DEB37E /* Default@2x.png in Resources */, 185 | 96EAAF85173D8EFF00DEB37E /* Default-568h@2x.png in Resources */, 186 | 96EAAF97173D9A3300DEB37E /* test.jpg in Resources */, 187 | 96EAAF98173D9A3300DEB37E /* test@2x.jpg in Resources */, 188 | ); 189 | runOnlyForDeploymentPostprocessing = 0; 190 | }; 191 | /* End PBXResourcesBuildPhase section */ 192 | 193 | /* Begin PBXSourcesBuildPhase section */ 194 | 96EAAF67173D8EFE00DEB37E /* Sources */ = { 195 | isa = PBXSourcesBuildPhase; 196 | buildActionMask = 2147483647; 197 | files = ( 198 | 96EAAF7B173D8EFE00DEB37E /* main.m in Sources */, 199 | 96EAAF7F173D8EFE00DEB37E /* RCAppDelegate.m in Sources */, 200 | 96EAAF8F173D8FE900DEB37E /* RCBlurredImageView.m in Sources */, 201 | 96EAAF94173D986800DEB37E /* RCTestViewController.m in Sources */, 202 | ); 203 | runOnlyForDeploymentPostprocessing = 0; 204 | }; 205 | /* End PBXSourcesBuildPhase section */ 206 | 207 | /* Begin PBXVariantGroup section */ 208 | 96EAAF77173D8EFE00DEB37E /* InfoPlist.strings */ = { 209 | isa = PBXVariantGroup; 210 | children = ( 211 | 96EAAF78173D8EFE00DEB37E /* en */, 212 | ); 213 | name = InfoPlist.strings; 214 | sourceTree = ""; 215 | }; 216 | /* End PBXVariantGroup section */ 217 | 218 | /* Begin XCBuildConfiguration section */ 219 | 96EAAF86173D8EFF00DEB37E /* Debug */ = { 220 | isa = XCBuildConfiguration; 221 | buildSettings = { 222 | ALWAYS_SEARCH_USER_PATHS = NO; 223 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 224 | CLANG_CXX_LIBRARY = "libc++"; 225 | CLANG_ENABLE_OBJC_ARC = YES; 226 | CLANG_WARN_CONSTANT_CONVERSION = YES; 227 | CLANG_WARN_EMPTY_BODY = YES; 228 | CLANG_WARN_ENUM_CONVERSION = YES; 229 | CLANG_WARN_INT_CONVERSION = YES; 230 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 231 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 232 | COPY_PHASE_STRIP = NO; 233 | GCC_C_LANGUAGE_STANDARD = gnu99; 234 | GCC_DYNAMIC_NO_PIC = NO; 235 | GCC_OPTIMIZATION_LEVEL = 0; 236 | GCC_PREPROCESSOR_DEFINITIONS = ( 237 | "DEBUG=1", 238 | "$(inherited)", 239 | ); 240 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 241 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 242 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 243 | GCC_WARN_UNUSED_VARIABLE = YES; 244 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 245 | ONLY_ACTIVE_ARCH = YES; 246 | SDKROOT = iphoneos; 247 | }; 248 | name = Debug; 249 | }; 250 | 96EAAF87173D8EFF00DEB37E /* Release */ = { 251 | isa = XCBuildConfiguration; 252 | buildSettings = { 253 | ALWAYS_SEARCH_USER_PATHS = NO; 254 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 255 | CLANG_CXX_LIBRARY = "libc++"; 256 | CLANG_ENABLE_OBJC_ARC = YES; 257 | CLANG_WARN_CONSTANT_CONVERSION = YES; 258 | CLANG_WARN_EMPTY_BODY = YES; 259 | CLANG_WARN_ENUM_CONVERSION = YES; 260 | CLANG_WARN_INT_CONVERSION = YES; 261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 262 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 263 | COPY_PHASE_STRIP = YES; 264 | GCC_C_LANGUAGE_STANDARD = gnu99; 265 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 266 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 267 | GCC_WARN_UNUSED_VARIABLE = YES; 268 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 269 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 270 | SDKROOT = iphoneos; 271 | VALIDATE_PRODUCT = YES; 272 | }; 273 | name = Release; 274 | }; 275 | 96EAAF89173D8EFF00DEB37E /* Debug */ = { 276 | isa = XCBuildConfiguration; 277 | buildSettings = { 278 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 279 | GCC_PREFIX_HEADER = "RCBlurredImageViewTestApp/RCBlurredImageViewTestApp-Prefix.pch"; 280 | INFOPLIST_FILE = "$(SRCROOT)/RCBlurredImageViewTestApp/RCBlurredImageViewTestApp-Info.plist"; 281 | PRODUCT_NAME = RCBlurredImageViewTestApp; 282 | WRAPPER_EXTENSION = app; 283 | }; 284 | name = Debug; 285 | }; 286 | 96EAAF8A173D8EFF00DEB37E /* Release */ = { 287 | isa = XCBuildConfiguration; 288 | buildSettings = { 289 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 290 | GCC_PREFIX_HEADER = "RCBlurredImageViewTestApp/RCBlurredImageViewTestApp-Prefix.pch"; 291 | INFOPLIST_FILE = "$(SRCROOT)/RCBlurredImageViewTestApp/RCBlurredImageViewTestApp-Info.plist"; 292 | PRODUCT_NAME = RCBlurredImageViewTestApp; 293 | WRAPPER_EXTENSION = app; 294 | }; 295 | name = Release; 296 | }; 297 | /* End XCBuildConfiguration section */ 298 | 299 | /* Begin XCConfigurationList section */ 300 | 96EAAF66173D8EFE00DEB37E /* Build configuration list for PBXProject "RCBlurredImageViewTestApp" */ = { 301 | isa = XCConfigurationList; 302 | buildConfigurations = ( 303 | 96EAAF86173D8EFF00DEB37E /* Debug */, 304 | 96EAAF87173D8EFF00DEB37E /* Release */, 305 | ); 306 | defaultConfigurationIsVisible = 0; 307 | defaultConfigurationName = Release; 308 | }; 309 | 96EAAF88173D8EFF00DEB37E /* Build configuration list for PBXNativeTarget "RCBlurredImageViewTestApp" */ = { 310 | isa = XCConfigurationList; 311 | buildConfigurations = ( 312 | 96EAAF89173D8EFF00DEB37E /* Debug */, 313 | 96EAAF8A173D8EFF00DEB37E /* Release */, 314 | ); 315 | defaultConfigurationIsVisible = 0; 316 | defaultConfigurationName = Release; 317 | }; 318 | /* End XCConfigurationList section */ 319 | }; 320 | rootObject = 96EAAF63173D8EFE00DEB37E /* Project object */; 321 | } 322 | -------------------------------------------------------------------------------- /RCBlurredImageViewTestApp/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rcameron/RCBlurredImageView/e7e7bec5112661a838f39858b479409ce4a802af/RCBlurredImageViewTestApp/Default-568h@2x.png -------------------------------------------------------------------------------- /RCBlurredImageViewTestApp/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rcameron/RCBlurredImageView/e7e7bec5112661a838f39858b479409ce4a802af/RCBlurredImageViewTestApp/Default.png -------------------------------------------------------------------------------- /RCBlurredImageViewTestApp/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rcameron/RCBlurredImageView/e7e7bec5112661a838f39858b479409ce4a802af/RCBlurredImageViewTestApp/Default@2x.png -------------------------------------------------------------------------------- /RCBlurredImageViewTestApp/RCAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCAppDelegate.h 3 | // RCBlurredImageView 4 | // 5 | // Created by Rich Cameron on 5/10/13. 6 | // Copyright (c) 2013 Rich Cameron. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RCAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /RCBlurredImageViewTestApp/RCAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCAppDelegate.m 3 | // RCBlurredImageView 4 | // 5 | // Created by Rich Cameron on 5/10/13. 6 | // Copyright (c) 2013 Rich Cameron. All rights reserved. 7 | // 8 | 9 | #import "RCAppDelegate.h" 10 | #import "RCTestViewController.h" 11 | 12 | @implementation RCAppDelegate 13 | 14 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 15 | { 16 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 17 | 18 | // Add controller 19 | RCTestViewController *controller = [[RCTestViewController alloc] init]; 20 | [self.window setRootViewController:controller]; 21 | 22 | self.window.backgroundColor = [UIColor whiteColor]; 23 | [self.window makeKeyAndVisible]; 24 | return YES; 25 | } 26 | 27 | - (void)applicationWillResignActive:(UIApplication *)application 28 | { 29 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 30 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 31 | } 32 | 33 | - (void)applicationDidEnterBackground:(UIApplication *)application 34 | { 35 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 36 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 37 | } 38 | 39 | - (void)applicationWillEnterForeground:(UIApplication *)application 40 | { 41 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 42 | } 43 | 44 | - (void)applicationDidBecomeActive:(UIApplication *)application 45 | { 46 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 47 | } 48 | 49 | - (void)applicationWillTerminate:(UIApplication *)application 50 | { 51 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /RCBlurredImageViewTestApp/RCBlurredImageViewTestApp-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | Blur 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.rcameron.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /RCBlurredImageViewTestApp/RCBlurredImageViewTestApp-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'RCBlurredImageView' target in the 'RCBlurredImageView' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iOS SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /RCBlurredImageViewTestApp/RCTestViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // RCTestViewController.h 3 | // RCBlurredImageViewTestApp 4 | // 5 | // Created by Rich Cameron on 5/10/13. 6 | // Copyright (c) 2013 Rich Cameron. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RCTestViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /RCBlurredImageViewTestApp/RCTestViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // RCTestViewController.m 3 | // RCBlurredImageViewTestApp 4 | // 5 | // Created by Rich Cameron on 5/10/13. 6 | // Copyright (c) 2013 Rich Cameron. All rights reserved. 7 | // 8 | 9 | #import "RCTestViewController.h" 10 | #import "RCBlurredImageView.h" 11 | 12 | CGFloat const kFullBlurOffset = 200; // content offset of the scrollview that will result in the full blur effect 13 | CGFloat const kParallaxRatio = 4; // for every 4 pixels the foreground moves, we'll move the background 1 pixel 14 | CGFloat const kParallaxMax = 10; // our background can move 10 pixels up 15 | 16 | @interface RCTestViewController () 17 | 18 | @end 19 | 20 | @implementation RCTestViewController 21 | { 22 | RCBlurredImageView *_blurredImageView; 23 | 24 | UIScrollView *_scrollView; 25 | } 26 | 27 | //////////////////////////////////////////////////////// 28 | //////////////////////////////////////////////////////// 29 | #pragma mark - Init 30 | //////////////////////////////////////////////////////// 31 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 32 | { 33 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 34 | 35 | if (!self) 36 | return nil; 37 | 38 | return self; 39 | } 40 | 41 | //////////////////////////////////////////////////////// 42 | - (void)loadView 43 | { 44 | // Capture frame 45 | CGRect appFrame = [[UIScreen mainScreen] applicationFrame]; 46 | 47 | // Create a scrollview 48 | self.view = [[UIView alloc] initWithFrame:(CGRect){CGPointZero, appFrame.size}]; 49 | 50 | // Create blurred image view 51 | // Note that our image is 10px taller than the largest iPhone screen (568 + 10px), so we can have a parallax effect 52 | _blurredImageView = [[RCBlurredImageView alloc] initWithImage:[UIImage imageNamed:@"test.jpg"]]; 53 | [_blurredImageView setBlurIntensity:0.f]; 54 | [self.view addSubview:_blurredImageView]; 55 | 56 | // Set up our scrollview above the background 57 | _scrollView = [[UIScrollView alloc] initWithFrame:self.view.bounds]; 58 | [_scrollView setDelegate:self]; 59 | [self.view addSubview:_scrollView]; 60 | 61 | // Add text title 62 | UILabel *titleLabel = [[UILabel alloc] init]; 63 | [titleLabel setFont:[UIFont fontWithName:@"Avenir-Light" size:24.f]]; 64 | [titleLabel setBackgroundColor:[UIColor clearColor]]; 65 | [titleLabel setTextColor:[UIColor whiteColor]]; 66 | [titleLabel setShadowColor:[UIColor colorWithWhite:0.f alpha:0.3f]]; 67 | [titleLabel setShadowOffset:(CGSize){1,1}]; 68 | [titleLabel setText:@"RCBlurredImageView"]; 69 | [titleLabel sizeToFit]; 70 | [_scrollView addSubview:titleLabel]; 71 | 72 | // Position title label 73 | CGFloat margin = 20.f; 74 | CGPoint titleCenter = (CGPoint){margin + (titleLabel.frame.size.width * 0.5f), 75 | appFrame.size.height - margin - (titleLabel.frame.size.height * 0.5f)}; 76 | [titleLabel setCenter:titleCenter]; 77 | 78 | // Calculate scroll view's content size 79 | CGFloat contentHeight = CGRectGetMaxY(titleLabel.frame) + CGRectGetMinY(titleLabel.frame); 80 | CGSize contentSize = (CGSize){appFrame.size.width, contentHeight}; 81 | [_scrollView setContentSize:contentSize]; 82 | [_scrollView setShowsVerticalScrollIndicator:NO]; 83 | 84 | // Add info label 85 | UILabel *infoLabel = [[UILabel alloc] initWithFrame:CGRectMake(margin, 86 | CGRectGetMaxY(titleLabel.frame) + margin, 87 | appFrame.size.width - (margin*2), 88 | appFrame.size.height * 0.5f)]; 89 | [infoLabel setFont:[UIFont fontWithName:@"Avenir-Medium" size:17.f]]; 90 | [infoLabel setBackgroundColor:[UIColor clearColor]]; 91 | [infoLabel setTextColor:[UIColor whiteColor]]; 92 | [infoLabel setLineBreakMode:NSLineBreakByWordWrapping]; 93 | [infoLabel setNumberOfLines:0]; 94 | [infoLabel setText:@"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam vehicula nisi non odio egestas eu consequat purus posuere. Nullam eget eros vitae turpis volutpat consectetur id in est. Curabitur blandit accumsan pharetra. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vivamus rutrum pulvinar arcu, ut interdum tellus rhoncus non. Integer ac nunc laoreet erat suscipit gravida in eu mi. Maecenas et sem nec nulla commodo convallis eu non lectus. Praesent hendrerit, velit eget auctor pretium, neque ipsum commodo neque, a placerat dui risus eu tellus. Vivamus porta egestas sapien eget semper. Morbi et neque nec elit rhoncus scelerisque. Donec posuere bibendum felis, sit amet congue odio sagittis ut."]; 95 | [_scrollView addSubview:infoLabel]; 96 | } 97 | 98 | 99 | //////////////////////////////////////////////////////// 100 | //////////////////////////////////////////////////////// 101 | #pragma mark - ScrollView Delegate 102 | //////////////////////////////////////////////////////// 103 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView 104 | { 105 | CGFloat contentOffsetY = scrollView.contentOffset.y; 106 | 107 | // Bounds checks 108 | if (contentOffsetY < 0) 109 | contentOffsetY = 0; 110 | else if (contentOffsetY > kFullBlurOffset) 111 | contentOffsetY = kFullBlurOffset; 112 | 113 | // Update blur 114 | [_blurredImageView setBlurIntensity:contentOffsetY / kFullBlurOffset]; 115 | 116 | // Calculate image view's new frame 117 | CGFloat imageY = contentOffsetY / kParallaxRatio; 118 | 119 | if (contentOffsetY < kParallaxRatio) 120 | imageY = 0; 121 | else if (imageY > kParallaxMax) 122 | imageY = kParallaxMax; 123 | 124 | CGRect imageFrame = _blurredImageView.frame; 125 | imageFrame.origin.y = -imageY; // make origin negative since we want the frame to go up 126 | 127 | [_blurredImageView setFrame:imageFrame]; 128 | } 129 | 130 | //////////////////////////////////////////////////////// 131 | @end 132 | -------------------------------------------------------------------------------- /RCBlurredImageViewTestApp/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /RCBlurredImageViewTestApp/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // RCBlurredImageView 4 | // 5 | // Created by Rich Cameron on 5/10/13. 6 | // Copyright (c) 2013 Rich Cameron. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "RCAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([RCAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /RCBlurredImageViewTestApp/test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rcameron/RCBlurredImageView/e7e7bec5112661a838f39858b479409ce4a802af/RCBlurredImageViewTestApp/test.jpg -------------------------------------------------------------------------------- /RCBlurredImageViewTestApp/test@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rcameron/RCBlurredImageView/e7e7bec5112661a838f39858b479409ce4a802af/RCBlurredImageViewTestApp/test@2x.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RCBlurredImageView 2 | 3 | ![demo](https://github.com/rcameron/RCBlurredImageView/blob/master/RCBlurredImageView.gif?raw=true) 4 | 5 | An iOS component that mimics the Yahoo Weather app's blurring effect 6 | 7 | ## Installation 8 | 9 | - Drag the `RCBlurredImageView/RCBlurredImageView` folder into your project 10 | - Add the **CoreImage** framework to your project 11 | 12 | 13 | ## Usage 14 | 15 | Use just like UIImageView: 16 | 17 | ```objective-c 18 | UIImage *image = [UIImage imageNamed:@"test.jpg"]; 19 | RCBlurredImageView *blurredImageView = [[RCBlurredImageView alloc] initWithImage:image]; 20 | [self.view addSubview:blurredImageView]; 21 | ``` 22 | 23 | To change the blur intensity: 24 | 25 | ```objective-c 26 | [blurredImageView setBlurIntensity:0.5f]; 27 | ``` 28 | --------------------------------------------------------------------------------