├── EssentialImagerDemo ├── Default-568h@2x.png ├── EssentialImagerDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── dilliontan.xcuserdatad │ │ │ ├── UserInterfaceState.xcuserstate │ │ │ └── WorkspaceSettings.xcsettings │ └── xcuserdata │ │ └── dilliontan.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints.xcbkptlist │ │ └── xcschemes │ │ ├── Full Demo.xcscheme │ │ ├── Simple Demo.xcscheme │ │ └── xcschememanagement.plist └── EssentialImagerDemo │ ├── EssentialImager │ ├── EIImagePickerDelegate.h │ ├── EIImagePickerDelegate.m │ ├── EIOperationManager.h │ ├── EIOperationManager.m │ ├── EssentialImager.h │ ├── NSData+Storage.h │ ├── NSData+Storage.m │ ├── StandardPaths │ │ ├── StandardPaths.h │ │ └── StandardPaths.m │ ├── UIImage+Resize.h │ └── UIImage+Resize.m │ ├── EssentialImagerDemo-Prefix.pch │ ├── EssentialImagerFullDemo-Info.plist │ ├── EssentialImagerSimpleDemo-Info.plist │ ├── Full Demo │ ├── EIFullDemoViewController.h │ ├── EIFullDemoViewController.m │ ├── FullDemoAppDelegate.h │ ├── FullDemoAppDelegate.m │ └── main.m │ ├── Icon.png │ ├── Icon@2x.png │ ├── Simple Demo │ ├── EISimpleDemoViewController.h │ ├── EISimpleDemoViewController.m │ ├── SimpleDemoAppDelegate.h │ ├── SimpleDemoAppDelegate.m │ └── main.m │ ├── en.lproj │ └── InfoPlist.strings │ └── pattern.png ├── README.md └── screenshot.png /EssentialImagerDemo/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dillion/EssentialImager/789bae62f758b70a3c5712b715a92c62b369c5a6/EssentialImagerDemo/Default-568h@2x.png -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4D19929E171D01AC009F6E18 /* EIOperationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D19929B171D01AC009F6E18 /* EIOperationManager.m */; }; 11 | 4D19929F171D01AC009F6E18 /* NSData+Storage.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D19929D171D01AC009F6E18 /* NSData+Storage.m */; }; 12 | 4D1992A1171D094D009F6E18 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D1992A0171D094D009F6E18 /* Default-568h@2x.png */; }; 13 | 4D1992A5171D097B009F6E18 /* EIImagePickerDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D79EC6215B0816E007C9A90 /* EIImagePickerDelegate.m */; }; 14 | 4D1992A6171D097B009F6E18 /* StandardPaths.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D79EC6615B0816E007C9A90 /* StandardPaths.m */; }; 15 | 4D1992A7171D097B009F6E18 /* UIImage+Resize.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D79EC6815B0816E007C9A90 /* UIImage+Resize.m */; }; 16 | 4D1992AA171D097B009F6E18 /* EIOperationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D19929B171D01AC009F6E18 /* EIOperationManager.m */; }; 17 | 4D1992AB171D097B009F6E18 /* NSData+Storage.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D19929D171D01AC009F6E18 /* NSData+Storage.m */; }; 18 | 4D1992AD171D097B009F6E18 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D79EC4E15B08127007C9A90 /* QuartzCore.framework */; }; 19 | 4D1992AE171D097B009F6E18 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D79EC3715B08111007C9A90 /* UIKit.framework */; }; 20 | 4D1992AF171D097B009F6E18 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D79EC3915B08111007C9A90 /* Foundation.framework */; }; 21 | 4D1992B0171D097B009F6E18 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D79EC3B15B08111007C9A90 /* CoreGraphics.framework */; }; 22 | 4D1992B2171D097B009F6E18 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4D79EC4015B08111007C9A90 /* InfoPlist.strings */; }; 23 | 4D1992B3171D097B009F6E18 /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D79EC5015B08161007C9A90 /* Icon.png */; }; 24 | 4D1992B4171D097B009F6E18 /* Icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D79EC5115B08161007C9A90 /* Icon@2x.png */; }; 25 | 4D1992B5171D097B009F6E18 /* pattern.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D79EC5215B08161007C9A90 /* pattern.png */; }; 26 | 4D1992B6171D097B009F6E18 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D1992A0171D094D009F6E18 /* Default-568h@2x.png */; }; 27 | 4D1992C2171D0B7F009F6E18 /* EIFullDemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D1992BE171D0B7F009F6E18 /* EIFullDemoViewController.m */; }; 28 | 4D1992C3171D0B7F009F6E18 /* FullDemoAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D1992C0171D0B7F009F6E18 /* FullDemoAppDelegate.m */; }; 29 | 4D1992C4171D0B7F009F6E18 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D1992C1171D0B7F009F6E18 /* main.m */; }; 30 | 4D1992CB171D0B9C009F6E18 /* EISimpleDemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D1992C7171D0B9C009F6E18 /* EISimpleDemoViewController.m */; }; 31 | 4D1992CC171D0B9C009F6E18 /* SimpleDemoAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D1992C9171D0B9C009F6E18 /* SimpleDemoAppDelegate.m */; }; 32 | 4D1992CD171D0B9C009F6E18 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D1992CA171D0B9C009F6E18 /* main.m */; }; 33 | 4D79EC3815B08111007C9A90 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D79EC3715B08111007C9A90 /* UIKit.framework */; }; 34 | 4D79EC3A15B08111007C9A90 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D79EC3915B08111007C9A90 /* Foundation.framework */; }; 35 | 4D79EC3C15B08111007C9A90 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D79EC3B15B08111007C9A90 /* CoreGraphics.framework */; }; 36 | 4D79EC4215B08111007C9A90 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 4D79EC4015B08111007C9A90 /* InfoPlist.strings */; }; 37 | 4D79EC4F15B08127007C9A90 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4D79EC4E15B08127007C9A90 /* QuartzCore.framework */; }; 38 | 4D79EC5315B08161007C9A90 /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D79EC5015B08161007C9A90 /* Icon.png */; }; 39 | 4D79EC5415B08161007C9A90 /* Icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D79EC5115B08161007C9A90 /* Icon@2x.png */; }; 40 | 4D79EC5515B08161007C9A90 /* pattern.png in Resources */ = {isa = PBXBuildFile; fileRef = 4D79EC5215B08161007C9A90 /* pattern.png */; }; 41 | 4D79EC6D15B0816E007C9A90 /* EIImagePickerDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D79EC6215B0816E007C9A90 /* EIImagePickerDelegate.m */; }; 42 | 4D79EC6E15B0816E007C9A90 /* StandardPaths.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D79EC6615B0816E007C9A90 /* StandardPaths.m */; }; 43 | 4D79EC6F15B0816E007C9A90 /* UIImage+Resize.m in Sources */ = {isa = PBXBuildFile; fileRef = 4D79EC6815B0816E007C9A90 /* UIImage+Resize.m */; }; 44 | /* End PBXBuildFile section */ 45 | 46 | /* Begin PBXFileReference section */ 47 | 4D19929A171D01AC009F6E18 /* EIOperationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EIOperationManager.h; sourceTree = ""; }; 48 | 4D19929B171D01AC009F6E18 /* EIOperationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EIOperationManager.m; sourceTree = ""; }; 49 | 4D19929C171D01AC009F6E18 /* NSData+Storage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+Storage.h"; sourceTree = ""; }; 50 | 4D19929D171D01AC009F6E18 /* NSData+Storage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+Storage.m"; sourceTree = ""; }; 51 | 4D1992A0171D094D009F6E18 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "../Default-568h@2x.png"; sourceTree = ""; }; 52 | 4D1992BA171D097B009F6E18 /* EssentialImagerFullDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EssentialImagerFullDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 53 | 4D1992BD171D0B7F009F6E18 /* EIFullDemoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EIFullDemoViewController.h; sourceTree = ""; }; 54 | 4D1992BE171D0B7F009F6E18 /* EIFullDemoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EIFullDemoViewController.m; sourceTree = ""; }; 55 | 4D1992BF171D0B7F009F6E18 /* FullDemoAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FullDemoAppDelegate.h; sourceTree = ""; }; 56 | 4D1992C0171D0B7F009F6E18 /* FullDemoAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FullDemoAppDelegate.m; sourceTree = ""; }; 57 | 4D1992C1171D0B7F009F6E18 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 58 | 4D1992C6171D0B9C009F6E18 /* EISimpleDemoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EISimpleDemoViewController.h; sourceTree = ""; }; 59 | 4D1992C7171D0B9C009F6E18 /* EISimpleDemoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EISimpleDemoViewController.m; sourceTree = ""; }; 60 | 4D1992C8171D0B9C009F6E18 /* SimpleDemoAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleDemoAppDelegate.h; sourceTree = ""; }; 61 | 4D1992C9171D0B9C009F6E18 /* SimpleDemoAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SimpleDemoAppDelegate.m; sourceTree = ""; }; 62 | 4D1992CA171D0B9C009F6E18 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 63 | 4D1992CE171D0D7A009F6E18 /* EssentialImagerFullDemo-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "EssentialImagerFullDemo-Info.plist"; path = "EssentialImagerDemo/EssentialImagerFullDemo-Info.plist"; sourceTree = ""; }; 64 | 4D1992D0171D0D82009F6E18 /* EssentialImagerSimpleDemo-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "EssentialImagerSimpleDemo-Info.plist"; path = "EssentialImagerDemo/EssentialImagerSimpleDemo-Info.plist"; sourceTree = ""; }; 65 | 4D79EC3315B08111007C9A90 /* EssentialImagerSimpleDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = EssentialImagerSimpleDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 66 | 4D79EC3715B08111007C9A90 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 67 | 4D79EC3915B08111007C9A90 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 68 | 4D79EC3B15B08111007C9A90 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 69 | 4D79EC4115B08111007C9A90 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 70 | 4D79EC4515B08111007C9A90 /* EssentialImagerDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "EssentialImagerDemo-Prefix.pch"; sourceTree = ""; }; 71 | 4D79EC4E15B08127007C9A90 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 72 | 4D79EC5015B08161007C9A90 /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = ""; }; 73 | 4D79EC5115B08161007C9A90 /* Icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon@2x.png"; sourceTree = ""; }; 74 | 4D79EC5215B08161007C9A90 /* pattern.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = pattern.png; sourceTree = ""; }; 75 | 4D79EC6115B0816E007C9A90 /* EIImagePickerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EIImagePickerDelegate.h; sourceTree = ""; }; 76 | 4D79EC6215B0816E007C9A90 /* EIImagePickerDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EIImagePickerDelegate.m; sourceTree = ""; }; 77 | 4D79EC6315B0816E007C9A90 /* EssentialImager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EssentialImager.h; sourceTree = ""; }; 78 | 4D79EC6515B0816E007C9A90 /* StandardPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StandardPaths.h; sourceTree = ""; }; 79 | 4D79EC6615B0816E007C9A90 /* StandardPaths.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StandardPaths.m; sourceTree = ""; }; 80 | 4D79EC6715B0816E007C9A90 /* UIImage+Resize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+Resize.h"; sourceTree = ""; }; 81 | 4D79EC6815B0816E007C9A90 /* UIImage+Resize.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+Resize.m"; sourceTree = ""; }; 82 | /* End PBXFileReference section */ 83 | 84 | /* Begin PBXFrameworksBuildPhase section */ 85 | 4D1992AC171D097B009F6E18 /* Frameworks */ = { 86 | isa = PBXFrameworksBuildPhase; 87 | buildActionMask = 2147483647; 88 | files = ( 89 | 4D1992AD171D097B009F6E18 /* QuartzCore.framework in Frameworks */, 90 | 4D1992AE171D097B009F6E18 /* UIKit.framework in Frameworks */, 91 | 4D1992AF171D097B009F6E18 /* Foundation.framework in Frameworks */, 92 | 4D1992B0171D097B009F6E18 /* CoreGraphics.framework in Frameworks */, 93 | ); 94 | runOnlyForDeploymentPostprocessing = 0; 95 | }; 96 | 4D79EC3015B08111007C9A90 /* Frameworks */ = { 97 | isa = PBXFrameworksBuildPhase; 98 | buildActionMask = 2147483647; 99 | files = ( 100 | 4D79EC4F15B08127007C9A90 /* QuartzCore.framework in Frameworks */, 101 | 4D79EC3815B08111007C9A90 /* UIKit.framework in Frameworks */, 102 | 4D79EC3A15B08111007C9A90 /* Foundation.framework in Frameworks */, 103 | 4D79EC3C15B08111007C9A90 /* CoreGraphics.framework in Frameworks */, 104 | ); 105 | runOnlyForDeploymentPostprocessing = 0; 106 | }; 107 | /* End PBXFrameworksBuildPhase section */ 108 | 109 | /* Begin PBXGroup section */ 110 | 4D1992BC171D0B7E009F6E18 /* Full Demo */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 4D1992BD171D0B7F009F6E18 /* EIFullDemoViewController.h */, 114 | 4D1992BE171D0B7F009F6E18 /* EIFullDemoViewController.m */, 115 | 4D1992BF171D0B7F009F6E18 /* FullDemoAppDelegate.h */, 116 | 4D1992C0171D0B7F009F6E18 /* FullDemoAppDelegate.m */, 117 | 4D1992C1171D0B7F009F6E18 /* main.m */, 118 | ); 119 | path = "Full Demo"; 120 | sourceTree = ""; 121 | }; 122 | 4D1992C5171D0B9C009F6E18 /* Simple Demo */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | 4D1992C6171D0B9C009F6E18 /* EISimpleDemoViewController.h */, 126 | 4D1992C7171D0B9C009F6E18 /* EISimpleDemoViewController.m */, 127 | 4D1992C8171D0B9C009F6E18 /* SimpleDemoAppDelegate.h */, 128 | 4D1992C9171D0B9C009F6E18 /* SimpleDemoAppDelegate.m */, 129 | 4D1992CA171D0B9C009F6E18 /* main.m */, 130 | ); 131 | path = "Simple Demo"; 132 | sourceTree = ""; 133 | }; 134 | 4D79EC2815B08111007C9A90 = { 135 | isa = PBXGroup; 136 | children = ( 137 | 4D79EC3D15B08111007C9A90 /* EssentialImagerDemo */, 138 | 4D1992D0171D0D82009F6E18 /* EssentialImagerSimpleDemo-Info.plist */, 139 | 4D1992CE171D0D7A009F6E18 /* EssentialImagerFullDemo-Info.plist */, 140 | 4D79EC3615B08111007C9A90 /* Frameworks */, 141 | 4D79EC3415B08111007C9A90 /* Products */, 142 | ); 143 | sourceTree = ""; 144 | }; 145 | 4D79EC3415B08111007C9A90 /* Products */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | 4D79EC3315B08111007C9A90 /* EssentialImagerSimpleDemo.app */, 149 | 4D1992BA171D097B009F6E18 /* EssentialImagerFullDemo.app */, 150 | ); 151 | name = Products; 152 | sourceTree = ""; 153 | }; 154 | 4D79EC3615B08111007C9A90 /* Frameworks */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | 4D79EC4E15B08127007C9A90 /* QuartzCore.framework */, 158 | 4D79EC3715B08111007C9A90 /* UIKit.framework */, 159 | 4D79EC3915B08111007C9A90 /* Foundation.framework */, 160 | 4D79EC3B15B08111007C9A90 /* CoreGraphics.framework */, 161 | ); 162 | name = Frameworks; 163 | sourceTree = ""; 164 | }; 165 | 4D79EC3D15B08111007C9A90 /* EssentialImagerDemo */ = { 166 | isa = PBXGroup; 167 | children = ( 168 | 4D1992C5171D0B9C009F6E18 /* Simple Demo */, 169 | 4D1992BC171D0B7E009F6E18 /* Full Demo */, 170 | 4D79EC5615B0816E007C9A90 /* EssentialImager */, 171 | 4D79EC3E15B08111007C9A90 /* Supporting Files */, 172 | ); 173 | path = EssentialImagerDemo; 174 | sourceTree = ""; 175 | }; 176 | 4D79EC3E15B08111007C9A90 /* Supporting Files */ = { 177 | isa = PBXGroup; 178 | children = ( 179 | 4D1992A0171D094D009F6E18 /* Default-568h@2x.png */, 180 | 4D79EC5015B08161007C9A90 /* Icon.png */, 181 | 4D79EC5115B08161007C9A90 /* Icon@2x.png */, 182 | 4D79EC5215B08161007C9A90 /* pattern.png */, 183 | 4D79EC4015B08111007C9A90 /* InfoPlist.strings */, 184 | 4D79EC4515B08111007C9A90 /* EssentialImagerDemo-Prefix.pch */, 185 | ); 186 | name = "Supporting Files"; 187 | sourceTree = ""; 188 | }; 189 | 4D79EC5615B0816E007C9A90 /* EssentialImager */ = { 190 | isa = PBXGroup; 191 | children = ( 192 | 4D19929A171D01AC009F6E18 /* EIOperationManager.h */, 193 | 4D19929B171D01AC009F6E18 /* EIOperationManager.m */, 194 | 4D19929C171D01AC009F6E18 /* NSData+Storage.h */, 195 | 4D19929D171D01AC009F6E18 /* NSData+Storage.m */, 196 | 4D79EC6115B0816E007C9A90 /* EIImagePickerDelegate.h */, 197 | 4D79EC6215B0816E007C9A90 /* EIImagePickerDelegate.m */, 198 | 4D79EC6315B0816E007C9A90 /* EssentialImager.h */, 199 | 4D79EC6415B0816E007C9A90 /* StandardPaths */, 200 | 4D79EC6715B0816E007C9A90 /* UIImage+Resize.h */, 201 | 4D79EC6815B0816E007C9A90 /* UIImage+Resize.m */, 202 | ); 203 | path = EssentialImager; 204 | sourceTree = ""; 205 | }; 206 | 4D79EC6415B0816E007C9A90 /* StandardPaths */ = { 207 | isa = PBXGroup; 208 | children = ( 209 | 4D79EC6515B0816E007C9A90 /* StandardPaths.h */, 210 | 4D79EC6615B0816E007C9A90 /* StandardPaths.m */, 211 | ); 212 | path = StandardPaths; 213 | sourceTree = ""; 214 | }; 215 | /* End PBXGroup section */ 216 | 217 | /* Begin PBXNativeTarget section */ 218 | 4D1992A2171D097B009F6E18 /* EssentialImagerFullDemo */ = { 219 | isa = PBXNativeTarget; 220 | buildConfigurationList = 4D1992B7171D097B009F6E18 /* Build configuration list for PBXNativeTarget "EssentialImagerFullDemo" */; 221 | buildPhases = ( 222 | 4D1992A3171D097B009F6E18 /* Sources */, 223 | 4D1992AC171D097B009F6E18 /* Frameworks */, 224 | 4D1992B1171D097B009F6E18 /* Resources */, 225 | ); 226 | buildRules = ( 227 | ); 228 | dependencies = ( 229 | ); 230 | name = EssentialImagerFullDemo; 231 | productName = EssentialImagerDemo; 232 | productReference = 4D1992BA171D097B009F6E18 /* EssentialImagerFullDemo.app */; 233 | productType = "com.apple.product-type.application"; 234 | }; 235 | 4D79EC3215B08111007C9A90 /* EssentialImagerSimpleDemo */ = { 236 | isa = PBXNativeTarget; 237 | buildConfigurationList = 4D79EC4B15B08111007C9A90 /* Build configuration list for PBXNativeTarget "EssentialImagerSimpleDemo" */; 238 | buildPhases = ( 239 | 4D79EC2F15B08111007C9A90 /* Sources */, 240 | 4D79EC3015B08111007C9A90 /* Frameworks */, 241 | 4D79EC3115B08111007C9A90 /* Resources */, 242 | ); 243 | buildRules = ( 244 | ); 245 | dependencies = ( 246 | ); 247 | name = EssentialImagerSimpleDemo; 248 | productName = EssentialImagerDemo; 249 | productReference = 4D79EC3315B08111007C9A90 /* EssentialImagerSimpleDemo.app */; 250 | productType = "com.apple.product-type.application"; 251 | }; 252 | /* End PBXNativeTarget section */ 253 | 254 | /* Begin PBXProject section */ 255 | 4D79EC2A15B08111007C9A90 /* Project object */ = { 256 | isa = PBXProject; 257 | attributes = { 258 | LastUpgradeCheck = 0460; 259 | }; 260 | buildConfigurationList = 4D79EC2D15B08111007C9A90 /* Build configuration list for PBXProject "EssentialImagerDemo" */; 261 | compatibilityVersion = "Xcode 3.2"; 262 | developmentRegion = English; 263 | hasScannedForEncodings = 0; 264 | knownRegions = ( 265 | en, 266 | ); 267 | mainGroup = 4D79EC2815B08111007C9A90; 268 | productRefGroup = 4D79EC3415B08111007C9A90 /* Products */; 269 | projectDirPath = ""; 270 | projectRoot = ""; 271 | targets = ( 272 | 4D79EC3215B08111007C9A90 /* EssentialImagerSimpleDemo */, 273 | 4D1992A2171D097B009F6E18 /* EssentialImagerFullDemo */, 274 | ); 275 | }; 276 | /* End PBXProject section */ 277 | 278 | /* Begin PBXResourcesBuildPhase section */ 279 | 4D1992B1171D097B009F6E18 /* Resources */ = { 280 | isa = PBXResourcesBuildPhase; 281 | buildActionMask = 2147483647; 282 | files = ( 283 | 4D1992B2171D097B009F6E18 /* InfoPlist.strings in Resources */, 284 | 4D1992B3171D097B009F6E18 /* Icon.png in Resources */, 285 | 4D1992B4171D097B009F6E18 /* Icon@2x.png in Resources */, 286 | 4D1992B5171D097B009F6E18 /* pattern.png in Resources */, 287 | 4D1992B6171D097B009F6E18 /* Default-568h@2x.png in Resources */, 288 | ); 289 | runOnlyForDeploymentPostprocessing = 0; 290 | }; 291 | 4D79EC3115B08111007C9A90 /* Resources */ = { 292 | isa = PBXResourcesBuildPhase; 293 | buildActionMask = 2147483647; 294 | files = ( 295 | 4D79EC4215B08111007C9A90 /* InfoPlist.strings in Resources */, 296 | 4D79EC5315B08161007C9A90 /* Icon.png in Resources */, 297 | 4D79EC5415B08161007C9A90 /* Icon@2x.png in Resources */, 298 | 4D79EC5515B08161007C9A90 /* pattern.png in Resources */, 299 | 4D1992A1171D094D009F6E18 /* Default-568h@2x.png in Resources */, 300 | ); 301 | runOnlyForDeploymentPostprocessing = 0; 302 | }; 303 | /* End PBXResourcesBuildPhase section */ 304 | 305 | /* Begin PBXSourcesBuildPhase section */ 306 | 4D1992A3171D097B009F6E18 /* Sources */ = { 307 | isa = PBXSourcesBuildPhase; 308 | buildActionMask = 2147483647; 309 | files = ( 310 | 4D1992A5171D097B009F6E18 /* EIImagePickerDelegate.m in Sources */, 311 | 4D1992A6171D097B009F6E18 /* StandardPaths.m in Sources */, 312 | 4D1992A7171D097B009F6E18 /* UIImage+Resize.m in Sources */, 313 | 4D1992AA171D097B009F6E18 /* EIOperationManager.m in Sources */, 314 | 4D1992AB171D097B009F6E18 /* NSData+Storage.m in Sources */, 315 | 4D1992C2171D0B7F009F6E18 /* EIFullDemoViewController.m in Sources */, 316 | 4D1992C3171D0B7F009F6E18 /* FullDemoAppDelegate.m in Sources */, 317 | 4D1992C4171D0B7F009F6E18 /* main.m in Sources */, 318 | ); 319 | runOnlyForDeploymentPostprocessing = 0; 320 | }; 321 | 4D79EC2F15B08111007C9A90 /* Sources */ = { 322 | isa = PBXSourcesBuildPhase; 323 | buildActionMask = 2147483647; 324 | files = ( 325 | 4D79EC6D15B0816E007C9A90 /* EIImagePickerDelegate.m in Sources */, 326 | 4D79EC6E15B0816E007C9A90 /* StandardPaths.m in Sources */, 327 | 4D79EC6F15B0816E007C9A90 /* UIImage+Resize.m in Sources */, 328 | 4D19929E171D01AC009F6E18 /* EIOperationManager.m in Sources */, 329 | 4D19929F171D01AC009F6E18 /* NSData+Storage.m in Sources */, 330 | 4D1992CB171D0B9C009F6E18 /* EISimpleDemoViewController.m in Sources */, 331 | 4D1992CC171D0B9C009F6E18 /* SimpleDemoAppDelegate.m in Sources */, 332 | 4D1992CD171D0B9C009F6E18 /* main.m in Sources */, 333 | ); 334 | runOnlyForDeploymentPostprocessing = 0; 335 | }; 336 | /* End PBXSourcesBuildPhase section */ 337 | 338 | /* Begin PBXVariantGroup section */ 339 | 4D79EC4015B08111007C9A90 /* InfoPlist.strings */ = { 340 | isa = PBXVariantGroup; 341 | children = ( 342 | 4D79EC4115B08111007C9A90 /* en */, 343 | ); 344 | name = InfoPlist.strings; 345 | sourceTree = ""; 346 | }; 347 | /* End PBXVariantGroup section */ 348 | 349 | /* Begin XCBuildConfiguration section */ 350 | 4D1992B8171D097B009F6E18 /* Debug */ = { 351 | isa = XCBuildConfiguration; 352 | buildSettings = { 353 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 354 | GCC_PREFIX_HEADER = "EssentialImagerDemo/EssentialImagerDemo-Prefix.pch"; 355 | INFOPLIST_FILE = "$(SRCROOT)/EssentialImagerDemo/EssentialImagerFullDemo-Info.plist"; 356 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 357 | PRODUCT_NAME = EssentialImagerFullDemo; 358 | WRAPPER_EXTENSION = app; 359 | }; 360 | name = Debug; 361 | }; 362 | 4D1992B9171D097B009F6E18 /* Release */ = { 363 | isa = XCBuildConfiguration; 364 | buildSettings = { 365 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 366 | GCC_PREFIX_HEADER = "EssentialImagerDemo/EssentialImagerDemo-Prefix.pch"; 367 | INFOPLIST_FILE = "$(SRCROOT)/EssentialImagerDemo/EssentialImagerFullDemo-Info.plist"; 368 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 369 | PRODUCT_NAME = EssentialImagerFullDemo; 370 | WRAPPER_EXTENSION = app; 371 | }; 372 | name = Release; 373 | }; 374 | 4D79EC4915B08111007C9A90 /* Debug */ = { 375 | isa = XCBuildConfiguration; 376 | buildSettings = { 377 | ALWAYS_SEARCH_USER_PATHS = NO; 378 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 379 | CLANG_ENABLE_OBJC_ARC = YES; 380 | CLANG_WARN_CONSTANT_CONVERSION = YES; 381 | CLANG_WARN_ENUM_CONVERSION = YES; 382 | CLANG_WARN_INT_CONVERSION = YES; 383 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 384 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 385 | COPY_PHASE_STRIP = NO; 386 | GCC_C_LANGUAGE_STANDARD = gnu99; 387 | GCC_DYNAMIC_NO_PIC = NO; 388 | GCC_OPTIMIZATION_LEVEL = 0; 389 | GCC_PREPROCESSOR_DEFINITIONS = ( 390 | "DEBUG=1", 391 | "$(inherited)", 392 | ); 393 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 394 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 395 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 396 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 397 | GCC_WARN_UNUSED_VARIABLE = YES; 398 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 399 | SDKROOT = iphoneos; 400 | }; 401 | name = Debug; 402 | }; 403 | 4D79EC4A15B08111007C9A90 /* Release */ = { 404 | isa = XCBuildConfiguration; 405 | buildSettings = { 406 | ALWAYS_SEARCH_USER_PATHS = NO; 407 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 408 | CLANG_ENABLE_OBJC_ARC = YES; 409 | CLANG_WARN_CONSTANT_CONVERSION = YES; 410 | CLANG_WARN_ENUM_CONVERSION = YES; 411 | CLANG_WARN_INT_CONVERSION = YES; 412 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 413 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 414 | COPY_PHASE_STRIP = YES; 415 | GCC_C_LANGUAGE_STANDARD = gnu99; 416 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 417 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 418 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 419 | GCC_WARN_UNUSED_VARIABLE = YES; 420 | IPHONEOS_DEPLOYMENT_TARGET = 5.1; 421 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 422 | SDKROOT = iphoneos; 423 | VALIDATE_PRODUCT = YES; 424 | }; 425 | name = Release; 426 | }; 427 | 4D79EC4C15B08111007C9A90 /* Debug */ = { 428 | isa = XCBuildConfiguration; 429 | buildSettings = { 430 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 431 | GCC_PREFIX_HEADER = "EssentialImagerDemo/EssentialImagerDemo-Prefix.pch"; 432 | INFOPLIST_FILE = "$(SRCROOT)/EssentialImagerDemo/EssentialImagerSimpleDemo-Info.plist"; 433 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 434 | PRODUCT_NAME = "$(TARGET_NAME)"; 435 | WRAPPER_EXTENSION = app; 436 | }; 437 | name = Debug; 438 | }; 439 | 4D79EC4D15B08111007C9A90 /* Release */ = { 440 | isa = XCBuildConfiguration; 441 | buildSettings = { 442 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 443 | GCC_PREFIX_HEADER = "EssentialImagerDemo/EssentialImagerDemo-Prefix.pch"; 444 | INFOPLIST_FILE = "$(SRCROOT)/EssentialImagerDemo/EssentialImagerSimpleDemo-Info.plist"; 445 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 446 | PRODUCT_NAME = "$(TARGET_NAME)"; 447 | WRAPPER_EXTENSION = app; 448 | }; 449 | name = Release; 450 | }; 451 | /* End XCBuildConfiguration section */ 452 | 453 | /* Begin XCConfigurationList section */ 454 | 4D1992B7171D097B009F6E18 /* Build configuration list for PBXNativeTarget "EssentialImagerFullDemo" */ = { 455 | isa = XCConfigurationList; 456 | buildConfigurations = ( 457 | 4D1992B8171D097B009F6E18 /* Debug */, 458 | 4D1992B9171D097B009F6E18 /* Release */, 459 | ); 460 | defaultConfigurationIsVisible = 0; 461 | defaultConfigurationName = Release; 462 | }; 463 | 4D79EC2D15B08111007C9A90 /* Build configuration list for PBXProject "EssentialImagerDemo" */ = { 464 | isa = XCConfigurationList; 465 | buildConfigurations = ( 466 | 4D79EC4915B08111007C9A90 /* Debug */, 467 | 4D79EC4A15B08111007C9A90 /* Release */, 468 | ); 469 | defaultConfigurationIsVisible = 0; 470 | defaultConfigurationName = Release; 471 | }; 472 | 4D79EC4B15B08111007C9A90 /* Build configuration list for PBXNativeTarget "EssentialImagerSimpleDemo" */ = { 473 | isa = XCConfigurationList; 474 | buildConfigurations = ( 475 | 4D79EC4C15B08111007C9A90 /* Debug */, 476 | 4D79EC4D15B08111007C9A90 /* Release */, 477 | ); 478 | defaultConfigurationIsVisible = 0; 479 | defaultConfigurationName = Release; 480 | }; 481 | /* End XCConfigurationList section */ 482 | }; 483 | rootObject = 4D79EC2A15B08111007C9A90 /* Project object */; 484 | } 485 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo.xcodeproj/project.xcworkspace/xcuserdata/dilliontan.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dillion/EssentialImager/789bae62f758b70a3c5712b715a92c62b369c5a6/EssentialImagerDemo/EssentialImagerDemo.xcodeproj/project.xcworkspace/xcuserdata/dilliontan.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo.xcodeproj/project.xcworkspace/xcuserdata/dilliontan.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo.xcodeproj/xcuserdata/dilliontan.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo.xcodeproj/xcuserdata/dilliontan.xcuserdatad/xcschemes/Full Demo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo.xcodeproj/xcuserdata/dilliontan.xcuserdatad/xcschemes/Simple Demo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo.xcodeproj/xcuserdata/dilliontan.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Full Demo.xcscheme 8 | 9 | orderHint 10 | 1 11 | 12 | Simple Demo.xcscheme 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 4D1992A2171D097B009F6E18 21 | 22 | primary 23 | 24 | 25 | 4D79EC3215B08111007C9A90 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/EssentialImager/EIImagePickerDelegate.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: EIImagePickerDelegate.h 4 | Abstract: ARC-ed image picker delegate with blocks 5 | 6 | Copyright (c) 2012 Dillion Tan 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation 10 | files (the "Software"), to deal in the Software without 11 | restriction, including without limitation the rights to use, 12 | copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the 14 | Software is furnished to do so, subject to the following 15 | conditions: 16 | 17 | The above copyright notice and this permission notice shall be 18 | included in all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | OTHER DEALINGS IN THE SOFTWARE. 28 | 29 | */ 30 | 31 | #import 32 | 33 | typedef void (^PickerCompletionBlock) (UIImage *); 34 | typedef void (^PickerCancelBlock) (void); 35 | 36 | @interface EIImagePickerDelegate : UIViewController 37 | { 38 | 39 | } 40 | 41 | @property (nonatomic, retain) UIImagePickerController *imagePicker; 42 | 43 | @property (nonatomic, copy) PickerCompletionBlock pickerCompletionBlock; 44 | @property (nonatomic, copy) PickerCancelBlock pickerCancelBlock; 45 | 46 | - (void)presentFromController:(UIViewController *)aController withSourceType:(UIImagePickerControllerSourceType)sourceType; 47 | - (void)setImagePickerCompletionBlock:(void (^)(UIImage *))block; 48 | - (void)setImagePickerCancelBlock:(void (^)(void))block; 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/EssentialImager/EIImagePickerDelegate.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: EIImagePickerDelegate.m 4 | Abstract: ARC-ed image picker delegate with blocks 5 | 6 | Copyright (c) 2012 Dillion Tan 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation 10 | files (the "Software"), to deal in the Software without 11 | restriction, including without limitation the rights to use, 12 | copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the 14 | Software is furnished to do so, subject to the following 15 | conditions: 16 | 17 | The above copyright notice and this permission notice shall be 18 | included in all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | OTHER DEALINGS IN THE SOFTWARE. 28 | 29 | */ 30 | 31 | #import "EIImagePickerDelegate.h" 32 | 33 | @interface EIImagePickerDelegate () 34 | 35 | @end 36 | 37 | @implementation EIImagePickerDelegate 38 | 39 | @synthesize imagePicker; 40 | @synthesize pickerCompletionBlock; 41 | @synthesize pickerCancelBlock; 42 | 43 | - (id)init 44 | { 45 | self = [super init]; 46 | if (self) { 47 | self.imagePicker = [[UIImagePickerController alloc] init]; 48 | imagePicker.delegate = self; 49 | // configure source type just before presenting 50 | } 51 | return self; 52 | } 53 | 54 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 55 | { 56 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 57 | if (self) { 58 | // Custom initialization 59 | } 60 | return self; 61 | } 62 | 63 | - (void)viewDidLoad 64 | { 65 | [super viewDidLoad]; 66 | // Do any additional setup after loading the view. 67 | } 68 | 69 | - (void)viewDidUnload 70 | { 71 | [super viewDidUnload]; 72 | // Release any retained subviews of the main view. 73 | } 74 | 75 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 76 | { 77 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 78 | } 79 | 80 | - (void)presentFromController:(UIViewController *)aController withSourceType:(UIImagePickerControllerSourceType)sourceType 81 | { 82 | // media types is still image by default, so we don't need to change it here 83 | imagePicker.sourceType = sourceType; 84 | [aController presentModalViewController:imagePicker animated:YES]; 85 | } 86 | 87 | - (void)imagePickerController:(UIImagePickerController *)aPicker didFinishPickingMediaWithInfo:(NSDictionary *)info 88 | { 89 | [aPicker dismissModalViewControllerAnimated:YES]; 90 | 91 | UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage]; 92 | 93 | if (image && pickerCompletionBlock) { 94 | pickerCompletionBlock(image); 95 | } 96 | } 97 | 98 | - (void)imagePickerControllerDidCancel:(UIImagePickerController *)aPicker 99 | { 100 | [aPicker dismissModalViewControllerAnimated:YES]; 101 | 102 | if (pickerCancelBlock) { 103 | pickerCancelBlock(); 104 | } 105 | } 106 | 107 | - (void)setImagePickerCompletionBlock:(void (^)(UIImage *))block 108 | { 109 | self.pickerCompletionBlock = block; 110 | } 111 | 112 | - (void)setImagePickerCancelBlock:(void (^)(void))block 113 | { 114 | self.pickerCancelBlock = block; 115 | } 116 | 117 | @end 118 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/EssentialImager/EIOperationManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // EIOperationManager.h 3 | // EssentialImagerDemo 4 | // 5 | // Created by Dillion Tan on 16/4/13. 6 | // 7 | // 8 | 9 | #import 10 | 11 | @interface EIOperationManager : NSObject 12 | 13 | @property (nonatomic, strong) NSOperationQueue *storageQueue; 14 | @property (nonatomic, strong) NSMutableDictionary *storageOperationDictionary; 15 | 16 | + (EIOperationManager *)defaultManager; 17 | 18 | - (void)saveImage:(UIImage *)image toPath:(NSString *)pathString withBlock:(void(^)(BOOL success))block; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/EssentialImager/EIOperationManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // EIOperationManager.m 3 | // EssentialImagerDemo 4 | // 5 | // Created by Dillion Tan on 16/4/13. 6 | // 7 | // 8 | 9 | #import "EIOperationManager.h" 10 | 11 | @implementation EIOperationManager 12 | 13 | @synthesize storageQueue; 14 | @synthesize storageOperationDictionary; 15 | 16 | + (EIOperationManager *)defaultManager 17 | { 18 | static dispatch_once_t pred = 0; 19 | __strong static id _defaultManager = nil; 20 | dispatch_once(&pred, ^{ 21 | _defaultManager = [[self alloc] init]; 22 | }); 23 | return _defaultManager; 24 | } 25 | 26 | - (id)init 27 | { 28 | self = [super init]; 29 | if (self) { 30 | storageQueue = [[NSOperationQueue alloc] init]; 31 | storageOperationDictionary = [NSMutableDictionary dictionary]; 32 | } 33 | return self; 34 | } 35 | 36 | // assume we are saving PNG 37 | - (void)saveImage:(UIImage *)image toPath:(NSString *)pathString withBlock:(void(^)(BOOL success))block 38 | { 39 | if (![storageOperationDictionary objectForKey:pathString]) { 40 | __block UIImage *imageToSave = image; 41 | 42 | NSBlockOperation *writeBlockOperation = [[NSBlockOperation alloc] init]; 43 | __weak NSBlockOperation *weakSelf = writeBlockOperation; 44 | 45 | [writeBlockOperation addExecutionBlock:^{ 46 | NSData *imageData = UIImagePNGRepresentation(imageToSave); 47 | 48 | if (!weakSelf.isCancelled) { 49 | 50 | [imageData writeToFile:pathString atomically:YES]; 51 | 52 | if (!weakSelf.isCancelled) { 53 | [storageOperationDictionary removeObjectForKey:pathString]; 54 | dispatch_async(dispatch_get_main_queue(), ^{ 55 | block(YES); 56 | }); 57 | } else { 58 | block(NO); 59 | } 60 | } else { 61 | block(NO); 62 | } 63 | }]; 64 | 65 | [storageOperationDictionary setObject:writeBlockOperation forKey:pathString]; 66 | 67 | [storageQueue addOperation:writeBlockOperation]; 68 | } else { // already queued for writing 69 | block(NO); 70 | } 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/EssentialImager/EssentialImager.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: EssentialImager.h 4 | Abstract: main header file 5 | 6 | Copyright (c) 2012 Dillion Tan 7 | 8 | Permission is hereby granted, free of charge, to any person 9 | obtaining a copy of this software and associated documentation 10 | files (the "Software"), to deal in the Software without 11 | restriction, including without limitation the rights to use, 12 | copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the 14 | Software is furnished to do so, subject to the following 15 | conditions: 16 | 17 | The above copyright notice and this permission notice shall be 18 | included in all copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 22 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 23 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 24 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 25 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27 | OTHER DEALINGS IN THE SOFTWARE. 28 | 29 | */ 30 | 31 | #ifndef EssentialImager_EssentialImager_h 32 | #define EssentialImager_EssentialImager_h 33 | 34 | #import "StandardPaths.h" 35 | #import "UIImage+Resize.h" 36 | #import "NSData+Storage.h" 37 | #import "EIImagePickerDelegate.h" 38 | #import "EIOperationManager.h" 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/EssentialImager/NSData+Storage.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: NSData+Storage.h 4 | Abstract: Modified to add retrieval of image from file url and 5 | set scale based on suffix 6 | 7 | Copyright (c) 2012 Dillion Tan 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | */ 31 | 32 | // 33 | // NSData+Storage.h 34 | // storage 35 | // 36 | // Created by Andrew Sliwinski on 6/24/12. 37 | // Copyright (c) 2012 DIY, Co. All rights reserved. 38 | // 39 | 40 | #import 41 | #import 42 | 43 | @interface NSData (Storage) 44 | 45 | + (UIImage *)imageFromFile:(NSString *)filePath; 46 | 47 | @end -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/EssentialImager/NSData+Storage.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: NSData+Storage.m 4 | Abstract: Modified to add retrieval of image from file url and 5 | set scale based on suffix 6 | 7 | Copyright (c) 2012 Dillion Tan 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | */ 31 | 32 | // 33 | // NSData+Storage.m 34 | // storage 35 | // 36 | // Created by Andrew Sliwinski on 6/24/12. 37 | // Copyright (c) 2012 DIY, Co. All rights reserved. 38 | // 39 | 40 | #import "NSData+Storage.h" 41 | #import "StandardPaths.h" 42 | 43 | @implementation NSData (Storage) 44 | 45 | + (UIImage *)imageFromFile:(NSString *)filePath 46 | { 47 | float scale = [filePath scale]; 48 | 49 | NSData *imageData = [NSData dataWithContentsOfFile:filePath]; 50 | 51 | if (!imageData) { 52 | NSLog(@"file at %@ does not contain valid data", filePath); 53 | return nil; 54 | } 55 | 56 | UIImage *image = [UIImage imageWithData:imageData]; 57 | 58 | if (!image) { 59 | NSLog(@"could not initialize image from data"); 60 | return nil; 61 | } 62 | 63 | return [UIImage imageWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation]; 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/EssentialImager/StandardPaths/StandardPaths.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: StandardPaths.h 4 | Abstract: Modified to add folder creation function, move scale 5 | define to header 6 | 7 | Copyright (c) 2012 Dillion Tan 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | */ 31 | 32 | // 33 | // StandardPaths.h 34 | // 35 | // Version 1.2 36 | // 37 | // Created by Nick Lockwood on 10/11/2011. 38 | // Copyright (C) 2012 Charcoal Design 39 | // 40 | // Distributed under the permissive zlib License 41 | // Get the latest version from either of these locations: 42 | // 43 | // http://charcoaldesign.co.uk/source/cocoa#standardpaths 44 | // https://github.com/nicklockwood/StandardPaths 45 | // 46 | // This software is provided 'as-is', without any express or implied 47 | // warranty. In no event will the authors be held liable for any damages 48 | // arising from the use of this software. 49 | // 50 | // Permission is granted to anyone to use this software for any purpose, 51 | // including commercial applications, and to alter it and redistribute it 52 | // freely, subject to the following restrictions: 53 | // 54 | // 1. The origin of this software must not be misrepresented; you must not 55 | // claim that you wrote the original software. If you use this software 56 | // in a product, an acknowledgment in the product documentation would be 57 | // appreciated but is not required. 58 | // 59 | // 2. Altered source versions must be plainly marked as such, and must not be 60 | // misrepresented as being the original software. 61 | // 62 | // 3. This notice may not be removed or altered from any source distribution. 63 | // 64 | 65 | 66 | #import 67 | #import 68 | #ifdef __IPHONE_OS_VERSION_MAX_ALLOWED 69 | #import 70 | #endif 71 | 72 | 73 | #ifndef UI_USER_INTERFACE_IDIOM 74 | #define UI_USER_INTERFACE_IDIOM() UIUserInterfaceIdiomDesktop 75 | 76 | typedef enum 77 | { 78 | UIUserInterfaceIdiomPhone, 79 | UIUserInterfaceIdiomPad, 80 | UIUserInterfaceIdiomDesktop 81 | } 82 | UIUserInterfaceIdiom; 83 | 84 | #endif 85 | 86 | #ifndef __IPHONE_OS_VERSION_MAX_ALLOWED 87 | #define SP_SCREEN_SCALE() ([[NSScreen mainScreen] respondsToSelector:@selector(backingScaleFactor)]? [[NSScreen mainScreen] backingScaleFactor]: 1.0f) 88 | #else 89 | #define SP_SCREEN_SCALE() ([UIScreen mainScreen].scale) 90 | #endif 91 | 92 | @interface NSFileManager (StandardPaths) 93 | 94 | - (NSString *)publicDataPath; 95 | - (NSString *)privateDataPath; 96 | - (NSString *)cacheDataPath; 97 | - (NSString *)offlineDataPath; 98 | - (NSString *)temporaryDataPath; 99 | - (NSString *)resourcePath; 100 | 101 | - (NSString *)pathForPublicFile:(NSString *)file; 102 | - (NSString *)pathForPrivateFile:(NSString *)file; 103 | - (NSString *)pathForCacheFile:(NSString *)file; 104 | - (NSString *)pathForOfflineFile:(NSString *)file; 105 | - (NSString *)pathForTemporaryFile:(NSString *)file; 106 | - (NSString *)pathForResource:(NSString *)file; 107 | 108 | - (NSString *)normalizedPathForFile:(NSString *)fileOrPath; 109 | 110 | - (void)createFoldersIfRequired:(NSString *)folderPath; 111 | 112 | @end 113 | 114 | 115 | @interface NSString (StandardPaths) 116 | 117 | - (NSString *)stringByAppendingInterfaceIdiomSuffix; 118 | - (NSString *)stringByDeletingInterfaceIdiomSuffix; 119 | - (NSString *)interfaceIdiomSuffix; 120 | - (UIUserInterfaceIdiom)interfaceIdiom; 121 | 122 | - (NSString *)stringByAppendingScaleSuffix; 123 | - (NSString *)stringByDeletingScaleSuffix; 124 | - (NSString *)scaleSuffix; 125 | - (CGFloat)scale; 126 | 127 | - (NSString *)stringByAppendingHDSuffix; 128 | - (NSString *)stringByDeletingHDSuffix; 129 | - (NSString *)HDSuffix; 130 | - (BOOL)isHD; 131 | 132 | @end -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/EssentialImager/StandardPaths/StandardPaths.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: StandardPaths.m 4 | Abstract: Modified to add folder creation function, move scale 5 | define to header 6 | 7 | Copyright (c) 2012 Dillion Tan 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | */ 31 | 32 | // 33 | // StandardPaths.h 34 | // 35 | // Version 1.2 36 | // 37 | // Created by Nick Lockwood on 10/11/2011. 38 | // Copyright (C) 2012 Charcoal Design 39 | // 40 | // Distributed under the permissive zlib License 41 | // Get the latest version from either of these locations: 42 | // 43 | // http://charcoaldesign.co.uk/source/cocoa#standardpaths 44 | // https://github.com/nicklockwood/StandardPaths 45 | // 46 | // This software is provided 'as-is', without any express or implied 47 | // warranty. In no event will the authors be held liable for any damages 48 | // arising from the use of this software. 49 | // 50 | // Permission is granted to anyone to use this software for any purpose, 51 | // including commercial applications, and to alter it and redistribute it 52 | // freely, subject to the following restrictions: 53 | // 54 | // 1. The origin of this software must not be misrepresented; you must not 55 | // claim that you wrote the original software. If you use this software 56 | // in a product, an acknowledgment in the product documentation would be 57 | // appreciated but is not required. 58 | // 59 | // 2. Altered source versions must be plainly marked as such, and must not be 60 | // misrepresented as being the original software. 61 | // 62 | // 3. This notice may not be removed or altered from any source distribution. 63 | // 64 | 65 | 66 | #import "StandardPaths.h" 67 | #include 68 | 69 | @implementation NSFileManager (StandardPaths) 70 | 71 | - (NSString *)publicDataPath 72 | { 73 | @synchronized ([NSFileManager class]) 74 | { 75 | static NSString *path = nil; 76 | if (!path) 77 | { 78 | //user documents folder 79 | path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; 80 | 81 | //retain path 82 | path = [[NSString alloc] initWithString:path]; 83 | } 84 | return path; 85 | } 86 | } 87 | 88 | - (NSString *)privateDataPath 89 | { 90 | @synchronized ([NSFileManager class]) 91 | { 92 | static NSString *path = nil; 93 | if (!path) 94 | { 95 | //application support folder 96 | path = [NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES) lastObject]; 97 | 98 | #ifndef __IPHONE_OS_VERSION_MAX_ALLOWED 99 | 100 | //append application name on Mac OS 101 | NSString *identifier = [[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleNameKey]; 102 | path = [path stringByAppendingPathComponent:identifier]; 103 | 104 | #endif 105 | 106 | //create the folder if it doesn't exist 107 | if (![self fileExistsAtPath:path]) 108 | { 109 | [self createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:NULL]; 110 | } 111 | 112 | //retain path 113 | path = [[NSString alloc] initWithString:path]; 114 | } 115 | return path; 116 | } 117 | } 118 | 119 | - (NSString *)cacheDataPath 120 | { 121 | @synchronized ([NSFileManager class]) 122 | { 123 | static NSString *path = nil; 124 | if (!path) 125 | { 126 | //cache folder 127 | path = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; 128 | 129 | #ifndef __IPHONE_OS_VERSION_MAX_ALLOWED 130 | 131 | //append application bundle ID on Mac OS 132 | NSString *identifier = [[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleIdentifierKey]; 133 | path = [path stringByAppendingPathComponent:identifier]; 134 | 135 | #endif 136 | 137 | //create the folder if it doesn't exist 138 | if (![self fileExistsAtPath:path]) 139 | { 140 | [self createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:NULL]; 141 | } 142 | 143 | //retain path 144 | path = [[NSString alloc] initWithString:path]; 145 | } 146 | return path; 147 | } 148 | } 149 | 150 | - (NSString *)offlineDataPath 151 | { 152 | static NSString *path = nil; 153 | if (!path) 154 | { 155 | //offline data folder 156 | path = [[self privateDataPath] stringByAppendingPathComponent:@"Offline Data"]; 157 | 158 | //create the folder if it doesn't exist 159 | if (![self fileExistsAtPath:path]) 160 | { 161 | [self createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:NULL]; 162 | } 163 | 164 | if (&NSURLIsExcludedFromBackupKey && [NSURL instancesRespondToSelector:@selector(setResourceValue:forKey:error:)]) 165 | { 166 | //use iOS 5.1 method to exclude file from backp 167 | NSURL *URL = [NSURL fileURLWithPath:path isDirectory:YES]; 168 | [URL setResourceValue:[NSNumber numberWithBool:YES] forKey:NSURLIsExcludedFromBackupKey error:NULL]; 169 | } 170 | else 171 | { 172 | //use the iOS 5.0.1 mobile backup flag to exclude file from backp 173 | u_int8_t b = 1; 174 | setxattr([path fileSystemRepresentation], "com.apple.MobileBackup", &b, 1, 0, 0); 175 | } 176 | 177 | //retain path 178 | path = [[NSString alloc] initWithString:path]; 179 | } 180 | return path; 181 | } 182 | 183 | - (NSString *)temporaryDataPath 184 | { 185 | static NSString *path = nil; 186 | if (!path) 187 | { 188 | //temporary directory (shouldn't change during app lifetime) 189 | path = NSTemporaryDirectory(); 190 | 191 | //apparently NSTemporaryDirectory() can return nil in some cases 192 | if (!path) 193 | { 194 | path = [[self cacheDataPath] stringByAppendingPathComponent:@"Temporary Files"]; 195 | } 196 | 197 | //retain path 198 | path = [[NSString alloc] initWithString:path]; 199 | } 200 | return path; 201 | } 202 | 203 | - (NSString *)resourcePath 204 | { 205 | static NSString *path = nil; 206 | if (!path) 207 | { 208 | //bundle path 209 | path = [[NSString alloc] initWithString:[[NSBundle mainBundle] resourcePath]]; 210 | } 211 | return path; 212 | } 213 | 214 | - (NSString *)pathForPublicFile:(NSString *)file 215 | { 216 | return [[self publicDataPath] stringByAppendingPathComponent:file]; 217 | } 218 | 219 | - (NSString *)pathForPrivateFile:(NSString *)file 220 | { 221 | return [[self privateDataPath] stringByAppendingPathComponent:file]; 222 | } 223 | 224 | - (NSString *)pathForCacheFile:(NSString *)file 225 | { 226 | return [[self cacheDataPath] stringByAppendingPathComponent:file]; 227 | } 228 | 229 | - (NSString *)pathForOfflineFile:(NSString *)file 230 | { 231 | return [[self offlineDataPath] stringByAppendingPathComponent:file]; 232 | } 233 | 234 | - (NSString *)pathForTemporaryFile:(NSString *)file 235 | { 236 | return [[self temporaryDataPath] stringByAppendingPathComponent:file]; 237 | } 238 | 239 | - (NSString *)pathForResource:(NSString *)file 240 | { 241 | return [[self resourcePath] stringByAppendingPathComponent:file]; 242 | } 243 | 244 | - (NSString *)normalizedPathForFile:(NSString *)fileOrPath 245 | { 246 | @synchronized ([NSFileManager class]) 247 | { 248 | //set up cache 249 | static NSCache *cache = nil; 250 | if (cache == nil) 251 | { 252 | cache = [[NSCache alloc] init]; 253 | } 254 | 255 | //convert to absolute path 256 | NSString *path = fileOrPath; 257 | if (![path isAbsolutePath]) 258 | { 259 | path = [[self resourcePath] stringByAppendingPathComponent:path]; 260 | } 261 | 262 | //check cache 263 | NSString *cacheKey = path; 264 | BOOL cachable = [path hasPrefix:[self resourcePath]]; 265 | if (cachable) 266 | { 267 | NSString *_path = [cache objectForKey:cacheKey]; 268 | if (_path) 269 | { 270 | return [_path length]? _path: nil; 271 | } 272 | } 273 | 274 | if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPhone) 275 | { 276 | //check for HD version 277 | NSString *_path = [path stringByAppendingHDSuffix]; 278 | if ([[NSFileManager defaultManager] fileExistsAtPath:_path]) 279 | { 280 | path = _path; 281 | } 282 | else if ([[_path pathExtension] isEqualToString:@"png"]) 283 | { 284 | //check for HiDPI tiff file 285 | _path = [[_path stringByDeletingPathExtension] stringByAppendingPathExtension:@"tiff"]; 286 | if ([[NSFileManager defaultManager] fileExistsAtPath:_path]) 287 | { 288 | path = _path; 289 | } 290 | } 291 | 292 | //check for scaled version 293 | if (SP_SCREEN_SCALE() > 1.0f) 294 | { 295 | NSString *_path = [path stringByAppendingScaleSuffix]; 296 | if ([[NSFileManager defaultManager] fileExistsAtPath:_path]) 297 | { 298 | path = _path; 299 | } 300 | } 301 | } 302 | else if (SP_SCREEN_SCALE() > 1.0f) 303 | { 304 | //check for HD version 305 | NSString *_path = [path stringByAppendingHDSuffix]; 306 | if ([[NSFileManager defaultManager] fileExistsAtPath:_path]) 307 | { 308 | path = _path; 309 | } 310 | else 311 | { 312 | //check for scaled version 313 | NSString *_path = [path stringByAppendingScaleSuffix]; 314 | if ([[NSFileManager defaultManager] fileExistsAtPath:_path]) 315 | { 316 | path = _path; 317 | } 318 | } 319 | } 320 | 321 | //check for ipad/iphone version 322 | NSString *_path = [path stringByAppendingInterfaceIdiomSuffix]; 323 | if ([[NSFileManager defaultManager] fileExistsAtPath:_path]) 324 | { 325 | path = _path; 326 | } 327 | else if ([[_path pathExtension] isEqualToString:@"png"]) 328 | { 329 | //check for HiDPI tiff file 330 | _path = [[_path stringByDeletingPathExtension] stringByAppendingPathExtension:@"tiff"]; 331 | if ([[NSFileManager defaultManager] fileExistsAtPath:_path]) 332 | { 333 | path = _path; 334 | } 335 | } 336 | 337 | if ([[path pathExtension] isEqualToString:@"png"]) 338 | { 339 | //check for HiDPI tiff file 340 | NSString *_path = [[path stringByDeletingPathExtension] stringByAppendingPathExtension:@"tiff"]; 341 | if ([[NSFileManager defaultManager] fileExistsAtPath:_path]) 342 | { 343 | path = _path; 344 | } 345 | } 346 | else if (![[NSFileManager defaultManager] fileExistsAtPath:path]) 347 | { 348 | //file doesn't exist 349 | path = nil; 350 | } 351 | 352 | //add to cache 353 | if (cachable) 354 | { 355 | [cache setObject:path ?: @"" forKey:cacheKey]; 356 | } 357 | 358 | //return path 359 | return path; 360 | } 361 | } 362 | 363 | - (void)createFoldersIfRequired:(NSString *)folderPath 364 | { 365 | BOOL isDir; 366 | 367 | if (![self fileExistsAtPath:folderPath isDirectory:&isDir] && isDir) 368 | { 369 | [self createDirectoryAtPath:folderPath withIntermediateDirectories:YES attributes:nil error:NULL]; 370 | } 371 | } 372 | 373 | @end 374 | 375 | 376 | @implementation NSString (StandardPaths) 377 | 378 | - (NSString *)stringByAppendingInterfaceIdiomSuffix 379 | { 380 | NSString *suffix = @""; 381 | if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) 382 | { 383 | suffix = @"~iphone"; 384 | } 385 | else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) 386 | { 387 | suffix = @"~ipad"; 388 | } 389 | else 390 | { 391 | suffix = @"~mac"; 392 | } 393 | NSString *extension = [self pathExtension]; 394 | NSString *path = [[self stringByDeletingPathExtension] stringByAppendingString:suffix]; 395 | return [extension length]? [path stringByAppendingPathExtension:extension]: path; 396 | } 397 | 398 | - (NSString *)stringByDeletingInterfaceIdiomSuffix 399 | { 400 | NSString *suffix = [self interfaceIdiomSuffix]; 401 | if ([suffix length]) 402 | { 403 | NSString *extension = [self pathExtension]; 404 | NSString *path = [self stringByDeletingPathExtension]; 405 | path = [path substringToIndex:[path length] - [suffix length]]; 406 | return [extension length]? [path stringByAppendingPathExtension:extension]: path; 407 | } 408 | return self; 409 | } 410 | 411 | - (NSString *)interfaceIdiomSuffix 412 | { 413 | NSString *path = [self stringByDeletingPathExtension]; 414 | for (NSString *suffix in [NSArray arrayWithObjects:@"~iphone", @"~ipad", @"~mac", nil]) 415 | { 416 | if ([path hasSuffix:suffix]) return suffix; 417 | } 418 | return @""; 419 | } 420 | 421 | - (UIUserInterfaceIdiom)interfaceIdiom 422 | { 423 | NSString *suffix = [self interfaceIdiomSuffix]; 424 | if ([suffix isEqualToString:@"~ipad"]) 425 | { 426 | return UIUserInterfaceIdiomPad; 427 | } 428 | else if ([suffix isEqualToString:@"~iphone"]) 429 | { 430 | return UIUserInterfaceIdiomPhone; 431 | } 432 | return UI_USER_INTERFACE_IDIOM(); 433 | } 434 | 435 | - (NSString *)stringByAppendingScaleSuffix 436 | { 437 | if (SP_SCREEN_SCALE() > 1.0f) 438 | { 439 | NSString *extension = [self pathExtension]; 440 | NSString *deviceSuffix = [self interfaceIdiomSuffix]; 441 | NSString *scaleSuffix = [NSString stringWithFormat:@"@%ix", (int)SP_SCREEN_SCALE()]; 442 | NSString *path = [[self stringByDeletingPathExtension] stringByDeletingInterfaceIdiomSuffix]; 443 | path = [path stringByAppendingFormat:@"%@%@", scaleSuffix, deviceSuffix]; 444 | return [extension length]? [path stringByAppendingPathExtension:extension]: path; 445 | } 446 | return self; 447 | } 448 | 449 | - (NSString *)stringByDeletingScaleSuffix 450 | { 451 | NSString *scaleSuffix = [self scaleSuffix]; 452 | if ([scaleSuffix length]) 453 | { 454 | NSString *extension = [self pathExtension]; 455 | NSString *deviceSuffix = [self interfaceIdiomSuffix]; 456 | NSString *path = [[self stringByDeletingPathExtension] stringByDeletingInterfaceIdiomSuffix]; 457 | path = [[path substringToIndex:[path length] - [scaleSuffix length]] stringByAppendingString:deviceSuffix]; 458 | return [extension length]? [path stringByAppendingPathExtension:extension]: path; 459 | } 460 | return self; 461 | } 462 | 463 | - (NSString *)scaleSuffix 464 | { 465 | //note: this isn't very robust as it only handles single-digit integer scales 466 | //for the forseeable future though, it's unlikely that we'll have to worry about that 467 | NSString *path = [[self stringByDeletingPathExtension] stringByDeletingInterfaceIdiomSuffix]; 468 | if ([path length] >= 3) 469 | { 470 | NSString *scaleSuffix = [path substringFromIndex:[path length] - 3]; 471 | if ([[scaleSuffix substringToIndex:1] isEqualToString:@"@"] && 472 | [[scaleSuffix substringFromIndex:2] isEqualToString:@"x"]) 473 | { 474 | return scaleSuffix; 475 | } 476 | } 477 | return @""; 478 | } 479 | 480 | - (CGFloat)scale 481 | { 482 | NSString *scaleSuffix = [self scaleSuffix]; 483 | if ([scaleSuffix length]) 484 | { 485 | return [[scaleSuffix substringWithRange:NSMakeRange(1, 1)] floatValue]; 486 | } 487 | else if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone && [self isHD]) 488 | { 489 | return 2.0f; 490 | } 491 | return 1.0f; 492 | } 493 | 494 | - (NSString *)stringByAppendingHDSuffix 495 | { 496 | if (SP_SCREEN_SCALE() > 1.0f || UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPhone) 497 | { 498 | NSString *extension = [self pathExtension]; 499 | NSString *deviceSuffix = [self interfaceIdiomSuffix]; 500 | NSString *scaleSuffix = [self scaleSuffix]; 501 | NSString *path = [[[self stringByDeletingPathExtension] stringByDeletingInterfaceIdiomSuffix] stringByDeletingScaleSuffix]; 502 | path = [path stringByAppendingFormat:@"-hd%@%@", scaleSuffix, deviceSuffix]; 503 | return [extension length]? [path stringByAppendingPathExtension:extension]: path; 504 | } 505 | return self; 506 | } 507 | 508 | - (NSString *)stringByDeletingHDSuffix 509 | { 510 | NSString *HDSuffix = [self HDSuffix]; 511 | if ([HDSuffix length]) 512 | { 513 | NSString *extension = [self pathExtension]; 514 | NSString *deviceSuffix = [self interfaceIdiomSuffix]; 515 | NSString *scaleSuffix = [self scaleSuffix]; 516 | NSString *path = [[[self stringByDeletingPathExtension] stringByDeletingInterfaceIdiomSuffix] stringByDeletingScaleSuffix]; 517 | path = [path substringToIndex:[path length] - [HDSuffix length]]; 518 | path = [path stringByAppendingFormat:@"%@%@", scaleSuffix, deviceSuffix]; 519 | return [extension length]? [path stringByAppendingPathExtension:extension]: path; 520 | } 521 | return self; 522 | } 523 | 524 | - (NSString *)HDSuffix 525 | { 526 | NSString *path = [[[self stringByDeletingPathExtension] stringByDeletingInterfaceIdiomSuffix] stringByDeletingScaleSuffix]; 527 | if ([path hasSuffix:@"-hd"]) 528 | { 529 | return @"-hd"; 530 | } 531 | return @""; 532 | } 533 | 534 | - (BOOL)isHD 535 | { 536 | return [[self HDSuffix] length] > 0; 537 | } 538 | 539 | @end -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/EssentialImager/UIImage+Resize.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: UIImage+Resize.h 4 | Abstract: Modified to focus on resizing for logical display size 5 | or uncompressed size in MB, using scale determined by StandardPaths 6 | 7 | Copyright (c) 2012 Dillion Tan 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | */ 31 | 32 | // UIImage+Resize.h 33 | // Created by Trevor Harmon on 8/5/09. 34 | // Free for personal or commercial use, with or without modification. 35 | // No warranty is expressed or implied. 36 | 37 | // Extends the UIImage class to support resizing/cropping 38 | 39 | @interface UIImage (Resize) 40 | 41 | #define imageBytesPerMB 1048576.0f 42 | #define imageBytesPerPixel 4.0f 43 | #define imagePixelsPerMB ( imageBytesPerMB / imageBytesPerPixel ) // 262144 pixels, for 4 bytes per pixel. 44 | 45 | - (UIImage *)resizedImageWithContentMode:(UIViewContentMode)contentMode 46 | bounds:(CGSize)bounds 47 | interpolationQuality:(CGInterpolationQuality)quality; 48 | - (UIImage *)resizedImageWithUncompressedSizeInMB:(CGFloat)destImageSize 49 | interpolationQuality:(CGInterpolationQuality)quality; 50 | 51 | // helper functions 52 | - (UIImage *)resizedImage:(CGSize)newSize 53 | interpolationQuality:(CGInterpolationQuality)quality; 54 | - (UIImage *)resizedImage:(CGSize)newSize 55 | transform:(CGAffineTransform)transform 56 | drawTransposed:(BOOL)transpose 57 | interpolationQuality:(CGInterpolationQuality)quality; 58 | - (CGAffineTransform)transformForOrientation:(CGSize)newSize; 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/EssentialImager/UIImage+Resize.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: UIImage+Resize.m 4 | Abstract: Modified to focus on resizing for logical display size 5 | or uncompressed size in MB, using scale determined by StandardPaths 6 | 7 | Copyright (c) 2012 Dillion Tan 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | */ 31 | 32 | // UIImage+Resize.m 33 | // Created by Trevor Harmon on 8/5/09. 34 | // Free for personal or commercial use, with or without modification. 35 | // No warranty is expressed or implied. 36 | 37 | #import "UIImage+Resize.h" 38 | #import "StandardPaths.h" 39 | 40 | @implementation UIImage (Resize) 41 | 42 | # pragma mark - 43 | # pragma mark Main utility functions 44 | 45 | // Resizes the image according to the given content mode, taking into account the image's orientation 46 | - (UIImage *)resizedImageWithContentMode:(UIViewContentMode)contentMode 47 | bounds:(CGSize)bounds 48 | interpolationQuality:(CGInterpolationQuality)quality { 49 | CGFloat screenScale = SP_SCREEN_SCALE(); 50 | 51 | // note! CGImageGetWidth/CGImageGetHeight return different values from self.size.width/self.size.height depending on orientation 52 | CGFloat horizontalRatio = bounds.width / self.size.width; 53 | CGFloat verticalRatio = bounds.height / self.size.height; 54 | CGFloat ratio; 55 | 56 | switch (contentMode) { 57 | case UIViewContentModeScaleAspectFill: 58 | ratio = MAX(horizontalRatio, verticalRatio); 59 | break; 60 | 61 | case UIViewContentModeScaleAspectFit: 62 | ratio = MIN(horizontalRatio, verticalRatio); 63 | break; 64 | 65 | default: 66 | [NSException raise:NSInvalidArgumentException format:@"Unsupported content mode: %d", contentMode]; 67 | } 68 | 69 | CGSize newSize = CGSizeMake(floorf(self.size.width * screenScale * ratio), floorf(self.size.height * screenScale * ratio)); 70 | 71 | return [self resizedImage:newSize interpolationQuality:quality]; 72 | } 73 | 74 | // Resizes the image to fit an uncompressed destination size in MB 75 | - (UIImage *)resizedImageWithUncompressedSizeInMB:(CGFloat)destImageSize 76 | interpolationQuality:(CGInterpolationQuality)quality 77 | { 78 | CGSize sourceResolution = CGSizeZero; 79 | sourceResolution.width = self.size.width; 80 | sourceResolution.height = self.size.height; 81 | 82 | CGFloat sourceTotalPixels = sourceResolution.width * sourceResolution.height; 83 | 84 | CGFloat ratio = destImageSize * imagePixelsPerMB / sourceTotalPixels; 85 | 86 | CGSize newSize = CGSizeMake(floorf(self.size.width * ratio), floorf(self.size.height * ratio)); 87 | 88 | return [self resizedImage:newSize interpolationQuality:quality]; 89 | } 90 | 91 | # pragma mark - 92 | # pragma mark Helper functions 93 | 94 | // Returns a rescaled copy of the image, taking into account its orientation 95 | // The image will be scaled disproportionately if necessary to fit the bounds specified by the parameter 96 | - (UIImage *)resizedImage:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)quality { 97 | BOOL drawTransposed; 98 | 99 | switch (self.imageOrientation) { 100 | case UIImageOrientationLeft: 101 | case UIImageOrientationLeftMirrored: 102 | case UIImageOrientationRight: 103 | case UIImageOrientationRightMirrored: 104 | drawTransposed = YES; 105 | break; 106 | 107 | default: 108 | drawTransposed = NO; 109 | } 110 | 111 | return [self resizedImage:newSize 112 | transform:[self transformForOrientation:newSize] 113 | drawTransposed:drawTransposed 114 | interpolationQuality:quality]; 115 | } 116 | 117 | // Returns a copy of the image that has been transformed using the given affine transform and scaled to the new size 118 | // The new image's orientation will be UIImageOrientationUp, regardless of the current image's orientation 119 | // If the new size is not integral, it will be rounded up 120 | - (UIImage *)resizedImage:(CGSize)newSize 121 | transform:(CGAffineTransform)transform 122 | drawTransposed:(BOOL)transpose 123 | interpolationQuality:(CGInterpolationQuality)quality { 124 | 125 | CGFloat screenScale = SP_SCREEN_SCALE(); 126 | 127 | CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height)); 128 | CGRect transposedRect = CGRectMake(0, 0, newRect.size.height, newRect.size.width); 129 | CGImageRef imageRef = self.CGImage; 130 | 131 | // Build a context that's the same dimensions as the new size 132 | CGContextRef bitmap = CGBitmapContextCreate(NULL, 133 | newRect.size.width, 134 | newRect.size.height, 135 | CGImageGetBitsPerComponent(imageRef), 136 | 0, 137 | CGImageGetColorSpace(imageRef), 138 | CGImageGetBitmapInfo(imageRef)); 139 | 140 | if (bitmap == NULL) { 141 | NSLog(@"Failed context creation - image format is not supported by device. To force creation, try setting colorspace as CGColorSpaceCreateDeviceRGB() and/or bitmapinfo as kCGImageAlphaNone"); 142 | } else { 143 | 144 | // Rotate and/or flip the image if required by its orientation 145 | CGContextConcatCTM(bitmap, transform); 146 | 147 | // Set the quality level to use when rescaling 148 | CGContextSetInterpolationQuality(bitmap, quality); 149 | 150 | // Draw into the context; this scales the image 151 | CGContextDrawImage(bitmap, transpose ? transposedRect : newRect, imageRef); 152 | 153 | // Get the resized image from the context and a UIImage 154 | CGImageRef newImageRef = CGBitmapContextCreateImage(bitmap); 155 | UIImage *newImage = [UIImage imageWithCGImage:newImageRef scale:screenScale orientation:UIImageOrientationUp]; 156 | 157 | // Clean up 158 | CGContextRelease(bitmap); 159 | CGImageRelease(newImageRef); 160 | 161 | return newImage; 162 | } 163 | return nil; 164 | } 165 | 166 | // Returns an affine transform that takes into account the image orientation when drawing a scaled image 167 | - (CGAffineTransform)transformForOrientation:(CGSize)newSize { 168 | CGAffineTransform transform = CGAffineTransformIdentity; 169 | 170 | switch (self.imageOrientation) { 171 | case UIImageOrientationUp: 172 | case UIImageOrientationUpMirrored: 173 | break; 174 | case UIImageOrientationDown: // EXIF = 3 175 | case UIImageOrientationDownMirrored: // EXIF = 4 176 | transform = CGAffineTransformTranslate(transform, newSize.width, newSize.height); 177 | transform = CGAffineTransformRotate(transform, M_PI); 178 | break; 179 | 180 | case UIImageOrientationLeft: // EXIF = 6 181 | case UIImageOrientationLeftMirrored: // EXIF = 5 182 | transform = CGAffineTransformTranslate(transform, newSize.width, 0); 183 | transform = CGAffineTransformRotate(transform, M_PI_2); 184 | break; 185 | 186 | case UIImageOrientationRight: // EXIF = 8 187 | case UIImageOrientationRightMirrored: // EXIF = 7 188 | transform = CGAffineTransformTranslate(transform, 0, newSize.height); 189 | transform = CGAffineTransformRotate(transform, -M_PI_2); 190 | break; 191 | } 192 | 193 | switch (self.imageOrientation) { 194 | case UIImageOrientationUp: 195 | case UIImageOrientationLeft: 196 | case UIImageOrientationRight: 197 | case UIImageOrientationDown: 198 | break; 199 | 200 | case UIImageOrientationUpMirrored: // EXIF = 2 201 | case UIImageOrientationDownMirrored: // EXIF = 4 202 | transform = CGAffineTransformTranslate(transform, newSize.width, 0); 203 | transform = CGAffineTransformScale(transform, -1, 1); 204 | break; 205 | 206 | case UIImageOrientationLeftMirrored: // EXIF = 5 207 | case UIImageOrientationRightMirrored: // EXIF = 7 208 | transform = CGAffineTransformTranslate(transform, newSize.height, 0); 209 | transform = CGAffineTransformScale(transform, -1, 1); 210 | break; 211 | } 212 | 213 | return transform; 214 | } 215 | 216 | @end 217 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/EssentialImagerDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'EssentialImagerDemo' target in the 'EssentialImagerDemo' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iOS SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #import 15 | #import "EssentialImager.h" 16 | #endif 17 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/EssentialImagerFullDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | full demo 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.buuuk.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIPrerenderedIcon 28 | 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UIStatusBarHidden 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/EssentialImagerSimpleDemo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | simple demo 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.buuuk.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIPrerenderedIcon 28 | 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UIStatusBarHidden 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/Full Demo/EIFullDemoViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: EIDemoViewController.h 4 | Abstract: Demo Controller to show usage of image picker with blocks, 5 | and subsequent resizing, saving, clipping and masking of returned image 6 | 7 | Copyright (c) 2012 Dillion Tan 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | */ 31 | 32 | #import 33 | 34 | @interface EIFullDemoViewController : UIViewController 35 | 36 | @property (nonatomic, strong) UILabel *summaryLabel; 37 | @property (nonatomic, strong) UIButton *buttonWithImage; 38 | @property (nonatomic, strong) UIButton *buttonWithBackgroundImage; 39 | 40 | @property (nonatomic, strong) UIImageView *imageViewWithRoundedCorners; 41 | @property (nonatomic, strong) UIImageView *layerMaskedCircleImageView; 42 | @property (nonatomic, strong) UIImageView *imageMaskedRadialGradientImageView; 43 | 44 | @property (nonatomic, strong) EIImagePickerDelegate *imagePickerDelegate; 45 | 46 | - (void)presentPhotoPicker; 47 | - (void)setOriginalImage:(UIImage *)aImage resizedImage:(UIImage *)bImage; 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/Full Demo/EIFullDemoViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: EIDemoViewController.m 4 | Abstract: Demo Controller to show usage of image picker with blocks, 5 | and subsequent resizing, saving, clipping and masking of returned image 6 | 7 | Copyright (c) 2012 Dillion Tan 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | */ 31 | 32 | #import "EIFullDemoViewController.h" 33 | 34 | @interface EIFullDemoViewController () 35 | 36 | @end 37 | 38 | @implementation EIFullDemoViewController 39 | 40 | @synthesize summaryLabel; 41 | @synthesize buttonWithImage; 42 | @synthesize buttonWithBackgroundImage; 43 | @synthesize imageViewWithRoundedCorners; 44 | @synthesize layerMaskedCircleImageView; 45 | @synthesize imageMaskedRadialGradientImageView; 46 | @synthesize imagePickerDelegate; 47 | 48 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 49 | { 50 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 51 | if (self) { 52 | // Custom initialization 53 | } 54 | return self; 55 | } 56 | 57 | - (void)viewDidLoad 58 | { 59 | [super viewDidLoad]; 60 | // Do any additional setup after loading the view. 61 | 62 | // show how a button looks with returned image set as button image without resizing 63 | self.buttonWithImage = [[UIButton alloc] initWithFrame:CGRectMake(20, 10, 120, 120)]; 64 | buttonWithImage.layer.cornerRadius = 20.0f; 65 | buttonWithImage.layer.borderColor = [UIColor blueColor].CGColor; 66 | buttonWithImage.layer.borderWidth = 1.0f; 67 | [buttonWithImage setImage:[UIImage imageNamed:@"Icon.png"] forState:UIControlStateNormal]; 68 | [buttonWithImage addTarget:self action:@selector(presentPhotoPicker) forControlEvents:UIControlEventTouchUpInside]; 69 | [self.view addSubview:buttonWithImage]; 70 | 71 | // show how a button looks with returned image set as background button image without resizing 72 | self.buttonWithBackgroundImage = [[UIButton alloc] initWithFrame:CGRectMake(160, 10, 120, 120)]; 73 | buttonWithBackgroundImage.layer.cornerRadius = 20.0f; 74 | buttonWithBackgroundImage.layer.borderColor = [UIColor blueColor].CGColor; 75 | buttonWithBackgroundImage.layer.borderWidth = 1.0f; 76 | [buttonWithBackgroundImage setBackgroundImage:[UIImage imageNamed:@"Icon.png"] forState:UIControlStateNormal]; 77 | [buttonWithBackgroundImage addTarget:self action:@selector(presentPhotoPicker) forControlEvents:UIControlEventTouchUpInside]; 78 | [self.view addSubview:buttonWithBackgroundImage]; 79 | 80 | 81 | self.summaryLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 140, 280, 30)]; 82 | summaryLabel.font = [summaryLabel.font fontWithSize:11]; 83 | summaryLabel.numberOfLines = 0; 84 | summaryLabel.text = @"Select one of the 2 buttons above to add an image from the picker."; 85 | [self.view addSubview:summaryLabel]; 86 | 87 | 88 | // displaying the image in a rounded rect 89 | UIImageView *backingViewForRoundedCorner = [[UIImageView alloc] initWithFrame:CGRectMake(20, 180, 120, 120)]; 90 | backingViewForRoundedCorner.layer.cornerRadius = 20.0f; 91 | backingViewForRoundedCorner.clipsToBounds = YES; 92 | [self.view addSubview:backingViewForRoundedCorner]; 93 | 94 | self.imageViewWithRoundedCorners = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 120, 120)]; 95 | imageViewWithRoundedCorners.backgroundColor = [UIColor lightGrayColor]; 96 | [backingViewForRoundedCorner addSubview:imageViewWithRoundedCorners]; 97 | 98 | 99 | // displaying the image in a circle by using a shape layer 100 | // layer fill color controls the masking 101 | CAShapeLayer *maskLayer = [CAShapeLayer layer]; 102 | maskLayer.backgroundColor = [UIColor whiteColor].CGColor; 103 | UIBezierPath *layerPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(1, 1, 118, 118)]; 104 | maskLayer.path = layerPath.CGPath; 105 | maskLayer.fillColor = [UIColor blackColor].CGColor; 106 | 107 | // use another view for clipping so that when the image size changes, the masking layer does not need to be repositioned 108 | UIView *clippingViewForLayerMask = [[UIView alloc] initWithFrame:CGRectMake(160, 180, 120, 120)]; 109 | clippingViewForLayerMask.layer.mask = maskLayer; 110 | clippingViewForLayerMask.clipsToBounds = YES; 111 | [self.view addSubview:clippingViewForLayerMask]; 112 | 113 | self.layerMaskedCircleImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 120, 120)]; 114 | layerMaskedCircleImageView.backgroundColor = [UIColor lightGrayColor]; 115 | [clippingViewForLayerMask addSubview:layerMaskedCircleImageView]; 116 | 117 | 118 | // displaying the image in a radial gradient by using a png mask 119 | // image alpha channel controls the masking 120 | CALayer *imageMaskLayer = [CALayer layer]; 121 | UIImage *pattern = [UIImage imageNamed:@"pattern.png"]; 122 | imageMaskLayer.contents = (__bridge id)pattern.CGImage; 123 | imageMaskLayer.frame = CGRectMake(0, 0, pattern.size.width, pattern.size.height); 124 | 125 | // use another view for clipping so that when the image size changes, the masking layer does not need to be repositioned 126 | UIView *clippingViewForLayerImageMask = [[UIView alloc] initWithFrame:CGRectMake(20, 310, 120, 120)]; 127 | clippingViewForLayerImageMask.layer.mask = imageMaskLayer; 128 | clippingViewForLayerImageMask.clipsToBounds = YES; 129 | [self.view addSubview:clippingViewForLayerImageMask]; 130 | 131 | self.imageMaskedRadialGradientImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 120, 120)]; 132 | imageMaskedRadialGradientImageView.backgroundColor = [UIColor lightGrayColor]; 133 | [clippingViewForLayerImageMask addSubview:imageMaskedRadialGradientImageView]; 134 | 135 | if ([[NSUserDefaults standardUserDefaults] objectForKey:@"savedImage"]) { // test cached image 136 | NSString *urlString = [[NSUserDefaults standardUserDefaults] objectForKey:@"savedImage"]; 137 | 138 | UIImage *cachedImage = [NSData imageFromFile:[[[NSFileManager defaultManager] cacheDataPath] stringByAppendingPathComponent:urlString]]; 139 | 140 | if (cachedImage) { 141 | NSLog(@"logical size is %f:%f scale %f", cachedImage.size.width, cachedImage.size.height, cachedImage.scale); 142 | 143 | [self setOriginalImage:[UIImage imageNamed:@"Icon.png"] resizedImage:cachedImage]; 144 | } 145 | } 146 | 147 | } 148 | 149 | - (void)viewDidUnload 150 | { 151 | [super viewDidUnload]; 152 | // Release any retained subviews of the main view. 153 | } 154 | 155 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 156 | { 157 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 158 | } 159 | 160 | - (void)presentPhotoPicker 161 | { 162 | if (!imagePickerDelegate) { 163 | self.imagePickerDelegate = [[EIImagePickerDelegate alloc] init]; 164 | 165 | __weak EIFullDemoViewController *weakController = self; 166 | [imagePickerDelegate setImagePickerCompletionBlock:^(UIImage *pickerImage) { 167 | 168 | __strong EIFullDemoViewController *strongController = weakController; 169 | 170 | NSLog(@"logical size is %f:%f scale %f", pickerImage.size.width, pickerImage.size.height, pickerImage.scale); 171 | 172 | // Use display size to constrain resizing 173 | // 120 is the logical display size 174 | UIImage *resizedImage = [pickerImage resizedImageWithContentMode:UIViewContentModeScaleAspectFill bounds:CGSizeMake(120, 120) interpolationQuality:kCGInterpolationDefault]; 175 | 176 | // Use uncompressed size to constrain resizing 177 | // UIImage *resizedImage = [pickerImage resizedImageWithUncompressedSizeInMB:1.0 interpolationQuality:kCGInterpolationDefault]; 178 | 179 | NSLog(@"logical size is %f:%f scale %f", resizedImage.size.width, resizedImage.size.height, resizedImage.scale); 180 | 181 | [strongController setOriginalImage:pickerImage resizedImage:resizedImage]; 182 | 183 | // remove the image if previously saved 184 | if ([[NSUserDefaults standardUserDefaults] objectForKey:@"savedImage"]) { 185 | NSString *cachedFilePath = [[NSUserDefaults standardUserDefaults] objectForKey:@"savedImage"]; 186 | [[NSFileManager defaultManager] removeItemAtURL:[NSURL URLWithString:cachedFilePath] error:NULL]; 187 | } 188 | 189 | NSString *assetName = [NSString stringWithFormat:@"%@.png", [[NSProcessInfo processInfo] globallyUniqueString]]; 190 | assetName = [assetName stringByAppendingScaleSuffix]; // add scale suffix to extension 191 | NSString *assetPath = [[[NSFileManager defaultManager] cacheDataPath] stringByAppendingPathComponent:assetName]; 192 | 193 | // saving synchronously 194 | // [UIImagePNGRepresentation(resizedImage) writeToFile:assetPath atomically:NO]; 195 | // [[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithFormat:@"%@", assetName] forKey:@"savedImage"]; 196 | 197 | [[EIOperationManager defaultManager] saveImage:resizedImage toPath:assetPath withBlock:^(BOOL success) { 198 | [[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithFormat:@"%@", assetName] forKey:@"savedImage"]; 199 | }]; 200 | 201 | }]; 202 | } 203 | 204 | if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { 205 | UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Photo Library", @"Camera", nil]; 206 | [actionSheet showInView:self.view]; 207 | 208 | } else { 209 | UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Photo Library", nil]; 210 | [actionSheet showInView:self.view]; 211 | } 212 | } 213 | 214 | - (void)setOriginalImage:(UIImage *)aImage resizedImage:(UIImage *)bImage 215 | { 216 | [buttonWithImage setImage:aImage forState:UIControlStateNormal]; 217 | [buttonWithBackgroundImage setBackgroundImage:aImage forState:UIControlStateNormal]; 218 | 219 | imageViewWithRoundedCorners.image = bImage; 220 | imageViewWithRoundedCorners.frame = CGRectMake(0, 0, bImage.size.width, bImage.size.height); 221 | imageViewWithRoundedCorners.center = CGPointMake(imageViewWithRoundedCorners.superview.frame.size.width/2, imageViewWithRoundedCorners.superview.frame.size.height/2); 222 | 223 | layerMaskedCircleImageView.image = bImage; 224 | layerMaskedCircleImageView.frame = CGRectMake(0, 0, bImage.size.width, bImage.size.height); 225 | layerMaskedCircleImageView.center = CGPointMake(layerMaskedCircleImageView.superview.frame.size.width/2, layerMaskedCircleImageView.superview.frame.size.height/2); 226 | 227 | imageMaskedRadialGradientImageView.image = bImage; 228 | imageMaskedRadialGradientImageView.frame = CGRectMake(0, 0, bImage.size.width, bImage.size.height); 229 | imageMaskedRadialGradientImageView.center = CGPointMake(layerMaskedCircleImageView.superview.frame.size.width/2, layerMaskedCircleImageView.superview.frame.size.height/2); 230 | } 231 | 232 | # pragma mark - 233 | # pragma mark UIActionSheetDelegate 234 | 235 | - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { 236 | switch (buttonIndex) { 237 | case 0: 238 | [imagePickerDelegate presentFromController:self withSourceType:UIImagePickerControllerSourceTypePhotoLibrary]; 239 | break; 240 | case 1: 241 | if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { 242 | [imagePickerDelegate presentFromController:self withSourceType:UIImagePickerControllerSourceTypeCamera]; 243 | } 244 | break; 245 | default: 246 | break; 247 | } 248 | } 249 | 250 | @end 251 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/Full Demo/FullDemoAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // EssentialImager 4 | // 5 | // Created by Dillion Tan on 9/7/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "EIFullDemoViewController.h" 11 | 12 | @interface FullDemoAppDelegate : UIResponder 13 | 14 | @property (strong, nonatomic) UIWindow *window; 15 | @property (nonatomic, strong) EIFullDemoViewController *rootViewController; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/Full Demo/FullDemoAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // EssentialImager 4 | // 5 | // Created by Dillion Tan on 9/7/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "FullDemoAppDelegate.h" 10 | 11 | @implementation FullDemoAppDelegate 12 | 13 | @synthesize window = _window; 14 | @synthesize rootViewController; 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 17 | { 18 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 19 | // Override point for customization after application launch. 20 | self.window.backgroundColor = [UIColor whiteColor]; 21 | 22 | self.window.rootViewController = [[EIFullDemoViewController alloc] init]; 23 | [self.window makeKeyAndVisible]; 24 | 25 | return YES; 26 | } 27 | 28 | - (void)applicationWillResignActive:(UIApplication *)application 29 | { 30 | // 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. 31 | // 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. 32 | } 33 | 34 | - (void)applicationDidEnterBackground:(UIApplication *)application 35 | { 36 | // 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. 37 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 38 | } 39 | 40 | - (void)applicationWillEnterForeground:(UIApplication *)application 41 | { 42 | // 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. 43 | } 44 | 45 | - (void)applicationDidBecomeActive:(UIApplication *)application 46 | { 47 | // 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. 48 | } 49 | 50 | - (void)applicationWillTerminate:(UIApplication *)application 51 | { 52 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/Full Demo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // EssentialImagerDemo 4 | // 5 | // Created by Dillion Tan on 14/7/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "FullDemoAppDelegate.h" 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | @autoreleasepool { 15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([FullDemoAppDelegate class])); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dillion/EssentialImager/789bae62f758b70a3c5712b715a92c62b369c5a6/EssentialImagerDemo/EssentialImagerDemo/Icon.png -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/Icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dillion/EssentialImager/789bae62f758b70a3c5712b715a92c62b369c5a6/EssentialImagerDemo/EssentialImagerDemo/Icon@2x.png -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/Simple Demo/EISimpleDemoViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: EIDemoViewController.h 4 | Abstract: Demo Controller to show usage of image picker with blocks, 5 | and subsequent resizing, saving, clipping and masking of returned image 6 | 7 | Copyright (c) 2012 Dillion Tan 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | */ 31 | 32 | #import 33 | 34 | @interface EISimpleDemoViewController : UIViewController 35 | 36 | @property (nonatomic, strong) UIButton *buttonWithImage; 37 | @property (nonatomic, strong) UIImageView *imageViewWithRoundedCorners; 38 | 39 | @property (nonatomic, strong) EIImagePickerDelegate *imagePickerDelegate; 40 | 41 | - (void)presentPhotoPicker; 42 | - (void)setOriginalImage:(UIImage *)aImage resizedImage:(UIImage *)bImage; 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/Simple Demo/EISimpleDemoViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: EIDemoViewController.m 4 | Abstract: Demo Controller to show usage of image picker with blocks, 5 | and subsequent resizing, saving, clipping and masking of returned image 6 | 7 | Copyright (c) 2012 Dillion Tan 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | */ 31 | 32 | #import "EISimpleDemoViewController.h" 33 | 34 | @interface EISimpleDemoViewController () 35 | 36 | @end 37 | 38 | @implementation EISimpleDemoViewController 39 | 40 | @synthesize buttonWithImage; 41 | @synthesize imageViewWithRoundedCorners; 42 | @synthesize imagePickerDelegate; 43 | 44 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 45 | { 46 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 47 | if (self) { 48 | // Custom initialization 49 | } 50 | return self; 51 | } 52 | 53 | - (void)viewDidLoad 54 | { 55 | [super viewDidLoad]; 56 | // Do any additional setup after loading the view. 57 | 58 | // show how a button looks with returned image set as button image without resizing 59 | self.buttonWithImage = [[UIButton alloc] initWithFrame:CGRectMake(70, 40, 180, 180)]; 60 | buttonWithImage.layer.cornerRadius = 20.0f; 61 | buttonWithImage.layer.borderColor = [UIColor blueColor].CGColor; 62 | buttonWithImage.layer.borderWidth = 1.0f; 63 | [buttonWithImage setImage:[UIImage imageNamed:@"Icon.png"] forState:UIControlStateNormal]; 64 | [buttonWithImage addTarget:self action:@selector(presentPhotoPicker) forControlEvents:UIControlEventTouchUpInside]; 65 | [self.view addSubview:buttonWithImage]; 66 | 67 | // displaying the image in a rounded rect 68 | UIImageView *backingViewForRoundedCorner = [[UIImageView alloc] initWithFrame:CGRectMake(70, 260, 180, 180)]; 69 | backingViewForRoundedCorner.layer.cornerRadius = 20.0f; 70 | backingViewForRoundedCorner.clipsToBounds = YES; 71 | [self.view addSubview:backingViewForRoundedCorner]; 72 | 73 | self.imageViewWithRoundedCorners = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 180, 180)]; 74 | imageViewWithRoundedCorners.backgroundColor = [UIColor lightGrayColor]; 75 | [backingViewForRoundedCorner addSubview:imageViewWithRoundedCorners]; 76 | 77 | if ([[NSUserDefaults standardUserDefaults] objectForKey:@"savedImage"]) { // test cached image 78 | NSString *urlString = [[NSUserDefaults standardUserDefaults] objectForKey:@"savedImage"]; 79 | 80 | UIImage *cachedImage = [NSData imageFromFile:[[[NSFileManager defaultManager] cacheDataPath] stringByAppendingPathComponent:urlString]]; 81 | 82 | if (cachedImage) { 83 | NSLog(@"logical size is %f:%f scale %f", cachedImage.size.width, cachedImage.size.height, cachedImage.scale); 84 | 85 | [self setOriginalImage:[UIImage imageNamed:@"Icon.png"] resizedImage:cachedImage]; 86 | } 87 | } 88 | 89 | } 90 | 91 | - (void)viewDidUnload 92 | { 93 | [super viewDidUnload]; 94 | // Release any retained subviews of the main view. 95 | } 96 | 97 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 98 | { 99 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 100 | } 101 | 102 | - (void)presentPhotoPicker 103 | { 104 | if (!imagePickerDelegate) { 105 | self.imagePickerDelegate = [[EIImagePickerDelegate alloc] init]; 106 | 107 | __weak EISimpleDemoViewController *weakController = self; 108 | [imagePickerDelegate setImagePickerCompletionBlock:^(UIImage *pickerImage) { 109 | 110 | __strong EISimpleDemoViewController *strongController = weakController; 111 | 112 | NSLog(@"logical size is %f:%f scale %f", pickerImage.size.width, pickerImage.size.height, pickerImage.scale); 113 | 114 | // Use display size to constrain resizing 115 | // 120 is the logical display size 116 | UIImage *resizedImage = [pickerImage resizedImageWithContentMode:UIViewContentModeScaleAspectFill bounds:CGSizeMake(180, 180) interpolationQuality:kCGInterpolationDefault]; 117 | 118 | // Use uncompressed size to constrain resizing 119 | // UIImage *resizedImage = [pickerImage resizedImageWithUncompressedSizeInMB:1.0 interpolationQuality:kCGInterpolationDefault]; 120 | 121 | NSLog(@"logical size is %f:%f scale %f", resizedImage.size.width, resizedImage.size.height, resizedImage.scale); 122 | 123 | [strongController setOriginalImage:pickerImage resizedImage:resizedImage]; 124 | 125 | // remove the image if previously saved 126 | if ([[NSUserDefaults standardUserDefaults] objectForKey:@"savedImage"]) { 127 | NSString *cachedFilePath = [[NSUserDefaults standardUserDefaults] objectForKey:@"savedImage"]; 128 | [[NSFileManager defaultManager] removeItemAtURL:[NSURL URLWithString:cachedFilePath] error:NULL]; 129 | } 130 | 131 | NSString *assetName = [NSString stringWithFormat:@"%@.png", [[NSProcessInfo processInfo] globallyUniqueString]]; 132 | assetName = [assetName stringByAppendingScaleSuffix]; // add scale suffix to extension 133 | NSString *assetPath = [[[NSFileManager defaultManager] cacheDataPath] stringByAppendingPathComponent:assetName]; 134 | 135 | // saving synchronously 136 | // [UIImagePNGRepresentation(resizedImage) writeToFile:assetPath atomically:NO]; 137 | // [[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithFormat:@"%@", assetName] forKey:@"savedImage"]; 138 | 139 | [[EIOperationManager defaultManager] saveImage:resizedImage toPath:assetPath withBlock:^(BOOL success) { 140 | [[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithFormat:@"%@", assetName] forKey:@"savedImage"]; 141 | }]; 142 | 143 | }]; 144 | } 145 | 146 | if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { 147 | UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Photo Library", @"Camera", nil]; 148 | [actionSheet showInView:self.view]; 149 | 150 | } else { 151 | UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Photo Library", nil]; 152 | [actionSheet showInView:self.view]; 153 | } 154 | } 155 | 156 | - (void)setOriginalImage:(UIImage *)aImage resizedImage:(UIImage *)bImage 157 | { 158 | [buttonWithImage setImage:aImage forState:UIControlStateNormal]; 159 | 160 | imageViewWithRoundedCorners.image = bImage; 161 | imageViewWithRoundedCorners.frame = CGRectMake(0, 0, bImage.size.width, bImage.size.height); 162 | imageViewWithRoundedCorners.center = CGPointMake(imageViewWithRoundedCorners.superview.frame.size.width/2, imageViewWithRoundedCorners.superview.frame.size.height/2); 163 | } 164 | 165 | # pragma mark - 166 | # pragma mark UIActionSheetDelegate 167 | 168 | - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { 169 | switch (buttonIndex) { 170 | case 0: 171 | [imagePickerDelegate presentFromController:self withSourceType:UIImagePickerControllerSourceTypePhotoLibrary]; 172 | break; 173 | case 1: 174 | if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { 175 | [imagePickerDelegate presentFromController:self withSourceType:UIImagePickerControllerSourceTypeCamera]; 176 | } 177 | break; 178 | default: 179 | break; 180 | } 181 | } 182 | 183 | @end 184 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/Simple Demo/SimpleDemoAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // EssentialImager 4 | // 5 | // Created by Dillion Tan on 9/7/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "EISimpleDemoViewController.h" 11 | 12 | @interface SimpleDemoAppDelegate : UIResponder 13 | 14 | @property (strong, nonatomic) UIWindow *window; 15 | @property (nonatomic, strong) EISimpleDemoViewController *rootViewController; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/Simple Demo/SimpleDemoAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // EssentialImager 4 | // 5 | // Created by Dillion Tan on 9/7/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "SimpleDemoAppDelegate.h" 10 | 11 | @implementation SimpleDemoAppDelegate 12 | 13 | @synthesize window = _window; 14 | @synthesize rootViewController; 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 17 | { 18 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 19 | // Override point for customization after application launch. 20 | self.window.backgroundColor = [UIColor whiteColor]; 21 | 22 | self.window.rootViewController = [[EISimpleDemoViewController alloc] init]; 23 | [self.window makeKeyAndVisible]; 24 | 25 | return YES; 26 | } 27 | 28 | - (void)applicationWillResignActive:(UIApplication *)application 29 | { 30 | // 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. 31 | // 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. 32 | } 33 | 34 | - (void)applicationDidEnterBackground:(UIApplication *)application 35 | { 36 | // 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. 37 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 38 | } 39 | 40 | - (void)applicationWillEnterForeground:(UIApplication *)application 41 | { 42 | // 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. 43 | } 44 | 45 | - (void)applicationDidBecomeActive:(UIApplication *)application 46 | { 47 | // 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. 48 | } 49 | 50 | - (void)applicationWillTerminate:(UIApplication *)application 51 | { 52 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/Simple Demo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // EssentialImagerDemo 4 | // 5 | // Created by Dillion Tan on 14/7/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SimpleDemoAppDelegate.h" 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | @autoreleasepool { 15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([SimpleDemoAppDelegate class])); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /EssentialImagerDemo/EssentialImagerDemo/pattern.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dillion/EssentialImager/789bae62f758b70a3c5712b715a92c62b369c5a6/EssentialImagerDemo/EssentialImagerDemo/pattern.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ##Essential Imager 2 | 3 | ###Summary 4 | A painless solution for 5 | 6 | - Block based UIImagePickerController delegate in ARC 7 | - Resizing images, taking into account orientation and scale 8 | - Caching images (sync or async) with a scale suffix 9 | - Retrieving images from cache, taking into account scale 10 | - Clipping or masking images to a desired frame and centering 11 | 12 | 13 | 14 | -- 15 | 16 | ###Usage 17 | 18 | Requires iOS5 19 | Copy the EssentialImager folder 20 | Set -fno-objc-arc compiler flag on EDStorageManager and EDStorageOperation 21 | Import EssentialImager.h 22 | 23 | Start using! 24 | Take a look at the demo project for examples 25 | 26 | -- 27 | 28 | ###Credits 29 | [Trevor Harmon](http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-way/) for image resizing operations 30 | [Nick Lockwood](https://github.com/nicklockwood/StandardPaths) for file paths 31 | [Andrew Sliwinski](https://github.com/thisandagain/storage) for async file storage 32 | 33 | Camera icon by Stanislav Levin, from The Noun Project (Attribution ( CC BY 3.0 )) 34 | 35 | -- 36 | 37 | http://twitter.com/dilliontan -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dillion/EssentialImager/789bae62f758b70a3c5712b715a92c62b369c5a6/screenshot.png --------------------------------------------------------------------------------