├── CoreImageDemo ├── CoreImageDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── Colin.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── Colin.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── CoreImageDemo.xcscheme │ │ └── xcschememanagement.plist └── CoreImageDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ ├── MainTableViewController.h │ ├── MainTableViewController.m │ ├── MetalKernel │ ├── MetalKernelFilter.h │ ├── MetalKernelFilter.m │ ├── MetalKernelViewController.h │ ├── MetalKernelViewController.m │ └── Vignette.metal │ ├── Mosaic │ ├── Mosaic.cikernel │ ├── MosaicFilter.h │ ├── MosaicFilter.m │ ├── MosaicViewController.h │ ├── MosaicViewController.m │ ├── mosaicImage.jpg │ ├── mosaic_asset_1.png │ └── mosaic_asset_2.png │ ├── Pixellate │ ├── Pixellate.cikernel │ ├── PixellateFilter.h │ ├── PixellateFilter.m │ ├── PixellateViewController.h │ ├── PixellateViewController.m │ └── pixellateImage.jpg │ ├── Vignette │ ├── Vignette.cikernel │ ├── VignetteFilter.h │ ├── VignetteFilter.m │ ├── VignetteViewController.h │ ├── VignetteViewController.m │ └── vignetteImage.jpg │ └── main.m ├── EnlargeEyes.qtz └── README.md /CoreImageDemo/CoreImageDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3B384E411DACCF5800E5A40E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B384E401DACCF5800E5A40E /* main.m */; }; 11 | 3B384E441DACCF5800E5A40E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B384E431DACCF5800E5A40E /* AppDelegate.m */; }; 12 | 3B384E4A1DACCF5800E5A40E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3B384E481DACCF5800E5A40E /* Main.storyboard */; }; 13 | 3B384E4C1DACCF5800E5A40E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3B384E4B1DACCF5800E5A40E /* Assets.xcassets */; }; 14 | 3B384E4F1DACCF5800E5A40E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3B384E4D1DACCF5800E5A40E /* LaunchScreen.storyboard */; }; 15 | 3B384E581DACD04200E5A40E /* MainTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B384E571DACD04200E5A40E /* MainTableViewController.m */; }; 16 | 3B429BDF1DAE041C00B56070 /* MosaicFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B429BDE1DAE041C00B56070 /* MosaicFilter.m */; }; 17 | 3B429BE21DAE043500B56070 /* MosaicViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B429BE11DAE043500B56070 /* MosaicViewController.m */; }; 18 | 3B429BE41DAE045000B56070 /* Mosaic.cikernel in Resources */ = {isa = PBXBuildFile; fileRef = 3B429BE31DAE045000B56070 /* Mosaic.cikernel */; }; 19 | 3B429BE61DAE06E400B56070 /* mosaic_asset_1.png in Resources */ = {isa = PBXBuildFile; fileRef = 3B429BE51DAE06E400B56070 /* mosaic_asset_1.png */; }; 20 | 3B429BE81DAE070300B56070 /* mosaicImage.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 3B429BE71DAE070300B56070 /* mosaicImage.jpg */; }; 21 | 3B67C1BE20EBA5E600694AA5 /* MetalKernelViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B67C1BD20EBA5E600694AA5 /* MetalKernelViewController.m */; }; 22 | 3B67C1C020EBA60F00694AA5 /* Vignette.metal in Sources */ = {isa = PBXBuildFile; fileRef = 3B67C1BF20EBA60F00694AA5 /* Vignette.metal */; }; 23 | 3B67C1C320EBA63F00694AA5 /* MetalKernelFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B67C1C220EBA63F00694AA5 /* MetalKernelFilter.m */; }; 24 | 3B7B0CD41DAD2337009FF36C /* PixellateViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B7B0CD31DAD2337009FF36C /* PixellateViewController.m */; }; 25 | 3B7B0CD71DAD2349009FF36C /* PixellateFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B7B0CD61DAD2349009FF36C /* PixellateFilter.m */; }; 26 | 3B7B0CD91DAD235B009FF36C /* Pixellate.cikernel in Resources */ = {isa = PBXBuildFile; fileRef = 3B7B0CD81DAD235B009FF36C /* Pixellate.cikernel */; }; 27 | 3B7B0CDB1DAD2DC2009FF36C /* pixellateImage.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 3B7B0CDA1DAD2DC2009FF36C /* pixellateImage.jpg */; }; 28 | 3B89167B1DACD7D800262F26 /* VignetteViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B89167A1DACD7D800262F26 /* VignetteViewController.m */; }; 29 | 3B89167E1DACD7FA00262F26 /* VignetteFilter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B89167D1DACD7FA00262F26 /* VignetteFilter.m */; }; 30 | 3B8916801DACDA9300262F26 /* Vignette.cikernel in Resources */ = {isa = PBXBuildFile; fileRef = 3B89167F1DACDA9300262F26 /* Vignette.cikernel */; }; 31 | 3B8916821DACE0F900262F26 /* vignetteImage.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 3B8916811DACE0F900262F26 /* vignetteImage.jpg */; }; 32 | 3B8916851DACEA3300262F26 /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B8916841DACEA3300262F26 /* GLKit.framework */; }; 33 | 3BBF5FAA1DAE2AB1001D9A3F /* mosaic_asset_2.png in Resources */ = {isa = PBXBuildFile; fileRef = 3BBF5FA91DAE2AB1001D9A3F /* mosaic_asset_2.png */; }; 34 | /* End PBXBuildFile section */ 35 | 36 | /* Begin PBXFileReference section */ 37 | 3B384E3C1DACCF5800E5A40E /* CoreImageDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CoreImageDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | 3B384E401DACCF5800E5A40E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 39 | 3B384E421DACCF5800E5A40E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 40 | 3B384E431DACCF5800E5A40E /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 41 | 3B384E491DACCF5800E5A40E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 42 | 3B384E4B1DACCF5800E5A40E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 43 | 3B384E4E1DACCF5800E5A40E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 44 | 3B384E501DACCF5800E5A40E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 45 | 3B384E561DACD04200E5A40E /* MainTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainTableViewController.h; sourceTree = ""; }; 46 | 3B384E571DACD04200E5A40E /* MainTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MainTableViewController.m; sourceTree = ""; }; 47 | 3B429BDD1DAE041C00B56070 /* MosaicFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MosaicFilter.h; sourceTree = ""; }; 48 | 3B429BDE1DAE041C00B56070 /* MosaicFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MosaicFilter.m; sourceTree = ""; }; 49 | 3B429BE01DAE043500B56070 /* MosaicViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MosaicViewController.h; sourceTree = ""; }; 50 | 3B429BE11DAE043500B56070 /* MosaicViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MosaicViewController.m; sourceTree = ""; }; 51 | 3B429BE31DAE045000B56070 /* Mosaic.cikernel */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Mosaic.cikernel; sourceTree = ""; }; 52 | 3B429BE51DAE06E400B56070 /* mosaic_asset_1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mosaic_asset_1.png; sourceTree = ""; }; 53 | 3B429BE71DAE070300B56070 /* mosaicImage.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = mosaicImage.jpg; sourceTree = ""; }; 54 | 3B67C1BC20EBA5E600694AA5 /* MetalKernelViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MetalKernelViewController.h; sourceTree = ""; }; 55 | 3B67C1BD20EBA5E600694AA5 /* MetalKernelViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MetalKernelViewController.m; sourceTree = ""; }; 56 | 3B67C1BF20EBA60F00694AA5 /* Vignette.metal */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.metal; path = Vignette.metal; sourceTree = ""; }; 57 | 3B67C1C120EBA63F00694AA5 /* MetalKernelFilter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MetalKernelFilter.h; sourceTree = ""; }; 58 | 3B67C1C220EBA63F00694AA5 /* MetalKernelFilter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MetalKernelFilter.m; sourceTree = ""; }; 59 | 3B7B0CD21DAD2337009FF36C /* PixellateViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PixellateViewController.h; sourceTree = ""; }; 60 | 3B7B0CD31DAD2337009FF36C /* PixellateViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PixellateViewController.m; sourceTree = ""; }; 61 | 3B7B0CD51DAD2349009FF36C /* PixellateFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PixellateFilter.h; sourceTree = ""; }; 62 | 3B7B0CD61DAD2349009FF36C /* PixellateFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PixellateFilter.m; sourceTree = ""; }; 63 | 3B7B0CD81DAD235B009FF36C /* Pixellate.cikernel */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Pixellate.cikernel; sourceTree = ""; }; 64 | 3B7B0CDA1DAD2DC2009FF36C /* pixellateImage.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = pixellateImage.jpg; sourceTree = ""; }; 65 | 3B8916791DACD7D800262F26 /* VignetteViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VignetteViewController.h; sourceTree = ""; }; 66 | 3B89167A1DACD7D800262F26 /* VignetteViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VignetteViewController.m; sourceTree = ""; }; 67 | 3B89167C1DACD7FA00262F26 /* VignetteFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VignetteFilter.h; sourceTree = ""; }; 68 | 3B89167D1DACD7FA00262F26 /* VignetteFilter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VignetteFilter.m; sourceTree = ""; }; 69 | 3B89167F1DACDA9300262F26 /* Vignette.cikernel */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Vignette.cikernel; sourceTree = ""; }; 70 | 3B8916811DACE0F900262F26 /* vignetteImage.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = vignetteImage.jpg; sourceTree = ""; }; 71 | 3B8916841DACEA3300262F26 /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; }; 72 | 3BBF5FA91DAE2AB1001D9A3F /* mosaic_asset_2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mosaic_asset_2.png; sourceTree = ""; }; 73 | /* End PBXFileReference section */ 74 | 75 | /* Begin PBXFrameworksBuildPhase section */ 76 | 3B384E391DACCF5800E5A40E /* Frameworks */ = { 77 | isa = PBXFrameworksBuildPhase; 78 | buildActionMask = 2147483647; 79 | files = ( 80 | 3B8916851DACEA3300262F26 /* GLKit.framework in Frameworks */, 81 | ); 82 | runOnlyForDeploymentPostprocessing = 0; 83 | }; 84 | /* End PBXFrameworksBuildPhase section */ 85 | 86 | /* Begin PBXGroup section */ 87 | 3B384E331DACCF5800E5A40E = { 88 | isa = PBXGroup; 89 | children = ( 90 | 3B384E3E1DACCF5800E5A40E /* CoreImageDemo */, 91 | 3B384E3D1DACCF5800E5A40E /* Products */, 92 | 3B8916831DACEA3300262F26 /* Frameworks */, 93 | ); 94 | sourceTree = ""; 95 | }; 96 | 3B384E3D1DACCF5800E5A40E /* Products */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | 3B384E3C1DACCF5800E5A40E /* CoreImageDemo.app */, 100 | ); 101 | name = Products; 102 | sourceTree = ""; 103 | }; 104 | 3B384E3E1DACCF5800E5A40E /* CoreImageDemo */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | 3B67C1BB20EBA5C300694AA5 /* MetalKernel */, 108 | 3B429BDC1DAE040800B56070 /* Mosaic */, 109 | 3B8916771DACD7BB00262F26 /* Pixellate */, 110 | 3B8916781DACD7BB00262F26 /* Vignette */, 111 | 3B384E421DACCF5800E5A40E /* AppDelegate.h */, 112 | 3B384E431DACCF5800E5A40E /* AppDelegate.m */, 113 | 3B384E561DACD04200E5A40E /* MainTableViewController.h */, 114 | 3B384E571DACD04200E5A40E /* MainTableViewController.m */, 115 | 3B384E481DACCF5800E5A40E /* Main.storyboard */, 116 | 3B384E4B1DACCF5800E5A40E /* Assets.xcassets */, 117 | 3B384E4D1DACCF5800E5A40E /* LaunchScreen.storyboard */, 118 | 3B384E501DACCF5800E5A40E /* Info.plist */, 119 | 3B384E3F1DACCF5800E5A40E /* Supporting Files */, 120 | ); 121 | path = CoreImageDemo; 122 | sourceTree = ""; 123 | }; 124 | 3B384E3F1DACCF5800E5A40E /* Supporting Files */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | 3B384E401DACCF5800E5A40E /* main.m */, 128 | ); 129 | name = "Supporting Files"; 130 | sourceTree = ""; 131 | }; 132 | 3B429BDC1DAE040800B56070 /* Mosaic */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | 3B429BE71DAE070300B56070 /* mosaicImage.jpg */, 136 | 3B429BE51DAE06E400B56070 /* mosaic_asset_1.png */, 137 | 3BBF5FA91DAE2AB1001D9A3F /* mosaic_asset_2.png */, 138 | 3B429BE01DAE043500B56070 /* MosaicViewController.h */, 139 | 3B429BE11DAE043500B56070 /* MosaicViewController.m */, 140 | 3B429BDD1DAE041C00B56070 /* MosaicFilter.h */, 141 | 3B429BDE1DAE041C00B56070 /* MosaicFilter.m */, 142 | 3B429BE31DAE045000B56070 /* Mosaic.cikernel */, 143 | ); 144 | path = Mosaic; 145 | sourceTree = ""; 146 | }; 147 | 3B67C1BB20EBA5C300694AA5 /* MetalKernel */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | 3B67C1BF20EBA60F00694AA5 /* Vignette.metal */, 151 | 3B67C1BC20EBA5E600694AA5 /* MetalKernelViewController.h */, 152 | 3B67C1BD20EBA5E600694AA5 /* MetalKernelViewController.m */, 153 | 3B67C1C120EBA63F00694AA5 /* MetalKernelFilter.h */, 154 | 3B67C1C220EBA63F00694AA5 /* MetalKernelFilter.m */, 155 | ); 156 | path = MetalKernel; 157 | sourceTree = ""; 158 | }; 159 | 3B8916771DACD7BB00262F26 /* Pixellate */ = { 160 | isa = PBXGroup; 161 | children = ( 162 | 3B7B0CDA1DAD2DC2009FF36C /* pixellateImage.jpg */, 163 | 3B7B0CD21DAD2337009FF36C /* PixellateViewController.h */, 164 | 3B7B0CD31DAD2337009FF36C /* PixellateViewController.m */, 165 | 3B7B0CD51DAD2349009FF36C /* PixellateFilter.h */, 166 | 3B7B0CD61DAD2349009FF36C /* PixellateFilter.m */, 167 | 3B7B0CD81DAD235B009FF36C /* Pixellate.cikernel */, 168 | ); 169 | path = Pixellate; 170 | sourceTree = ""; 171 | }; 172 | 3B8916781DACD7BB00262F26 /* Vignette */ = { 173 | isa = PBXGroup; 174 | children = ( 175 | 3B8916811DACE0F900262F26 /* vignetteImage.jpg */, 176 | 3B8916791DACD7D800262F26 /* VignetteViewController.h */, 177 | 3B89167A1DACD7D800262F26 /* VignetteViewController.m */, 178 | 3B89167C1DACD7FA00262F26 /* VignetteFilter.h */, 179 | 3B89167D1DACD7FA00262F26 /* VignetteFilter.m */, 180 | 3B89167F1DACDA9300262F26 /* Vignette.cikernel */, 181 | ); 182 | path = Vignette; 183 | sourceTree = ""; 184 | }; 185 | 3B8916831DACEA3300262F26 /* Frameworks */ = { 186 | isa = PBXGroup; 187 | children = ( 188 | 3B8916841DACEA3300262F26 /* GLKit.framework */, 189 | ); 190 | name = Frameworks; 191 | sourceTree = ""; 192 | }; 193 | /* End PBXGroup section */ 194 | 195 | /* Begin PBXNativeTarget section */ 196 | 3B384E3B1DACCF5800E5A40E /* CoreImageDemo */ = { 197 | isa = PBXNativeTarget; 198 | buildConfigurationList = 3B384E531DACCF5800E5A40E /* Build configuration list for PBXNativeTarget "CoreImageDemo" */; 199 | buildPhases = ( 200 | 3B384E381DACCF5800E5A40E /* Sources */, 201 | 3B384E391DACCF5800E5A40E /* Frameworks */, 202 | 3B384E3A1DACCF5800E5A40E /* Resources */, 203 | ); 204 | buildRules = ( 205 | ); 206 | dependencies = ( 207 | ); 208 | name = CoreImageDemo; 209 | productName = CoreImageDemo; 210 | productReference = 3B384E3C1DACCF5800E5A40E /* CoreImageDemo.app */; 211 | productType = "com.apple.product-type.application"; 212 | }; 213 | /* End PBXNativeTarget section */ 214 | 215 | /* Begin PBXProject section */ 216 | 3B384E341DACCF5800E5A40E /* Project object */ = { 217 | isa = PBXProject; 218 | attributes = { 219 | LastUpgradeCheck = 0800; 220 | ORGANIZATIONNAME = Colin; 221 | TargetAttributes = { 222 | 3B384E3B1DACCF5800E5A40E = { 223 | CreatedOnToolsVersion = 8.0; 224 | DevelopmentTeam = 55C567ZLGU; 225 | ProvisioningStyle = Automatic; 226 | }; 227 | }; 228 | }; 229 | buildConfigurationList = 3B384E371DACCF5800E5A40E /* Build configuration list for PBXProject "CoreImageDemo" */; 230 | compatibilityVersion = "Xcode 3.2"; 231 | developmentRegion = English; 232 | hasScannedForEncodings = 0; 233 | knownRegions = ( 234 | en, 235 | Base, 236 | ); 237 | mainGroup = 3B384E331DACCF5800E5A40E; 238 | productRefGroup = 3B384E3D1DACCF5800E5A40E /* Products */; 239 | projectDirPath = ""; 240 | projectRoot = ""; 241 | targets = ( 242 | 3B384E3B1DACCF5800E5A40E /* CoreImageDemo */, 243 | ); 244 | }; 245 | /* End PBXProject section */ 246 | 247 | /* Begin PBXResourcesBuildPhase section */ 248 | 3B384E3A1DACCF5800E5A40E /* Resources */ = { 249 | isa = PBXResourcesBuildPhase; 250 | buildActionMask = 2147483647; 251 | files = ( 252 | 3B8916821DACE0F900262F26 /* vignetteImage.jpg in Resources */, 253 | 3B384E4F1DACCF5800E5A40E /* LaunchScreen.storyboard in Resources */, 254 | 3B384E4C1DACCF5800E5A40E /* Assets.xcassets in Resources */, 255 | 3B7B0CD91DAD235B009FF36C /* Pixellate.cikernel in Resources */, 256 | 3B429BE81DAE070300B56070 /* mosaicImage.jpg in Resources */, 257 | 3BBF5FAA1DAE2AB1001D9A3F /* mosaic_asset_2.png in Resources */, 258 | 3B429BE61DAE06E400B56070 /* mosaic_asset_1.png in Resources */, 259 | 3B8916801DACDA9300262F26 /* Vignette.cikernel in Resources */, 260 | 3B384E4A1DACCF5800E5A40E /* Main.storyboard in Resources */, 261 | 3B429BE41DAE045000B56070 /* Mosaic.cikernel in Resources */, 262 | 3B7B0CDB1DAD2DC2009FF36C /* pixellateImage.jpg in Resources */, 263 | ); 264 | runOnlyForDeploymentPostprocessing = 0; 265 | }; 266 | /* End PBXResourcesBuildPhase section */ 267 | 268 | /* Begin PBXSourcesBuildPhase section */ 269 | 3B384E381DACCF5800E5A40E /* Sources */ = { 270 | isa = PBXSourcesBuildPhase; 271 | buildActionMask = 2147483647; 272 | files = ( 273 | 3B67C1C320EBA63F00694AA5 /* MetalKernelFilter.m in Sources */, 274 | 3B89167E1DACD7FA00262F26 /* VignetteFilter.m in Sources */, 275 | 3B67C1C020EBA60F00694AA5 /* Vignette.metal in Sources */, 276 | 3B89167B1DACD7D800262F26 /* VignetteViewController.m in Sources */, 277 | 3B384E581DACD04200E5A40E /* MainTableViewController.m in Sources */, 278 | 3B429BDF1DAE041C00B56070 /* MosaicFilter.m in Sources */, 279 | 3B7B0CD41DAD2337009FF36C /* PixellateViewController.m in Sources */, 280 | 3B429BE21DAE043500B56070 /* MosaicViewController.m in Sources */, 281 | 3B7B0CD71DAD2349009FF36C /* PixellateFilter.m in Sources */, 282 | 3B67C1BE20EBA5E600694AA5 /* MetalKernelViewController.m in Sources */, 283 | 3B384E441DACCF5800E5A40E /* AppDelegate.m in Sources */, 284 | 3B384E411DACCF5800E5A40E /* main.m in Sources */, 285 | ); 286 | runOnlyForDeploymentPostprocessing = 0; 287 | }; 288 | /* End PBXSourcesBuildPhase section */ 289 | 290 | /* Begin PBXVariantGroup section */ 291 | 3B384E481DACCF5800E5A40E /* Main.storyboard */ = { 292 | isa = PBXVariantGroup; 293 | children = ( 294 | 3B384E491DACCF5800E5A40E /* Base */, 295 | ); 296 | name = Main.storyboard; 297 | sourceTree = ""; 298 | }; 299 | 3B384E4D1DACCF5800E5A40E /* LaunchScreen.storyboard */ = { 300 | isa = PBXVariantGroup; 301 | children = ( 302 | 3B384E4E1DACCF5800E5A40E /* Base */, 303 | ); 304 | name = LaunchScreen.storyboard; 305 | sourceTree = ""; 306 | }; 307 | /* End PBXVariantGroup section */ 308 | 309 | /* Begin XCBuildConfiguration section */ 310 | 3B384E511DACCF5800E5A40E /* Debug */ = { 311 | isa = XCBuildConfiguration; 312 | buildSettings = { 313 | ALWAYS_SEARCH_USER_PATHS = NO; 314 | CLANG_ANALYZER_NONNULL = YES; 315 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 316 | CLANG_CXX_LIBRARY = "libc++"; 317 | CLANG_ENABLE_MODULES = YES; 318 | CLANG_ENABLE_OBJC_ARC = YES; 319 | CLANG_WARN_BOOL_CONVERSION = YES; 320 | CLANG_WARN_CONSTANT_CONVERSION = YES; 321 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 322 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 323 | CLANG_WARN_EMPTY_BODY = YES; 324 | CLANG_WARN_ENUM_CONVERSION = YES; 325 | CLANG_WARN_INFINITE_RECURSION = YES; 326 | CLANG_WARN_INT_CONVERSION = YES; 327 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 328 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 329 | CLANG_WARN_UNREACHABLE_CODE = YES; 330 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 331 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 332 | COPY_PHASE_STRIP = NO; 333 | DEBUG_INFORMATION_FORMAT = dwarf; 334 | ENABLE_STRICT_OBJC_MSGSEND = YES; 335 | ENABLE_TESTABILITY = YES; 336 | GCC_C_LANGUAGE_STANDARD = gnu99; 337 | GCC_DYNAMIC_NO_PIC = NO; 338 | GCC_NO_COMMON_BLOCKS = YES; 339 | GCC_OPTIMIZATION_LEVEL = 0; 340 | GCC_PREPROCESSOR_DEFINITIONS = ( 341 | "DEBUG=1", 342 | "$(inherited)", 343 | ); 344 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 345 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 346 | GCC_WARN_UNDECLARED_SELECTOR = YES; 347 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 348 | GCC_WARN_UNUSED_FUNCTION = YES; 349 | GCC_WARN_UNUSED_VARIABLE = YES; 350 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 351 | MTL_ENABLE_DEBUG_INFO = YES; 352 | ONLY_ACTIVE_ARCH = YES; 353 | SDKROOT = iphoneos; 354 | TARGETED_DEVICE_FAMILY = "1,2"; 355 | }; 356 | name = Debug; 357 | }; 358 | 3B384E521DACCF5800E5A40E /* Release */ = { 359 | isa = XCBuildConfiguration; 360 | buildSettings = { 361 | ALWAYS_SEARCH_USER_PATHS = NO; 362 | CLANG_ANALYZER_NONNULL = YES; 363 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 364 | CLANG_CXX_LIBRARY = "libc++"; 365 | CLANG_ENABLE_MODULES = YES; 366 | CLANG_ENABLE_OBJC_ARC = YES; 367 | CLANG_WARN_BOOL_CONVERSION = YES; 368 | CLANG_WARN_CONSTANT_CONVERSION = YES; 369 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 370 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 371 | CLANG_WARN_EMPTY_BODY = YES; 372 | CLANG_WARN_ENUM_CONVERSION = YES; 373 | CLANG_WARN_INFINITE_RECURSION = YES; 374 | CLANG_WARN_INT_CONVERSION = YES; 375 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 376 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 377 | CLANG_WARN_UNREACHABLE_CODE = YES; 378 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 379 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 380 | COPY_PHASE_STRIP = NO; 381 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 382 | ENABLE_NS_ASSERTIONS = NO; 383 | ENABLE_STRICT_OBJC_MSGSEND = YES; 384 | GCC_C_LANGUAGE_STANDARD = gnu99; 385 | GCC_NO_COMMON_BLOCKS = YES; 386 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 387 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 388 | GCC_WARN_UNDECLARED_SELECTOR = YES; 389 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 390 | GCC_WARN_UNUSED_FUNCTION = YES; 391 | GCC_WARN_UNUSED_VARIABLE = YES; 392 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 393 | MTL_ENABLE_DEBUG_INFO = NO; 394 | SDKROOT = iphoneos; 395 | TARGETED_DEVICE_FAMILY = "1,2"; 396 | VALIDATE_PRODUCT = YES; 397 | }; 398 | name = Release; 399 | }; 400 | 3B384E541DACCF5800E5A40E /* Debug */ = { 401 | isa = XCBuildConfiguration; 402 | buildSettings = { 403 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 404 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 405 | DEVELOPMENT_TEAM = 55C567ZLGU; 406 | INFOPLIST_FILE = CoreImageDemo/Info.plist; 407 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 408 | MTLLINKER_FLAGS = "-cikernel"; 409 | MTL_COMPILER_FLAGS = "-fcikernel"; 410 | MTL_PREPROCESSOR_DEFINITIONS = ""; 411 | PRODUCT_BUNDLE_IDENTIFIER = com.Colin.MetalDemo; 412 | PRODUCT_NAME = "$(TARGET_NAME)"; 413 | }; 414 | name = Debug; 415 | }; 416 | 3B384E551DACCF5800E5A40E /* Release */ = { 417 | isa = XCBuildConfiguration; 418 | buildSettings = { 419 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 420 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 421 | DEVELOPMENT_TEAM = 55C567ZLGU; 422 | INFOPLIST_FILE = CoreImageDemo/Info.plist; 423 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 424 | MTLLINKER_FLAGS = "-cikernel"; 425 | MTL_COMPILER_FLAGS = "-fcikernel"; 426 | MTL_PREPROCESSOR_DEFINITIONS = ""; 427 | PRODUCT_BUNDLE_IDENTIFIER = com.Colin.MetalDemo; 428 | PRODUCT_NAME = "$(TARGET_NAME)"; 429 | }; 430 | name = Release; 431 | }; 432 | /* End XCBuildConfiguration section */ 433 | 434 | /* Begin XCConfigurationList section */ 435 | 3B384E371DACCF5800E5A40E /* Build configuration list for PBXProject "CoreImageDemo" */ = { 436 | isa = XCConfigurationList; 437 | buildConfigurations = ( 438 | 3B384E511DACCF5800E5A40E /* Debug */, 439 | 3B384E521DACCF5800E5A40E /* Release */, 440 | ); 441 | defaultConfigurationIsVisible = 0; 442 | defaultConfigurationName = Release; 443 | }; 444 | 3B384E531DACCF5800E5A40E /* Build configuration list for PBXNativeTarget "CoreImageDemo" */ = { 445 | isa = XCConfigurationList; 446 | buildConfigurations = ( 447 | 3B384E541DACCF5800E5A40E /* Debug */, 448 | 3B384E551DACCF5800E5A40E /* Release */, 449 | ); 450 | defaultConfigurationIsVisible = 0; 451 | defaultConfigurationName = Release; 452 | }; 453 | /* End XCConfigurationList section */ 454 | }; 455 | rootObject = 3B384E341DACCF5800E5A40E /* Project object */; 456 | } 457 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo.xcodeproj/project.xcworkspace/xcuserdata/Colin.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colin1994/CoreImageDemo/25041fd21f31321b07146b55372b9f4d8a1f21e1/CoreImageDemo/CoreImageDemo.xcodeproj/project.xcworkspace/xcuserdata/Colin.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo.xcodeproj/xcuserdata/Colin.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo.xcodeproj/xcuserdata/Colin.xcuserdatad/xcschemes/CoreImageDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 69 | 70 | 71 | 72 | 73 | 74 | 80 | 82 | 88 | 89 | 90 | 91 | 93 | 94 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo.xcodeproj/xcuserdata/Colin.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CoreImageDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 3B384E3B1DACCF5800E5A40E 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 16/10/11. 6 | // Copyright © 2016年 Colin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 16/10/11. 6 | // Copyright © 2016年 Colin. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // 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. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // 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. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // 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. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Assets.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" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 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 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/MainTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MainTableViewController.h 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 16/10/11. 6 | // Copyright © 2016年 Colin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MainTableViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/MainTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // MainTableViewController.m 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 16/10/11. 6 | // Copyright © 2016年 Colin. All rights reserved. 7 | // 8 | 9 | #import "MainTableViewController.h" 10 | 11 | @interface MainTableViewController () 12 | 13 | @end 14 | 15 | @implementation MainTableViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | // Uncomment the following line to preserve selection between presentations. 21 | // self.clearsSelectionOnViewWillAppear = NO; 22 | 23 | // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 24 | // self.navigationItem.rightBarButtonItem = self.editButtonItem; 25 | } 26 | 27 | - (void)didReceiveMemoryWarning { 28 | [super didReceiveMemoryWarning]; 29 | // Dispose of any resources that can be recreated. 30 | } 31 | 32 | #pragma mark - Table view data source 33 | 34 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 35 | return 1; 36 | } 37 | 38 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 39 | return 4; 40 | } 41 | 42 | /* 43 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 44 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:<#@"reuseIdentifier"#> forIndexPath:indexPath]; 45 | 46 | // Configure the cell... 47 | 48 | return cell; 49 | } 50 | */ 51 | 52 | /* 53 | // Override to support conditional editing of the table view. 54 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { 55 | // Return NO if you do not want the specified item to be editable. 56 | return YES; 57 | } 58 | */ 59 | 60 | /* 61 | // Override to support editing the table view. 62 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 63 | if (editingStyle == UITableViewCellEditingStyleDelete) { 64 | // Delete the row from the data source 65 | [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; 66 | } else if (editingStyle == UITableViewCellEditingStyleInsert) { 67 | // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view 68 | } 69 | } 70 | */ 71 | 72 | /* 73 | // Override to support rearranging the table view. 74 | - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { 75 | } 76 | */ 77 | 78 | /* 79 | // Override to support conditional rearranging of the table view. 80 | - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { 81 | // Return NO if you do not want the item to be re-orderable. 82 | return YES; 83 | } 84 | */ 85 | 86 | /* 87 | #pragma mark - Navigation 88 | 89 | // In a storyboard-based application, you will often want to do a little preparation before navigation 90 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 91 | // Get the new view controller using [segue destinationViewController]. 92 | // Pass the selected object to the new view controller. 93 | } 94 | */ 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/MetalKernel/MetalKernelFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalKernelFilter.h 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 2018/7/3. 6 | // Copyright © 2018年 Colin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MetalKernelFilter : CIFilter 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/MetalKernel/MetalKernelFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MetalKernelFilter.m 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 2018/7/3. 6 | // Copyright © 2018年 Colin. All rights reserved. 7 | // 8 | 9 | #import "MetalKernelFilter.h" 10 | 11 | @interface MetalKernelFilter () { 12 | CIImage *inputImage; 13 | NSNumber *inputAlpha; 14 | } 15 | 16 | @end 17 | 18 | @implementation MetalKernelFilter 19 | 20 | static CIColorKernel *customKernel = nil; 21 | 22 | - (instancetype)init { 23 | self = [super init]; 24 | if (self) { 25 | if (customKernel == nil) { 26 | NSURL *kernelURL = [[NSBundle mainBundle] URLForResource:@"default" withExtension:@"metallib"]; 27 | NSError *error; 28 | NSData *data = [NSData dataWithContentsOfURL:kernelURL]; 29 | customKernel = [CIColorKernel kernelWithFunctionName:@"vignetteMetal" 30 | fromMetalLibraryData:data 31 | error:&error]; 32 | 33 | if (@available(iOS 11.0, *)) { 34 | } 35 | } 36 | } 37 | 38 | return self; 39 | } 40 | 41 | - (CIImage *)outputImage { 42 | CGRect dod = inputImage.extent; 43 | CGFloat radius = 0.5 * MAX(dod.size.width, dod.size.height); 44 | CIVector *center = [CIVector vectorWithX:dod.size.width / 2.0 45 | Y:dod.size.height / 2.0]; 46 | 47 | return [customKernel applyWithExtent:dod roiCallback:^CGRect(int index, CGRect destRect) { 48 | return destRect; 49 | } arguments:@[inputImage, center, @(radius), inputAlpha ?: @(0.0)]]; 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/MetalKernel/MetalKernelViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MetalKernelViewController.h 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 2018/7/3. 6 | // Copyright © 2018年 Colin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MetalKernelViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/MetalKernel/MetalKernelViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // MetalKernelViewController.m 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 2018/7/3. 6 | // Copyright © 2018年 Colin. All rights reserved. 7 | // 8 | 9 | #import "MetalKernelViewController.h" 10 | #import "MetalKernelFilter.h" 11 | 12 | @interface MetalKernelViewController () 13 | 14 | @property (strong, nonatomic) MetalKernelFilter *vignetteFilter; 15 | @property (strong, nonatomic) CIImage *inputImage; 16 | @property (strong, nonatomic) IBOutlet UIImageView *imageView; 17 | 18 | @end 19 | 20 | @implementation MetalKernelViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | // Do any additional setup after loading the view. 25 | 26 | // 初始化 Filter 27 | self.vignetteFilter = [[MetalKernelFilter alloc] init]; 28 | NSURL *imageURL = [[NSBundle mainBundle] URLForResource:@"vignetteImage" withExtension:@"jpg"]; 29 | self.inputImage = [CIImage imageWithContentsOfURL:imageURL]; 30 | [self.vignetteFilter setValue:_inputImage forKey:@"inputImage"]; 31 | 32 | self.imageView.image = [UIImage imageWithCIImage:self.inputImage]; 33 | 34 | } 35 | 36 | #pragma mark - Action 37 | - (IBAction)alphaChanged:(UISlider *)sender { 38 | [self.vignetteFilter setValue:@(sender.value) forKey:@"inputAlpha"]; 39 | CIImage *result = _vignetteFilter.outputImage; 40 | self.imageView.image = [UIImage imageWithCIImage:result]; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/MetalKernel/Vignette.metal: -------------------------------------------------------------------------------- 1 | // 2 | // Vignette.metal 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 2018/7/3. 6 | // Copyright © 2018年 Colin. All rights reserved. 7 | // 8 | 9 | #include 10 | using namespace metal; 11 | 12 | #include // includes CIKernelMetalLib.h 13 | 14 | extern "C" { namespace coreimage { 15 | float4 vignetteMetal(sample_t image, float2 center, float radius, float alpha, destination dest) { 16 | // 计算出当前点与中心的距离 17 | float distance2 = distance(dest.coord(), center); 18 | 19 | // 根据距离计算出暗淡程度 20 | float darken = 1.0 - (distance2 / radius * alpha); 21 | // 返回该像素点最终的色值 22 | image.rgb *= darken; 23 | 24 | return image.rgba; 25 | } 26 | }} 27 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Mosaic/Mosaic.cikernel: -------------------------------------------------------------------------------- 1 | kernel vec4 mosaicKernel(sampler image, sampler maskImage, float radius, vec2 point, float maskWidth, float maskHeight) 2 | { 3 | // 获取当前点坐标 4 | vec2 textureCoordinate = destCoord(); 5 | // 计算当前点与传入点的距离 6 | float distance = distance(textureCoordinate, point); 7 | if (distance < radius) { 8 | // 在处理范围内, 计算对应马赛克贴图中的位置 9 | float resultX = mod(textureCoordinate.x, maskWidth); 10 | float resultY = mod(textureCoordinate.y, maskHeight); 11 | return sample(maskImage, samplerTransform(maskImage, vec2(resultX, resultY))); 12 | } 13 | else { 14 | // 返回原图对应像素点色值 15 | return sample(image, samplerTransform(image, textureCoordinate)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Mosaic/MosaicFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // MosaicFilter.h 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 16/10/12. 6 | // Copyright © 2016年 Colin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MosaicFilter : CIFilter 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Mosaic/MosaicFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // MosaicFilter.m 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 16/10/12. 6 | // Copyright © 2016年 Colin. All rights reserved. 7 | // 8 | 9 | #import "MosaicFilter.h" 10 | 11 | @interface MosaicFilter () { 12 | CIImage *inputImage; 13 | CIImage *inputMaskImage; 14 | NSNumber *inputRadius; 15 | CIVector *inputPoint; 16 | } 17 | 18 | @end 19 | 20 | @implementation MosaicFilter 21 | 22 | static CIKernel *customKernel = nil; 23 | 24 | - (instancetype)init { 25 | 26 | self = [super init]; 27 | 28 | if (self) { 29 | 30 | if (customKernel == nil) 31 | { 32 | NSBundle *bundle = [NSBundle bundleForClass: [self class]]; 33 | NSURL *kernelURL = [bundle URLForResource:@"Mosaic" withExtension:@"cikernel"]; 34 | 35 | NSError *error; 36 | NSString *kernelCode = [NSString stringWithContentsOfURL:kernelURL 37 | encoding:NSUTF8StringEncoding error:&error]; 38 | if (kernelCode == nil) { 39 | NSLog(@"Error loading kernel code string in %@\n%@", 40 | NSStringFromSelector(_cmd), 41 | [error localizedDescription]); 42 | abort(); 43 | } 44 | 45 | NSArray *kernels = [CIKernel kernelsWithString:kernelCode]; 46 | customKernel = [kernels objectAtIndex:0]; 47 | } 48 | } 49 | 50 | return self; 51 | } 52 | 53 | - (CIImage *)outputImage 54 | { 55 | CGRect dod = inputImage.extent; 56 | 57 | if (!inputPoint) { 58 | return inputImage; 59 | } 60 | return [customKernel applyWithExtent:dod roiCallback:^CGRect(int index, CGRect destRect) { 61 | if (index == 0) { 62 | return inputImage.extent; 63 | } 64 | else 65 | { 66 | return inputMaskImage.extent; 67 | } 68 | } arguments:@[inputImage, inputMaskImage, inputRadius, inputPoint, @(inputMaskImage.extent.size.width), @(inputMaskImage.extent.size.height)]]; 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Mosaic/MosaicViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MosaicViewController.h 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 16/10/12. 6 | // Copyright © 2016年 Colin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MosaicViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Mosaic/MosaicViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // MosaicViewController.m 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 16/10/12. 6 | // Copyright © 2016年 Colin. All rights reserved. 7 | // 8 | 9 | #import "MosaicViewController.h" 10 | #import 11 | #import "MosaicFilter.h" 12 | 13 | @interface MosaicViewController () 14 | 15 | @property (weak, nonatomic) IBOutlet GLKView *glkView; 16 | @property (strong, nonatomic) CIContext *context; 17 | @property (strong, nonatomic) MosaicFilter *mosaicFilter; 18 | @property (assign, nonatomic) CGRect targetBounds; 19 | @property (strong, nonatomic) CIImage *inputImage; 20 | 21 | @end 22 | 23 | @implementation MosaicViewController 24 | 25 | - (void)viewDidLoad { 26 | [super viewDidLoad]; 27 | 28 | // 设置 OpenGLES 渲染环境 29 | EAGLContext *eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; 30 | self.glkView.context = eaglContext; 31 | self.context = [CIContext contextWithEAGLContext:eaglContext]; 32 | 33 | // 初始化 Filter 34 | self.mosaicFilter = [[MosaicFilter alloc] init]; 35 | NSURL *imageURL = [[NSBundle mainBundle] URLForResource:@"mosaicImage" withExtension:@"jpg"]; 36 | self.inputImage = [CIImage imageWithContentsOfURL:imageURL]; 37 | CIImage *maskImage = [[CIImage alloc] initWithImage:[UIImage imageNamed:@"mosaic_asset_2"]]; 38 | 39 | [self.mosaicFilter setValue:_inputImage forKey:@"inputImage"]; 40 | [self.mosaicFilter setValue:maskImage forKey:@"inputMaskImage"]; 41 | [self.mosaicFilter setValue:@(35.f) forKey:@"inputRadius"]; 42 | 43 | [self.glkView layoutIfNeeded]; 44 | [self viewDidLayoutSubviews]; 45 | } 46 | 47 | #pragma mark - Layout 48 | - (void)viewDidLayoutSubviews { 49 | [super viewDidLayoutSubviews]; 50 | 51 | // 获取绘制区域 52 | self.targetBounds = [self aspectFit:_inputImage.extent 53 | toRect:CGRectMake(0.0, 0.0, _glkView.drawableWidth, _glkView.drawableHeight)]; 54 | [self.context drawImage:_inputImage inRect:_targetBounds fromRect:_inputImage.extent]; 55 | [self.glkView display]; 56 | } 57 | 58 | #pragma mark - Action 59 | - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 60 | 61 | UITouch *touch = touches.anyObject; 62 | CGPoint point = [touch locationInView:_glkView]; 63 | point.y = _glkView.frame.size.height - point.y; 64 | point = [self converPointToImagePoint:point]; 65 | CIVector *pVector = [CIVector vectorWithCGPoint:point]; 66 | 67 | CGImageRef cgImage = [self.context createCGImage:self.mosaicFilter.outputImage fromRect:[self.mosaicFilter.outputImage extent]]; 68 | self.inputImage = [CIImage imageWithCGImage:cgImage]; 69 | CGImageRelease(cgImage); 70 | 71 | [self.mosaicFilter setValue:_inputImage forKey:@"inputImage"]; 72 | [self.mosaicFilter setValue:pVector forKey:@"inputPoint"]; 73 | [self.context drawImage:_mosaicFilter.outputImage inRect:_targetBounds fromRect:_inputImage.extent]; 74 | [self.glkView.context presentRenderbuffer:GL_RENDERBUFFER]; 75 | } 76 | 77 | #pragma mark - Private 78 | /** 79 | 获取实际显示区域 80 | 81 | @param fromRect 图片实际大小 82 | @param toRect GLKView 显示区域 83 | 84 | @return Fit 后的实际显示区域 85 | */ 86 | - (CGRect)aspectFit:(CGRect)fromRect toRect:(CGRect)toRect { 87 | CGFloat fromAspectRatio = fromRect.size.width / fromRect.size.height; 88 | CGFloat toAspectRatio = toRect.size.width / toRect.size.height; 89 | 90 | CGRect fitRect = toRect; 91 | 92 | if (fromAspectRatio > toAspectRatio) { 93 | fitRect.size.height = toRect.size.width / fromAspectRatio; 94 | fitRect.origin.y += (toRect.size.height - fitRect.size.height) * 0.5; 95 | } else { 96 | fitRect.size.width = toRect.size.height * fromAspectRatio; 97 | fitRect.origin.x += (toRect.size.width - fitRect.size.width) * 0.5; 98 | } 99 | 100 | return CGRectIntegral(fitRect); 101 | } 102 | 103 | - (CGPoint)converPointToImagePoint:(CGPoint)imageViewPoint { 104 | CGPoint imagePoint = CGPointZero; 105 | CGFloat scale = self.inputImage.extent.size.width / self.targetBounds.size.width; 106 | 107 | imagePoint.x = (imageViewPoint.x * [UIScreen mainScreen].scale - self.targetBounds.origin.x) * scale; 108 | imagePoint.y = (imageViewPoint.y * [UIScreen mainScreen].scale - self.targetBounds.origin.y) * scale; 109 | 110 | return imagePoint; 111 | } 112 | 113 | 114 | 115 | @end 116 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Mosaic/mosaicImage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colin1994/CoreImageDemo/25041fd21f31321b07146b55372b9f4d8a1f21e1/CoreImageDemo/CoreImageDemo/Mosaic/mosaicImage.jpg -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Mosaic/mosaic_asset_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colin1994/CoreImageDemo/25041fd21f31321b07146b55372b9f4d8a1f21e1/CoreImageDemo/CoreImageDemo/Mosaic/mosaic_asset_1.png -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Mosaic/mosaic_asset_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colin1994/CoreImageDemo/25041fd21f31321b07146b55372b9f4d8a1f21e1/CoreImageDemo/CoreImageDemo/Mosaic/mosaic_asset_2.png -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Pixellate/Pixellate.cikernel: -------------------------------------------------------------------------------- 1 | kernel vec2 pixellateKernel(float radius) 2 | { 3 | vec2 positionOfDestPixel, centerPoint; 4 | // 获取当前点坐标 5 | positionOfDestPixel = destCoord(); 6 | // 获取对应晶格内的中心像素点 7 | centerPoint.x = positionOfDestPixel.x - mod(positionOfDestPixel.x, radius * 2.0) + radius; 8 | centerPoint.y = positionOfDestPixel.y - mod(positionOfDestPixel.y, radius * 2.0) + radius; 9 | 10 | return centerPoint; 11 | } 12 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Pixellate/PixellateFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // PixellateFilter.h 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 16/10/11. 6 | // Copyright © 2016年 Colin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PixellateFilter : CIFilter 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Pixellate/PixellateFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // PixellateFilter.m 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 16/10/11. 6 | // Copyright © 2016年 Colin. All rights reserved. 7 | // 8 | 9 | #import "PixellateFilter.h" 10 | 11 | @interface PixellateFilter () { 12 | CIImage *inputImage; 13 | NSNumber *inputRadius; 14 | } 15 | 16 | @end 17 | 18 | @implementation PixellateFilter 19 | 20 | static CIWarpKernel *customKernel = nil; 21 | 22 | - (instancetype)init { 23 | 24 | self = [super init]; 25 | 26 | if (self) { 27 | 28 | if (customKernel == nil) 29 | { 30 | NSBundle *bundle = [NSBundle bundleForClass: [self class]]; 31 | NSURL *kernelURL = [bundle URLForResource:@"Pixellate" withExtension:@"cikernel"]; 32 | 33 | NSError *error; 34 | NSString *kernelCode = [NSString stringWithContentsOfURL:kernelURL 35 | encoding:NSUTF8StringEncoding error:&error]; 36 | if (kernelCode == nil) { 37 | NSLog(@"Error loading kernel code string in %@\n%@", 38 | NSStringFromSelector(_cmd), 39 | [error localizedDescription]); 40 | abort(); 41 | } 42 | 43 | NSArray *kernels = [CIWarpKernel kernelsWithString:kernelCode]; 44 | customKernel = [kernels objectAtIndex:0]; 45 | } 46 | } 47 | 48 | return self; 49 | } 50 | 51 | - (CIImage *)outputImage 52 | { 53 | CGRect dod = inputImage.extent; 54 | return [customKernel applyWithExtent:dod roiCallback:^CGRect(int index, CGRect destRect) { 55 | return destRect; 56 | } inputImage:inputImage arguments:@[inputRadius]]; 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Pixellate/PixellateViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // PixellateViewController.h 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 16/10/11. 6 | // Copyright © 2016年 Colin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PixellateViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Pixellate/PixellateViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // PixellateViewController.m 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 16/10/11. 6 | // Copyright © 2016年 Colin. All rights reserved. 7 | // 8 | 9 | #import "PixellateViewController.h" 10 | #import 11 | #import "PixellateFilter.h" 12 | 13 | @interface PixellateViewController () 14 | 15 | @property (weak, nonatomic) IBOutlet GLKView *glkView; 16 | @property (strong, nonatomic) CIContext *context; 17 | @property (strong, nonatomic) PixellateFilter *pixellateFilter; 18 | @property (assign, nonatomic) CGRect targetBounds; 19 | @property (strong, nonatomic) CIImage *inputImage; 20 | 21 | @end 22 | 23 | @implementation PixellateViewController 24 | 25 | - (void)viewDidLoad { 26 | [super viewDidLoad]; 27 | 28 | // 设置 OpenGLES 渲染环境 29 | EAGLContext *eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; 30 | self.glkView.context = eaglContext; 31 | self.context = [CIContext contextWithEAGLContext:eaglContext]; 32 | 33 | // 初始化 Filter 34 | self.pixellateFilter = [[PixellateFilter alloc] init]; 35 | NSURL *imageURL = [[NSBundle mainBundle] URLForResource:@"pixellateImage" withExtension:@"jpg"]; 36 | self.inputImage = [CIImage imageWithContentsOfURL:imageURL]; 37 | [self.pixellateFilter setValue:_inputImage forKey:@"inputImage"]; 38 | 39 | [self.glkView layoutIfNeeded]; 40 | } 41 | 42 | #pragma mark - Layout 43 | - (void)viewDidLayoutSubviews { 44 | [super viewDidLayoutSubviews]; 45 | 46 | // 获取绘制区域 47 | self.targetBounds = [self aspectFit:_inputImage.extent 48 | toRect:CGRectMake(0.0, 0.0, _glkView.drawableWidth, _glkView.drawableHeight)]; 49 | [self.context drawImage:_inputImage inRect:_targetBounds fromRect:_inputImage.extent]; 50 | [self.glkView display]; 51 | } 52 | 53 | #pragma mark - Action 54 | - (IBAction)radiusChanged:(UISlider *)sender { 55 | [self.pixellateFilter setValue:@(sender.value) forKey:@"inputRadius"]; 56 | 57 | [self.context drawImage:_pixellateFilter.outputImage inRect:_targetBounds fromRect:_inputImage.extent]; 58 | [self.glkView.context presentRenderbuffer:GL_RENDERBUFFER]; 59 | } 60 | 61 | #pragma mark - Private 62 | /** 63 | 获取实际显示区域 64 | 65 | @param fromRect 图片实际大小 66 | @param toRect GLKView 显示区域 67 | 68 | @return Fit 后的实际显示区域 69 | */ 70 | - (CGRect)aspectFit:(CGRect)fromRect toRect:(CGRect)toRect { 71 | CGFloat fromAspectRatio = fromRect.size.width / fromRect.size.height; 72 | CGFloat toAspectRatio = toRect.size.width / toRect.size.height; 73 | 74 | CGRect fitRect = toRect; 75 | 76 | if (fromAspectRatio > toAspectRatio) { 77 | fitRect.size.height = toRect.size.width / fromAspectRatio; 78 | fitRect.origin.y += (toRect.size.height - fitRect.size.height) * 0.5; 79 | } else { 80 | fitRect.size.width = toRect.size.height * fromAspectRatio; 81 | fitRect.origin.x += (toRect.size.width - fitRect.size.width) * 0.5; 82 | } 83 | 84 | return CGRectIntegral(fitRect); 85 | } 86 | 87 | 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Pixellate/pixellateImage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colin1994/CoreImageDemo/25041fd21f31321b07146b55372b9f4d8a1f21e1/CoreImageDemo/CoreImageDemo/Pixellate/pixellateImage.jpg -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Vignette/Vignette.cikernel: -------------------------------------------------------------------------------- 1 | kernel vec4 vignetteKernel(__sample image, vec2 center, float radius, float alpha) 2 | { 3 | // 计算出当前点与中心的距离 4 | float distance = distance(destCoord(), center) ; 5 | // 根据距离计算出暗淡程度 6 | float darken = 1.0 - (distance / radius * alpha); 7 | // 返回该像素点最终的色值 8 | image.rgb *= darken; 9 | 10 | return image.rgba; 11 | } 12 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Vignette/VignetteFilter.h: -------------------------------------------------------------------------------- 1 | // 2 | // VignetteFilter.h 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 16/10/11. 6 | // Copyright © 2016年 Colin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VignetteFilter : CIFilter 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Vignette/VignetteFilter.m: -------------------------------------------------------------------------------- 1 | // 2 | // VignetteFilter.m 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 16/10/11. 6 | // Copyright © 2016年 Colin. All rights reserved. 7 | // 8 | 9 | #import "VignetteFilter.h" 10 | 11 | @interface VignetteFilter () { 12 | CIImage *inputImage; 13 | NSNumber *inputAlpha; 14 | } 15 | 16 | @end 17 | 18 | @implementation VignetteFilter 19 | 20 | static CIColorKernel *customKernel = nil; 21 | 22 | - (instancetype)init { 23 | 24 | self = [super init]; 25 | 26 | if (self) { 27 | if (customKernel == nil) 28 | { 29 | NSBundle *bundle = [NSBundle bundleForClass: [self class]]; 30 | NSURL *kernelURL = [bundle URLForResource:@"Vignette" withExtension:@"cikernel"]; 31 | 32 | NSError *error; 33 | NSString *kernelCode = [NSString stringWithContentsOfURL:kernelURL 34 | encoding:NSUTF8StringEncoding error:&error]; 35 | if (kernelCode == nil) { 36 | NSLog(@"Error loading kernel code string in %@\n%@", 37 | NSStringFromSelector(_cmd), 38 | [error localizedDescription]); 39 | abort(); 40 | } 41 | 42 | NSArray *kernels = [CIColorKernel kernelsWithString:kernelCode]; 43 | customKernel = [kernels objectAtIndex:0]; 44 | } 45 | } 46 | 47 | return self; 48 | } 49 | 50 | - (CIImage *)outputImage 51 | { 52 | CGRect dod = inputImage.extent; 53 | CGFloat radius = 0.5 * MAX(dod.size.width, dod.size.height); 54 | CIVector *center = [CIVector vectorWithX:dod.size.width / 2.0 55 | Y:dod.size.height / 2.0]; 56 | 57 | return [customKernel applyWithExtent:dod roiCallback:^CGRect(int index, CGRect destRect) { 58 | return destRect; 59 | } arguments:@[inputImage, center, @(radius), inputAlpha ?: @(0.0)]]; 60 | } 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Vignette/VignetteViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // VignetteViewController.h 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 16/10/11. 6 | // Copyright © 2016年 Colin. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VignetteViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Vignette/VignetteViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // VignetteViewController.m 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 16/10/11. 6 | // Copyright © 2016年 Colin. All rights reserved. 7 | // 8 | 9 | #import "VignetteViewController.h" 10 | #import 11 | #import "VignetteFilter.h" 12 | 13 | @interface VignetteViewController () 14 | 15 | @property (weak, nonatomic) IBOutlet GLKView *glkView; 16 | @property (strong, nonatomic) CIContext *context; 17 | @property (strong, nonatomic) VignetteFilter *vignetteFilter; 18 | @property (assign, nonatomic) CGRect targetBounds; 19 | @property (strong, nonatomic) CIImage *inputImage; 20 | 21 | 22 | @end 23 | 24 | @implementation VignetteViewController 25 | 26 | - (void)viewDidLoad { 27 | [super viewDidLoad]; 28 | 29 | // 设置 OpenGLES 渲染环境 30 | EAGLContext *eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; 31 | self.glkView.context = eaglContext; 32 | self.context = [CIContext contextWithEAGLContext:eaglContext]; 33 | 34 | // 初始化 Filter 35 | self.vignetteFilter = [[VignetteFilter alloc] init]; 36 | NSURL *imageURL = [[NSBundle mainBundle] URLForResource:@"vignetteImage" withExtension:@"jpg"]; 37 | self.inputImage = [CIImage imageWithContentsOfURL:imageURL]; 38 | [self.vignetteFilter setValue:_inputImage forKey:@"inputImage"]; 39 | 40 | [self.glkView layoutIfNeeded]; 41 | } 42 | 43 | #pragma mark - Layout 44 | - (void)viewDidLayoutSubviews { 45 | [super viewDidLayoutSubviews]; 46 | 47 | // 获取绘制区域 48 | self.targetBounds = [self aspectFit:_inputImage.extent 49 | toRect:CGRectMake(0.0, 0.0, _glkView.drawableWidth, _glkView.drawableHeight)]; 50 | [self.context drawImage:_inputImage inRect:_targetBounds fromRect:_inputImage.extent]; 51 | [self.glkView display]; 52 | } 53 | 54 | #pragma mark - Action 55 | - (IBAction)alphaChanged:(UISlider *)sender { 56 | [self.vignetteFilter setValue:@(sender.value) forKey:@"inputAlpha"]; 57 | 58 | [self.context drawImage:_vignetteFilter.outputImage inRect:_targetBounds fromRect:_inputImage.extent]; 59 | [self.glkView.context presentRenderbuffer:GL_RENDERBUFFER]; 60 | } 61 | 62 | #pragma mark - Private 63 | /** 64 | 获取实际显示区域 65 | 66 | @param fromRect 图片实际大小 67 | @param toRect GLKView 显示区域 68 | 69 | @return Fit 后的实际显示区域 70 | */ 71 | - (CGRect)aspectFit:(CGRect)fromRect toRect:(CGRect)toRect { 72 | CGFloat fromAspectRatio = fromRect.size.width / fromRect.size.height; 73 | CGFloat toAspectRatio = toRect.size.width / toRect.size.height; 74 | 75 | CGRect fitRect = toRect; 76 | 77 | if (fromAspectRatio > toAspectRatio) { 78 | fitRect.size.height = toRect.size.width / fromAspectRatio; 79 | fitRect.origin.y += (toRect.size.height - fitRect.size.height) * 0.5; 80 | } else { 81 | fitRect.size.width = toRect.size.height * fromAspectRatio; 82 | fitRect.origin.x += (toRect.size.width - fitRect.size.width) * 0.5; 83 | } 84 | 85 | return CGRectIntegral(fitRect); 86 | } 87 | 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/Vignette/vignetteImage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colin1994/CoreImageDemo/25041fd21f31321b07146b55372b9f4d8a1f21e1/CoreImageDemo/CoreImageDemo/Vignette/vignetteImage.jpg -------------------------------------------------------------------------------- /CoreImageDemo/CoreImageDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // CoreImageDemo 4 | // 5 | // Created by Colin on 16/10/11. 6 | // Copyright © 2016年 Colin. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /EnlargeEyes.qtz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colin1994/CoreImageDemo/25041fd21f31321b07146b55372b9f4d8a1f21e1/EnlargeEyes.qtz -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Core Image 系列教程 2 | 3 | > 这是我的小专栏 [iOS 图像处理](https://xiaozhuanlan.com/colin) 对应的源码。欢迎订阅,配合教程看效果更佳~ 4 | 5 | 6 | 7 | Core Image 系列,目前的文章如下: 8 | 9 | - Core Image【1】—— 概述 10 | - Core Image【2】—— 自定义 Filter 11 | - Core Image【3】—— 2017 新特性 12 | - Core Image【4】—— 2018 新特性 13 | 14 | > PS: 15 | > 16 | > 如果想了解 Core Image 相关,建议按序阅读,前后有依赖。 17 | 18 | ------ 19 | 20 | 21 | 22 | 这个工程分别演示了 CIColorKernel,CIWarpKernel,CIKernel 的具体用法,另外附带了眼睛放大对应的 QC 文件。 23 | 24 | 感兴趣的了解下~ 25 | 26 | 具体效果如下: 27 | 28 | 29 | 30 | **CIColorKernel:Vignette** 31 | 32 | ![2016101796011vignette_demo.gif](http://7xkc7a.com1.z0.glb.clouddn.com/2016101796011vignette_demo.gif) 33 | 34 | 35 | 36 | **CIWarpKernel:Pixellate** 37 | 38 | ![2016101762677pixellate_demo.gif](http://7xkc7a.com1.z0.glb.clouddn.com/2016101762677pixellate_demo.gif) 39 | 40 | 41 | 42 | **CIKernel:Mosaic** 43 | 44 | ![2016101864134mosaic_demo.gif](http://7xkc7a.com1.z0.glb.clouddn.com/2016101864134mosaic_demo.gif) 45 | 46 | 47 | 48 | **QC:眼睛放大** 49 | 50 | ![201610184575enlargeEyes_demo.gif](http://7xkc7a.com1.z0.glb.clouddn.com/201610184575enlargeEyes_demo.gif) --------------------------------------------------------------------------------