├── .gitignore ├── README.md ├── Transparency Trim Demo ├── Transparency Trim Demo.xcodeproj │ └── project.pbxproj └── Transparency Trim Demo │ ├── Default-568h@2x.png │ ├── Default.png │ ├── Default@2x.png │ ├── ELCAppDelegate.h │ ├── ELCAppDelegate.m │ ├── ELCViewController.h │ ├── ELCViewController.m │ ├── Transparency Trim Demo-Info.plist │ ├── Transparency Trim Demo-Prefix.pch │ ├── UIImage+Trim.h │ ├── UIImage+Trim.m │ ├── demo_image.png │ ├── demo_image@2x.png │ ├── en.lproj │ ├── ELCViewController.xib │ └── InfoPlist.strings │ └── main.m ├── UIImage+Trim.h └── UIImage+Trim.m /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | build/* 3 | *.pbxuser 4 | !default.pbxuser 5 | *.mode1v3 6 | !default.mode1v3 7 | *.mode2v3 8 | !default.mode2v3 9 | *.perspectivev3 10 | !default.perspectivev3 11 | *.xcworkspace 12 | !default.xcworkspace 13 | xcuserdata 14 | profile 15 | *.moved-aside 16 | *.DS_Store 17 | Build/* 18 | DerivedData/* 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | UIImage-Trim 2 | ============ 3 | 4 | Category for trimming transparent pixels of an UIImage object. 5 | 6 | How to use 7 | ---------- 8 | Add the `UIImage+Trim` files to your project. Include `UIImage+Trim.h` in the files where you want to trim your images. 9 | 10 | Trimming is pretty straightforward: 11 | 12 | `[yourImage imageByTrimmingTransparentPixels];` 13 | 14 | Optionally, you may want to consider any non-opaque pixels as being transparent (for instance, cropping out a light drop shadow). This can be achieved by using the alternate method: 15 | 16 | `[yourImage imageByTrimmingTransparentPixelsRequiringFullOpacity:YES];` 17 | 18 | Additionally, if you merely desire to know the `UIEdgeInsets` of the transparency around the image, you may want to use the following: 19 | 20 | `[yourImage transparencyInsetsRequiringFullOpacity:YES];` 21 | 22 | This call works based on the same principles as the "advanced" trim method, with the boolean dictating whether non-opaque pixels should be considered transparent. -------------------------------------------------------------------------------- /Transparency Trim Demo/Transparency Trim Demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6B06371A177B30C400B55AC5 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6B063719177B30C400B55AC5 /* UIKit.framework */; }; 11 | 6B06371C177B30C400B55AC5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6B06371B177B30C400B55AC5 /* Foundation.framework */; }; 12 | 6B06371E177B30C400B55AC5 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6B06371D177B30C400B55AC5 /* CoreGraphics.framework */; }; 13 | 6B063724177B30C400B55AC5 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6B063722177B30C400B55AC5 /* InfoPlist.strings */; }; 14 | 6B063726177B30C400B55AC5 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B063725177B30C400B55AC5 /* main.m */; }; 15 | 6B06372A177B30C400B55AC5 /* ELCAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B063729177B30C400B55AC5 /* ELCAppDelegate.m */; }; 16 | 6B06372C177B30C400B55AC5 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 6B06372B177B30C400B55AC5 /* Default.png */; }; 17 | 6B06372E177B30C400B55AC5 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6B06372D177B30C400B55AC5 /* Default@2x.png */; }; 18 | 6B063730177B30C400B55AC5 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6B06372F177B30C400B55AC5 /* Default-568h@2x.png */; }; 19 | 6B063733177B30C400B55AC5 /* ELCViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B063732177B30C400B55AC5 /* ELCViewController.m */; }; 20 | 6B063736177B30C400B55AC5 /* ELCViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6B063734177B30C400B55AC5 /* ELCViewController.xib */; }; 21 | 6B06373E177B30D900B55AC5 /* UIImage+Trim.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B06373D177B30D900B55AC5 /* UIImage+Trim.m */; }; 22 | 6B063741177B33B900B55AC5 /* demo_image.png in Resources */ = {isa = PBXBuildFile; fileRef = 6B06373F177B33B900B55AC5 /* demo_image.png */; }; 23 | 6B063742177B33B900B55AC5 /* demo_image@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6B063740177B33B900B55AC5 /* demo_image@2x.png */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 6B063716177B30C400B55AC5 /* Transparency Trim Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Transparency Trim Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | 6B063719177B30C400B55AC5 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 29 | 6B06371B177B30C400B55AC5 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 30 | 6B06371D177B30C400B55AC5 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 31 | 6B063721177B30C400B55AC5 /* Transparency Trim Demo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Transparency Trim Demo-Info.plist"; sourceTree = ""; }; 32 | 6B063723177B30C400B55AC5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 33 | 6B063725177B30C400B55AC5 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 34 | 6B063727177B30C400B55AC5 /* Transparency Trim Demo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Transparency Trim Demo-Prefix.pch"; sourceTree = ""; }; 35 | 6B063728177B30C400B55AC5 /* ELCAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ELCAppDelegate.h; sourceTree = ""; }; 36 | 6B063729177B30C400B55AC5 /* ELCAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ELCAppDelegate.m; sourceTree = ""; }; 37 | 6B06372B177B30C400B55AC5 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 38 | 6B06372D177B30C400B55AC5 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 39 | 6B06372F177B30C400B55AC5 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 40 | 6B063731177B30C400B55AC5 /* ELCViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ELCViewController.h; sourceTree = ""; }; 41 | 6B063732177B30C400B55AC5 /* ELCViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ELCViewController.m; sourceTree = ""; }; 42 | 6B063735177B30C400B55AC5 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ELCViewController.xib; sourceTree = ""; }; 43 | 6B06373C177B30D900B55AC5 /* UIImage+Trim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+Trim.h"; sourceTree = ""; }; 44 | 6B06373D177B30D900B55AC5 /* UIImage+Trim.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+Trim.m"; sourceTree = ""; }; 45 | 6B06373F177B33B900B55AC5 /* demo_image.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = demo_image.png; sourceTree = ""; }; 46 | 6B063740177B33B900B55AC5 /* demo_image@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "demo_image@2x.png"; sourceTree = ""; }; 47 | /* End PBXFileReference section */ 48 | 49 | /* Begin PBXFrameworksBuildPhase section */ 50 | 6B063713177B30C400B55AC5 /* Frameworks */ = { 51 | isa = PBXFrameworksBuildPhase; 52 | buildActionMask = 2147483647; 53 | files = ( 54 | 6B06371A177B30C400B55AC5 /* UIKit.framework in Frameworks */, 55 | 6B06371C177B30C400B55AC5 /* Foundation.framework in Frameworks */, 56 | 6B06371E177B30C400B55AC5 /* CoreGraphics.framework in Frameworks */, 57 | ); 58 | runOnlyForDeploymentPostprocessing = 0; 59 | }; 60 | /* End PBXFrameworksBuildPhase section */ 61 | 62 | /* Begin PBXGroup section */ 63 | 6B06370D177B30C400B55AC5 = { 64 | isa = PBXGroup; 65 | children = ( 66 | 6B06371F177B30C400B55AC5 /* Transparency Trim Demo */, 67 | 6B063718177B30C400B55AC5 /* Frameworks */, 68 | 6B063717177B30C400B55AC5 /* Products */, 69 | ); 70 | sourceTree = ""; 71 | }; 72 | 6B063717177B30C400B55AC5 /* Products */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | 6B063716177B30C400B55AC5 /* Transparency Trim Demo.app */, 76 | ); 77 | name = Products; 78 | sourceTree = ""; 79 | }; 80 | 6B063718177B30C400B55AC5 /* Frameworks */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 6B063719177B30C400B55AC5 /* UIKit.framework */, 84 | 6B06371B177B30C400B55AC5 /* Foundation.framework */, 85 | 6B06371D177B30C400B55AC5 /* CoreGraphics.framework */, 86 | ); 87 | name = Frameworks; 88 | sourceTree = ""; 89 | }; 90 | 6B06371F177B30C400B55AC5 /* Transparency Trim Demo */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 6B06373C177B30D900B55AC5 /* UIImage+Trim.h */, 94 | 6B06373D177B30D900B55AC5 /* UIImage+Trim.m */, 95 | 6B063728177B30C400B55AC5 /* ELCAppDelegate.h */, 96 | 6B063729177B30C400B55AC5 /* ELCAppDelegate.m */, 97 | 6B063731177B30C400B55AC5 /* ELCViewController.h */, 98 | 6B063732177B30C400B55AC5 /* ELCViewController.m */, 99 | 6B063734177B30C400B55AC5 /* ELCViewController.xib */, 100 | 6B063720177B30C400B55AC5 /* Supporting Files */, 101 | ); 102 | path = "Transparency Trim Demo"; 103 | sourceTree = ""; 104 | }; 105 | 6B063720177B30C400B55AC5 /* Supporting Files */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | 6B06373F177B33B900B55AC5 /* demo_image.png */, 109 | 6B063740177B33B900B55AC5 /* demo_image@2x.png */, 110 | 6B063721177B30C400B55AC5 /* Transparency Trim Demo-Info.plist */, 111 | 6B063722177B30C400B55AC5 /* InfoPlist.strings */, 112 | 6B063725177B30C400B55AC5 /* main.m */, 113 | 6B063727177B30C400B55AC5 /* Transparency Trim Demo-Prefix.pch */, 114 | 6B06372B177B30C400B55AC5 /* Default.png */, 115 | 6B06372D177B30C400B55AC5 /* Default@2x.png */, 116 | 6B06372F177B30C400B55AC5 /* Default-568h@2x.png */, 117 | ); 118 | name = "Supporting Files"; 119 | sourceTree = ""; 120 | }; 121 | /* End PBXGroup section */ 122 | 123 | /* Begin PBXNativeTarget section */ 124 | 6B063715177B30C400B55AC5 /* Transparency Trim Demo */ = { 125 | isa = PBXNativeTarget; 126 | buildConfigurationList = 6B063739177B30C400B55AC5 /* Build configuration list for PBXNativeTarget "Transparency Trim Demo" */; 127 | buildPhases = ( 128 | 6B063712177B30C400B55AC5 /* Sources */, 129 | 6B063713177B30C400B55AC5 /* Frameworks */, 130 | 6B063714177B30C400B55AC5 /* Resources */, 131 | ); 132 | buildRules = ( 133 | ); 134 | dependencies = ( 135 | ); 136 | name = "Transparency Trim Demo"; 137 | productName = "Transparency Trim Demo"; 138 | productReference = 6B063716177B30C400B55AC5 /* Transparency Trim Demo.app */; 139 | productType = "com.apple.product-type.application"; 140 | }; 141 | /* End PBXNativeTarget section */ 142 | 143 | /* Begin PBXProject section */ 144 | 6B06370E177B30C400B55AC5 /* Project object */ = { 145 | isa = PBXProject; 146 | attributes = { 147 | CLASSPREFIX = ELC; 148 | LastUpgradeCheck = 0460; 149 | ORGANIZATIONNAME = "Chris Stroud"; 150 | }; 151 | buildConfigurationList = 6B063711177B30C400B55AC5 /* Build configuration list for PBXProject "Transparency Trim Demo" */; 152 | compatibilityVersion = "Xcode 3.2"; 153 | developmentRegion = English; 154 | hasScannedForEncodings = 0; 155 | knownRegions = ( 156 | en, 157 | ); 158 | mainGroup = 6B06370D177B30C400B55AC5; 159 | productRefGroup = 6B063717177B30C400B55AC5 /* Products */; 160 | projectDirPath = ""; 161 | projectRoot = ""; 162 | targets = ( 163 | 6B063715177B30C400B55AC5 /* Transparency Trim Demo */, 164 | ); 165 | }; 166 | /* End PBXProject section */ 167 | 168 | /* Begin PBXResourcesBuildPhase section */ 169 | 6B063714177B30C400B55AC5 /* Resources */ = { 170 | isa = PBXResourcesBuildPhase; 171 | buildActionMask = 2147483647; 172 | files = ( 173 | 6B063724177B30C400B55AC5 /* InfoPlist.strings in Resources */, 174 | 6B06372C177B30C400B55AC5 /* Default.png in Resources */, 175 | 6B06372E177B30C400B55AC5 /* Default@2x.png in Resources */, 176 | 6B063730177B30C400B55AC5 /* Default-568h@2x.png in Resources */, 177 | 6B063736177B30C400B55AC5 /* ELCViewController.xib in Resources */, 178 | 6B063741177B33B900B55AC5 /* demo_image.png in Resources */, 179 | 6B063742177B33B900B55AC5 /* demo_image@2x.png in Resources */, 180 | ); 181 | runOnlyForDeploymentPostprocessing = 0; 182 | }; 183 | /* End PBXResourcesBuildPhase section */ 184 | 185 | /* Begin PBXSourcesBuildPhase section */ 186 | 6B063712177B30C400B55AC5 /* Sources */ = { 187 | isa = PBXSourcesBuildPhase; 188 | buildActionMask = 2147483647; 189 | files = ( 190 | 6B063726177B30C400B55AC5 /* main.m in Sources */, 191 | 6B06372A177B30C400B55AC5 /* ELCAppDelegate.m in Sources */, 192 | 6B063733177B30C400B55AC5 /* ELCViewController.m in Sources */, 193 | 6B06373E177B30D900B55AC5 /* UIImage+Trim.m in Sources */, 194 | ); 195 | runOnlyForDeploymentPostprocessing = 0; 196 | }; 197 | /* End PBXSourcesBuildPhase section */ 198 | 199 | /* Begin PBXVariantGroup section */ 200 | 6B063722177B30C400B55AC5 /* InfoPlist.strings */ = { 201 | isa = PBXVariantGroup; 202 | children = ( 203 | 6B063723177B30C400B55AC5 /* en */, 204 | ); 205 | name = InfoPlist.strings; 206 | sourceTree = ""; 207 | }; 208 | 6B063734177B30C400B55AC5 /* ELCViewController.xib */ = { 209 | isa = PBXVariantGroup; 210 | children = ( 211 | 6B063735177B30C400B55AC5 /* en */, 212 | ); 213 | name = ELCViewController.xib; 214 | sourceTree = ""; 215 | }; 216 | /* End PBXVariantGroup section */ 217 | 218 | /* Begin XCBuildConfiguration section */ 219 | 6B063737177B30C400B55AC5 /* Debug */ = { 220 | isa = XCBuildConfiguration; 221 | buildSettings = { 222 | ALWAYS_SEARCH_USER_PATHS = NO; 223 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 224 | CLANG_CXX_LIBRARY = "libc++"; 225 | CLANG_ENABLE_OBJC_ARC = YES; 226 | CLANG_WARN_CONSTANT_CONVERSION = YES; 227 | CLANG_WARN_EMPTY_BODY = YES; 228 | CLANG_WARN_ENUM_CONVERSION = YES; 229 | CLANG_WARN_INT_CONVERSION = YES; 230 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 231 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 232 | COPY_PHASE_STRIP = NO; 233 | GCC_C_LANGUAGE_STANDARD = gnu99; 234 | GCC_DYNAMIC_NO_PIC = NO; 235 | GCC_OPTIMIZATION_LEVEL = 0; 236 | GCC_PREPROCESSOR_DEFINITIONS = ( 237 | "DEBUG=1", 238 | "$(inherited)", 239 | ); 240 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 241 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 242 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 243 | GCC_WARN_UNUSED_VARIABLE = YES; 244 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 245 | ONLY_ACTIVE_ARCH = YES; 246 | SDKROOT = iphoneos; 247 | }; 248 | name = Debug; 249 | }; 250 | 6B063738177B30C400B55AC5 /* Release */ = { 251 | isa = XCBuildConfiguration; 252 | buildSettings = { 253 | ALWAYS_SEARCH_USER_PATHS = NO; 254 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 255 | CLANG_CXX_LIBRARY = "libc++"; 256 | CLANG_ENABLE_OBJC_ARC = YES; 257 | CLANG_WARN_CONSTANT_CONVERSION = YES; 258 | CLANG_WARN_EMPTY_BODY = YES; 259 | CLANG_WARN_ENUM_CONVERSION = YES; 260 | CLANG_WARN_INT_CONVERSION = YES; 261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 262 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 263 | COPY_PHASE_STRIP = YES; 264 | GCC_C_LANGUAGE_STANDARD = gnu99; 265 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 266 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 267 | GCC_WARN_UNUSED_VARIABLE = YES; 268 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 269 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 270 | SDKROOT = iphoneos; 271 | VALIDATE_PRODUCT = YES; 272 | }; 273 | name = Release; 274 | }; 275 | 6B06373A177B30C400B55AC5 /* Debug */ = { 276 | isa = XCBuildConfiguration; 277 | buildSettings = { 278 | CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; 279 | CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; 280 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 281 | GCC_PREFIX_HEADER = "Transparency Trim Demo/Transparency Trim Demo-Prefix.pch"; 282 | GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; 283 | GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; 284 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 285 | GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; 286 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES; 287 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 288 | GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; 289 | GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; 290 | GCC_WARN_SHADOW = YES; 291 | GCC_WARN_SIGN_COMPARE = YES; 292 | GCC_WARN_UNKNOWN_PRAGMAS = YES; 293 | GCC_WARN_UNUSED_FUNCTION = YES; 294 | GCC_WARN_UNUSED_LABEL = YES; 295 | GCC_WARN_UNUSED_PARAMETER = NO; 296 | INFOPLIST_FILE = "Transparency Trim Demo/Transparency Trim Demo-Info.plist"; 297 | PRODUCT_NAME = "$(TARGET_NAME)"; 298 | WRAPPER_EXTENSION = app; 299 | }; 300 | name = Debug; 301 | }; 302 | 6B06373B177B30C400B55AC5 /* Release */ = { 303 | isa = XCBuildConfiguration; 304 | buildSettings = { 305 | CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES; 306 | CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; 307 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 308 | GCC_PREFIX_HEADER = "Transparency Trim Demo/Transparency Trim Demo-Prefix.pch"; 309 | GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; 310 | GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; 311 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 312 | GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; 313 | GCC_WARN_ABOUT_MISSING_NEWLINE = YES; 314 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 315 | GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; 316 | GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; 317 | GCC_WARN_SHADOW = YES; 318 | GCC_WARN_SIGN_COMPARE = YES; 319 | GCC_WARN_UNKNOWN_PRAGMAS = YES; 320 | GCC_WARN_UNUSED_FUNCTION = YES; 321 | GCC_WARN_UNUSED_LABEL = YES; 322 | GCC_WARN_UNUSED_PARAMETER = NO; 323 | INFOPLIST_FILE = "Transparency Trim Demo/Transparency Trim Demo-Info.plist"; 324 | PRODUCT_NAME = "$(TARGET_NAME)"; 325 | WRAPPER_EXTENSION = app; 326 | }; 327 | name = Release; 328 | }; 329 | /* End XCBuildConfiguration section */ 330 | 331 | /* Begin XCConfigurationList section */ 332 | 6B063711177B30C400B55AC5 /* Build configuration list for PBXProject "Transparency Trim Demo" */ = { 333 | isa = XCConfigurationList; 334 | buildConfigurations = ( 335 | 6B063737177B30C400B55AC5 /* Debug */, 336 | 6B063738177B30C400B55AC5 /* Release */, 337 | ); 338 | defaultConfigurationIsVisible = 0; 339 | defaultConfigurationName = Release; 340 | }; 341 | 6B063739177B30C400B55AC5 /* Build configuration list for PBXNativeTarget "Transparency Trim Demo" */ = { 342 | isa = XCConfigurationList; 343 | buildConfigurations = ( 344 | 6B06373A177B30C400B55AC5 /* Debug */, 345 | 6B06373B177B30C400B55AC5 /* Release */, 346 | ); 347 | defaultConfigurationIsVisible = 0; 348 | }; 349 | /* End XCConfigurationList section */ 350 | }; 351 | rootObject = 6B06370E177B30C400B55AC5 /* Project object */; 352 | } 353 | -------------------------------------------------------------------------------- /Transparency Trim Demo/Transparency Trim Demo/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wrep/UIImage-Trim/6856b68a9018a32711b8bf956d04d294e283bc8a/Transparency Trim Demo/Transparency Trim Demo/Default-568h@2x.png -------------------------------------------------------------------------------- /Transparency Trim Demo/Transparency Trim Demo/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wrep/UIImage-Trim/6856b68a9018a32711b8bf956d04d294e283bc8a/Transparency Trim Demo/Transparency Trim Demo/Default.png -------------------------------------------------------------------------------- /Transparency Trim Demo/Transparency Trim Demo/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wrep/UIImage-Trim/6856b68a9018a32711b8bf956d04d294e283bc8a/Transparency Trim Demo/Transparency Trim Demo/Default@2x.png -------------------------------------------------------------------------------- /Transparency Trim Demo/Transparency Trim Demo/ELCAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // ELCAppDelegate.h 3 | // Transparency Trim Demo 4 | // 5 | // Created by Chris Stroud on 6/26/13. 6 | // Copyright (c) 2013 Chris Stroud. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class ELCViewController; 12 | 13 | @interface ELCAppDelegate : UIResponder 14 | 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | @property (strong, nonatomic) ELCViewController *viewController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Transparency Trim Demo/Transparency Trim Demo/ELCAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // ELCAppDelegate.m 3 | // Transparency Trim Demo 4 | // 5 | // Created by Chris Stroud on 6/26/13. 6 | // Copyright (c) 2013 Chris Stroud. All rights reserved. 7 | // 8 | 9 | #import "ELCAppDelegate.h" 10 | 11 | #import "ELCViewController.h" 12 | 13 | @implementation ELCAppDelegate 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 16 | { 17 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 18 | // Override point for customization after application launch. 19 | self.viewController = [[ELCViewController alloc] initWithNibName:@"ELCViewController" bundle:nil]; 20 | self.window.rootViewController = self.viewController; 21 | [self.window makeKeyAndVisible]; 22 | 23 | return YES; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Transparency Trim Demo/Transparency Trim Demo/ELCViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ELCViewController.h 3 | // Transparency Trim Demo 4 | // 5 | // Created by Chris Stroud on 6/26/13. 6 | // Copyright (c) 2013 Chris Stroud. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ELCViewController : UIViewController 12 | 13 | @property (weak, nonatomic) IBOutlet UIImageView *semiTransparentImageView; 14 | @property (weak, nonatomic) IBOutlet UIImageView *originalImageView; 15 | @property (weak, nonatomic) IBOutlet UIImageView *fullyOpaqueImageView; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Transparency Trim Demo/Transparency Trim Demo/ELCViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ELCViewController.m 3 | // Transparency Trim Demo 4 | // 5 | // Created by Chris Stroud on 6/26/13. 6 | // Copyright (c) 2013 Chris Stroud. All rights reserved. 7 | // 8 | 9 | #import "ELCViewController.h" 10 | #import "UIImage+Trim.h" 11 | 12 | @implementation ELCViewController 13 | 14 | - (void)viewDidLoad 15 | { 16 | [super viewDidLoad]; 17 | 18 | UIImage *originalImage = [UIImage imageNamed:@"demo_image"]; 19 | UIImage *semiTransparentCrop = [originalImage imageByTrimmingTransparentPixelsRequiringFullOpacity:NO]; 20 | UIImage *fullOpacityCrop = [originalImage imageByTrimmingTransparentPixelsRequiringFullOpacity:YES]; 21 | 22 | [self.originalImageView setImage:originalImage]; 23 | [self.semiTransparentImageView setImage:semiTransparentCrop]; 24 | [self.fullyOpaqueImageView setImage:fullOpacityCrop]; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Transparency Trim Demo/Transparency Trim Demo/Transparency Trim Demo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.elevecreations..${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Transparency Trim Demo/Transparency Trim Demo/Transparency Trim Demo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Transparency Trim Demo' target in the 'Transparency Trim Demo' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /Transparency Trim Demo/Transparency Trim Demo/UIImage+Trim.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Trim.h 3 | // 4 | // Created by Rick Pastoor on 26-09-12. 5 | // Based on gist:3549921 ( https://gist.github.com/3549921/8abea8ac9e2450f6a38540de9724d3bf850a62df ) 6 | // 7 | // Copyright (c) 2012 Wrep - http://www.wrep.nl/ 8 | // 9 | 10 | #import 11 | 12 | @interface UIImage (Trim) 13 | 14 | - (UIEdgeInsets)transparencyInsetsRequiringFullOpacity:(BOOL)fullyOpaque; 15 | - (UIImage *)imageByTrimmingTransparentPixels; 16 | - (UIImage *)imageByTrimmingTransparentPixelsRequiringFullOpacity:(BOOL)fullyOpaque; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Transparency Trim Demo/Transparency Trim Demo/UIImage+Trim.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Trim.m 3 | // 4 | // Created by Rick Pastoor on 26-09-12. 5 | // Based on gist:3549921 ( https://gist.github.com/3549921/8abea8ac9e2450f6a38540de9724d3bf850a62df ) 6 | // 7 | // Copyright (c) 2012 Wrep - http://www.wrep.nl/ 8 | // 9 | 10 | #import "UIImage+Trim.h" 11 | 12 | @implementation UIImage (Trim) 13 | 14 | /* 15 | * Calculates the insets of transparency around all sides of the image 16 | * 17 | * @param fullyOpaque 18 | * Whether the algorithm should consider pixels with an alpha value of something other than 255 as being transparent. Otherwise a non-zero value would be considered opaque. 19 | */ 20 | - (UIEdgeInsets)transparencyInsetsRequiringFullOpacity:(BOOL)fullyOpaque 21 | { 22 | // Draw our image on that context 23 | NSInteger width = (NSInteger)CGImageGetWidth([self CGImage]); 24 | NSInteger height = (NSInteger)CGImageGetHeight([self CGImage]); 25 | NSInteger bytesPerRow = width * (NSInteger)sizeof(uint8_t); 26 | 27 | // Allocate array to hold alpha channel 28 | uint8_t * bitmapData = calloc((size_t)(width * height), sizeof(uint8_t)); 29 | 30 | // Create alpha-only bitmap context 31 | CGContextRef contextRef = CGBitmapContextCreate(bitmapData, (NSUInteger)width, (NSUInteger)height, 8, (NSUInteger)bytesPerRow, NULL, kCGImageAlphaOnly); 32 | 33 | CGImageRef cgImage = self.CGImage; 34 | CGRect rect = CGRectMake(0, 0, width, height); 35 | CGContextDrawImage(contextRef, rect, cgImage); 36 | 37 | // Sum all non-transparent pixels in every row and every column 38 | uint16_t * rowSum = calloc((size_t)height, sizeof(uint16_t)); 39 | uint16_t * colSum = calloc((size_t)width, sizeof(uint16_t)); 40 | 41 | // Enumerate through all pixels 42 | for (NSInteger row = 0; row < height; row++) { 43 | 44 | for (NSInteger col = 0; col < width; col++) { 45 | 46 | if (fullyOpaque) { 47 | 48 | // Found non-transparent pixel 49 | if (bitmapData[row*bytesPerRow + col] == UINT8_MAX) { 50 | 51 | rowSum[row]++; 52 | colSum[col]++; 53 | 54 | } 55 | 56 | } else { 57 | 58 | // Found non-transparent pixel 59 | if (bitmapData[row*bytesPerRow + col]) { 60 | 61 | rowSum[row]++; 62 | colSum[col]++; 63 | 64 | } 65 | 66 | } 67 | 68 | } 69 | 70 | } 71 | 72 | // Initialize crop insets and enumerate cols/rows arrays until we find non-empty columns or row 73 | UIEdgeInsets crop = UIEdgeInsetsZero; 74 | 75 | // Top 76 | for (NSInteger i = 0; i < height; i++) { 77 | 78 | if (rowSum[i] > 0) { 79 | 80 | crop.top = i; 81 | break; 82 | 83 | } 84 | 85 | } 86 | 87 | // Bottom 88 | for (NSInteger i = height - 1; i >= 0; i--) { 89 | 90 | if (rowSum[i] > 0) { 91 | crop.bottom = MAX(0, height - i - 1); 92 | break; 93 | } 94 | 95 | } 96 | 97 | // Left 98 | for (NSInteger i = 0; i < width; i++) { 99 | 100 | if (colSum[i] > 0) { 101 | crop.left = i; 102 | break; 103 | } 104 | 105 | } 106 | 107 | // Right 108 | for (NSInteger i = width - 1; i >= 0; i--) { 109 | 110 | if (colSum[i] > 0) { 111 | 112 | crop.right = MAX(0, width - i - 1); 113 | break; 114 | 115 | } 116 | } 117 | 118 | free(bitmapData); 119 | free(colSum); 120 | free(rowSum); 121 | 122 | CGContextRelease(contextRef); 123 | 124 | return crop; 125 | } 126 | 127 | /* 128 | * Original method signature; behavior should be identical. 129 | */ 130 | - (UIImage *)imageByTrimmingTransparentPixels 131 | { 132 | return [self imageByTrimmingTransparentPixelsRequiringFullOpacity:NO]; 133 | } 134 | 135 | /* 136 | * Alternative method signature allowing for the use of cropping based on semi-transparency. 137 | */ 138 | - (UIImage *)imageByTrimmingTransparentPixelsRequiringFullOpacity:(BOOL)fullyOpaque 139 | { 140 | if (self.size.height < 2 || self.size.width < 2) { 141 | 142 | return self; 143 | 144 | } 145 | 146 | CGRect rect = CGRectMake(0, 0, self.size.width * self.scale, self.size.height * self.scale); 147 | UIEdgeInsets crop = [self transparencyInsetsRequiringFullOpacity:fullyOpaque]; 148 | 149 | UIImage *img = self; 150 | 151 | if (crop.top == 0 && crop.bottom == 0 && crop.left == 0 && crop.right == 0) { 152 | 153 | // No cropping needed 154 | 155 | } else { 156 | 157 | // Calculate new crop bounds 158 | rect.origin.x += crop.left; 159 | rect.origin.y += crop.top; 160 | rect.size.width -= crop.left + crop.right; 161 | rect.size.height -= crop.top + crop.bottom; 162 | 163 | // Crop it 164 | CGImageRef newImage = CGImageCreateWithImageInRect([self CGImage], rect); 165 | 166 | // Convert back to UIImage 167 | img = [UIImage imageWithCGImage:newImage scale:self.scale orientation:self.imageOrientation]; 168 | 169 | CGImageRelease(newImage); 170 | } 171 | 172 | return img; 173 | } 174 | 175 | @end 176 | -------------------------------------------------------------------------------- /Transparency Trim Demo/Transparency Trim Demo/demo_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wrep/UIImage-Trim/6856b68a9018a32711b8bf956d04d294e283bc8a/Transparency Trim Demo/Transparency Trim Demo/demo_image.png -------------------------------------------------------------------------------- /Transparency Trim Demo/Transparency Trim Demo/demo_image@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wrep/UIImage-Trim/6856b68a9018a32711b8bf956d04d294e283bc8a/Transparency Trim Demo/Transparency Trim Demo/demo_image@2x.png -------------------------------------------------------------------------------- /Transparency Trim Demo/Transparency Trim Demo/en.lproj/ELCViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1552 5 | 12E55 6 | 3084 7 | 1187.39 8 | 626.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 2083 12 | 13 | 14 | IBNSLayoutConstraint 15 | IBProxyObject 16 | IBUIImageView 17 | IBUILabel 18 | IBUIView 19 | 20 | 21 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 22 | 23 | 24 | PluginDependencyRecalculationVersion 25 | 26 | 27 | 28 | 29 | IBFilesOwner 30 | IBCocoaTouchFramework 31 | 32 | 33 | IBFirstResponder 34 | IBCocoaTouchFramework 35 | 36 | 37 | 38 | 274 39 | 40 | 41 | 42 | 274 43 | {{180, 20}, {120, 120}} 44 | 45 | 46 | _NS:9 47 | 4 48 | NO 49 | IBCocoaTouchFramework 50 | 51 | 52 | 53 | 274 54 | {{180, 214}, {120, 120}} 55 | 56 | 57 | _NS:9 58 | 4 59 | NO 60 | IBCocoaTouchFramework 61 | 62 | 63 | 64 | 274 65 | {{180, 408}, {120, 120}} 66 | 67 | 68 | _NS:9 69 | 4 70 | NO 71 | IBCocoaTouchFramework 72 | 73 | 74 | 75 | 292 76 | {{20, 69}, {152, 21}} 77 | 78 | 79 | _NS:9 80 | NO 81 | YES 82 | 7 83 | NO 84 | IBCocoaTouchFramework 85 | Non-Fully Opaque 86 | 87 | 1 88 | MCAwIDAAA 89 | darkTextColor 90 | 91 | 92 | 0 93 | 2 94 | 95 | 1 96 | 17 97 | 98 | 99 | Helvetica 100 | 17 101 | 16 102 | 103 | NO 104 | 105 | 106 | 107 | 292 108 | {{20, 457}, {152, 21}} 109 | 110 | 111 | _NS:9 112 | NO 113 | YES 114 | 7 115 | NO 116 | IBCocoaTouchFramework 117 | Fully Opaque 118 | 119 | 120 | 0 121 | 2 122 | 123 | 124 | NO 125 | 126 | 127 | 128 | 292 129 | {{20, 263}, {152, 21}} 130 | 131 | 132 | _NS:9 133 | NO 134 | YES 135 | 7 136 | NO 137 | IBCocoaTouchFramework 138 | Original 139 | 140 | 141 | 0 142 | 2 143 | 144 | 145 | NO 146 | 147 | 148 | {{0, 20}, {320, 548}} 149 | 150 | 151 | 152 | 3 153 | MC43NQA 154 | 155 | 2 156 | 157 | 158 | NO 159 | 160 | 161 | IBUIScreenMetrics 162 | 163 | YES 164 | 165 | 166 | 167 | 168 | 169 | {320, 568} 170 | {568, 320} 171 | 172 | 173 | IBCocoaTouchFramework 174 | Retina 4 Full Screen 175 | 2 176 | 177 | IBCocoaTouchFramework 178 | 179 | 180 | 181 | 182 | 183 | 184 | view 185 | 186 | 187 | 188 | 7 189 | 190 | 191 | 192 | semiTransparentImageView 193 | 194 | 195 | 196 | 18 197 | 198 | 199 | 200 | originalImageView 201 | 202 | 203 | 204 | 19 205 | 206 | 207 | 208 | fullyOpaqueImageView 209 | 210 | 211 | 212 | 20 213 | 214 | 215 | 216 | 217 | 218 | 0 219 | 220 | 221 | 222 | 223 | 224 | -1 225 | 226 | 227 | File's Owner 228 | 229 | 230 | -2 231 | 232 | 233 | 234 | 235 | 6 236 | 237 | 238 | 239 | 240 | 5 241 | 0 242 | 243 | 5 244 | 1 245 | 246 | 20 247 | 248 | 1000 249 | 250 | 8 251 | 29 252 | 3 253 | 254 | 255 | 256 | 4 257 | 0 258 | 259 | 4 260 | 1 261 | 262 | 70 263 | 264 | 1000 265 | 266 | 3 267 | 9 268 | 3 269 | 270 | 271 | 272 | 5 273 | 0 274 | 275 | 6 276 | 1 277 | 278 | 8 279 | 280 | 1000 281 | 282 | 6 283 | 24 284 | 3 285 | 286 | 287 | 288 | 4 289 | 0 290 | 291 | 4 292 | 1 293 | 294 | 20 295 | 296 | 1000 297 | 298 | 8 299 | 29 300 | 3 301 | 302 | 303 | 304 | 5 305 | 0 306 | 307 | 5 308 | 1 309 | 310 | 0.0 311 | 312 | 1000 313 | 314 | 6 315 | 24 316 | 2 317 | 318 | 319 | 320 | 6 321 | 0 322 | 323 | 6 324 | 1 325 | 326 | 20 327 | 328 | 1000 329 | 330 | 8 331 | 29 332 | 3 333 | 334 | 335 | 336 | 5 337 | 0 338 | 339 | 6 340 | 1 341 | 342 | 8 343 | 344 | 1000 345 | 346 | 6 347 | 24 348 | 3 349 | 350 | 351 | 352 | 6 353 | 0 354 | 355 | 6 356 | 1 357 | 358 | 20 359 | 360 | 1000 361 | 362 | 8 363 | 29 364 | 3 365 | 366 | 367 | 368 | 10 369 | 0 370 | 371 | 10 372 | 1 373 | 374 | 0.0 375 | 376 | 1000 377 | 378 | 5 379 | 22 380 | 2 381 | 382 | 383 | 384 | 5 385 | 0 386 | 387 | 5 388 | 1 389 | 390 | 20 391 | 392 | 1000 393 | 394 | 8 395 | 29 396 | 3 397 | 398 | 399 | 400 | 3 401 | 0 402 | 403 | 3 404 | 1 405 | 406 | 263 407 | 408 | 1000 409 | 410 | 3 411 | 9 412 | 3 413 | 414 | 415 | 416 | 5 417 | 0 418 | 419 | 6 420 | 1 421 | 422 | 8 423 | 424 | 1000 425 | 426 | 6 427 | 24 428 | 3 429 | 430 | 431 | 432 | 6 433 | 0 434 | 435 | 6 436 | 1 437 | 438 | 20 439 | 440 | 1000 441 | 442 | 8 443 | 29 444 | 3 445 | 446 | 447 | 448 | 5 449 | 0 450 | 451 | 5 452 | 1 453 | 454 | 0.0 455 | 456 | 1000 457 | 458 | 6 459 | 24 460 | 2 461 | 462 | 463 | 464 | 3 465 | 0 466 | 467 | 3 468 | 1 469 | 470 | 20 471 | 472 | 1000 473 | 474 | 8 475 | 29 476 | 3 477 | 478 | 479 | 480 | 3 481 | 0 482 | 483 | 3 484 | 1 485 | 486 | 69 487 | 488 | 1000 489 | 490 | 3 491 | 9 492 | 3 493 | 494 | 495 | 496 | 5 497 | 0 498 | 499 | 5 500 | 1 501 | 502 | 20 503 | 504 | 1000 505 | 506 | 8 507 | 29 508 | 3 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 8 521 | 522 | 523 | 524 | 525 | 8 526 | 0 527 | 528 | 0 529 | 1 530 | 531 | 120 532 | 533 | 1000 534 | 535 | 3 536 | 9 537 | 1 538 | 539 | 540 | 541 | 7 542 | 0 543 | 544 | 0 545 | 1 546 | 547 | 120 548 | 549 | 1000 550 | 551 | 3 552 | 9 553 | 1 554 | 555 | 556 | 557 | 558 | 559 | 13 560 | 561 | 562 | 563 | 564 | 8 565 | 0 566 | 567 | 0 568 | 1 569 | 570 | 120 571 | 572 | 1000 573 | 574 | 3 575 | 9 576 | 1 577 | 578 | 579 | 580 | 581 | 582 | 14 583 | 584 | 585 | 586 | 587 | 8 588 | 0 589 | 590 | 0 591 | 1 592 | 593 | 120 594 | 595 | 1000 596 | 597 | 3 598 | 9 599 | 1 600 | 601 | 602 | 603 | 604 | 605 | 15 606 | 607 | 608 | 609 | 610 | 16 611 | 612 | 613 | 614 | 615 | 616 | 17 617 | 618 | 619 | 620 | 621 | 622 | 22 623 | 624 | 625 | 626 | 627 | 23 628 | 629 | 630 | 631 | 632 | 40 633 | 634 | 635 | 636 | 637 | 42 638 | 639 | 640 | 641 | 642 | 61 643 | 644 | 645 | 646 | 647 | 69 648 | 649 | 650 | 651 | 652 | 72 653 | 654 | 655 | 656 | 657 | 73 658 | 659 | 660 | 661 | 662 | 74 663 | 664 | 665 | 666 | 667 | 76 668 | 669 | 670 | 671 | 672 | 79 673 | 674 | 675 | 676 | 677 | 81 678 | 679 | 680 | 681 | 682 | 88 683 | 684 | 685 | 686 | 687 | 89 688 | 689 | 690 | 691 | 692 | 91 693 | 694 | 695 | 696 | 697 | 93 698 | 699 | 700 | 701 | 702 | 97 703 | 704 | 705 | 706 | 707 | 98 708 | 709 | 710 | 711 | 712 | 99 713 | 714 | 715 | 716 | 717 | 100 718 | 719 | 720 | 721 | 722 | 101 723 | 724 | 725 | 726 | 727 | 728 | 729 | ELCViewController 730 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 731 | UIResponder 732 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 733 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 734 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 735 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 736 | 737 | 738 | 739 | 740 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 741 | 742 | 743 | 744 | 745 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 746 | 747 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 748 | 749 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 750 | 751 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 752 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 753 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 754 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 755 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 776 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 777 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 778 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 779 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 780 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 781 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 782 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 783 | 784 | 785 | 786 | 787 | 788 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 789 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 790 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 791 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 792 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 793 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 794 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 795 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 796 | 797 | 798 | 799 | 800 | 801 | 101 802 | 803 | 804 | 805 | 806 | ELCViewController 807 | UIViewController 808 | 809 | UIImageView 810 | UIImageView 811 | UIImageView 812 | 813 | 814 | 815 | fullyOpaqueImageView 816 | UIImageView 817 | 818 | 819 | originalImageView 820 | UIImageView 821 | 822 | 823 | semiTransparentImageView 824 | UIImageView 825 | 826 | 827 | 828 | IBProjectSource 829 | ./Classes/ELCViewController.h 830 | 831 | 832 | 833 | NSLayoutConstraint 834 | NSObject 835 | 836 | IBProjectSource 837 | ./Classes/NSLayoutConstraint.h 838 | 839 | 840 | 841 | 842 | 0 843 | IBCocoaTouchFramework 844 | YES 845 | 3 846 | YES 847 | 2083 848 | 849 | 850 | -------------------------------------------------------------------------------- /Transparency Trim Demo/Transparency Trim Demo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Transparency Trim Demo/Transparency Trim Demo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Transparency Trim Demo 4 | // 5 | // Created by Chris Stroud on 6/26/13. 6 | // Copyright (c) 2013 Chris Stroud. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "ELCAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([ELCAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /UIImage+Trim.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Trim.h 3 | // 4 | // Created by Rick Pastoor on 26-09-12. 5 | // Based on gist:3549921 ( https://gist.github.com/3549921/8abea8ac9e2450f6a38540de9724d3bf850a62df ) 6 | // 7 | // Copyright (c) 2012 Wrep - http://www.wrep.nl/ 8 | // 9 | 10 | #import 11 | 12 | @interface UIImage (Trim) 13 | 14 | - (UIEdgeInsets)transparencyInsetsRequiringFullOpacity:(BOOL)fullyOpaque; 15 | - (UIImage *)imageByTrimmingTransparentPixels; 16 | - (UIImage *)imageByTrimmingTransparentPixelsRequiringFullOpacity:(BOOL)fullyOpaque; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /UIImage+Trim.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+Trim.m 3 | // 4 | // Created by Rick Pastoor on 26-09-12. 5 | // Based on gist:3549921 ( https://gist.github.com/3549921/8abea8ac9e2450f6a38540de9724d3bf850a62df ) 6 | // 7 | // Copyright (c) 2012 Wrep - http://www.wrep.nl/ 8 | // 9 | 10 | #import "UIImage+Trim.h" 11 | 12 | @implementation UIImage (Trim) 13 | 14 | /* 15 | * Calculates the insets of transparency around all sides of the image 16 | * 17 | * @param fullyOpaque 18 | * Whether the algorithm should consider pixels with an alpha value of something other than 255 as being transparent. Otherwise a non-zero value would be considered opaque. 19 | */ 20 | - (UIEdgeInsets)transparencyInsetsRequiringFullOpacity:(BOOL)fullyOpaque 21 | { 22 | // Draw our image on that context 23 | NSInteger width = (NSInteger)CGImageGetWidth([self CGImage]); 24 | NSInteger height = (NSInteger)CGImageGetHeight([self CGImage]); 25 | NSInteger bytesPerRow = width * (NSInteger)sizeof(uint8_t); 26 | 27 | // Allocate array to hold alpha channel 28 | uint8_t * bitmapData = calloc((size_t)(width * height), sizeof(uint8_t)); 29 | 30 | // Create alpha-only bitmap context 31 | CGContextRef contextRef = CGBitmapContextCreate(bitmapData, (NSUInteger)width, (NSUInteger)height, 8, (NSUInteger)bytesPerRow, NULL, kCGImageAlphaOnly); 32 | 33 | CGImageRef cgImage = self.CGImage; 34 | CGRect rect = CGRectMake(0, 0, width, height); 35 | CGContextDrawImage(contextRef, rect, cgImage); 36 | 37 | // Sum all non-transparent pixels in every row and every column 38 | uint16_t * rowSum = calloc((size_t)height, sizeof(uint16_t)); 39 | uint16_t * colSum = calloc((size_t)width, sizeof(uint16_t)); 40 | 41 | // Enumerate through all pixels 42 | for (NSInteger row = 0; row < height; row++) { 43 | 44 | for (NSInteger col = 0; col < width; col++) { 45 | 46 | if (fullyOpaque) { 47 | 48 | // Found non-transparent pixel 49 | if (bitmapData[row*bytesPerRow + col] == UINT8_MAX) { 50 | 51 | rowSum[row]++; 52 | colSum[col]++; 53 | 54 | } 55 | 56 | } else { 57 | 58 | // Found non-transparent pixel 59 | if (bitmapData[row*bytesPerRow + col]) { 60 | 61 | rowSum[row]++; 62 | colSum[col]++; 63 | 64 | } 65 | 66 | } 67 | 68 | } 69 | 70 | } 71 | 72 | // Initialize crop insets and enumerate cols/rows arrays until we find non-empty columns or row 73 | UIEdgeInsets crop = UIEdgeInsetsZero; 74 | 75 | // Top 76 | for (NSInteger i = 0; i < height; i++) { 77 | 78 | if (rowSum[i] > 0) { 79 | 80 | crop.top = i; 81 | break; 82 | 83 | } 84 | 85 | } 86 | 87 | // Bottom 88 | for (NSInteger i = height - 1; i >= 0; i--) { 89 | 90 | if (rowSum[i] > 0) { 91 | crop.bottom = MAX(0, height - i - 1); 92 | break; 93 | } 94 | 95 | } 96 | 97 | // Left 98 | for (NSInteger i = 0; i < width; i++) { 99 | 100 | if (colSum[i] > 0) { 101 | crop.left = i; 102 | break; 103 | } 104 | 105 | } 106 | 107 | // Right 108 | for (NSInteger i = width - 1; i >= 0; i--) { 109 | 110 | if (colSum[i] > 0) { 111 | 112 | crop.right = MAX(0, width - i - 1); 113 | break; 114 | 115 | } 116 | } 117 | 118 | free(bitmapData); 119 | free(colSum); 120 | free(rowSum); 121 | 122 | CGContextRelease(contextRef); 123 | 124 | return crop; 125 | } 126 | 127 | /* 128 | * Original method signature; behavior should be identical. 129 | */ 130 | - (UIImage *)imageByTrimmingTransparentPixels 131 | { 132 | return [self imageByTrimmingTransparentPixelsRequiringFullOpacity:NO]; 133 | } 134 | 135 | /* 136 | * Alternative method signature allowing for the use of cropping based on semi-transparency. 137 | */ 138 | - (UIImage *)imageByTrimmingTransparentPixelsRequiringFullOpacity:(BOOL)fullyOpaque 139 | { 140 | if (self.size.height < 2 || self.size.width < 2) { 141 | 142 | return self; 143 | 144 | } 145 | 146 | CGRect rect = CGRectMake(0, 0, self.size.width * self.scale, self.size.height * self.scale); 147 | UIEdgeInsets crop = [self transparencyInsetsRequiringFullOpacity:fullyOpaque]; 148 | 149 | UIImage *img = self; 150 | 151 | if (crop.top == 0 && crop.bottom == 0 && crop.left == 0 && crop.right == 0) { 152 | 153 | // No cropping needed 154 | 155 | } else { 156 | 157 | // Calculate new crop bounds 158 | rect.origin.x += crop.left; 159 | rect.origin.y += crop.top; 160 | rect.size.width -= crop.left + crop.right; 161 | rect.size.height -= crop.top + crop.bottom; 162 | 163 | // Crop it 164 | CGImageRef newImage = CGImageCreateWithImageInRect([self CGImage], rect); 165 | 166 | // Convert back to UIImage 167 | img = [UIImage imageWithCGImage:newImage scale:self.scale orientation:self.imageOrientation]; 168 | 169 | CGImageRelease(newImage); 170 | } 171 | 172 | return img; 173 | } 174 | 175 | @end 176 | --------------------------------------------------------------------------------