├── .gitignore ├── Example ├── Classes │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── DemoViewController.h │ └── DemoViewController.m ├── Example.xcodeproj │ └── project.pbxproj ├── Other Sources │ ├── Example-Prefix.pch │ └── main.m ├── Podfile ├── Podfile.lock └── Resources │ ├── Example-Info.plist │ ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── LaunchImage.launchimage │ │ └── Contents.json │ └── image.imageset │ │ ├── Contents.json │ │ └── image@2x.png │ └── en.lproj │ └── InfoPlist.strings ├── LICENSE ├── Readme.markdown ├── SAMCoreImageView.podspec └── SAMCoreImageView ├── SAMCoreImageView.h └── SAMCoreImageView.m /.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.pbxuser 3 | *.perspectivev3 4 | *.xcworkspace 5 | xcuserdata 6 | 7 | Pods 8 | -------------------------------------------------------------------------------- /Example/Classes/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // Example 4 | // 5 | // Created by Sam Soffes on 2/6/14. 6 | // Copyright (c) 2014 Sam Soffes. All rights reserved. 7 | // 8 | 9 | @interface AppDelegate : UIResponder 10 | 11 | @property (nonatomic) UIWindow *window; 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/Classes/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // Example 4 | // 5 | // Created by Sam Soffes on 2/6/14. 6 | // Copyright (c) 2014 Sam Soffes. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "DemoViewController.h" 11 | 12 | @implementation AppDelegate 13 | 14 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 15 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 16 | self.window.rootViewController = [[DemoViewController alloc] init]; 17 | self.window.backgroundColor = [UIColor whiteColor]; 18 | [self.window makeKeyAndVisible]; 19 | return YES; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Example/Classes/DemoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoViewController.h 3 | // Example 4 | // 5 | // Created by Sam Soffes on 2/6/14. 6 | // Copyright (c) 2014 Sam Soffes. All rights reserved. 7 | // 8 | 9 | @interface DemoViewController : UIViewController 10 | @end 11 | -------------------------------------------------------------------------------- /Example/Classes/DemoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoViewController.m 3 | // Example 4 | // 5 | // Created by Sam Soffes on 2/6/14. 6 | // Copyright (c) 2014 Sam Soffes. All rights reserved. 7 | // 8 | 9 | #import "DemoViewController.h" 10 | 11 | @import CoreImage; 12 | #import 13 | 14 | @interface DemoViewController () 15 | @property (nonatomic, readonly) SAMCoreImageView *imageView; 16 | @property (nonatomic, readonly) UISlider *slider; 17 | @property (nonatomic) CIImage *inputImage; 18 | @end 19 | 20 | @implementation DemoViewController 21 | 22 | #pragma mark - Accessors 23 | 24 | @synthesize imageView = _imageView; 25 | @synthesize slider = _slider; 26 | 27 | - (SAMCoreImageView *)imageView { 28 | if (!_imageView) { 29 | _imageView = [[SAMCoreImageView alloc] init]; 30 | } 31 | return _imageView; 32 | } 33 | 34 | 35 | - (UISlider *)slider { 36 | if (!_slider) { 37 | _slider = [[UISlider alloc] init]; 38 | [_slider addTarget:self action:@selector(sliderChanged:) forControlEvents:UIControlEventValueChanged]; 39 | _slider.minimumValue = -1.0f; 40 | } 41 | return _slider; 42 | } 43 | 44 | 45 | - (void)setInputImage:(CIImage *)inputImage { 46 | _inputImage = inputImage; 47 | self.imageView.image = _inputImage; 48 | } 49 | 50 | 51 | #pragma mark - UIViewController 52 | 53 | - (void)viewDidLoad { 54 | [super viewDidLoad]; 55 | 56 | self.view.backgroundColor = [UIColor whiteColor]; 57 | 58 | self.inputImage = [CIImage imageWithCGImage:[UIImage imageNamed:@"image"].CGImage]; 59 | 60 | [self.view addSubview:self.imageView]; 61 | [self.view addSubview:self.slider]; 62 | } 63 | 64 | 65 | - (void)viewDidLayoutSubviews { 66 | [super viewDidLayoutSubviews]; 67 | 68 | CGSize size = self.view.bounds.size; 69 | 70 | if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)) { 71 | self.imageView.frame = CGRectMake(0.0f, 20.0f, size.width, size.width); 72 | } else { 73 | self.imageView.frame = CGRectMake(roundf((size.width - 200.0f) / 2.0f), 20.0f, 200.0f, 200.0f); 74 | } 75 | self.slider.frame = CGRectMake(self.imageView.frame.origin.x + 10.0f, CGRectGetMaxY(self.imageView.frame) + 10.0f, self.imageView.frame.size.width - 20.0f, 32.0f); 76 | } 77 | 78 | 79 | #pragma mark - Actions 80 | 81 | - (void)sliderChanged:(UISlider *)slider { 82 | CIFilter *vibrance = [CIFilter filterWithName:@"CIVibrance"]; 83 | [vibrance setValue:self.inputImage forKey:@"inputImage"]; 84 | [vibrance setValue:@(slider.value) forKey:@"inputAmount"]; 85 | 86 | self.imageView.image = [vibrance outputImage]; 87 | } 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /Example/Example.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 21FEC14518A490C3009C69A3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21FEC14418A490C3009C69A3 /* Foundation.framework */; }; 11 | 21FEC14718A490C3009C69A3 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21FEC14618A490C3009C69A3 /* CoreGraphics.framework */; }; 12 | 21FEC14918A490C3009C69A3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 21FEC14818A490C3009C69A3 /* UIKit.framework */; }; 13 | 21FEC17E18A49110009C69A3 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 21FEC17518A49110009C69A3 /* AppDelegate.m */; }; 14 | 21FEC18018A49110009C69A3 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 21FEC17A18A49110009C69A3 /* InfoPlist.strings */; }; 15 | 21FEC18218A49110009C69A3 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 21FEC17D18A49110009C69A3 /* Images.xcassets */; }; 16 | 21FEC18618A4913C009C69A3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 21FEC18518A4913C009C69A3 /* main.m */; }; 17 | 21FEC18918A4919F009C69A3 /* DemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 21FEC18818A4919F009C69A3 /* DemoViewController.m */; }; 18 | C57537DD27D2533C1D3D1E68 /* libPods-Example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 26F027357278E396D7A3E2EB /* libPods-Example.a */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXFileReference section */ 22 | 21FEC14118A490C3009C69A3 /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 23 | 21FEC14418A490C3009C69A3 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 24 | 21FEC14618A490C3009C69A3 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 25 | 21FEC14818A490C3009C69A3 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 26 | 21FEC15D18A490C3009C69A3 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 27 | 21FEC17418A49110009C69A3 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 28 | 21FEC17518A49110009C69A3 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 29 | 21FEC17B18A49110009C69A3 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 30 | 21FEC17C18A49110009C69A3 /* Example-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Example-Info.plist"; sourceTree = ""; }; 31 | 21FEC17D18A49110009C69A3 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 32 | 21FEC18418A4913C009C69A3 /* Example-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Example-Prefix.pch"; sourceTree = ""; }; 33 | 21FEC18518A4913C009C69A3 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 34 | 21FEC18718A4919F009C69A3 /* DemoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoViewController.h; sourceTree = ""; }; 35 | 21FEC18818A4919F009C69A3 /* DemoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoViewController.m; sourceTree = ""; }; 36 | 26F027357278E396D7A3E2EB /* libPods-Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Example.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 37 | 53123488339F19B77F85F8A6 /* Pods-Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Example/Pods-Example.debug.xcconfig"; sourceTree = ""; }; 38 | 81A81DECE7C72AF44B4FFC1F /* Pods-Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-Example/Pods-Example.release.xcconfig"; sourceTree = ""; }; 39 | /* End PBXFileReference section */ 40 | 41 | /* Begin PBXFrameworksBuildPhase section */ 42 | 21FEC13E18A490C3009C69A3 /* Frameworks */ = { 43 | isa = PBXFrameworksBuildPhase; 44 | buildActionMask = 2147483647; 45 | files = ( 46 | 21FEC14718A490C3009C69A3 /* CoreGraphics.framework in Frameworks */, 47 | 21FEC14918A490C3009C69A3 /* UIKit.framework in Frameworks */, 48 | 21FEC14518A490C3009C69A3 /* Foundation.framework in Frameworks */, 49 | C57537DD27D2533C1D3D1E68 /* libPods-Example.a in Frameworks */, 50 | ); 51 | runOnlyForDeploymentPostprocessing = 0; 52 | }; 53 | /* End PBXFrameworksBuildPhase section */ 54 | 55 | /* Begin PBXGroup section */ 56 | 21FEC13818A490C3009C69A3 = { 57 | isa = PBXGroup; 58 | children = ( 59 | 21FEC17318A49110009C69A3 /* Classes */, 60 | 21FEC18318A4913C009C69A3 /* Other Sources */, 61 | 21FEC17918A49110009C69A3 /* Resources */, 62 | 21FEC14318A490C3009C69A3 /* Frameworks */, 63 | 21FEC14218A490C3009C69A3 /* Products */, 64 | B0D822BC59EA6CECB7E89757 /* Pods */, 65 | ); 66 | sourceTree = ""; 67 | }; 68 | 21FEC14218A490C3009C69A3 /* Products */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 21FEC14118A490C3009C69A3 /* Example.app */, 72 | ); 73 | name = Products; 74 | sourceTree = ""; 75 | }; 76 | 21FEC14318A490C3009C69A3 /* Frameworks */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 21FEC14418A490C3009C69A3 /* Foundation.framework */, 80 | 21FEC14618A490C3009C69A3 /* CoreGraphics.framework */, 81 | 21FEC14818A490C3009C69A3 /* UIKit.framework */, 82 | 21FEC15D18A490C3009C69A3 /* XCTest.framework */, 83 | 26F027357278E396D7A3E2EB /* libPods-Example.a */, 84 | ); 85 | name = Frameworks; 86 | sourceTree = ""; 87 | }; 88 | 21FEC17318A49110009C69A3 /* Classes */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 21FEC17418A49110009C69A3 /* AppDelegate.h */, 92 | 21FEC17518A49110009C69A3 /* AppDelegate.m */, 93 | 21FEC18718A4919F009C69A3 /* DemoViewController.h */, 94 | 21FEC18818A4919F009C69A3 /* DemoViewController.m */, 95 | ); 96 | path = Classes; 97 | sourceTree = ""; 98 | }; 99 | 21FEC17918A49110009C69A3 /* Resources */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 21FEC17A18A49110009C69A3 /* InfoPlist.strings */, 103 | 21FEC17C18A49110009C69A3 /* Example-Info.plist */, 104 | 21FEC17D18A49110009C69A3 /* Images.xcassets */, 105 | ); 106 | path = Resources; 107 | sourceTree = ""; 108 | }; 109 | 21FEC18318A4913C009C69A3 /* Other Sources */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 21FEC18418A4913C009C69A3 /* Example-Prefix.pch */, 113 | 21FEC18518A4913C009C69A3 /* main.m */, 114 | ); 115 | path = "Other Sources"; 116 | sourceTree = ""; 117 | }; 118 | B0D822BC59EA6CECB7E89757 /* Pods */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 53123488339F19B77F85F8A6 /* Pods-Example.debug.xcconfig */, 122 | 81A81DECE7C72AF44B4FFC1F /* Pods-Example.release.xcconfig */, 123 | ); 124 | name = Pods; 125 | sourceTree = ""; 126 | }; 127 | /* End PBXGroup section */ 128 | 129 | /* Begin PBXNativeTarget section */ 130 | 21FEC14018A490C3009C69A3 /* Example */ = { 131 | isa = PBXNativeTarget; 132 | buildConfigurationList = 21FEC16D18A490C4009C69A3 /* Build configuration list for PBXNativeTarget "Example" */; 133 | buildPhases = ( 134 | D0FDE33A392952C3B7A75BC3 /* [CP] Check Pods Manifest.lock */, 135 | 21FEC13D18A490C3009C69A3 /* Sources */, 136 | 21FEC13E18A490C3009C69A3 /* Frameworks */, 137 | 21FEC13F18A490C3009C69A3 /* Resources */, 138 | 7FBAF1DB7801B2DDA84CEC27 /* [CP] Embed Pods Frameworks */, 139 | 24569222713CEDD82094F3C1 /* [CP] Copy Pods Resources */, 140 | ); 141 | buildRules = ( 142 | ); 143 | dependencies = ( 144 | ); 145 | name = Example; 146 | productName = Example; 147 | productReference = 21FEC14118A490C3009C69A3 /* Example.app */; 148 | productType = "com.apple.product-type.application"; 149 | }; 150 | /* End PBXNativeTarget section */ 151 | 152 | /* Begin PBXProject section */ 153 | 21FEC13918A490C3009C69A3 /* Project object */ = { 154 | isa = PBXProject; 155 | attributes = { 156 | LastUpgradeCheck = 0810; 157 | ORGANIZATIONNAME = "Sam Soffes"; 158 | }; 159 | buildConfigurationList = 21FEC13C18A490C3009C69A3 /* Build configuration list for PBXProject "Example" */; 160 | compatibilityVersion = "Xcode 3.2"; 161 | developmentRegion = English; 162 | hasScannedForEncodings = 0; 163 | knownRegions = ( 164 | en, 165 | ); 166 | mainGroup = 21FEC13818A490C3009C69A3; 167 | productRefGroup = 21FEC14218A490C3009C69A3 /* Products */; 168 | projectDirPath = ""; 169 | projectRoot = ""; 170 | targets = ( 171 | 21FEC14018A490C3009C69A3 /* Example */, 172 | ); 173 | }; 174 | /* End PBXProject section */ 175 | 176 | /* Begin PBXResourcesBuildPhase section */ 177 | 21FEC13F18A490C3009C69A3 /* Resources */ = { 178 | isa = PBXResourcesBuildPhase; 179 | buildActionMask = 2147483647; 180 | files = ( 181 | 21FEC18218A49110009C69A3 /* Images.xcassets in Resources */, 182 | 21FEC18018A49110009C69A3 /* InfoPlist.strings in Resources */, 183 | ); 184 | runOnlyForDeploymentPostprocessing = 0; 185 | }; 186 | /* End PBXResourcesBuildPhase section */ 187 | 188 | /* Begin PBXShellScriptBuildPhase section */ 189 | 24569222713CEDD82094F3C1 /* [CP] Copy Pods Resources */ = { 190 | isa = PBXShellScriptBuildPhase; 191 | buildActionMask = 2147483647; 192 | files = ( 193 | ); 194 | inputPaths = ( 195 | ); 196 | name = "[CP] Copy Pods Resources"; 197 | outputPaths = ( 198 | ); 199 | runOnlyForDeploymentPostprocessing = 0; 200 | shellPath = /bin/sh; 201 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example/Pods-Example-resources.sh\"\n"; 202 | showEnvVarsInLog = 0; 203 | }; 204 | 7FBAF1DB7801B2DDA84CEC27 /* [CP] Embed Pods Frameworks */ = { 205 | isa = PBXShellScriptBuildPhase; 206 | buildActionMask = 2147483647; 207 | files = ( 208 | ); 209 | inputPaths = ( 210 | ); 211 | name = "[CP] Embed Pods Frameworks"; 212 | outputPaths = ( 213 | ); 214 | runOnlyForDeploymentPostprocessing = 0; 215 | shellPath = /bin/sh; 216 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example/Pods-Example-frameworks.sh\"\n"; 217 | showEnvVarsInLog = 0; 218 | }; 219 | D0FDE33A392952C3B7A75BC3 /* [CP] Check Pods Manifest.lock */ = { 220 | isa = PBXShellScriptBuildPhase; 221 | buildActionMask = 2147483647; 222 | files = ( 223 | ); 224 | inputPaths = ( 225 | ); 226 | name = "[CP] Check Pods Manifest.lock"; 227 | outputPaths = ( 228 | ); 229 | runOnlyForDeploymentPostprocessing = 0; 230 | shellPath = /bin/sh; 231 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; 232 | showEnvVarsInLog = 0; 233 | }; 234 | /* End PBXShellScriptBuildPhase section */ 235 | 236 | /* Begin PBXSourcesBuildPhase section */ 237 | 21FEC13D18A490C3009C69A3 /* Sources */ = { 238 | isa = PBXSourcesBuildPhase; 239 | buildActionMask = 2147483647; 240 | files = ( 241 | 21FEC18918A4919F009C69A3 /* DemoViewController.m in Sources */, 242 | 21FEC18618A4913C009C69A3 /* main.m in Sources */, 243 | 21FEC17E18A49110009C69A3 /* AppDelegate.m in Sources */, 244 | ); 245 | runOnlyForDeploymentPostprocessing = 0; 246 | }; 247 | /* End PBXSourcesBuildPhase section */ 248 | 249 | /* Begin PBXVariantGroup section */ 250 | 21FEC17A18A49110009C69A3 /* InfoPlist.strings */ = { 251 | isa = PBXVariantGroup; 252 | children = ( 253 | 21FEC17B18A49110009C69A3 /* en */, 254 | ); 255 | name = InfoPlist.strings; 256 | sourceTree = ""; 257 | }; 258 | /* End PBXVariantGroup section */ 259 | 260 | /* Begin XCBuildConfiguration section */ 261 | 21FEC16B18A490C4009C69A3 /* Debug */ = { 262 | isa = XCBuildConfiguration; 263 | buildSettings = { 264 | ALWAYS_SEARCH_USER_PATHS = NO; 265 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 266 | CLANG_CXX_LIBRARY = "libc++"; 267 | CLANG_ENABLE_MODULES = YES; 268 | CLANG_ENABLE_OBJC_ARC = YES; 269 | CLANG_WARN_BOOL_CONVERSION = YES; 270 | CLANG_WARN_CONSTANT_CONVERSION = YES; 271 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 272 | CLANG_WARN_EMPTY_BODY = YES; 273 | CLANG_WARN_ENUM_CONVERSION = YES; 274 | CLANG_WARN_INFINITE_RECURSION = YES; 275 | CLANG_WARN_INT_CONVERSION = YES; 276 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 277 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 278 | CLANG_WARN_UNREACHABLE_CODE = YES; 279 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 280 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 281 | COPY_PHASE_STRIP = NO; 282 | ENABLE_STRICT_OBJC_MSGSEND = YES; 283 | ENABLE_TESTABILITY = YES; 284 | GCC_C_LANGUAGE_STANDARD = gnu99; 285 | GCC_DYNAMIC_NO_PIC = NO; 286 | GCC_NO_COMMON_BLOCKS = YES; 287 | GCC_OPTIMIZATION_LEVEL = 0; 288 | GCC_PREPROCESSOR_DEFINITIONS = ( 289 | "DEBUG=1", 290 | "$(inherited)", 291 | ); 292 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 293 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 294 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 295 | GCC_WARN_UNDECLARED_SELECTOR = YES; 296 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 297 | GCC_WARN_UNUSED_FUNCTION = YES; 298 | GCC_WARN_UNUSED_VARIABLE = YES; 299 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 300 | ONLY_ACTIVE_ARCH = YES; 301 | SDKROOT = iphoneos; 302 | }; 303 | name = Debug; 304 | }; 305 | 21FEC16C18A490C4009C69A3 /* Release */ = { 306 | isa = XCBuildConfiguration; 307 | buildSettings = { 308 | ALWAYS_SEARCH_USER_PATHS = NO; 309 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 310 | CLANG_CXX_LIBRARY = "libc++"; 311 | CLANG_ENABLE_MODULES = YES; 312 | CLANG_ENABLE_OBJC_ARC = YES; 313 | CLANG_WARN_BOOL_CONVERSION = YES; 314 | CLANG_WARN_CONSTANT_CONVERSION = YES; 315 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 316 | CLANG_WARN_EMPTY_BODY = YES; 317 | CLANG_WARN_ENUM_CONVERSION = YES; 318 | CLANG_WARN_INFINITE_RECURSION = YES; 319 | CLANG_WARN_INT_CONVERSION = YES; 320 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 321 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 322 | CLANG_WARN_UNREACHABLE_CODE = YES; 323 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 324 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 325 | COPY_PHASE_STRIP = YES; 326 | ENABLE_NS_ASSERTIONS = NO; 327 | ENABLE_STRICT_OBJC_MSGSEND = YES; 328 | GCC_C_LANGUAGE_STANDARD = gnu99; 329 | GCC_NO_COMMON_BLOCKS = YES; 330 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 331 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 332 | GCC_WARN_UNDECLARED_SELECTOR = YES; 333 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 334 | GCC_WARN_UNUSED_FUNCTION = YES; 335 | GCC_WARN_UNUSED_VARIABLE = YES; 336 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 337 | SDKROOT = iphoneos; 338 | VALIDATE_PRODUCT = YES; 339 | }; 340 | name = Release; 341 | }; 342 | 21FEC16E18A490C4009C69A3 /* Debug */ = { 343 | isa = XCBuildConfiguration; 344 | baseConfigurationReference = 53123488339F19B77F85F8A6 /* Pods-Example.debug.xcconfig */; 345 | buildSettings = { 346 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 347 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 348 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 349 | GCC_PREFIX_HEADER = "Other Sources/Example-Prefix.pch"; 350 | INFOPLIST_FILE = "Resources/Example-Info.plist"; 351 | PRODUCT_BUNDLE_IDENTIFIER = "com.samsoffes.${PRODUCT_NAME:rfc1034identifier}"; 352 | PRODUCT_NAME = "$(TARGET_NAME)"; 353 | WRAPPER_EXTENSION = app; 354 | }; 355 | name = Debug; 356 | }; 357 | 21FEC16F18A490C4009C69A3 /* Release */ = { 358 | isa = XCBuildConfiguration; 359 | baseConfigurationReference = 81A81DECE7C72AF44B4FFC1F /* Pods-Example.release.xcconfig */; 360 | buildSettings = { 361 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 362 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 363 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 364 | GCC_PREFIX_HEADER = "Other Sources/Example-Prefix.pch"; 365 | INFOPLIST_FILE = "Resources/Example-Info.plist"; 366 | PRODUCT_BUNDLE_IDENTIFIER = "com.samsoffes.${PRODUCT_NAME:rfc1034identifier}"; 367 | PRODUCT_NAME = "$(TARGET_NAME)"; 368 | WRAPPER_EXTENSION = app; 369 | }; 370 | name = Release; 371 | }; 372 | /* End XCBuildConfiguration section */ 373 | 374 | /* Begin XCConfigurationList section */ 375 | 21FEC13C18A490C3009C69A3 /* Build configuration list for PBXProject "Example" */ = { 376 | isa = XCConfigurationList; 377 | buildConfigurations = ( 378 | 21FEC16B18A490C4009C69A3 /* Debug */, 379 | 21FEC16C18A490C4009C69A3 /* Release */, 380 | ); 381 | defaultConfigurationIsVisible = 0; 382 | defaultConfigurationName = Release; 383 | }; 384 | 21FEC16D18A490C4009C69A3 /* Build configuration list for PBXNativeTarget "Example" */ = { 385 | isa = XCConfigurationList; 386 | buildConfigurations = ( 387 | 21FEC16E18A490C4009C69A3 /* Debug */, 388 | 21FEC16F18A490C4009C69A3 /* Release */, 389 | ); 390 | defaultConfigurationIsVisible = 0; 391 | defaultConfigurationName = Release; 392 | }; 393 | /* End XCConfigurationList section */ 394 | }; 395 | rootObject = 21FEC13918A490C3009C69A3 /* Project object */; 396 | } 397 | -------------------------------------------------------------------------------- /Example/Other Sources/Example-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_3_0 10 | #warning "This project uses features only available in iOS SDK 3.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | @import UIKit; 15 | #endif 16 | -------------------------------------------------------------------------------- /Example/Other Sources/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Example 4 | // 5 | // Created by Sam Soffes on 2/6/14. 6 | // Copyright (c) 2014 Sam Soffes. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | int main(int argc, char * argv[]) { 12 | @autoreleasepool { 13 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | target 'Example' do 2 | pod 'SAMCoreImageView', :path => '../' 3 | end 4 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - SAMContentMode (0.1.3) 3 | - SAMCoreImageView (0.1.4): 4 | - SAMContentMode 5 | 6 | DEPENDENCIES: 7 | - SAMCoreImageView (from `../`) 8 | 9 | EXTERNAL SOURCES: 10 | SAMCoreImageView: 11 | :path: "../" 12 | 13 | SPEC CHECKSUMS: 14 | SAMContentMode: 4bce04c3d5d7eab19a8e7cf790836775fed8ad05 15 | SAMCoreImageView: 329edc0da1ef38cca61317eb0431ccccc9f6ede7 16 | 17 | PODFILE CHECKSUM: ed0b6b61a652369ff6cf2f7975b6a8138eb5ef6a 18 | 19 | COCOAPODS: 1.1.0.rc.2 20 | -------------------------------------------------------------------------------- /Example/Resources/Example-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 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 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Example/Resources/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/Resources/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Example/Resources/Images.xcassets/image.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "image@2x.png" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /Example/Resources/Images.xcassets/image.imageset/image@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/soffes/SAMCoreImageView/f89dd42f70255663fd405a152ffbb51acc6d743f/Example/Resources/Images.xcassets/image.imageset/image@2x.png -------------------------------------------------------------------------------- /Example/Resources/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009-2014 Sam Soffes, http://soff.es 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Readme.markdown: -------------------------------------------------------------------------------- 1 | # SAMCoreImageView 2 | 3 | Render a CIImage in an OpenGL thingy so it's real fast and junk. You won't see any speed up on the simulator, but on the device it's nuts fast. 4 | 5 | This is was inspired by [TLDFastCoreImageView](https://github.com/patr1ck/TLDCoreImageDemo/blob/master/TLDCoreImageDemo/TLDFastCoreImageView.h) by [Patrick Gibson](https://github.com/patr1ck). Thanks Patrick! 6 | 7 | 8 | ## Usage 9 | 10 | ``` objc 11 | SAMCoreImageView *imageView = [[SAMCoreImageView alloc] init]; 12 | imageView.image = [someFilter outputImage]; 13 | ``` 14 | 15 | SAMCoreImageView's `contentMode` behaves just like UIImageView's so go nuts. Internally, it uses [SAMContentMode](https://github.com/soffes/SAMContentMode) to do its magic. 16 | 17 | 18 | ## Running the Example 19 | 20 | `cd` into the `Example` directory and run `pod install`. Then open `Example.xcworkspace` and build like normal. The performance on the simulator isn't great. Try it on a device. 21 | 22 | 23 | ## Limitations 24 | 25 | The only thing SAMCoreImageView doesn't do well is resizing. If you need to resize the view, I recommend destroying it and making a new one for now. I started working on a fix for this, but couldn't get it to work right just yet. 26 | -------------------------------------------------------------------------------- /SAMCoreImageView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = 'SAMCoreImageView' 3 | spec.version = '0.1.4' 4 | spec.authors = {'Sam Soffes' => 'sam@soff.es'} 5 | spec.homepage = 'https://github.com/soffes/SAMCoreImageView' 6 | spec.summary = 'Fast image view for CIImage\'s.' 7 | spec.source = {:git => 'https://github.com/soffes/SAMCoreImageView.git', :tag => "v#{spec.version}"} 8 | spec.license = { :type => 'MIT', :file => 'LICENSE' } 9 | 10 | spec.platform = :ios 11 | spec.requires_arc = true 12 | spec.frameworks = 'Foundation', 'UIKit', 'CoreGraphics', 'CoreImage', 'GLKit', 'OpenGLES' 13 | spec.source_files = 'SAMCoreImageView' 14 | 15 | spec.dependency 'SAMContentMode' 16 | end 17 | -------------------------------------------------------------------------------- /SAMCoreImageView/SAMCoreImageView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SAMCoreImageView.h 3 | // SAMCoreImageView 4 | // 5 | // Created by Sam Soffes on 2/6/14. 6 | // Copyright (c) 2014 Sam Soffes. All rights reserved. 7 | // 8 | 9 | @import Foundation; 10 | @import GLKit; 11 | @class CIImage; 12 | 13 | /** 14 | Fast image view for Core Image. 15 | */ 16 | @interface SAMCoreImageView : GLKView 17 | 18 | /** 19 | The image to draw into the receiver. 20 | */ 21 | @property (nonatomic) CIImage *image; 22 | 23 | /** 24 | The Core Image context (read-only). 25 | 26 | This is configured to draw into the view's EAGLContext with `contextOptions`. 27 | */ 28 | @property (nonatomic, readonly) CIContext *ciContext; 29 | 30 | /** 31 | Options used to initalize the CIContext. 32 | 33 | @return CIContext options. 34 | */ 35 | - (NSDictionary *)contextOptions; 36 | 37 | /** 38 | Get a rect in the CIImage's coordinate space in pixels for drawing. 39 | 40 | @param bounds The receiver's bounds (in points). 41 | @return The rect to draw. 42 | */ 43 | - (CGRect)imageRectForBounds:(CGRect)bounds; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /SAMCoreImageView/SAMCoreImageView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SAMCoreImageView.m 3 | // SAMCoreImageView 4 | // 5 | // Created by Sam Soffes on 2/6/14. 6 | // Copyright (c) 2014 Sam Soffes. All rights reserved. 7 | // 8 | 9 | #import "SAMCoreImageView.h" 10 | #import 11 | 12 | @import OpenGLES; 13 | @import CoreImage; 14 | 15 | @interface SAMCoreImageView () 16 | @property (nonatomic, readwrite) CIContext *ciContext; 17 | @end 18 | 19 | @implementation SAMCoreImageView 20 | 21 | 22 | #pragma mark - Accessors 23 | 24 | @synthesize ciContext = _ciContext; 25 | 26 | - (CIContext *)ciContext { 27 | if (!_ciContext) { 28 | _ciContext = [CIContext contextWithEAGLContext:self.context options:[self contextOptions]]; 29 | } 30 | return _ciContext; 31 | } 32 | 33 | 34 | - (void)setImage:(CIImage *)image { 35 | _image = image; 36 | [self _display]; 37 | } 38 | 39 | 40 | #pragma mark - UIView 41 | 42 | - (instancetype)initWithFrame:(CGRect)frame { 43 | EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; 44 | if ((self = [super initWithFrame:frame context:context])) { 45 | self.userInteractionEnabled = NO; 46 | self.enableSetNeedsDisplay = NO; 47 | } 48 | return self; 49 | } 50 | 51 | 52 | - (void)drawRect:(CGRect)rect { 53 | if (!self.window || !self.image) { 54 | return; 55 | } 56 | 57 | CGSize size = self.bounds.size; 58 | CGFloat scale = self.contentScaleFactor; 59 | CGRect bounds = CGRectMake(0.0f, 0.0f, size.width * scale, size.height * scale); 60 | CGRect imageRect = [self imageRectForBounds:self.bounds]; 61 | [self.ciContext drawImage:self.image inRect:bounds fromRect:imageRect]; 62 | } 63 | 64 | 65 | - (void)layoutSubviews { 66 | self.ciContext = nil; 67 | [self _display]; 68 | } 69 | 70 | 71 | - (void)setContentMode:(UIViewContentMode)contentMode { 72 | [super setContentMode:contentMode]; 73 | [self _display]; 74 | } 75 | 76 | 77 | #pragma mark - Configuring 78 | 79 | - (NSDictionary *)contextOptions { 80 | return @{ 81 | kCIContextUseSoftwareRenderer: @NO, 82 | kCIContextWorkingColorSpace: [NSNull null] 83 | }; 84 | } 85 | 86 | 87 | - (CGRect)imageRectForBounds:(CGRect)bounds { 88 | bounds.size.width *= self.contentScaleFactor; 89 | bounds.size.height *= self.contentScaleFactor; 90 | 91 | return SAMRectForContentMode(bounds, self.contentMode, self.image.extent); 92 | } 93 | 94 | 95 | #pragma mark - Private 96 | 97 | - (void)_display { 98 | if (self.enableSetNeedsDisplay) { 99 | [self setNeedsDisplay]; 100 | } else { 101 | [self display]; 102 | } 103 | } 104 | 105 | @end 106 | --------------------------------------------------------------------------------