├── .gitignore ├── FiltrrApp ├── FiltrrApp.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcuserdata │ │ └── omid.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── FiltrrApp │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Filtrr │ ├── UIImage+Filtrr.h │ ├── UIImage+Filtrr.m │ ├── UIImage+FiltrrCompositions.h │ ├── UIImage+FiltrrCompositions.m │ ├── UIImage+Scale.h │ └── UIImage+Scale.m │ ├── FiltrrApp-Info.plist │ ├── FiltrrApp-Prefix.pch │ ├── ImageViewController.h │ ├── ImageViewController.m │ ├── ImageViewController.xib │ ├── ViewController.h │ ├── ViewController.m │ ├── en.lproj │ ├── InfoPlist.strings │ └── ViewController.xib │ ├── filtrr_back.jpg │ └── main.m └── README /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | FiltrrApp/.DS_Store 3 | 4 | FiltrrApp/FiltrrApp.xcodeproj/xcuserdata/omid.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist 5 | 6 | FiltrrApp/FiltrrApp.xcodeproj/project.xcworkspace/xcuserdata/omid.xcuserdatad/UserInterfaceState.xcuserstate 7 | 8 | FiltrrApp/FiltrrApp.xcodeproj/project.xcworkspace/xcuserdata/omid.xcuserdatad/WorkspaceSettings.xcsettings 9 | 10 | FiltrrApp/FiltrrApp.xcodeproj/project.xcworkspace/xcuserdata/omid.xcuserdatad/UserInterfaceState.xcuserstate 11 | 12 | FiltrrApp/FiltrrApp.xcodeproj/xcuserdata/omid.xcuserdatad/xcschemes/FiltrrApp.xcscheme 13 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2E40719E14E526B800E4982C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E40719D14E526B800E4982C /* UIKit.framework */; }; 11 | 2E4071A014E526B800E4982C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E40719F14E526B800E4982C /* Foundation.framework */; }; 12 | 2E4071A214E526B800E4982C /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E4071A114E526B800E4982C /* CoreGraphics.framework */; }; 13 | 2E4071A814E526B800E4982C /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2E4071A614E526B800E4982C /* InfoPlist.strings */; }; 14 | 2E4071AA14E526B800E4982C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E4071A914E526B800E4982C /* main.m */; }; 15 | 2E4071AE14E526B800E4982C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E4071AD14E526B800E4982C /* AppDelegate.m */; }; 16 | 2E4071B114E526B800E4982C /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E4071B014E526B800E4982C /* ViewController.m */; }; 17 | 2E4071B414E526B800E4982C /* ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2E4071B214E526B800E4982C /* ViewController.xib */; }; 18 | 2E4071C814E526F700E4982C /* UIImage+Filtrr.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E4071C114E526F700E4982C /* UIImage+Filtrr.m */; }; 19 | 2E4071C914E526F700E4982C /* UIImage+FiltrrCompositions.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E4071C314E526F700E4982C /* UIImage+FiltrrCompositions.m */; }; 20 | 2E4071CA14E526F700E4982C /* filtrr_back.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 2E4071C414E526F700E4982C /* filtrr_back.jpg */; }; 21 | 2E4071CB14E526F700E4982C /* ImageViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E4071C614E526F700E4982C /* ImageViewController.m */; }; 22 | 2E4071CC14E526F700E4982C /* ImageViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2E4071C714E526F700E4982C /* ImageViewController.xib */; }; 23 | 2E53DA1914E92A17006F1CC9 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E53DA1814E92A17006F1CC9 /* ImageIO.framework */; }; 24 | 2E86673A14E57929006C7CE8 /* UIImage+Scale.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E86673914E57929006C7CE8 /* UIImage+Scale.m */; }; 25 | /* End PBXBuildFile section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | 2E40719914E526B800E4982C /* FiltrrApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FiltrrApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 29 | 2E40719D14E526B800E4982C /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 30 | 2E40719F14E526B800E4982C /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 31 | 2E4071A114E526B800E4982C /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 32 | 2E4071A514E526B800E4982C /* FiltrrApp-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "FiltrrApp-Info.plist"; sourceTree = ""; }; 33 | 2E4071A714E526B800E4982C /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 34 | 2E4071A914E526B800E4982C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 35 | 2E4071AB14E526B800E4982C /* FiltrrApp-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FiltrrApp-Prefix.pch"; sourceTree = ""; }; 36 | 2E4071AC14E526B800E4982C /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 37 | 2E4071AD14E526B800E4982C /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 38 | 2E4071AF14E526B800E4982C /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 39 | 2E4071B014E526B800E4982C /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 40 | 2E4071B314E526B800E4982C /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ViewController.xib; sourceTree = ""; }; 41 | 2E4071C014E526F700E4982C /* UIImage+Filtrr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+Filtrr.h"; sourceTree = ""; }; 42 | 2E4071C114E526F700E4982C /* UIImage+Filtrr.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+Filtrr.m"; sourceTree = ""; }; 43 | 2E4071C214E526F700E4982C /* UIImage+FiltrrCompositions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+FiltrrCompositions.h"; sourceTree = ""; }; 44 | 2E4071C314E526F700E4982C /* UIImage+FiltrrCompositions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+FiltrrCompositions.m"; sourceTree = ""; }; 45 | 2E4071C414E526F700E4982C /* filtrr_back.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = filtrr_back.jpg; sourceTree = ""; }; 46 | 2E4071C514E526F700E4982C /* ImageViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageViewController.h; sourceTree = ""; }; 47 | 2E4071C614E526F700E4982C /* ImageViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImageViewController.m; sourceTree = ""; }; 48 | 2E4071C714E526F700E4982C /* ImageViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ImageViewController.xib; sourceTree = ""; }; 49 | 2E53DA1814E92A17006F1CC9 /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; }; 50 | 2E86673814E57929006C7CE8 /* UIImage+Scale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+Scale.h"; sourceTree = ""; }; 51 | 2E86673914E57929006C7CE8 /* UIImage+Scale.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+Scale.m"; sourceTree = ""; }; 52 | /* End PBXFileReference section */ 53 | 54 | /* Begin PBXFrameworksBuildPhase section */ 55 | 2E40719614E526B800E4982C /* Frameworks */ = { 56 | isa = PBXFrameworksBuildPhase; 57 | buildActionMask = 2147483647; 58 | files = ( 59 | 2E53DA1914E92A17006F1CC9 /* ImageIO.framework in Frameworks */, 60 | 2E40719E14E526B800E4982C /* UIKit.framework in Frameworks */, 61 | 2E4071A014E526B800E4982C /* Foundation.framework in Frameworks */, 62 | 2E4071A214E526B800E4982C /* CoreGraphics.framework in Frameworks */, 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | /* End PBXFrameworksBuildPhase section */ 67 | 68 | /* Begin PBXGroup section */ 69 | 2E40718E14E526B800E4982C = { 70 | isa = PBXGroup; 71 | children = ( 72 | 2E53DA1814E92A17006F1CC9 /* ImageIO.framework */, 73 | 2E4071A314E526B800E4982C /* FiltrrApp */, 74 | 2E40719C14E526B800E4982C /* Frameworks */, 75 | 2E40719A14E526B800E4982C /* Products */, 76 | ); 77 | sourceTree = ""; 78 | }; 79 | 2E40719A14E526B800E4982C /* Products */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 2E40719914E526B800E4982C /* FiltrrApp.app */, 83 | ); 84 | name = Products; 85 | sourceTree = ""; 86 | }; 87 | 2E40719C14E526B800E4982C /* Frameworks */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | 2E40719D14E526B800E4982C /* UIKit.framework */, 91 | 2E40719F14E526B800E4982C /* Foundation.framework */, 92 | 2E4071A114E526B800E4982C /* CoreGraphics.framework */, 93 | ); 94 | name = Frameworks; 95 | sourceTree = ""; 96 | }; 97 | 2E4071A314E526B800E4982C /* FiltrrApp */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 2E4071BF14E526F700E4982C /* Filtrr */, 101 | 2E4071C414E526F700E4982C /* filtrr_back.jpg */, 102 | 2E4071C514E526F700E4982C /* ImageViewController.h */, 103 | 2E4071C614E526F700E4982C /* ImageViewController.m */, 104 | 2E4071C714E526F700E4982C /* ImageViewController.xib */, 105 | 2E4071AC14E526B800E4982C /* AppDelegate.h */, 106 | 2E4071AD14E526B800E4982C /* AppDelegate.m */, 107 | 2E4071AF14E526B800E4982C /* ViewController.h */, 108 | 2E4071B014E526B800E4982C /* ViewController.m */, 109 | 2E4071B214E526B800E4982C /* ViewController.xib */, 110 | 2E4071A414E526B800E4982C /* Supporting Files */, 111 | ); 112 | path = FiltrrApp; 113 | sourceTree = ""; 114 | }; 115 | 2E4071A414E526B800E4982C /* Supporting Files */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 2E4071A514E526B800E4982C /* FiltrrApp-Info.plist */, 119 | 2E4071A614E526B800E4982C /* InfoPlist.strings */, 120 | 2E4071A914E526B800E4982C /* main.m */, 121 | 2E4071AB14E526B800E4982C /* FiltrrApp-Prefix.pch */, 122 | ); 123 | name = "Supporting Files"; 124 | sourceTree = ""; 125 | }; 126 | 2E4071BF14E526F700E4982C /* Filtrr */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 2E4071C014E526F700E4982C /* UIImage+Filtrr.h */, 130 | 2E4071C114E526F700E4982C /* UIImage+Filtrr.m */, 131 | 2E4071C214E526F700E4982C /* UIImage+FiltrrCompositions.h */, 132 | 2E4071C314E526F700E4982C /* UIImage+FiltrrCompositions.m */, 133 | 2E86673814E57929006C7CE8 /* UIImage+Scale.h */, 134 | 2E86673914E57929006C7CE8 /* UIImage+Scale.m */, 135 | ); 136 | path = Filtrr; 137 | sourceTree = ""; 138 | }; 139 | /* End PBXGroup section */ 140 | 141 | /* Begin PBXNativeTarget section */ 142 | 2E40719814E526B800E4982C /* FiltrrApp */ = { 143 | isa = PBXNativeTarget; 144 | buildConfigurationList = 2E4071B714E526B800E4982C /* Build configuration list for PBXNativeTarget "FiltrrApp" */; 145 | buildPhases = ( 146 | 2E40719514E526B800E4982C /* Sources */, 147 | 2E40719614E526B800E4982C /* Frameworks */, 148 | 2E40719714E526B800E4982C /* Resources */, 149 | ); 150 | buildRules = ( 151 | ); 152 | dependencies = ( 153 | ); 154 | name = FiltrrApp; 155 | productName = FiltrrApp; 156 | productReference = 2E40719914E526B800E4982C /* FiltrrApp.app */; 157 | productType = "com.apple.product-type.application"; 158 | }; 159 | /* End PBXNativeTarget section */ 160 | 161 | /* Begin PBXProject section */ 162 | 2E40719014E526B800E4982C /* Project object */ = { 163 | isa = PBXProject; 164 | attributes = { 165 | LastUpgradeCheck = 0450; 166 | ORGANIZATIONNAME = 42dp; 167 | }; 168 | buildConfigurationList = 2E40719314E526B800E4982C /* Build configuration list for PBXProject "FiltrrApp" */; 169 | compatibilityVersion = "Xcode 3.2"; 170 | developmentRegion = English; 171 | hasScannedForEncodings = 0; 172 | knownRegions = ( 173 | en, 174 | ); 175 | mainGroup = 2E40718E14E526B800E4982C; 176 | productRefGroup = 2E40719A14E526B800E4982C /* Products */; 177 | projectDirPath = ""; 178 | projectRoot = ""; 179 | targets = ( 180 | 2E40719814E526B800E4982C /* FiltrrApp */, 181 | ); 182 | }; 183 | /* End PBXProject section */ 184 | 185 | /* Begin PBXResourcesBuildPhase section */ 186 | 2E40719714E526B800E4982C /* Resources */ = { 187 | isa = PBXResourcesBuildPhase; 188 | buildActionMask = 2147483647; 189 | files = ( 190 | 2E4071A814E526B800E4982C /* InfoPlist.strings in Resources */, 191 | 2E4071B414E526B800E4982C /* ViewController.xib in Resources */, 192 | 2E4071CA14E526F700E4982C /* filtrr_back.jpg in Resources */, 193 | 2E4071CC14E526F700E4982C /* ImageViewController.xib in Resources */, 194 | ); 195 | runOnlyForDeploymentPostprocessing = 0; 196 | }; 197 | /* End PBXResourcesBuildPhase section */ 198 | 199 | /* Begin PBXSourcesBuildPhase section */ 200 | 2E40719514E526B800E4982C /* Sources */ = { 201 | isa = PBXSourcesBuildPhase; 202 | buildActionMask = 2147483647; 203 | files = ( 204 | 2E4071AA14E526B800E4982C /* main.m in Sources */, 205 | 2E4071AE14E526B800E4982C /* AppDelegate.m in Sources */, 206 | 2E4071B114E526B800E4982C /* ViewController.m in Sources */, 207 | 2E4071C814E526F700E4982C /* UIImage+Filtrr.m in Sources */, 208 | 2E4071C914E526F700E4982C /* UIImage+FiltrrCompositions.m in Sources */, 209 | 2E4071CB14E526F700E4982C /* ImageViewController.m in Sources */, 210 | 2E86673A14E57929006C7CE8 /* UIImage+Scale.m in Sources */, 211 | ); 212 | runOnlyForDeploymentPostprocessing = 0; 213 | }; 214 | /* End PBXSourcesBuildPhase section */ 215 | 216 | /* Begin PBXVariantGroup section */ 217 | 2E4071A614E526B800E4982C /* InfoPlist.strings */ = { 218 | isa = PBXVariantGroup; 219 | children = ( 220 | 2E4071A714E526B800E4982C /* en */, 221 | ); 222 | name = InfoPlist.strings; 223 | sourceTree = ""; 224 | }; 225 | 2E4071B214E526B800E4982C /* ViewController.xib */ = { 226 | isa = PBXVariantGroup; 227 | children = ( 228 | 2E4071B314E526B800E4982C /* en */, 229 | ); 230 | name = ViewController.xib; 231 | sourceTree = ""; 232 | }; 233 | /* End PBXVariantGroup section */ 234 | 235 | /* Begin XCBuildConfiguration section */ 236 | 2E4071B514E526B800E4982C /* Debug */ = { 237 | isa = XCBuildConfiguration; 238 | buildSettings = { 239 | ALWAYS_SEARCH_USER_PATHS = NO; 240 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 241 | CLANG_ENABLE_OBJC_ARC = YES; 242 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 243 | COPY_PHASE_STRIP = NO; 244 | GCC_C_LANGUAGE_STANDARD = gnu99; 245 | GCC_DYNAMIC_NO_PIC = NO; 246 | GCC_OPTIMIZATION_LEVEL = 0; 247 | GCC_PREPROCESSOR_DEFINITIONS = ( 248 | "DEBUG=1", 249 | "$(inherited)", 250 | ); 251 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 252 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 253 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 254 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 255 | GCC_WARN_UNUSED_VARIABLE = YES; 256 | IPHONEOS_DEPLOYMENT_TARGET = 4.3; 257 | SDKROOT = iphoneos; 258 | }; 259 | name = Debug; 260 | }; 261 | 2E4071B614E526B800E4982C /* Release */ = { 262 | isa = XCBuildConfiguration; 263 | buildSettings = { 264 | ALWAYS_SEARCH_USER_PATHS = NO; 265 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 266 | CLANG_ENABLE_OBJC_ARC = YES; 267 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 268 | COPY_PHASE_STRIP = YES; 269 | GCC_C_LANGUAGE_STANDARD = gnu99; 270 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 271 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 272 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 273 | GCC_WARN_UNUSED_VARIABLE = YES; 274 | IPHONEOS_DEPLOYMENT_TARGET = 4.3; 275 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 276 | SDKROOT = iphoneos; 277 | VALIDATE_PRODUCT = YES; 278 | }; 279 | name = Release; 280 | }; 281 | 2E4071B814E526B800E4982C /* Debug */ = { 282 | isa = XCBuildConfiguration; 283 | buildSettings = { 284 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 285 | GCC_PREFIX_HEADER = "FiltrrApp/FiltrrApp-Prefix.pch"; 286 | INFOPLIST_FILE = "FiltrrApp/FiltrrApp-Info.plist"; 287 | IPHONEOS_DEPLOYMENT_TARGET = 4.3; 288 | PRODUCT_NAME = "$(TARGET_NAME)"; 289 | WRAPPER_EXTENSION = app; 290 | }; 291 | name = Debug; 292 | }; 293 | 2E4071B914E526B800E4982C /* Release */ = { 294 | isa = XCBuildConfiguration; 295 | buildSettings = { 296 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 297 | GCC_PREFIX_HEADER = "FiltrrApp/FiltrrApp-Prefix.pch"; 298 | INFOPLIST_FILE = "FiltrrApp/FiltrrApp-Info.plist"; 299 | IPHONEOS_DEPLOYMENT_TARGET = 4.3; 300 | PRODUCT_NAME = "$(TARGET_NAME)"; 301 | WRAPPER_EXTENSION = app; 302 | }; 303 | name = Release; 304 | }; 305 | /* End XCBuildConfiguration section */ 306 | 307 | /* Begin XCConfigurationList section */ 308 | 2E40719314E526B800E4982C /* Build configuration list for PBXProject "FiltrrApp" */ = { 309 | isa = XCConfigurationList; 310 | buildConfigurations = ( 311 | 2E4071B514E526B800E4982C /* Debug */, 312 | 2E4071B614E526B800E4982C /* Release */, 313 | ); 314 | defaultConfigurationIsVisible = 0; 315 | defaultConfigurationName = Release; 316 | }; 317 | 2E4071B714E526B800E4982C /* Build configuration list for PBXNativeTarget "FiltrrApp" */ = { 318 | isa = XCConfigurationList; 319 | buildConfigurations = ( 320 | 2E4071B814E526B800E4982C /* Debug */, 321 | 2E4071B914E526B800E4982C /* Release */, 322 | ); 323 | defaultConfigurationIsVisible = 0; 324 | defaultConfigurationName = Release; 325 | }; 326 | /* End XCConfigurationList section */ 327 | }; 328 | rootObject = 2E40719014E526B800E4982C /* Project object */; 329 | } 330 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp.xcodeproj/xcuserdata/omid.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | FiltrrApp.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 2E40719814E526B800E4982C 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // ImageViewController.h 3 | // FilterTest 4 | // 5 | // Created by Omid Hashemi & Stefan Klefisch on 2/6/12. 6 | // Copyright (c) 2012 42dp. All rights reserved. 7 | // http://www.42dp.com 8 | // 9 | 10 | #import 11 | 12 | @class ViewController; 13 | 14 | @interface AppDelegate : UIResponder 15 | 16 | @property (strong, nonatomic) UIWindow *window; 17 | 18 | @property (strong, nonatomic) ViewController *viewController; 19 | @property (strong, nonatomic) UINavigationController *navController; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageViewController.h 3 | // FilterTest 4 | // 5 | // Created by Omid Hashemi & Stefan Klefisch on 2/6/12. 6 | // Copyright (c) 2012 42dp. All rights reserved. 7 | // http://www.42dp.com 8 | // 9 | 10 | #import "AppDelegate.h" 11 | 12 | #import "ViewController.h" 13 | 14 | @implementation AppDelegate 15 | 16 | @synthesize window = _window; 17 | @synthesize viewController = _viewController; 18 | @synthesize navController = _navController; 19 | 20 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 21 | { 22 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 23 | // Override point for customization after application launch. 24 | self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; 25 | 26 | self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil]; 27 | self.navController = [[UINavigationController alloc] initWithRootViewController:self.viewController]; 28 | self.navController.title = @"Effects"; 29 | self.navController.navigationBar.tintColor = [UIColor blackColor]; 30 | self.navController.delegate = self.viewController; 31 | 32 | [self.window addSubview:self.navController.view]; 33 | 34 | [self.window makeKeyAndVisible]; 35 | return YES; 36 | } 37 | 38 | - (void)applicationWillResignActive:(UIApplication *)application 39 | { 40 | /* 41 | 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. 42 | Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 43 | */ 44 | } 45 | 46 | - (void)applicationDidEnterBackground:(UIApplication *)application 47 | { 48 | /* 49 | 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. 50 | If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 51 | */ 52 | } 53 | 54 | - (void)applicationWillEnterForeground:(UIApplication *)application 55 | { 56 | /* 57 | Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 58 | */ 59 | } 60 | 61 | - (void)applicationDidBecomeActive:(UIApplication *)application 62 | { 63 | /* 64 | 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. 65 | */ 66 | } 67 | 68 | - (void)applicationWillTerminate:(UIApplication *)application 69 | { 70 | /* 71 | Called when the application is about to terminate. 72 | Save data if appropriate. 73 | See also applicationDidEnterBackground:. 74 | */ 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp/Filtrr/UIImage+Filtrr.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Filtrr.h 3 | // fltr 4 | // 5 | // Created by Omid Hashemi & Stefan Klefisch on 2/6/12. 6 | // Copyright (c) 2012 42dp. All rights reserved. 7 | // http://www.42dp.com 8 | // Github: https://github.com/OmidH/Filtrr 9 | // 10 | // Based on Alex Michael's filtrr for Javascript (thanks for sharing Alex) 11 | // https://github.com/alexmic/filtrr 12 | 13 | 14 | #import 15 | #import 16 | 17 | struct FieldPosition 18 | { 19 | unsigned char one; 20 | unsigned char two; 21 | unsigned char three; 22 | unsigned char four; 23 | }; 24 | 25 | typedef struct FieldPosition DataField; 26 | 27 | struct anRGBA 28 | { 29 | unsigned char red; 30 | unsigned char green; 31 | unsigned char blue; 32 | unsigned char alpha; 33 | }; 34 | 35 | typedef struct anRGBA RGBA; 36 | 37 | enum EdgeTypes { 38 | simple = 0, 39 | sobel = 1, 40 | canny = 2 41 | }; 42 | 43 | typedef enum EdgeTypes EdgeType; 44 | 45 | static inline DataField DataFieldMake(int first, int second, int third, int fourth) 46 | { 47 | DataField field; 48 | field.one = first; field.two = second; 49 | field.three = third; field.four = fourth; 50 | return field; 51 | } 52 | 53 | static inline RGBA RGBAMake(int r, int g, int b, int a) 54 | { 55 | RGBA field; 56 | field.red = r; field.blue = b; 57 | field.green = g; field.alpha = a; 58 | return field; 59 | } 60 | 61 | @interface UIImage (Filtrr) 62 | 63 | - (float) safe:(int) i; 64 | - (UIImage *) duplicate; 65 | 66 | - (id) applyFiltrr:(RGBA (^)(int r, int g, int b, int a))fn; 67 | - (id) applyFiltrrByStep:(int) step 68 | ShiftIn:(DataField)shiftIn 69 | ShiftOut:(DataField)shiftOut 70 | Callback:(RGBA (^)(int r, int g, int b, int a))fn; 71 | 72 | - (id) convolve:(NSArray *) kernel; 73 | - (id) edgeDetection:(EdgeType)edgetype; 74 | - (id) adjustRedChannel:(float) rS GreenChannel:(float) gS BlueChannel:(float) bS; 75 | - (id) brightnessByFactor:(float) t; 76 | - (id) fillRedChannel:(float)rF GreenChannel:(float) gF BlueChannel:(float) bF; 77 | - (id) opacityByFactor:(float) o; 78 | - (id) saturationByFactor:(float) t; 79 | - (id) thresholdByFactor:(float) t; 80 | - (id) posterizeByLevel:(float) level; 81 | - (id) gammaByValue:(float) value; 82 | - (id) negative; 83 | - (id) grayScale; 84 | - (id) bump; 85 | - (id) tintWithMinRGB:(RGBA)minRGB MaxRGB:(RGBA)maxRGB; 86 | - (id) maskRedChannel:(int)mR GreenChannel:(int) mG BlueChannel:(int) mB; 87 | - (id) sepia; 88 | - (id) biasByFactor:(float) val; 89 | - (id) contrastByFactor:(float) val; 90 | - (id) blur; 91 | - (id) sharpen; 92 | - (id) gaussianBlur; 93 | 94 | - (id) applyBlend:(UIImage *)topImage CallBack: (RGBA (^)(RGBA top, RGBA bottom))fn; 95 | - (id) multiply:(UIImage *)topImage; 96 | - (id) screen:(UIImage *)topFltr; 97 | - (id) overlay:(UIImage *)topFltr; 98 | - (id) difference:(UIImage *)topFltr; 99 | - (id) addition:(UIImage *)topFltr; 100 | - (id) exclusion:(UIImage *)topFltr; 101 | - (id) softLight:(UIImage *)topFltr; 102 | 103 | - (float) calc_bias:(float) f Bias:(float) bi; 104 | - (float) calc_contrast:(float) f contrast:(float) c; 105 | - (float) calc_overlay:(float)b other:(float) t; 106 | - (float) calc_softlight:(float)b other:(float) t; 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp/Filtrr/UIImage+Filtrr.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Filtrr.m 3 | // FilterTest 4 | // 5 | // Created by Omid Hashemi & Stefan Klefisch on 2/6/12. 6 | // Copyright (c) 2012 42dp. All rights reserved. 7 | // http://www.42dp.com 8 | // Github: https://github.com/OmidH/Filtrr 9 | // 10 | // Based on Alex Michael's filtrr for Javascript (thanks for sharing Alex) 11 | // https://github.com/alexmic/filtrr 12 | 13 | 14 | #import "UIImage+Filtrr.h" 15 | 16 | @interface UIImage () 17 | - (CGContextRef) createARGBBitmapContextFromImage:(CGImageRef) imageRef; 18 | - (UIImage *) createImageFromContext:(CGContextRef) cgctx WithSize:(CGSize) size; 19 | - (UIImage *) createImageFromPixels:(unsigned char*)outData Length:(NSUInteger)length; 20 | 21 | -(unsigned char*) convolveRaw:(NSArray *) kernel InData:(unsigned char *)inData OuData:(unsigned char*)outData Height:(uint)_height Width:(uint)_width; 22 | 23 | @end 24 | 25 | @implementation UIImage (Filtrr) 26 | 27 | #pragma mark - Helper 28 | 29 | -(UIImage *) duplicate { 30 | // Get the Core Graphics Reference to the Image 31 | CGImageRef cgImage = [self CGImage]; 32 | 33 | // Make a new image from the CG Reference 34 | return [[UIImage alloc] initWithCGImage:cgImage]; 35 | } 36 | 37 | - (CGContextRef) createARGBBitmapContextFromImage:(CGImageRef) imageRef { 38 | CGContextRef context = NULL; 39 | CGColorSpaceRef colorSpace; 40 | void * bitmapData; 41 | int bitmapByteCount; 42 | int bitmapBytesPerRow; 43 | 44 | // Get image width, height. We'll use the entire image. 45 | size_t pixelsWide = CGImageGetWidth(imageRef); 46 | size_t pixelsHigh = CGImageGetHeight(imageRef); 47 | 48 | // Declare the number of bytes per row. Each pixel in the bitmap in this 49 | // example is represented by 4 bytes; 8 bits each of red, green, blue, and 50 | // alpha. 51 | bitmapBytesPerRow = (pixelsWide * 4); 52 | bitmapByteCount = (bitmapBytesPerRow * pixelsHigh); 53 | 54 | // Use the generic RGB color space. 55 | colorSpace = CGColorSpaceCreateDeviceRGB(); 56 | if (colorSpace == NULL) 57 | { 58 | fprintf(stderr, "Error allocating color space\n"); 59 | return NULL; 60 | } 61 | 62 | // Allocate memory for image data. This is the destination in memory 63 | // where any drawing to the bitmap context will be rendered. 64 | bitmapData = malloc( bitmapByteCount ); 65 | if (bitmapData == NULL) 66 | { 67 | fprintf (stderr, "Memory not allocated!"); 68 | CGColorSpaceRelease( colorSpace ); 69 | return NULL; 70 | } 71 | 72 | // Create the bitmap context. We want pre-multiplied ARGB, 8-bits 73 | // per component. Regardless of what the source image format is 74 | // (CMYK, Grayscale, and so on) it will be converted over to the format 75 | // specified here by CGBitmapContextCreate. 76 | context = CGBitmapContextCreate (bitmapData, 77 | pixelsWide, 78 | pixelsHigh, 79 | 8, // bits per component 80 | bitmapBytesPerRow, 81 | colorSpace, 82 | kCGImageAlphaPremultipliedFirst); 83 | if (context == NULL) 84 | { 85 | free (bitmapData); 86 | fprintf (stderr, "Context not created!"); 87 | } 88 | 89 | CGRect rect = {{0,0},{pixelsWide, pixelsHigh}}; 90 | // 91 | // // Draw the image to the bitmap context. Once we draw, the memory 92 | // // allocated for the context for rendering will then contain the 93 | // // raw image data in the specified color space. 94 | CGContextDrawImage(context, rect, self.CGImage); 95 | 96 | // Make sure and release colorspace before returning 97 | CGColorSpaceRelease( colorSpace ); 98 | 99 | return context; 100 | } 101 | 102 | - (UIImage *) createImageFromContext:(CGContextRef) cgctx WithSize:(CGSize) size { 103 | 104 | if (cgctx == NULL) 105 | // error creating context 106 | return nil; 107 | 108 | CGContextScaleCTM(cgctx, 1, -1); 109 | CGContextTranslateCTM(cgctx, 0, -size.height); 110 | 111 | CGImageRef img = CGBitmapContextCreateImage(cgctx); 112 | UIImage* ui_img = [UIImage imageWithCGImage: img]; 113 | 114 | CGImageRelease(img); 115 | CGContextRelease(cgctx); 116 | 117 | return ui_img; 118 | } 119 | 120 | - (UIImage *) createImageFromPixels:(unsigned char*)outData Length:(NSUInteger)length { 121 | // create a new image from the modified pixel data 122 | size_t width = CGImageGetWidth(self.CGImage); 123 | size_t height = CGImageGetHeight(self.CGImage); 124 | size_t bitsPerComponent = CGImageGetBitsPerComponent(self.CGImage); 125 | size_t bitsPerPixel = CGImageGetBitsPerPixel(self.CGImage); 126 | size_t bytesPerRow = CGImageGetBytesPerRow(self.CGImage); 127 | 128 | CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB(); 129 | CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(self.CGImage); 130 | CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, outData, length, NULL); 131 | 132 | CGImageRef newImageRef = CGImageCreate ( 133 | width, 134 | height, 135 | bitsPerComponent, 136 | bitsPerPixel, 137 | bytesPerRow, 138 | colorspace, 139 | bitmapInfo, 140 | provider, 141 | NULL, 142 | false, 143 | kCGRenderingIntentDefault 144 | ); 145 | // the modified image 146 | UIImage *newImage = [UIImage imageWithCGImage:newImageRef]; 147 | 148 | // cleanup 149 | CGColorSpaceRelease(colorspace); 150 | CGDataProviderRelease(provider); 151 | CGImageRelease(newImageRef); 152 | 153 | return newImage; 154 | } 155 | 156 | - (float) safe:(int) i { 157 | return MIN(255, MAX(0, i)); 158 | } 159 | 160 | #pragma mark - Core 161 | // 162 | //- (id) applyFiltrr:(RGBA (^)(int r, int g, int b, int a))fn { 163 | // 164 | // int i = 0, j = 0; 165 | // 166 | // CGContextRef cgctx = [self createARGBBitmapContextFromImage:self.CGImage]; 167 | // size_t _width = CGImageGetWidth(self.CGImage); 168 | // size_t _height = CGImageGetHeight(self.CGImage); 169 | // 170 | // // Now we can get a pointer to the image data associated with the bitmap 171 | // // context. 172 | // unsigned char* data = CGBitmapContextGetData (cgctx); 173 | // if (data != NULL) { 174 | // for (i = 0; i < _height; i++) { 175 | // for (j = 0; j < _width; j++) { 176 | // //offset locates the pixel in the data from x,y. 177 | // //4 for 4 bytes of data per pixel, w is width of one row of data. 178 | // int offset = (i*_width*4)+(j*4); 179 | // int red = data[offset]; 180 | // int green = data[offset+1]; 181 | // int blue = data[offset+2]; 182 | // int alpha = data[offset+3]; 183 | // 184 | // RGBA newColors = fn(red, green, blue, alpha); 185 | // 186 | // data[offset] = newColors.red; 187 | // data[offset+1] = newColors.green; 188 | // data[offset+2] = newColors.blue; 189 | // data[offset+3] = newColors.alpha; 190 | // } 191 | // } 192 | // } 193 | // 194 | // UIImage *img = [self createImageFromContext:cgctx WithSize:CGSizeMake(_width, _height)]; 195 | // // Free image data memory for the context 196 | // if (data) { free(data); } 197 | // 198 | // return img; 199 | //} 200 | 201 | - (id) applyFiltrr:(RGBA (^)(int r, int g, int b, int a))fn { 202 | return [self applyFiltrrByStep:4 203 | ShiftIn:DataFieldMake(1, 2, 3, 0) 204 | ShiftOut:DataFieldMake(0, 1, 2, 3) 205 | Callback:fn]; 206 | } 207 | 208 | - (id) applyFiltrrByStep:(int) step ShiftIn:(DataField)shiftIn ShiftOut:(DataField)shiftOut Callback:(RGBA (^)(int r, int g, int b, int a))fn { 209 | 210 | int i = 0; 211 | 212 | step = (step == 0) ? 4 : step; 213 | 214 | CGContextRef cgctx = [self createARGBBitmapContextFromImage:self.CGImage]; 215 | size_t _width = CGImageGetWidth(self.CGImage); 216 | size_t _height = CGImageGetHeight(self.CGImage); 217 | 218 | unsigned char* data = CGBitmapContextGetData (cgctx); 219 | if (data != NULL) { 220 | int max = _width * _height * 4; 221 | 222 | for (i = 0; i < max; i+=step) { 223 | 224 | RGBA newColors; 225 | 226 | newColors = fn(data[i + shiftIn.one], data[i + shiftIn.two], data[i + shiftIn.three], data[i + shiftIn.four]); 227 | 228 | data[i + shiftOut.one] = newColors.alpha; 229 | data[i + shiftOut.two] = newColors.red; 230 | data[i + shiftOut.three] = newColors.green; 231 | data[i + shiftOut.four] = newColors.blue; 232 | } 233 | } 234 | 235 | UIImage *img = [self createImageFromContext:cgctx WithSize:CGSizeMake(_width, _height)]; 236 | 237 | if (data) { free(data); } 238 | 239 | return img; 240 | } 241 | 242 | -(unsigned char*) convolveRaw:(NSArray *) kernel InData:(unsigned char *)inData OuData:(unsigned char*)outData Height:(uint)_height Width:(uint)_width { 243 | 244 | int kh = kernel.count / 2; 245 | int kw = [(NSArray *)[kernel objectAtIndex:0] count]/2; 246 | 247 | int i = 0, j = 0, n = 0, m = 0; 248 | 249 | for (i = 0; i < _height; i++) { 250 | for (j = 0; j < _width; j++) { 251 | int outIndex = (i*_width*4) + (j*4); 252 | int r = 0, g = 0, b = 0; 253 | for (n = -kh; n <= kh; n++) { 254 | for (m = -kw; m <= kw; m++) { 255 | if (i+n >= 0 && i + n <_height) { 256 | if (j + m >= 0 && j + m < _width) { 257 | float f = [[[kernel objectAtIndex:n+kh] objectAtIndex:m+kw] floatValue]; 258 | if(f == 0) 259 | continue; 260 | 261 | int inIndex = ((i+n)*_width*4) +((j+m)*4); 262 | r += inData[inIndex] * f; 263 | g += inData[inIndex + 1] * f; 264 | b += inData[inIndex + 2] * f; 265 | } 266 | } 267 | } 268 | } 269 | 270 | outData[outIndex] = [self safe:r]; 271 | outData[outIndex + 1] = [self safe:g]; 272 | outData[outIndex + 2] = [self safe:b]; 273 | outData[outIndex + 3] = 255; 274 | } 275 | } 276 | 277 | return outData; 278 | } 279 | 280 | -(id) convolve:(NSArray *) kernel { 281 | 282 | CGContextRef cgctx = [self createARGBBitmapContextFromImage:self.CGImage]; 283 | size_t _width = CGImageGetWidth(self.CGImage); 284 | size_t _height = CGImageGetHeight(self.CGImage); 285 | 286 | unsigned char* inData = CGBitmapContextGetData (cgctx); 287 | NSData* pixelData = (__bridge NSData*) CGDataProviderCopyData(CGImageGetDataProvider(self.CGImage)); 288 | NSMutableData* mutablePixelData = [pixelData mutableCopy]; 289 | // unsigned char* outData = (unsigned char*)[pixelData bytes]; 290 | unsigned char* outData = (unsigned char*)[mutablePixelData mutableBytes]; 291 | 292 | outData = [self convolveRaw:kernel InData:inData OuData:outData Height:_height Width:_width]; 293 | 294 | UIImage *newImage = [self createImageFromPixels:outData Length:pixelData.length]; 295 | 296 | // if(outData) free(outData); 297 | if(inData) free(inData); 298 | 299 | return newImage; 300 | } 301 | 302 | -(id) edgeDetection:(EdgeType)edgetype { 303 | CGContextRef cgctx = [self createARGBBitmapContextFromImage:self.CGImage]; 304 | size_t _width = CGImageGetWidth(self.CGImage); 305 | size_t _height = CGImageGetHeight(self.CGImage); 306 | 307 | unsigned char* inData = CGBitmapContextGetData (cgctx); 308 | NSData* pixelData = (__bridge NSData*) CGDataProviderCopyData(CGImageGetDataProvider(self.CGImage)); 309 | unsigned char* outData = (unsigned char*)[pixelData bytes]; 310 | 311 | int i = 0, j = 0, index = 0; 312 | 313 | switch (edgetype) { 314 | case simple: 315 | { 316 | for (i = 0; i < _height; i++) { 317 | for (j = 0; j < _width; j++) { 318 | index = (i*_width*4) + (j*4); 319 | int leftIndex = (i*_width*4) + ((j-1)*4); 320 | 321 | outData[index] = [self safe:abs(inData[index] - inData[leftIndex])]; 322 | outData[index + 1] = [self safe:abs(inData[index + 1] - inData[leftIndex + 1])]; 323 | outData[index + 2] = [self safe:abs(inData[index + 2] - inData[leftIndex + 2])]; 324 | outData[index + 3] = 255; 325 | } 326 | } 327 | 328 | inData = outData; 329 | } 330 | break; 331 | case sobel: 332 | { 333 | 334 | NSArray *kernel = [NSArray arrayWithObjects: [NSArray arrayWithObjects:[NSNumber numberWithFloat:-1.0], [NSNumber numberWithFloat:-2.0], [NSNumber numberWithFloat:-1.0], nil], 335 | [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:0.0], nil], 336 | [NSArray arrayWithObjects:[NSNumber numberWithFloat:1.0], [NSNumber numberWithFloat:2.0], [NSNumber numberWithFloat:1.0], nil], nil]; 337 | unsigned char* gH = [self convolveRaw:kernel InData:inData OuData:outData Height:_height Width:_width]; 338 | 339 | NSArray *kernel2 = [NSArray arrayWithObjects:[NSArray arrayWithObjects:[NSNumber numberWithFloat:-1.0], [NSNumber numberWithFloat:-2.0], [NSNumber numberWithFloat:-1.0], nil], 340 | [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:0.0], nil], 341 | [NSArray arrayWithObjects:[NSNumber numberWithFloat:1.0], [NSNumber numberWithFloat:2.0], [NSNumber numberWithFloat:1.0], nil], nil]; 342 | unsigned char* gV = [self convolveRaw:kernel2 InData:inData OuData:outData Height:_height Width:_width]; 343 | 344 | for (i = 0; i < _height; i++) { 345 | for (j = 0; j < _width; j++) { 346 | index = (i*_width*4) + (j*4); 347 | float rH = gH[index], 348 | rV = gV[index], 349 | grH = gH[index + 1], 350 | grV = gV[index + 1], 351 | bH = gH[index + 2], 352 | bV = gV[index + 2]; 353 | inData[index] = sqrt(rH * rH + rV * rV); 354 | inData[index + 1] = sqrt(grH * grH + grV * grV); 355 | inData[index + 2] = sqrt(bH * bH + bV * bV); 356 | } 357 | } 358 | } 359 | break; 360 | case canny: 361 | NSLog(@"edgeDetection(canny) not implemented yet!"); 362 | break; 363 | default: 364 | break; 365 | } 366 | 367 | UIImage *newImage = [self createImageFromPixels:outData Length:pixelData.length]; 368 | 369 | if(outData) free(outData); 370 | if(inData) free(inData); 371 | 372 | return newImage; 373 | } 374 | 375 | -(id) adjustRedChannel:(float) rS GreenChannel:(float) gS BlueChannel:(float) bS { 376 | 377 | return [self applyFiltrr:^RGBA (int r, int g, int b, int a) { 378 | RGBA retVal; 379 | retVal.red = [self safe:r* (1 + rS)]; 380 | retVal.green = [self safe:g* (1 + gS)]; 381 | retVal.blue = [self safe:b* (1 + bS)]; 382 | retVal.alpha = a; 383 | 384 | return retVal; 385 | }]; 386 | 387 | } 388 | 389 | -(id) brightnessByFactor:(float) t { 390 | return [self applyFiltrr:^RGBA (int r, int g, int b, int a) { 391 | RGBA retVal; 392 | retVal.red = [self safe:r + t]; 393 | retVal.green = [self safe:g + t]; 394 | retVal.blue = [self safe:b + t]; 395 | retVal.alpha = a; 396 | 397 | return retVal; 398 | }]; 399 | } 400 | 401 | -(id) fillRedChannel:(float)rF GreenChannel:(float) gF BlueChannel:(float) bF { 402 | return [self applyFiltrr:^RGBA (int r, int g, int b, int a) { 403 | RGBA retVal; 404 | retVal.red = [self safe:rF]; 405 | retVal.green = [self safe:gF]; 406 | retVal.blue = [self safe:bF]; 407 | retVal.alpha = a; 408 | 409 | return retVal; 410 | }]; 411 | } 412 | 413 | /** 414 | * Multiply the opacity by a given factor. 415 | * 416 | * @param o The factor to multply the opacity by. 417 | */ 418 | -(id) opacityByFactor:(float) o { 419 | return [self applyFiltrr:^RGBA (int r, int g, int b, int a) { 420 | RGBA retVal; 421 | retVal.red = r; 422 | retVal.green = g; 423 | retVal.blue = b; 424 | retVal.alpha = [self safe:o * a]; 425 | 426 | return retVal; 427 | }]; 428 | } 429 | 430 | /** 431 | * Adjusts the saturation by a given factor. 432 | * 433 | * @param t The factor to adjust the saturation by. 434 | */ 435 | -(id) saturationByFactor:(float) t { 436 | return [self applyFiltrr:^RGBA (int r, int g, int b, int a) { 437 | RGBA retVal; 438 | float avg = (r + g + b) / 3.0; 439 | 440 | retVal.red = [self safe:avg + t * (r - avg)]; 441 | retVal.green = [self safe:avg + t * (g - avg)]; 442 | retVal.blue = [self safe:avg + t * (b - avg)]; 443 | retVal.alpha = a; 444 | 445 | return retVal; 446 | }]; 447 | } 448 | 449 | /** 450 | * Uses a threshold number on each channel - intensities below 451 | * the threshold are turned black and intensities above are turned white. 452 | * 453 | * @param t The threshold. 454 | */ 455 | -(id) thresholdByFactor:(float) t { 456 | return [self applyFiltrr:^RGBA (int r, int g, int b, int a) { 457 | RGBA retVal; 458 | 459 | int c = 255; 460 | if (r < t|| g < t || b < t) { 461 | c = 0; 462 | } 463 | 464 | retVal.red = c; 465 | retVal.green = c; 466 | retVal.blue = c; 467 | retVal.alpha = a; 468 | 469 | return retVal; 470 | }]; 471 | } 472 | 473 | /** 474 | * Quantizes the colors in the image like a posterization effect. 475 | * 476 | * @param levels The levels of quantization. 477 | */ 478 | -(id) posterizeByLevel:(float) level { 479 | float step = floorf(255.0/level); 480 | return [self applyFiltrr:^RGBA (int r, int g, int b, int a) { 481 | RGBA retVal; 482 | 483 | retVal.red = [self safe:floorf(r/step) * step]; 484 | retVal.green = [self safe:floorf(g/step) * step]; 485 | retVal.blue = [self safe:floorf(b/step) * step]; 486 | retVal.alpha = a; 487 | 488 | return retVal; 489 | }]; 490 | } 491 | 492 | /** 493 | * Changes the gamma of the image. 494 | * 495 | * @param value The gamma value. 496 | */ 497 | -(id) gammaByValue:(float) value { 498 | return [self applyFiltrr:^RGBA (int r, int g, int b, int a) { 499 | RGBA retVal; 500 | 501 | retVal.red = [self safe:powf(r, value)]; 502 | retVal.green = [self safe:powf(g, value)]; 503 | retVal.blue = [self safe:powf(b, value)]; 504 | retVal.alpha = a; 505 | 506 | return retVal; 507 | }]; 508 | } 509 | 510 | /** 511 | * Inverts the colors in the image. 512 | */ 513 | -(id) negative { 514 | return [self applyFiltrr:^RGBA (int r, int g, int b, int a) { 515 | RGBA retVal; 516 | 517 | retVal.red = [self safe:255.0 - r]; 518 | retVal.green = [self safe:255.0 - g]; 519 | retVal.blue = [self safe:255.0 - b]; 520 | retVal.alpha = a; 521 | 522 | return retVal; 523 | }]; 524 | } 525 | 526 | /** 527 | * Creates a grayscale version of the image. 528 | */ 529 | -(id) grayScale { 530 | return [self applyFiltrr:^RGBA (int r, int g, int b, int a) { 531 | RGBA retVal; 532 | float avg = (r + g + b) / 3.0; 533 | 534 | retVal.red = [self safe:avg]; 535 | retVal.green = [self safe:avg]; 536 | retVal.blue = [self safe:avg]; 537 | retVal.alpha = a; 538 | 539 | return retVal; 540 | }]; 541 | } 542 | 543 | /** 544 | * Embosses the edges of the image. 545 | */ 546 | -(id) bump { 547 | 548 | NSArray *kernel = [NSArray arrayWithObjects: [NSArray arrayWithObjects:[NSNumber numberWithFloat:-1.0], [NSNumber numberWithFloat:-1.0], [NSNumber numberWithFloat:0.0], nil], 549 | [NSArray arrayWithObjects:[NSNumber numberWithFloat:-1.0], [NSNumber numberWithFloat:1.0], [NSNumber numberWithFloat:1.0], nil], 550 | [NSArray arrayWithObjects:[NSNumber numberWithFloat:-1.0], [NSNumber numberWithFloat:1.0], [NSNumber numberWithFloat:1.0], nil], nil]; 551 | 552 | return [self convolve:kernel]; 553 | } 554 | 555 | /** 556 | * Interpolates between the given RGB values. Changes the tint of the image. 557 | * 558 | * @param maxRGB The maximum RGB values. 559 | * @param minRGB The minimum RGB values. 560 | */ 561 | -(id) tintWithMinRGB:(RGBA)minRGB MaxRGB:(RGBA)maxRGB { 562 | return [self applyFiltrr:^RGBA (int r, int g, int b, int a) { 563 | RGBA retVal; 564 | 565 | retVal.red = [self safe:(r - minRGB.red) * (255.0 / (maxRGB.red - minRGB.red))]; 566 | retVal.green = [self safe:(g - minRGB.green) * (255.0 / (maxRGB.green - minRGB.green))]; 567 | retVal.blue = [self safe:(b - minRGB.blue) * (255.0 / (maxRGB.blue - minRGB.blue))]; 568 | retVal.alpha = a; 569 | 570 | return retVal; 571 | }]; 572 | } 573 | 574 | /** 575 | * Applies a mask on each channel. 576 | * 577 | * @param mR Red channel mask. 578 | * @param mG Green channel mask. 579 | * @param mB Blue channel mask. 580 | */ 581 | -(id) maskRedChannel:(int)mR GreenChannel:(int) mG BlueChannel:(int) mB { 582 | return [self applyFiltrr:^RGBA (int r, int g, int b, int a) { 583 | RGBA retVal; 584 | 585 | retVal.red = [self safe:(r & mR)]; 586 | retVal.green = [self safe:(g & mG)]; 587 | retVal.blue = [self safe:(b & mB)]; 588 | retVal.alpha = a; 589 | 590 | return retVal; 591 | }]; 592 | } 593 | 594 | /** 595 | * Applies a sepia filter. 596 | */ 597 | -(id) sepia { 598 | return [self applyFiltrr:^RGBA (int r, int g, int b, int a) { 599 | RGBA retVal; 600 | 601 | retVal.red = [self safe:(r * 0.393) + (g * 0.769) + (b * 0.189)]; 602 | retVal.green = [self safe:(r * 0.349) + (g * 0.686) + (b * 0.168)]; 603 | retVal.blue = [self safe:(r * 0.272) + (g * 0.534) + (b * 0.131)]; 604 | retVal.alpha = a; 605 | 606 | return retVal; 607 | }]; 608 | } 609 | 610 | /** 611 | * Make color lighter or darker by a given factor. 612 | * 613 | * @param t The factor to adjust the bias by. 614 | */ 615 | 616 | -(float) calc_bias:(float) f Bias:(float) bi { 617 | return f / ((1.0 / bi - 1.9) * (0.9 - f) + 1.0); 618 | } 619 | 620 | -(id) biasByFactor:(float) val { 621 | return [self applyFiltrr:^RGBA (int r, int g, int b, int a) { 622 | RGBA retVal; 623 | 624 | retVal.red = [self safe:(r * [self calc_bias:r / 255.0 Bias:val])]; 625 | retVal.green = [self safe:(g * [self calc_bias:g / 255.0 Bias:val])]; 626 | retVal.blue = [self safe:(b * [self calc_bias:b / 255.0 Bias:val])]; 627 | retVal.alpha = a; 628 | 629 | return retVal; 630 | }]; 631 | } 632 | 633 | /** 634 | * Adjusts the contrast by a given factor. 635 | * 636 | * @param t The factor to adjust the contrast by. 637 | */ 638 | 639 | -(float) calc_contrast:(float) f contrast:(float) c { 640 | return (f - 0.5) * c + 0.5; 641 | } 642 | 643 | -(id) contrastByFactor:(float) val { 644 | return [self applyFiltrr:^RGBA (int r, int g, int b, int a) { 645 | RGBA retVal; 646 | 647 | retVal.red = [self safe:(255.0 * [self calc_contrast:(r / 255.0) contrast:val])]; 648 | retVal.green = [self safe:(255.0 * [self calc_contrast:(g / 255.0) contrast:val])]; 649 | retVal.blue = [self safe:(255.0 * [self calc_contrast:(b / 255.0) contrast:val])]; 650 | retVal.alpha = a; 651 | 652 | return retVal; 653 | }]; 654 | } 655 | 656 | /** 657 | * A simple convolution blur. 658 | */ 659 | -(id) blur { 660 | NSArray *kernel = [NSArray arrayWithObjects: 661 | [NSArray arrayWithObjects:[NSNumber numberWithFloat:1.0], [NSNumber numberWithFloat:2.0], [NSNumber numberWithFloat:1.0], nil], 662 | [NSArray arrayWithObjects:[NSNumber numberWithFloat:2.0], [NSNumber numberWithFloat:2.0], [NSNumber numberWithFloat:2.0], nil], 663 | [NSArray arrayWithObjects:[NSNumber numberWithFloat:1.0], [NSNumber numberWithFloat:2.0], [NSNumber numberWithFloat:1.0], nil], nil]; 664 | 665 | return [self convolve:kernel]; 666 | } 667 | 668 | /** 669 | * Convolution sharpening. 670 | */ 671 | -(id) sharpen { 672 | NSArray *kernel = [NSArray arrayWithObjects: 673 | [NSArray arrayWithObjects:[NSNumber numberWithFloat:0], [NSNumber numberWithFloat:-0.2], [NSNumber numberWithFloat:1.0], nil], 674 | [NSArray arrayWithObjects:[NSNumber numberWithFloat:-0.2], [NSNumber numberWithFloat:1.8], [NSNumber numberWithFloat:-0.2], nil], 675 | [NSArray arrayWithObjects:[NSNumber numberWithFloat:0], [NSNumber numberWithFloat:-0.2], [NSNumber numberWithFloat:0], nil], nil]; 676 | 677 | return [self convolve:kernel]; 678 | } 679 | 680 | /** 681 | * Gaussian blur with a 5x5 convolution kernel. 682 | */ 683 | -(id) gaussianBlur { 684 | 685 | NSArray *kernel = [NSArray arrayWithObjects: 686 | [NSArray arrayWithObjects:[NSNumber numberWithFloat:1/273], [NSNumber numberWithFloat:4/273], [NSNumber numberWithFloat:7/273],[NSNumber numberWithFloat:4/273],[NSNumber numberWithFloat:1/273], nil], 687 | 688 | [NSArray arrayWithObjects:[NSNumber numberWithFloat:4/273], [NSNumber numberWithFloat:16/273], [NSNumber numberWithFloat:26/273],[NSNumber numberWithFloat:16/273],[NSNumber numberWithFloat:4/273], nil], 689 | 690 | [NSArray arrayWithObjects:[NSNumber numberWithFloat:7/273], [NSNumber numberWithFloat:26/273], [NSNumber numberWithFloat:41/273],[NSNumber numberWithFloat:26/273],[NSNumber numberWithFloat:7/273], nil], 691 | 692 | [NSArray arrayWithObjects:[NSNumber numberWithFloat:4/273], [NSNumber numberWithFloat:16/273], [NSNumber numberWithFloat:26/273],[NSNumber numberWithFloat:16/273],[NSNumber numberWithFloat:4/273], nil], 693 | 694 | [NSArray arrayWithObjects:[NSNumber numberWithFloat:1/273], [NSNumber numberWithFloat:4/273], [NSNumber numberWithFloat:7/273],[NSNumber numberWithFloat:4/273],[NSNumber numberWithFloat:1/273], nil],nil]; 695 | 696 | return [self convolve:kernel]; 697 | } 698 | 699 | #pragma mark - Blend 700 | 701 | -(id) applyBlend:(UIImage *)topImage CallBack: (RGBA (^)(RGBA top, RGBA bottom))fn { 702 | CGContextRef topCGctx = [topImage createARGBBitmapContextFromImage:topImage.CGImage]; 703 | unsigned char* blendData = CGBitmapContextGetData (topCGctx); 704 | 705 | CGContextRef bottomCGctx = [self createARGBBitmapContextFromImage:self.CGImage]; 706 | unsigned char * imageData = CGBitmapContextGetData (bottomCGctx); 707 | 708 | size_t _width = CGImageGetWidth(self.CGImage); 709 | size_t _height = CGImageGetHeight(self.CGImage); 710 | 711 | int i = 0, j = 0; 712 | 713 | for (i = 0; i < _height; i++) { 714 | for (j = 0; j < _width; j++) { 715 | int index = (i*_width*4) + (j*4); 716 | 717 | RGBA top; 718 | top.red = blendData[index]; 719 | top.green = blendData[index + 1]; 720 | top.blue = blendData[index + 2]; 721 | top.alpha = blendData[index + 3]; 722 | 723 | RGBA bottom; 724 | bottom.red = imageData[index]; 725 | bottom.green = imageData[index + 1]; 726 | bottom.blue = imageData[index + 2]; 727 | bottom.alpha = imageData[index + 3]; 728 | 729 | RGBA retVal = fn(top, bottom); 730 | 731 | imageData[index] = retVal.red; 732 | imageData[index + 1] = retVal.green; 733 | imageData[index + 2] = retVal.blue; 734 | imageData[index + 3] = retVal.alpha; 735 | } 736 | } 737 | 738 | UIImage *newImage = [self createImageFromContext:bottomCGctx WithSize:CGSizeMake(_width, _height)]; 739 | 740 | if(blendData) free(blendData); 741 | //if(imageData) free(imageData); 742 | 743 | return newImage; 744 | 745 | } 746 | 747 | /** 748 | * Multiply blend mode. 749 | */ 750 | -(id) multiply:(UIImage *)topImage { 751 | return [self applyBlend:topImage CallBack:^RGBA(RGBA top, RGBA bottom) { 752 | RGBA retVal; 753 | retVal.red = [self safe:(top.red * bottom.red)/255.0]; 754 | retVal.green = [self safe:(top.green * bottom.green)/255.0]; 755 | retVal.blue = [self safe:(top.blue * bottom.blue)/255.0]; 756 | retVal.alpha = bottom.alpha; 757 | 758 | return retVal; 759 | }]; 760 | } 761 | 762 | -(id) screen:(UIImage *)topFltr { 763 | return [self applyBlend:topFltr CallBack:^RGBA(RGBA param1, RGBA param2) { 764 | RGBA retVal; 765 | retVal.red = [self safe:255.0 - ((((255.0 - param1.red) * (255.0 - param2.red)) / 255.0))]; 766 | retVal.green = [self safe:255.0 - ((((255.0 - param1.green) * (255.0 - param2.green)) / 255.0))]; 767 | retVal.blue = [self safe:255.0 - ((((255.0 - param1.blue) * (255.0 - param2.blue)) / 255.0))]; 768 | retVal.alpha = param2.alpha; 769 | 770 | return retVal; 771 | }]; 772 | } 773 | 774 | -(float) calc_overlay:(float)b other:(float) t { 775 | return (b > 128.0) ? 255.0 - 2.0 * (255.0 - t) * (255.0 - b) / 255.0: (b * t * 2.0) / 255.0; 776 | } 777 | 778 | -(id) overlay:(UIImage *)topFltr { 779 | return [self applyBlend:topFltr CallBack:^RGBA(RGBA param1, RGBA param2) { 780 | RGBA retVal; 781 | retVal.red = [self safe:[self calc_overlay: param2.red other:param1.red]]; 782 | retVal.green = [self safe:[self calc_overlay: param2.green other:param1.green]]; 783 | retVal.blue = [self safe:[self calc_overlay: param2.blue other:param1.blue]]; 784 | retVal.alpha = param2.alpha; 785 | 786 | return retVal; 787 | }]; 788 | } 789 | 790 | -(id) difference:(UIImage *)topFltr{ 791 | return [self applyBlend:topFltr CallBack:^RGBA(RGBA param1, RGBA param2) { 792 | RGBA retVal; 793 | retVal.red = [self safe:abs(param1.red - param2.red)]; 794 | retVal.green = [self safe:abs(param1.green - param2.green)]; 795 | retVal.blue = [self safe:abs(param1.blue - param2.blue)]; 796 | retVal.alpha = param2.alpha; 797 | 798 | return retVal; 799 | }]; 800 | } 801 | 802 | -(id) addition:(UIImage *)topFltr{ 803 | return [self applyBlend:topFltr CallBack:^RGBA(RGBA param1, RGBA param2) { 804 | RGBA retVal; 805 | retVal.red = [self safe:abs(param1.red + param2.red)]; 806 | retVal.green = [self safe:abs(param1.green + param2.green)]; 807 | retVal.blue = [self safe:abs(param1.blue + param2.blue)]; 808 | retVal.alpha = param2.alpha; 809 | 810 | return retVal; 811 | }]; 812 | } 813 | 814 | -(id) exclusion:(UIImage *)topFltr{ 815 | return [self applyBlend:topFltr CallBack:^RGBA(RGBA param1, RGBA param2) { 816 | RGBA retVal; 817 | retVal.red = [self safe:128.0 - 2.0 * (param2.red - 128.0) * (param1.red - 128.0) / 255.0]; 818 | retVal.green = [self safe:128.0 - 2.0 * (param2.green - 128.0) * (param1.green - 128.0) / 255.0]; 819 | retVal.blue = [self safe:128.0 - 2.0 * (param2.blue - 128.0) * (param1.blue - 128.0) / 255.0]; 820 | retVal.alpha = param2.alpha; 821 | 822 | return retVal; 823 | }]; 824 | 825 | } 826 | 827 | -(float) calc_softlight:(float)b other:(float) t { 828 | return (b > 128.0) ? 255.0 - ((255.0 - b) * (255.0 - (t - 128.0))) / 255.0 : (b * (t + 128.0)) / 255.0; 829 | } 830 | 831 | -(id) softLight:(UIImage *)topFltr { 832 | return [self applyBlend:topFltr CallBack:^RGBA(RGBA param1, RGBA param2) { 833 | RGBA retVal; 834 | retVal.red = [self safe:[self calc_softlight: param2.red other:param1.red]]; 835 | retVal.green = [self safe:[self calc_softlight: param2.green other:param1.green]]; 836 | retVal.blue = [self safe:[self calc_softlight: param2.blue other:param1.blue]]; 837 | retVal.alpha = param2.alpha; 838 | 839 | return retVal; 840 | }]; 841 | 842 | } 843 | 844 | @end 845 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp/Filtrr/UIImage+FiltrrCompositions.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+FiltrrCompositions.h 3 | // FilterTest 4 | // 5 | // Created by Omid Hashemi & Stefan Klefisch on 2/6/12. 6 | // Copyright (c) 2012 42dp. All rights reserved. 7 | // http://www.42dp.com 8 | // Github: https://github.com/OmidH/Filtrr 9 | // 10 | // Based on Alex Michael's filtrr for Javascript (thanks for sharing Alex) 11 | // https://github.com/alexmic/filtrr 12 | 13 | 14 | #import 15 | 16 | @interface UIImage (FiltrrCompositions) 17 | 18 | -(id) trackTime:(NSString *)method; 19 | 20 | - (id) e1; 21 | - (id) e2; 22 | - (id) e3; 23 | - (id) e4; 24 | - (id) e5; 25 | - (id) e6; 26 | - (id) e7; 27 | - (id) e8; 28 | - (id) e9; 29 | - (id) e10; 30 | - (id) e11; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp/Filtrr/UIImage+FiltrrCompositions.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+FiltrrCompositions.m 3 | // FilterTest 4 | // 5 | // Created by Omid Hashemi & Stefan Klefisch on 2/6/12. 6 | // Copyright (c) 2012 42dp. All rights reserved. 7 | // http://www.42dp.com 8 | // Github: https://github.com/OmidH/Filtrr 9 | // 10 | // Based on Alex Michael's filtrr for Javascript (thanks for sharing Alex) 11 | // https://github.com/alexmic/filtrr 12 | 13 | #import "UIImage+FiltrrCompositions.h" 14 | #import "UIImage+Filtrr.h" 15 | 16 | @implementation UIImage (FiltrrCompositions) 17 | 18 | #pragma mark - DebugHelper 19 | 20 | -(id) trackTime:(NSString *)method { 21 | NSDate *startdate = [NSDate date]; 22 | 23 | SEL _selector = NSSelectorFromString(method); 24 | id retVal = [self performSelector:_selector]; 25 | 26 | NSDate *enddate = [NSDate date]; 27 | 28 | NSTimeInterval diff = [enddate timeIntervalSinceDate:startdate]; 29 | NSLog(@"returning new image from %@ with time: %f", method, diff); 30 | 31 | return retVal; 32 | } 33 | 34 | #pragma mark - Compositions 35 | 36 | -(id) e1 { 37 | 38 | UIImage *topImage = [self duplicate]; 39 | topImage = [[topImage saturationByFactor:0] blur]; 40 | 41 | UIImage * newImage = [self multiply:topImage]; 42 | 43 | RGBA minrgb, maxrgb; 44 | 45 | minrgb.red = 60; 46 | minrgb.green = 35; 47 | minrgb.blue = 10; 48 | 49 | maxrgb.red = 170; 50 | maxrgb.green = 140; 51 | maxrgb.blue = 160; 52 | 53 | newImage = [[[self tintWithMinRGB:minrgb MaxRGB:maxrgb] contrastByFactor:0.8] brightnessByFactor:10]; 54 | 55 | return newImage; 56 | 57 | } 58 | 59 | -(id) e2 { 60 | 61 | RGBA minrgb, maxrgb; 62 | 63 | minrgb.red = 50; 64 | minrgb.green = 35; 65 | minrgb.blue = 10; 66 | 67 | maxrgb.red = 190; 68 | maxrgb.green = 190; 69 | maxrgb.blue = 230; 70 | 71 | return [[[self saturationByFactor:0.3] posterizeByLevel:70] tintWithMinRGB:minrgb MaxRGB:maxrgb]; 72 | } 73 | 74 | -(id) e3 { 75 | RGBA minrgb, maxrgb; 76 | 77 | minrgb.red = 60; 78 | minrgb.green = 35; 79 | minrgb.blue = 10; 80 | 81 | maxrgb.red = 170; 82 | maxrgb.green = 170; 83 | maxrgb.blue = 230; 84 | 85 | return [[self tintWithMinRGB:minrgb MaxRGB:maxrgb] contrastByFactor:0.8]; 86 | } 87 | 88 | -(id) e4 { 89 | RGBA minrgb, maxrgb; 90 | 91 | minrgb.red = 60; 92 | minrgb.green = 60; 93 | minrgb.blue = 30; 94 | 95 | maxrgb.red = 210; 96 | maxrgb.green = 210; 97 | maxrgb.blue = 210; 98 | 99 | return [[self grayScale] tintWithMinRGB:minrgb MaxRGB:maxrgb]; 100 | } 101 | 102 | -(id) e5 { 103 | RGBA minrgb, maxrgb; 104 | 105 | minrgb.red = 30; 106 | minrgb.green = 40; 107 | minrgb.blue = 30; 108 | 109 | maxrgb.red = 120; 110 | maxrgb.green = 170; 111 | maxrgb.blue = 210; 112 | 113 | return [[[[[self tintWithMinRGB:minrgb MaxRGB:maxrgb] contrastByFactor:0.75] biasByFactor:1] saturationByFactor:0.6] brightnessByFactor:20]; 114 | } 115 | 116 | -(id) e6 { 117 | RGBA minrgb, maxrgb; 118 | 119 | minrgb.red = 30; 120 | minrgb.green = 40; 121 | minrgb.blue = 30; 122 | 123 | maxrgb.red = 120; 124 | maxrgb.green = 170; 125 | maxrgb.blue = 210; 126 | 127 | return [[[self saturationByFactor:0.4] contrastByFactor:0.75] tintWithMinRGB:minrgb MaxRGB:maxrgb]; 128 | } 129 | 130 | - (id) e7 { 131 | UIImage *topImage = [self duplicate]; 132 | 133 | RGBA minrgb, maxrgb; 134 | 135 | minrgb.red = 20; 136 | minrgb.green = 35; 137 | minrgb.blue = 10; 138 | 139 | maxrgb.red = 150; 140 | maxrgb.green = 160; 141 | maxrgb.blue = 230; 142 | 143 | topImage = [[topImage tintWithMinRGB:minrgb MaxRGB:maxrgb] saturationByFactor:0.6]; 144 | 145 | UIImage *newImage = [[[self adjustRedChannel:0.1 GreenChannel:0.7 BlueChannel:0.4] saturationByFactor:0.6] contrastByFactor:0.8]; 146 | newImage = [newImage multiply:topImage]; 147 | 148 | return newImage; 149 | } 150 | 151 | - (id) e8 { 152 | UIImage *topImage1 = [self duplicate]; 153 | UIImage *topImage2 = [self duplicate]; 154 | UIImage *topImage3 = [self duplicate]; 155 | 156 | topImage3 = [topImage3 fillRedChannel:167 GreenChannel:118 BlueChannel:12]; 157 | topImage2 = [topImage2 gaussianBlur]; 158 | topImage1 = [topImage1 saturationByFactor:0]; 159 | 160 | return [[[[[self overlay:topImage1] softLight:topImage2] softLight:topImage3] saturationByFactor:0.5] contrastByFactor:0.86]; 161 | } 162 | 163 | - (id) e9 { 164 | 165 | UIImage *topImage = [self duplicate]; 166 | 167 | DataField shiftIn = DataFieldMake(2, 3, 0, 1); 168 | DataField shiftOut = DataFieldMake(3, 0, 1, 2); 169 | 170 | topImage = [topImage applyFiltrrByStep:4 171 | ShiftIn:shiftIn 172 | ShiftOut:shiftOut 173 | Callback:^RGBA (int r, int g, int b, int a) { 174 | RGBA retVal; 175 | int t = 0; 176 | float avg = (r + g + b) / 3.0; 177 | 178 | retVal.red = [topImage safe:avg + t * (r - avg)]; 179 | retVal.green = [topImage safe:avg + t * (g - avg)]; 180 | retVal.blue = [topImage safe:avg + t * (b - avg)]; 181 | retVal.alpha = a; 182 | 183 | return retVal; 184 | }]; 185 | 186 | topImage = [topImage blur]; 187 | 188 | UIImage * newImage = [self multiply:topImage]; 189 | 190 | RGBA minrgb, maxrgb; 191 | 192 | minrgb.red = 60; 193 | minrgb.green = 35; 194 | minrgb.blue = 10; 195 | 196 | maxrgb.red = 170; 197 | maxrgb.green = 140; 198 | maxrgb.blue = 160; 199 | 200 | newImage = [newImage applyFiltrrByStep:4 201 | ShiftIn:shiftIn 202 | ShiftOut:shiftOut 203 | Callback:^RGBA (int r, int g, int b, int a) { 204 | RGBA retVal; 205 | 206 | retVal.red = [newImage safe:(r - minrgb.red) * (255.0 / (maxrgb.red - minrgb.red))]; 207 | retVal.green = [newImage safe:(g - minrgb.green) * (255.0 / (maxrgb.green - minrgb.green))]; 208 | retVal.blue = [newImage safe:(b - minrgb.blue) * (255.0 / (maxrgb.blue - minrgb.blue))]; 209 | retVal.alpha = a; 210 | 211 | return retVal; 212 | }]; 213 | 214 | newImage = [newImage applyFiltrrByStep:4 215 | ShiftIn:shiftIn 216 | ShiftOut:shiftOut 217 | Callback:^RGBA (int r, int g, int b, int a) { 218 | RGBA retVal; 219 | float val = 0.8; 220 | 221 | retVal.red = [newImage safe:(255.0 * [newImage calc_contrast:(r / 255.0) contrast:val])]; 222 | retVal.green = [newImage safe:(255.0 * [newImage calc_contrast:(g / 255.0) contrast:val])]; 223 | retVal.blue = [newImage safe:(255.0 * [newImage calc_contrast:(b / 255.0) contrast:val])]; 224 | retVal.alpha = a; 225 | 226 | return retVal; 227 | }]; 228 | 229 | newImage = [newImage applyFiltrrByStep:4 230 | ShiftIn:shiftIn 231 | ShiftOut:shiftOut 232 | Callback:^RGBA (int r, int g, int b, int a) { 233 | RGBA retVal; 234 | float t = 10.0; 235 | retVal.red = [newImage safe:r + t]; 236 | retVal.green = [newImage safe:g + t]; 237 | retVal.blue = [newImage safe:b + t]; 238 | retVal.alpha = a; 239 | 240 | return retVal; 241 | }]; 242 | 243 | return newImage; 244 | 245 | } 246 | 247 | - (id) e10 { 248 | return [[self sepia] biasByFactor:0.6]; 249 | } 250 | 251 | 252 | - (id) e11 { 253 | 254 | UIImage *topImage = [self duplicate]; 255 | 256 | DataField shiftIn = DataFieldMake(1, 2, 3, 0); 257 | DataField shiftOut = DataFieldMake(1, 1, 1, 2); 258 | 259 | topImage = [topImage applyFiltrrByStep:4 260 | ShiftIn:shiftIn 261 | ShiftOut:shiftOut 262 | Callback:^RGBA (int r, int g, int b, int a) { 263 | RGBA retVal; 264 | int t = 0; 265 | float avg = (r + g + b) / 3.0; 266 | 267 | retVal.red = [topImage safe:avg + t * (r - avg)]; 268 | retVal.green = [topImage safe:avg + t * (g - avg)]; 269 | retVal.blue = [topImage safe:avg + t * (b - avg)]; 270 | retVal.alpha = a; 271 | 272 | return retVal; 273 | }]; 274 | 275 | topImage = [topImage blur]; 276 | 277 | UIImage * newImage = [self multiply:topImage]; 278 | 279 | RGBA minrgb, maxrgb; 280 | 281 | minrgb = RGBAMake(60, 35, 10, 255); 282 | maxrgb = RGBAMake(170, 140, 160, 255); 283 | 284 | newImage = [newImage applyFiltrrByStep:4 285 | ShiftIn:shiftIn 286 | ShiftOut:shiftOut 287 | Callback:^RGBA (int r, int g, int b, int a) { 288 | RGBA retVal; 289 | 290 | retVal.red = [newImage safe:(r - minrgb.red) * (255.0 / (maxrgb.red - minrgb.red))]; 291 | retVal.green = [newImage safe:(g - minrgb.green) * (255.0 / (maxrgb.green - minrgb.green))]; 292 | retVal.blue = [newImage safe:(b - minrgb.blue) * (255.0 / (maxrgb.blue - minrgb.blue))]; 293 | retVal.alpha = a; 294 | 295 | return retVal; 296 | }]; 297 | 298 | newImage = [newImage applyFiltrrByStep:4 299 | ShiftIn:shiftIn 300 | ShiftOut:shiftOut 301 | Callback:^RGBA (int r, int g, int b, int a) { 302 | RGBA retVal; 303 | float val = 0.8; 304 | 305 | retVal.red = [newImage safe:(255.0 * [newImage calc_contrast:(r / 255.0) contrast:val])]; 306 | retVal.green = [newImage safe:(255.0 * [newImage calc_contrast:(g / 255.0) contrast:val])]; 307 | retVal.blue = [newImage safe:(255.0 * [newImage calc_contrast:(b / 255.0) contrast:val])]; 308 | retVal.alpha = a; 309 | 310 | return retVal; 311 | }]; 312 | 313 | newImage = [newImage applyFiltrrByStep:4 314 | ShiftIn:shiftIn 315 | ShiftOut:shiftOut 316 | Callback:^RGBA (int r, int g, int b, int a) { 317 | RGBA retVal; 318 | float t = 10.0; 319 | retVal.red = [newImage safe:r + t]; 320 | retVal.green = [newImage safe:g + t]; 321 | retVal.blue = [newImage safe:b + t]; 322 | retVal.alpha = a; 323 | 324 | return retVal; 325 | }]; 326 | 327 | return newImage; 328 | 329 | } 330 | 331 | @end 332 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp/Filtrr/UIImage+Scale.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Scale.h 3 | // FiltrrApp 4 | // 5 | // Created by Omid Hashemi on 2/10/12. 6 | // Copyright (c) 2012 42dp. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImage (Scale) 12 | 13 | -(UIImage*)scaleToSize:(CGSize)size; 14 | -(UIImage *)crop:(CGRect) cropRect; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp/Filtrr/UIImage+Scale.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Scale.m 3 | // FiltrrApp 4 | // 5 | // Created by Omid Hashemi on 2/10/12. 6 | // Copyright (c) 2012 42dp. All rights reserved. 7 | // 8 | 9 | #import "UIImage+Scale.h" 10 | 11 | @implementation UIImage (Scale) 12 | 13 | -(UIImage*)scaleToSize:(CGSize)size { 14 | // Create a bitmap graphics context 15 | // This will also set it as the current context 16 | UIGraphicsBeginImageContext(size); 17 | // Draw the scaled image in the current context 18 | [self drawInRect:CGRectMake(0, 0, size.width, size.height)]; 19 | // Create a new image from current context 20 | UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext(); 21 | // Pop the current context from the stack 22 | UIGraphicsEndImageContext(); 23 | // Return our new scaled image 24 | return scaledImage; 25 | } 26 | 27 | -(UIImage *) crop:(CGRect) cropRect { 28 | // CGImageRef imageRef = CGImageCreateWithImageInRect(self.CGImage, cropRect); 29 | // // or use the UIImage wherever you like 30 | // UIImage *retImage = [UIImage imageWithCGImage:imageRef]; 31 | // CGImageRelease(imageRef); 32 | 33 | if (self.scale > 1.0f) { 34 | cropRect = CGRectMake(cropRect.origin.x * self.scale, 35 | cropRect.origin.y * self.scale, 36 | cropRect.size.width * self.scale, 37 | cropRect.size.height * self.scale); 38 | } 39 | 40 | CGImageRef imageRef = CGImageCreateWithImageInRect(self.CGImage, cropRect); 41 | UIImage *retImage = [UIImage imageWithCGImage:imageRef scale:self.scale orientation:self.imageOrientation]; 42 | CGImageRelease(imageRef); 43 | 44 | return retImage; 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp/FiltrrApp-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFiles 12 | 13 | CFBundleIdentifier 14 | com.42dp.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 1.0 27 | LSRequiresIPhoneOS 28 | 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp/FiltrrApp-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'FiltrrApp' target in the 'FiltrrApp' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | 16 | #define TRACKTIME 17 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp/ImageViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ImageViewController.h 3 | // FilterTest 4 | // 5 | // Created by Omid Hashemi & Stefan Klefisch on 2/6/12. 6 | // Copyright (c) 2012 42dp. All rights reserved. 7 | // http://www.42dp.com 8 | // 9 | 10 | 11 | #import 12 | 13 | @interface ImageViewController : UIViewController 14 | 15 | @property (nonatomic, retain) IBOutlet UIImageView *ivPic; 16 | 17 | 18 | -(void) setImage:(UIImage *)img; 19 | -(void) save; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp/ImageViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageViewController.m 3 | // FilterTest 4 | // 5 | // Created by Omid Hashemi & Stefan Klefisch on 2/6/12. 6 | // Copyright (c) 2012 42dp. All rights reserved. 7 | // http://www.42dp.com 8 | // 9 | 10 | 11 | #import "ImageViewController.h" 12 | #import 13 | 14 | @implementation ImageViewController 15 | 16 | @synthesize ivPic = _ivPic; 17 | 18 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 19 | { 20 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 21 | if (self) { 22 | } 23 | return self; 24 | } 25 | 26 | - (void)didReceiveMemoryWarning 27 | { 28 | // Releases the view if it doesn't have a superview. 29 | [super didReceiveMemoryWarning]; 30 | 31 | // Release any cached data, images, etc that aren't in use. 32 | } 33 | 34 | #pragma mark - View lifecycle 35 | 36 | - (void)viewDidLoad 37 | { 38 | [super viewDidLoad]; 39 | CALayer * l = [_ivPic layer]; 40 | [l setMasksToBounds:YES]; 41 | [l setCornerRadius:10.0]; 42 | 43 | UIBarButtonItem *save = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(save)]; 44 | self.navigationItem.rightBarButtonItem = save; 45 | } 46 | 47 | - (void)viewDidUnload 48 | { 49 | [super viewDidUnload]; 50 | // Release any retained subviews of the main view. 51 | // e.g. self.myOutlet = nil; 52 | } 53 | 54 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 55 | { 56 | // Return YES for supported orientations 57 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 58 | } 59 | 60 | -(void) setImage:(UIImage *)img { 61 | _ivPic.frame = CGRectMake((self.view.frame.size.width - img.size.width)/2, (self.view.frame.size.height - img.size.height)/2, img.size.width, img.size.height); 62 | _ivPic.image = img; 63 | } 64 | 65 | -(void) save { 66 | UIImageWriteToSavedPhotosAlbum(_ivPic.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); 67 | } 68 | 69 | - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo 70 | { 71 | if (error) 72 | NSLog(@"Unable to save image to Photo Album."); 73 | 74 | [self.navigationController popViewControllerAnimated:YES]; 75 | 76 | // UIAlertView *alert; 77 | 78 | // Unable to save the image 79 | // if (error) 80 | // alert = [[UIAlertView alloc] initWithTitle:@"Error" 81 | // message:@"Unable to save image to Photo Album." 82 | // delegate:self cancelButtonTitle:@"Ok" 83 | // otherButtonTitles:nil]; 84 | // else // All is well 85 | // alert = [[UIAlertView alloc] initWithTitle:@"Success" 86 | // message:@"Image saved to Photo Album." 87 | // delegate:self cancelButtonTitle:@"Ok" 88 | // otherButtonTitles:nil]; 89 | // [alert show]; 90 | } 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp/ImageViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1536 5 | 12C60 6 | 2844 7 | 1187.34 8 | 625.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 1930 12 | 13 | 14 | IBProxyObject 15 | IBUIImageView 16 | IBUIView 17 | 18 | 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | PluginDependencyRecalculationVersion 23 | 24 | 25 | 26 | 27 | IBFilesOwner 28 | IBCocoaTouchFramework 29 | 30 | 31 | IBFirstResponder 32 | IBCocoaTouchFramework 33 | 34 | 35 | 36 | 274 37 | 38 | 39 | 40 | 319 41 | {320, 460} 42 | 43 | 44 | _NS:567 45 | 46 | 1 47 | MCAwIDAAA 48 | darkTextColor 49 | 50 | 1 51 | NO 52 | IBCocoaTouchFramework 53 | 54 | NSImage 55 | filtrr_back.jpg 56 | 57 | 58 | 59 | {{0, 20}, {320, 460}} 60 | 61 | 62 | 63 | 64 | 65 | IBUISimulatedFreeformSizeMetricsSentinel 66 | Freeform 67 | 68 | IBCocoaTouchFramework 69 | 70 | 71 | 72 | 73 | 74 | 75 | view 76 | 77 | 78 | 79 | 3 80 | 81 | 82 | 83 | ivPic 84 | 85 | 86 | 87 | 5 88 | 89 | 90 | 91 | 92 | 93 | 0 94 | 95 | 96 | 97 | 98 | 99 | 1 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | -1 108 | 109 | 110 | File's Owner 111 | 112 | 113 | -2 114 | 115 | 116 | 117 | 118 | 4 119 | 120 | 121 | 122 | 123 | 124 | 125 | ImageViewController 126 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 127 | UIResponder 128 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 129 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 130 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 131 | 132 | 133 | 134 | 135 | 136 | 5 137 | 138 | 139 | 140 | 141 | ImageViewController 142 | UIViewController 143 | 144 | ivPic 145 | UIImageView 146 | 147 | 148 | ivPic 149 | 150 | ivPic 151 | UIImageView 152 | 153 | 154 | 155 | IBProjectSource 156 | ./Classes/ImageViewController.h 157 | 158 | 159 | 160 | 161 | 0 162 | IBCocoaTouchFramework 163 | YES 164 | 3 165 | 166 | filtrr_back.jpg 167 | {465, 333} 168 | 169 | 1930 170 | 171 | 172 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ImageViewController.h 3 | // FilterTest 4 | // 5 | // Created by Omid Hashemi & Stefan Klefisch on 2/6/12. 6 | // Copyright (c) 2012 42dp. All rights reserved. 7 | // http://www.42dp.com 8 | // 9 | 10 | #import 11 | 12 | @interface ViewController : UIViewController { 13 | NSString *filename; 14 | NSMutableArray *arrEffects; 15 | 16 | UIImagePickerController * imagePicker; 17 | UIImage *selectedImage, *thumbImage; 18 | UIImage *minithumbImage; 19 | } 20 | 21 | @property (nonatomic, retain) IBOutlet UITableView *tblEffects; 22 | 23 | -(void) showCam; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageViewController.h 3 | // FilterTest 4 | // 5 | // Created by Omid Hashemi & Stefan Klefisch on 2/6/12. 6 | // Copyright (c) 2012 42dp. All rights reserved. 7 | // http://www.42dp.com 8 | // 9 | 10 | #import "ViewController.h" 11 | #import "ImageViewController.h" 12 | #import "UIImage+FiltrrCompositions.h" 13 | #import "UIImage+Scale.h" 14 | 15 | @implementation ViewController 16 | 17 | @synthesize tblEffects = _tblEffects; 18 | 19 | - (void)didReceiveMemoryWarning 20 | { 21 | [super didReceiveMemoryWarning]; 22 | // Release any cached data, images, etc that aren't in use. 23 | } 24 | 25 | #pragma mark - View lifecycle 26 | 27 | - (void)viewDidLoad 28 | { 29 | [super viewDidLoad]; 30 | 31 | arrEffects = [[NSMutableArray alloc] initWithObjects: 32 | [NSDictionary dictionaryWithObjectsAndKeys:@"Original",@"title",@"",@"method", nil], 33 | [NSDictionary dictionaryWithObjectsAndKeys:@"E1",@"title",@"e1",@"method", nil], 34 | [NSDictionary dictionaryWithObjectsAndKeys:@"E2",@"title",@"e2",@"method", nil], 35 | [NSDictionary dictionaryWithObjectsAndKeys:@"E3",@"title",@"e3",@"method", nil], 36 | [NSDictionary dictionaryWithObjectsAndKeys:@"E4",@"title",@"e4",@"method", nil], 37 | [NSDictionary dictionaryWithObjectsAndKeys:@"E5",@"title",@"e5",@"method", nil], 38 | [NSDictionary dictionaryWithObjectsAndKeys:@"E6",@"title",@"e6",@"method", nil], 39 | [NSDictionary dictionaryWithObjectsAndKeys:@"E7",@"title",@"e7",@"method", nil], 40 | [NSDictionary dictionaryWithObjectsAndKeys:@"E8",@"title",@"e8",@"method", nil], 41 | [NSDictionary dictionaryWithObjectsAndKeys:@"E9",@"title",@"e9",@"method", nil], 42 | [NSDictionary dictionaryWithObjectsAndKeys:@"E10",@"title",@"e10",@"method", nil], 43 | [NSDictionary dictionaryWithObjectsAndKeys:@"E11",@"title",@"e11",@"method", nil], 44 | nil]; 45 | 46 | UIBarButtonItem *cam = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:@selector(showCam)]; 47 | self.navigationItem.rightBarButtonItem = cam; 48 | self.title = @"Effects"; 49 | 50 | selectedImage = [UIImage imageNamed:@"filtrr_back.jpg"]; 51 | thumbImage = [selectedImage scaleToSize:CGSizeMake(320, 320)]; 52 | minithumbImage = [thumbImage scaleToSize:CGSizeMake(40, 40)]; 53 | } 54 | 55 | - (void)viewDidUnload 56 | { 57 | [super viewDidUnload]; 58 | // Release any retained subviews of the main view. 59 | // e.g. self.myOutlet = nil; 60 | } 61 | 62 | -(void) showCam { 63 | NSLog(@"..."); 64 | imagePicker = [[UIImagePickerController alloc] init]; 65 | // Set source to the camera 66 | #if (TARGET_IPHONE_SIMULATOR) 67 | imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; 68 | #else 69 | imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera; 70 | #endif 71 | // Delegate is self 72 | imagePicker.delegate = self; 73 | // Allow editing of image ? 74 | [imagePicker setAllowsEditing:YES]; 75 | // Show image picker 76 | [self presentModalViewController:imagePicker animated:YES]; 77 | } 78 | 79 | -(int) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 80 | return arrEffects.count; 81 | } 82 | 83 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 84 | static NSString *cellIdentifier = @"EffectCell"; 85 | 86 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; 87 | if (cell == nil) { 88 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; 89 | } 90 | 91 | if(((NSString *)[[arrEffects objectAtIndex:indexPath.row] valueForKey:@"method"]).length > 0) { 92 | SEL _selector = NSSelectorFromString([[arrEffects objectAtIndex:indexPath.row] valueForKey:@"method"]); 93 | cell.imageView.image = [minithumbImage performSelector:_selector]; 94 | } else 95 | cell.imageView.image = minithumbImage; 96 | 97 | cell.textLabel.text = [(NSDictionary *)[arrEffects objectAtIndex:indexPath.row] valueForKey:@"title"]; 98 | 99 | return cell; 100 | } 101 | 102 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 103 | 104 | ImageViewController *nextViewController = [[ImageViewController alloc] initWithNibName:@"ImageViewController" bundle:nil]; 105 | nextViewController.title = [[arrEffects objectAtIndex:indexPath.row] valueForKey:@"title"]; 106 | 107 | [self.navigationController pushViewController:nextViewController animated:YES]; 108 | 109 | if(((NSString *)[[arrEffects objectAtIndex:indexPath.row] valueForKey:@"method"]).length > 0) { 110 | 111 | #ifndef TRACKTIME 112 | 113 | SEL _selector = NSSelectorFromString([[arrEffects objectAtIndex:indexPath.row] valueForKey:@"method"]); 114 | [nextViewController setImage:[thumbImage performSelector:_selector]]; 115 | 116 | #else 117 | 118 | SEL _track = NSSelectorFromString(@"trackTime:"); 119 | [nextViewController setImage:[thumbImage performSelector:_track withObject:[[arrEffects objectAtIndex:indexPath.row] valueForKey:@"method"]]]; 120 | 121 | #endif 122 | 123 | } else { 124 | [nextViewController setImage:thumbImage]; 125 | } 126 | 127 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 128 | } 129 | 130 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 131 | { 132 | // Return YES for supported orientations 133 | return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); 134 | } 135 | 136 | - (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info 137 | { 138 | // Access the uncropped image from info dictionary 139 | selectedImage = [info objectForKey:UIImagePickerControllerEditedImage];//[info objectForKey:@"UIImagePickerControllerOriginalImage"]; 140 | thumbImage = [selectedImage scaleToSize:CGSizeMake(320, 320)]; 141 | minithumbImage = [thumbImage scaleToSize:CGSizeMake(40, 40)]; 142 | 143 | [_tblEffects reloadData]; 144 | 145 | [picker dismissModalViewControllerAnimated:YES]; 146 | 147 | // Save image 148 | // UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); 149 | } 150 | 151 | @end 152 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp/en.lproj/ViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1536 5 | 12C60 6 | 2844 7 | 1187.34 8 | 625.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 1930 12 | 13 | 14 | IBProxyObject 15 | IBUITableView 16 | IBUIView 17 | 18 | 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | PluginDependencyRecalculationVersion 23 | 24 | 25 | 26 | 27 | IBFilesOwner 28 | IBCocoaTouchFramework 29 | 30 | 31 | IBFirstResponder 32 | IBCocoaTouchFramework 33 | 34 | 35 | 36 | 274 37 | 38 | 39 | 40 | 274 41 | {320, 460} 42 | 43 | 44 | _NS:418 45 | 46 | 3 47 | MQA 48 | 49 | YES 50 | IBCocoaTouchFramework 51 | YES 52 | 1 53 | 0 54 | YES 55 | 44 56 | 22 57 | 22 58 | 59 | 60 | {{0, 20}, {320, 460}} 61 | 62 | 63 | 64 | 1 65 | MCAwIDAAA 66 | darkTextColor 67 | 68 | NO 69 | 70 | 71 | IBUISimulatedFreeformSizeMetricsSentinel 72 | Freeform 73 | 74 | IBCocoaTouchFramework 75 | 76 | 77 | 78 | 79 | 80 | 81 | view 82 | 83 | 84 | 85 | 7 86 | 87 | 88 | 89 | tblEffects 90 | 91 | 92 | 93 | 11 94 | 95 | 96 | 97 | dataSource 98 | 99 | 100 | 101 | 9 102 | 103 | 104 | 105 | delegate 106 | 107 | 108 | 109 | 10 110 | 111 | 112 | 113 | 114 | 115 | 0 116 | 117 | 118 | 119 | 120 | 121 | -1 122 | 123 | 124 | File's Owner 125 | 126 | 127 | -2 128 | 129 | 130 | 131 | 132 | 6 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 8 141 | 142 | 143 | 144 | 145 | 146 | 147 | ViewController 148 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 149 | UIResponder 150 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 151 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 152 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 153 | 154 | 155 | 156 | 157 | 158 | 23 159 | 160 | 161 | 162 | 163 | ViewController 164 | UIViewController 165 | 166 | tblEffects 167 | UITableView 168 | 169 | 170 | tblEffects 171 | 172 | tblEffects 173 | UITableView 174 | 175 | 176 | 177 | IBProjectSource 178 | ./Classes/ViewController.h 179 | 180 | 181 | 182 | 183 | 0 184 | IBCocoaTouchFramework 185 | YES 186 | 3 187 | 1930 188 | 189 | 190 | -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp/filtrr_back.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OmidH/Filtrr/92c5aa9b0dd6776556fddc7e45ca1159a7fb0650/FiltrrApp/FiltrrApp/filtrr_back.jpg -------------------------------------------------------------------------------- /FiltrrApp/FiltrrApp/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // FiltrrApp 4 | // 5 | // Created by Omid Hashemi on 2/10/12. 6 | // Copyright (c) 2012 42dp. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Filtrr - An iOS Image filter library 2 | 3 | based on Alex Michael's filtrr.js (https://github.com/alexmic/filtrr) 4 | 5 | At this point thousand thanks to Alex for sharing. 6 | 7 | If you like this, like us on Facebook :) http://www.facebook.com/WeAre42dp 8 | and feel free to join the iOS developer group on Facebook: 9 | http://www.facebook.com/groups/130540617023687/ 10 | 11 | Copyright (C) 2012 42dp 12 | http://www.42dp.com 13 | 14 | Permission is hereby granted, free of charge, to any person obtaining a copy of 15 | this software and associated documentation files (the "Software"), to deal in 16 | the Software without restriction, including without limitation the rights to 17 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 18 | of the Software, and to permit persons to whom the Software is furnished to do 19 | so, subject to the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included in all 22 | copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | SOFTWARE. 31 | 32 | How to use 33 | ----------- 34 | 35 | This is pretty simple: 36 | 37 | 1. a) #import "UIImage+FiltrrCompositions.h" if you want to use the predefined effects 38 | or 39 | b) #import "UIImage+Filtrr.h" if you want to compose your own effects 40 | 41 | 2a) Just call the method on your image and you will get back a manipulated image. 42 | UIImage *img = [UIImage imageNamed:@"test.jpg"]; 43 | img = [img e1]; 44 | anImageViewController.image = img; 45 | 46 | 2b) To compose your own effect: 47 | 48 | UIImage *img = [UIImage imageNamed:@"test.jpg"]; 49 | 50 | UIImage *topImage = [img duplicate]; 51 | topImage = [[topImage saturationByFactor:0] blur]; 52 | 53 | img = [self multiply:topImage]; 54 | 55 | RGBA minrgb, maxrgb; 56 | 57 | minrgb = RGBAMake(60, 35, 10, 255); 58 | maxrgb = RGBAMake(170, 140, 160, 255); 59 | 60 | img = [[[self tintWithMinRGB:minrgb MaxRGB:maxrgb] contrastByFactor:0.8] brightnessByFactor:10]; 61 | 62 | anImageViewController.image = img; 63 | 64 | Enjoy it and feel free to send me your composed effects! 65 | --------------------------------------------------------------------------------