├── README.md └── UIImageDemon ├── UIImageDemon.xcodeproj └── project.pbxproj └── UIImageDemon ├── AppDelegate.swift ├── Assets.xcassets ├── AccentColor.colorset │ └── Contents.json ├── AppIcon.appiconset │ └── Contents.json └── Contents.json ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── Info.plist ├── SceneDelegate.swift ├── UIImage+.swift ├── UIImage+SubjectColor.h ├── UIImage+SubjectColor.m ├── UIImageDemon-Bridging-Header.h └── ViewController.swift /README.md: -------------------------------------------------------------------------------- 1 | # UIImageSubjectColor 2 | Get the theme color of the image (OC and swift) 3 | -------------------------------------------------------------------------------- /UIImageDemon/UIImageDemon.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 55; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | C427ED3B274E162C005F969F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C427ED3A274E162C005F969F /* AppDelegate.swift */; }; 11 | C427ED3D274E162C005F969F /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C427ED3C274E162C005F969F /* SceneDelegate.swift */; }; 12 | C427ED3F274E162C005F969F /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C427ED3E274E162C005F969F /* ViewController.swift */; }; 13 | C427ED42274E162C005F969F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C427ED40274E162C005F969F /* Main.storyboard */; }; 14 | C427ED44274E162E005F969F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C427ED43274E162E005F969F /* Assets.xcassets */; }; 15 | C427ED47274E162E005F969F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C427ED45274E162E005F969F /* LaunchScreen.storyboard */; }; 16 | C427ED4F274E164F005F969F /* UIImage+.swift in Sources */ = {isa = PBXBuildFile; fileRef = C427ED4E274E164F005F969F /* UIImage+.swift */; }; 17 | C427ED53274E27C5005F969F /* UIImage+SubjectColor.m in Sources */ = {isa = PBXBuildFile; fileRef = C427ED52274E27C5005F969F /* UIImage+SubjectColor.m */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | C427ED37274E162C005F969F /* UIImageDemon.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UIImageDemon.app; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | C427ED3A274E162C005F969F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 23 | C427ED3C274E162C005F969F /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 24 | C427ED3E274E162C005F969F /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 25 | C427ED41274E162C005F969F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 26 | C427ED43274E162E005F969F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 27 | C427ED46274E162E005F969F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 28 | C427ED48274E162E005F969F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 29 | C427ED4E274E164F005F969F /* UIImage+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+.swift"; sourceTree = ""; }; 30 | C427ED50274E27C5005F969F /* UIImageDemon-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIImageDemon-Bridging-Header.h"; sourceTree = ""; }; 31 | C427ED51274E27C5005F969F /* UIImage+SubjectColor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+SubjectColor.h"; sourceTree = ""; }; 32 | C427ED52274E27C5005F969F /* UIImage+SubjectColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+SubjectColor.m"; sourceTree = ""; }; 33 | /* End PBXFileReference section */ 34 | 35 | /* Begin PBXFrameworksBuildPhase section */ 36 | C427ED34274E162C005F969F /* Frameworks */ = { 37 | isa = PBXFrameworksBuildPhase; 38 | buildActionMask = 2147483647; 39 | files = ( 40 | ); 41 | runOnlyForDeploymentPostprocessing = 0; 42 | }; 43 | /* End PBXFrameworksBuildPhase section */ 44 | 45 | /* Begin PBXGroup section */ 46 | C427ED2E274E162C005F969F = { 47 | isa = PBXGroup; 48 | children = ( 49 | C427ED39274E162C005F969F /* UIImageDemon */, 50 | C427ED38274E162C005F969F /* Products */, 51 | ); 52 | sourceTree = ""; 53 | }; 54 | C427ED38274E162C005F969F /* Products */ = { 55 | isa = PBXGroup; 56 | children = ( 57 | C427ED37274E162C005F969F /* UIImageDemon.app */, 58 | ); 59 | name = Products; 60 | sourceTree = ""; 61 | }; 62 | C427ED39274E162C005F969F /* UIImageDemon */ = { 63 | isa = PBXGroup; 64 | children = ( 65 | C427ED3A274E162C005F969F /* AppDelegate.swift */, 66 | C427ED3C274E162C005F969F /* SceneDelegate.swift */, 67 | C427ED3E274E162C005F969F /* ViewController.swift */, 68 | C427ED4E274E164F005F969F /* UIImage+.swift */, 69 | C427ED51274E27C5005F969F /* UIImage+SubjectColor.h */, 70 | C427ED52274E27C5005F969F /* UIImage+SubjectColor.m */, 71 | C427ED40274E162C005F969F /* Main.storyboard */, 72 | C427ED43274E162E005F969F /* Assets.xcassets */, 73 | C427ED45274E162E005F969F /* LaunchScreen.storyboard */, 74 | C427ED48274E162E005F969F /* Info.plist */, 75 | C427ED50274E27C5005F969F /* UIImageDemon-Bridging-Header.h */, 76 | ); 77 | path = UIImageDemon; 78 | sourceTree = ""; 79 | }; 80 | /* End PBXGroup section */ 81 | 82 | /* Begin PBXNativeTarget section */ 83 | C427ED36274E162C005F969F /* UIImageDemon */ = { 84 | isa = PBXNativeTarget; 85 | buildConfigurationList = C427ED4B274E162E005F969F /* Build configuration list for PBXNativeTarget "UIImageDemon" */; 86 | buildPhases = ( 87 | C427ED33274E162C005F969F /* Sources */, 88 | C427ED34274E162C005F969F /* Frameworks */, 89 | C427ED35274E162C005F969F /* Resources */, 90 | ); 91 | buildRules = ( 92 | ); 93 | dependencies = ( 94 | ); 95 | name = UIImageDemon; 96 | productName = UIImageDemon; 97 | productReference = C427ED37274E162C005F969F /* UIImageDemon.app */; 98 | productType = "com.apple.product-type.application"; 99 | }; 100 | /* End PBXNativeTarget section */ 101 | 102 | /* Begin PBXProject section */ 103 | C427ED2F274E162C005F969F /* Project object */ = { 104 | isa = PBXProject; 105 | attributes = { 106 | BuildIndependentTargetsInParallel = 1; 107 | LastSwiftUpdateCheck = 1300; 108 | LastUpgradeCheck = 1300; 109 | TargetAttributes = { 110 | C427ED36274E162C005F969F = { 111 | CreatedOnToolsVersion = 13.0; 112 | LastSwiftMigration = 1300; 113 | }; 114 | }; 115 | }; 116 | buildConfigurationList = C427ED32274E162C005F969F /* Build configuration list for PBXProject "UIImageDemon" */; 117 | compatibilityVersion = "Xcode 13.0"; 118 | developmentRegion = en; 119 | hasScannedForEncodings = 0; 120 | knownRegions = ( 121 | en, 122 | Base, 123 | ); 124 | mainGroup = C427ED2E274E162C005F969F; 125 | productRefGroup = C427ED38274E162C005F969F /* Products */; 126 | projectDirPath = ""; 127 | projectRoot = ""; 128 | targets = ( 129 | C427ED36274E162C005F969F /* UIImageDemon */, 130 | ); 131 | }; 132 | /* End PBXProject section */ 133 | 134 | /* Begin PBXResourcesBuildPhase section */ 135 | C427ED35274E162C005F969F /* Resources */ = { 136 | isa = PBXResourcesBuildPhase; 137 | buildActionMask = 2147483647; 138 | files = ( 139 | C427ED47274E162E005F969F /* LaunchScreen.storyboard in Resources */, 140 | C427ED44274E162E005F969F /* Assets.xcassets in Resources */, 141 | C427ED42274E162C005F969F /* Main.storyboard in Resources */, 142 | ); 143 | runOnlyForDeploymentPostprocessing = 0; 144 | }; 145 | /* End PBXResourcesBuildPhase section */ 146 | 147 | /* Begin PBXSourcesBuildPhase section */ 148 | C427ED33274E162C005F969F /* Sources */ = { 149 | isa = PBXSourcesBuildPhase; 150 | buildActionMask = 2147483647; 151 | files = ( 152 | C427ED3F274E162C005F969F /* ViewController.swift in Sources */, 153 | C427ED53274E27C5005F969F /* UIImage+SubjectColor.m in Sources */, 154 | C427ED4F274E164F005F969F /* UIImage+.swift in Sources */, 155 | C427ED3B274E162C005F969F /* AppDelegate.swift in Sources */, 156 | C427ED3D274E162C005F969F /* SceneDelegate.swift in Sources */, 157 | ); 158 | runOnlyForDeploymentPostprocessing = 0; 159 | }; 160 | /* End PBXSourcesBuildPhase section */ 161 | 162 | /* Begin PBXVariantGroup section */ 163 | C427ED40274E162C005F969F /* Main.storyboard */ = { 164 | isa = PBXVariantGroup; 165 | children = ( 166 | C427ED41274E162C005F969F /* Base */, 167 | ); 168 | name = Main.storyboard; 169 | sourceTree = ""; 170 | }; 171 | C427ED45274E162E005F969F /* LaunchScreen.storyboard */ = { 172 | isa = PBXVariantGroup; 173 | children = ( 174 | C427ED46274E162E005F969F /* Base */, 175 | ); 176 | name = LaunchScreen.storyboard; 177 | sourceTree = ""; 178 | }; 179 | /* End PBXVariantGroup section */ 180 | 181 | /* Begin XCBuildConfiguration section */ 182 | C427ED49274E162E005F969F /* Debug */ = { 183 | isa = XCBuildConfiguration; 184 | buildSettings = { 185 | ALWAYS_SEARCH_USER_PATHS = NO; 186 | CLANG_ANALYZER_NONNULL = YES; 187 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 188 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 189 | CLANG_CXX_LIBRARY = "libc++"; 190 | CLANG_ENABLE_MODULES = YES; 191 | CLANG_ENABLE_OBJC_ARC = YES; 192 | CLANG_ENABLE_OBJC_WEAK = YES; 193 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 194 | CLANG_WARN_BOOL_CONVERSION = YES; 195 | CLANG_WARN_COMMA = YES; 196 | CLANG_WARN_CONSTANT_CONVERSION = YES; 197 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 198 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 199 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 200 | CLANG_WARN_EMPTY_BODY = YES; 201 | CLANG_WARN_ENUM_CONVERSION = YES; 202 | CLANG_WARN_INFINITE_RECURSION = YES; 203 | CLANG_WARN_INT_CONVERSION = YES; 204 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 205 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 206 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 207 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 208 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 209 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 210 | CLANG_WARN_STRICT_PROTOTYPES = YES; 211 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 212 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 213 | CLANG_WARN_UNREACHABLE_CODE = YES; 214 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 215 | COPY_PHASE_STRIP = NO; 216 | DEBUG_INFORMATION_FORMAT = dwarf; 217 | ENABLE_STRICT_OBJC_MSGSEND = YES; 218 | ENABLE_TESTABILITY = YES; 219 | GCC_C_LANGUAGE_STANDARD = gnu11; 220 | GCC_DYNAMIC_NO_PIC = NO; 221 | GCC_NO_COMMON_BLOCKS = YES; 222 | GCC_OPTIMIZATION_LEVEL = 0; 223 | GCC_PREPROCESSOR_DEFINITIONS = ( 224 | "DEBUG=1", 225 | "$(inherited)", 226 | ); 227 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 228 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 229 | GCC_WARN_UNDECLARED_SELECTOR = YES; 230 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 231 | GCC_WARN_UNUSED_FUNCTION = YES; 232 | GCC_WARN_UNUSED_VARIABLE = YES; 233 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 234 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 235 | MTL_FAST_MATH = YES; 236 | ONLY_ACTIVE_ARCH = YES; 237 | SDKROOT = iphoneos; 238 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 239 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 240 | }; 241 | name = Debug; 242 | }; 243 | C427ED4A274E162E005F969F /* Release */ = { 244 | isa = XCBuildConfiguration; 245 | buildSettings = { 246 | ALWAYS_SEARCH_USER_PATHS = NO; 247 | CLANG_ANALYZER_NONNULL = YES; 248 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 249 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 250 | CLANG_CXX_LIBRARY = "libc++"; 251 | CLANG_ENABLE_MODULES = YES; 252 | CLANG_ENABLE_OBJC_ARC = YES; 253 | CLANG_ENABLE_OBJC_WEAK = YES; 254 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 255 | CLANG_WARN_BOOL_CONVERSION = YES; 256 | CLANG_WARN_COMMA = YES; 257 | CLANG_WARN_CONSTANT_CONVERSION = YES; 258 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 259 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 260 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 261 | CLANG_WARN_EMPTY_BODY = YES; 262 | CLANG_WARN_ENUM_CONVERSION = YES; 263 | CLANG_WARN_INFINITE_RECURSION = YES; 264 | CLANG_WARN_INT_CONVERSION = YES; 265 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 266 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 267 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 268 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 269 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 270 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 271 | CLANG_WARN_STRICT_PROTOTYPES = YES; 272 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 273 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 274 | CLANG_WARN_UNREACHABLE_CODE = YES; 275 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 276 | COPY_PHASE_STRIP = NO; 277 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 278 | ENABLE_NS_ASSERTIONS = NO; 279 | ENABLE_STRICT_OBJC_MSGSEND = YES; 280 | GCC_C_LANGUAGE_STANDARD = gnu11; 281 | GCC_NO_COMMON_BLOCKS = YES; 282 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 283 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 284 | GCC_WARN_UNDECLARED_SELECTOR = YES; 285 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 286 | GCC_WARN_UNUSED_FUNCTION = YES; 287 | GCC_WARN_UNUSED_VARIABLE = YES; 288 | IPHONEOS_DEPLOYMENT_TARGET = 15.0; 289 | MTL_ENABLE_DEBUG_INFO = NO; 290 | MTL_FAST_MATH = YES; 291 | SDKROOT = iphoneos; 292 | SWIFT_COMPILATION_MODE = wholemodule; 293 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 294 | VALIDATE_PRODUCT = YES; 295 | }; 296 | name = Release; 297 | }; 298 | C427ED4C274E162E005F969F /* Debug */ = { 299 | isa = XCBuildConfiguration; 300 | buildSettings = { 301 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 302 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 303 | CLANG_ENABLE_MODULES = YES; 304 | CODE_SIGN_STYLE = Automatic; 305 | CURRENT_PROJECT_VERSION = 1; 306 | DEVELOPMENT_TEAM = 48RNR77GFN; 307 | GENERATE_INFOPLIST_FILE = YES; 308 | INFOPLIST_FILE = UIImageDemon/Info.plist; 309 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 310 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 311 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 312 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 313 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 314 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 315 | LD_RUNPATH_SEARCH_PATHS = ( 316 | "$(inherited)", 317 | "@executable_path/Frameworks", 318 | ); 319 | MARKETING_VERSION = 1.0; 320 | PRODUCT_BUNDLE_IDENTIFIER = lanlinxl.UIImageDemon; 321 | PRODUCT_NAME = "$(TARGET_NAME)"; 322 | SWIFT_EMIT_LOC_STRINGS = YES; 323 | SWIFT_OBJC_BRIDGING_HEADER = "UIImageDemon/UIImageDemon-Bridging-Header.h"; 324 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 325 | SWIFT_VERSION = 5.0; 326 | TARGETED_DEVICE_FAMILY = "1,2"; 327 | }; 328 | name = Debug; 329 | }; 330 | C427ED4D274E162E005F969F /* Release */ = { 331 | isa = XCBuildConfiguration; 332 | buildSettings = { 333 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 334 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 335 | CLANG_ENABLE_MODULES = YES; 336 | CODE_SIGN_STYLE = Automatic; 337 | CURRENT_PROJECT_VERSION = 1; 338 | DEVELOPMENT_TEAM = 48RNR77GFN; 339 | GENERATE_INFOPLIST_FILE = YES; 340 | INFOPLIST_FILE = UIImageDemon/Info.plist; 341 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; 342 | INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; 343 | INFOPLIST_KEY_UIMainStoryboardFile = Main; 344 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 345 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; 346 | IPHONEOS_DEPLOYMENT_TARGET = 14.0; 347 | LD_RUNPATH_SEARCH_PATHS = ( 348 | "$(inherited)", 349 | "@executable_path/Frameworks", 350 | ); 351 | MARKETING_VERSION = 1.0; 352 | PRODUCT_BUNDLE_IDENTIFIER = lanlinxl.UIImageDemon; 353 | PRODUCT_NAME = "$(TARGET_NAME)"; 354 | SWIFT_EMIT_LOC_STRINGS = YES; 355 | SWIFT_OBJC_BRIDGING_HEADER = "UIImageDemon/UIImageDemon-Bridging-Header.h"; 356 | SWIFT_VERSION = 5.0; 357 | TARGETED_DEVICE_FAMILY = "1,2"; 358 | }; 359 | name = Release; 360 | }; 361 | /* End XCBuildConfiguration section */ 362 | 363 | /* Begin XCConfigurationList section */ 364 | C427ED32274E162C005F969F /* Build configuration list for PBXProject "UIImageDemon" */ = { 365 | isa = XCConfigurationList; 366 | buildConfigurations = ( 367 | C427ED49274E162E005F969F /* Debug */, 368 | C427ED4A274E162E005F969F /* Release */, 369 | ); 370 | defaultConfigurationIsVisible = 0; 371 | defaultConfigurationName = Release; 372 | }; 373 | C427ED4B274E162E005F969F /* Build configuration list for PBXNativeTarget "UIImageDemon" */ = { 374 | isa = XCConfigurationList; 375 | buildConfigurations = ( 376 | C427ED4C274E162E005F969F /* Debug */, 377 | C427ED4D274E162E005F969F /* Release */, 378 | ); 379 | defaultConfigurationIsVisible = 0; 380 | defaultConfigurationName = Release; 381 | }; 382 | /* End XCConfigurationList section */ 383 | }; 384 | rootObject = C427ED2F274E162C005F969F /* Project object */; 385 | } 386 | -------------------------------------------------------------------------------- /UIImageDemon/UIImageDemon/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // UIImageDemon 4 | // 5 | // Created by lzwk_lanlin on 2021/11/24. 6 | // 7 | 8 | import UIKit 9 | 10 | @main 11 | class AppDelegate: UIResponder, UIApplicationDelegate { 12 | 13 | 14 | 15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 16 | // Override point for customization after application launch. 17 | return true 18 | } 19 | 20 | // MARK: UISceneSession Lifecycle 21 | 22 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 23 | // Called when a new scene session is being created. 24 | // Use this method to select a configuration to create the new scene with. 25 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 26 | } 27 | 28 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 29 | // Called when the user discards a scene session. 30 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 31 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 32 | } 33 | 34 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /UIImageDemon/UIImageDemon/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /UIImageDemon/UIImageDemon/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "scale" : "1x", 46 | "size" : "20x20" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "scale" : "2x", 51 | "size" : "20x20" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "scale" : "1x", 56 | "size" : "29x29" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "scale" : "2x", 61 | "size" : "29x29" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "scale" : "1x", 66 | "size" : "40x40" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "scale" : "2x", 71 | "size" : "40x40" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "scale" : "1x", 76 | "size" : "76x76" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "scale" : "2x", 81 | "size" : "76x76" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "scale" : "2x", 86 | "size" : "83.5x83.5" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "scale" : "1x", 91 | "size" : "1024x1024" 92 | } 93 | ], 94 | "info" : { 95 | "author" : "xcode", 96 | "version" : 1 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /UIImageDemon/UIImageDemon/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /UIImageDemon/UIImageDemon/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /UIImageDemon/UIImageDemon/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /UIImageDemon/UIImageDemon/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIApplicationSceneManifest 6 | 7 | UIApplicationSupportsMultipleScenes 8 | 9 | UISceneConfigurations 10 | 11 | UIWindowSceneSessionRoleApplication 12 | 13 | 14 | UISceneConfigurationName 15 | Default Configuration 16 | UISceneDelegateClassName 17 | $(PRODUCT_MODULE_NAME).SceneDelegate 18 | UISceneStoryboardFile 19 | Main 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /UIImageDemon/UIImageDemon/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // UIImageDemon 4 | // 5 | // Created by lzwk_lanlin on 2021/11/24. 6 | // 7 | 8 | import UIKit 9 | 10 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 11 | 12 | var window: UIWindow? 13 | 14 | 15 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 16 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 17 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 18 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 19 | guard let _ = (scene as? UIWindowScene) else { return } 20 | } 21 | 22 | func sceneDidDisconnect(_ scene: UIScene) { 23 | // Called as the scene is being released by the system. 24 | // This occurs shortly after the scene enters the background, or when its session is discarded. 25 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 26 | // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead). 27 | } 28 | 29 | func sceneDidBecomeActive(_ scene: UIScene) { 30 | // Called when the scene has moved from an inactive state to an active state. 31 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 32 | } 33 | 34 | func sceneWillResignActive(_ scene: UIScene) { 35 | // Called when the scene will move from an active state to an inactive state. 36 | // This may occur due to temporary interruptions (ex. an incoming phone call). 37 | } 38 | 39 | func sceneWillEnterForeground(_ scene: UIScene) { 40 | // Called as the scene transitions from the background to the foreground. 41 | // Use this method to undo the changes made on entering the background. 42 | } 43 | 44 | func sceneDidEnterBackground(_ scene: UIScene) { 45 | // Called as the scene transitions from the foreground to the background. 46 | // Use this method to save data, release shared resources, and store enough scene-specific state information 47 | // to restore the scene back to its current state. 48 | } 49 | 50 | 51 | } 52 | 53 | -------------------------------------------------------------------------------- /UIImageDemon/UIImageDemon/UIImage+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+.swift 3 | // UIImageDemon 4 | // 5 | // Created by lzwk_lanlin on 2021/11/24. 6 | // 7 | 8 | import Foundation 9 | import UIKit 10 | 11 | public extension UIImage { 12 | func subjectColor(_ completion: @escaping (_ color: UIColor?) -> Void){ 13 | DispatchQueue.global().async { 14 | if self.cgImage == nil { 15 | DispatchQueue.main.async { 16 | return completion(nil) 17 | } 18 | } 19 | let bitmapInfo = CGBitmapInfo(rawValue: 0).rawValue | CGImageAlphaInfo.premultipliedLast.rawValue 20 | 21 | // 第一步 先把图片缩小 加快计算速度. 但越小结果误差可能越大 22 | let thumbSize = CGSize(width: 40 , height: 40) 23 | let colorSpace = CGColorSpaceCreateDeviceRGB() 24 | guard let context = CGContext(data: nil, 25 | width: Int(thumbSize.width), 26 | height: Int(thumbSize.height), 27 | bitsPerComponent: 8, 28 | bytesPerRow: Int(thumbSize.width) * 4 , 29 | space: colorSpace, 30 | bitmapInfo: bitmapInfo) else { return completion(nil) } 31 | 32 | let drawRect = CGRect(x: 0, y: 0, width: thumbSize.width, height: thumbSize.height) 33 | context.draw(self.cgImage! , in: drawRect) 34 | 35 | // 第二步 取每个点的像素值 36 | if context.data == nil{ return completion(nil)} 37 | let countedSet = NSCountedSet(capacity: Int(thumbSize.width * thumbSize.height)) 38 | for x in 0 ..< Int(thumbSize.width) { 39 | for y in 0 ..< Int(thumbSize.height){ 40 | let offset = 4 * x * y 41 | let red = context.data!.load(fromByteOffset: offset, as: UInt8.self) 42 | let green = context.data!.load(fromByteOffset: offset + 1, as: UInt8.self) 43 | let blue = context.data!.load(fromByteOffset: offset + 2, as: UInt8.self) 44 | let alpha = context.data!.load(fromByteOffset: offset + 3, as: UInt8.self) 45 | // 过滤透明的、基本白色、基本黑色 46 | if alpha > 0 && (red < 250 && green < 250 && blue < 250) && (red > 5 && green > 5 && blue > 5) { 47 | let array = [red,green,blue,alpha] 48 | countedSet.add(array) 49 | } 50 | } 51 | } 52 | 53 | //第三步 找到出现次数最多的那个颜色 54 | let enumerator = countedSet.objectEnumerator() 55 | var maxColor: [Int] = [] 56 | var maxCount = 0 57 | while let curColor = enumerator.nextObject() as? [Int] , !curColor.isEmpty { 58 | let tmpCount = countedSet.count(for: curColor) 59 | if tmpCount < maxCount { continue } 60 | maxCount = tmpCount 61 | maxColor = curColor 62 | } 63 | let color = UIColor(red: CGFloat(maxColor[0]) / 255.0, green: CGFloat(maxColor[1]) / 255.0, blue: CGFloat(maxColor[2]) / 255.0, alpha: CGFloat(maxColor[3]) / 255.0) 64 | DispatchQueue.main.async { return completion(color) } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /UIImageDemon/UIImageDemon/UIImage+SubjectColor.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+SubjectColor.h 3 | // WatermarkAPP 4 | // 5 | // Created by lzwk_lanlin on 2021/11/24. 6 | // 7 | 8 | #import 9 | 10 | @interface UIImage (SubjectColor) 11 | 12 | -(void)getSubjectColor:(void(^)(UIColor*))callBack; 13 | @end 14 | 15 | 16 | -------------------------------------------------------------------------------- /UIImageDemon/UIImageDemon/UIImage+SubjectColor.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+SubjectColor.m 3 | // WatermarkAPP 4 | // 5 | // Created by lzwk_lanlin on 2021/11/24. 6 | // 7 | 8 | #import "UIImage+SubjectColor.h" 9 | 10 | @implementation UIImage (SubjectColor) 11 | //根据图片获取图片的主色调 12 | -(void)getSubjectColor:(void(^)(UIColor*))callBack { 13 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 14 | // 第一步 先把图片缩小 加快计算速度. 但越小结果误差可能越大 15 | int bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast; 16 | CGSize thumbSize = CGSizeMake(40, 40); 17 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 18 | CGContextRef context = CGBitmapContextCreate(NULL,thumbSize.width,thumbSize.height, 8, thumbSize.width*4, colorSpace,bitmapInfo); 19 | CGRect drawRect = CGRectMake(0, 0, thumbSize.width, thumbSize.height); 20 | CGContextDrawImage(context, drawRect, self.CGImage); 21 | CGColorSpaceRelease(colorSpace); 22 | 23 | // 第二步 取每个点的像素值 24 | unsigned char* data = CGBitmapContextGetData (context); 25 | if (data == NULL) { 26 | dispatch_async(dispatch_get_main_queue(), ^{ 27 | callBack(nil); 28 | }); 29 | }; 30 | NSCountedSet* cls = [NSCountedSet setWithCapacity: thumbSize.width * thumbSize.height]; 31 | for (int x = 0; x < thumbSize.width; x++) { 32 | for (int y = 0; y < thumbSize.height; y++) { 33 | int offset = 4 * (x * y); 34 | int red = data[offset]; 35 | int green = data[offset + 1]; 36 | int blue = data[offset + 2]; 37 | int alpha = data[offset + 3]; 38 | // 过滤透明的、基本白色、基本黑色 39 | if (alpha > 0 && (red < 250 && green < 250 && blue < 250) && (red > 5 && green > 5 && blue > 5)) { 40 | NSArray *clr = @[@(red),@(green),@(blue),@(alpha)]; 41 | [cls addObject:clr]; 42 | } 43 | } 44 | } 45 | CGContextRelease(context); 46 | 47 | //第三步 找到出现次数最多的那个颜色 48 | NSEnumerator *enumerator = [cls objectEnumerator]; 49 | NSArray *curColor = nil; 50 | NSArray *MaxColor = nil; 51 | NSUInteger MaxCount = 0; 52 | while ((curColor = [enumerator nextObject]) != nil){ 53 | NSUInteger tmpCount = [cls countForObject:curColor]; 54 | if ( tmpCount < MaxCount ) continue; 55 | MaxCount = tmpCount; 56 | MaxColor = curColor; 57 | } 58 | UIColor * subjectColor = [UIColor colorWithRed:([MaxColor[0] intValue]/255.0f) green:([MaxColor[1] intValue]/255.0f) blue:([MaxColor[2] intValue]/255.0f) alpha:([MaxColor[3] intValue]/255.0f)]; 59 | dispatch_async(dispatch_get_main_queue(), ^{ 60 | callBack(subjectColor); 61 | }); 62 | }); 63 | } 64 | 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /UIImageDemon/UIImageDemon/UIImageDemon-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | #import "UIImage+SubjectColor.h" 6 | -------------------------------------------------------------------------------- /UIImageDemon/UIImageDemon/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // UIImageDemon 4 | // 5 | // Created by lzwk_lanlin on 2021/11/24. 6 | // 7 | 8 | import UIKit 9 | 10 | class ViewController: UIViewController, UIImagePickerControllerDelegate , UINavigationControllerDelegate { 11 | 12 | var imagePicker: UIImagePickerController = UIImagePickerController() 13 | 14 | var imageView = UIImageView() 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | let button = UIButton(type: .system) 19 | view.addSubview(button) 20 | button.setTitle("选择照片", for: .normal) 21 | button.addTarget(self, action: #selector(buttonClick), for: .touchUpInside) 22 | button.frame = CGRect(x: 10, y: 100, width: 100, height: 20) 23 | 24 | view.addSubview(imageView) 25 | imageView.frame = CGRect(x: 100, y: 150, width: 150, height: 150) 26 | 27 | 28 | imagePicker.delegate = self 29 | imagePicker.sourceType = .photoLibrary 30 | 31 | } 32 | 33 | @objc func buttonClick(){ 34 | /// 4. 点击选图片时,展示这个 picker controller 35 | present(imagePicker, animated: true) { 36 | print("UIImagePickerController: presented") 37 | } 38 | } 39 | 40 | func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { 41 | guard let selectedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else { return } 42 | picker.dismiss(animated: true) { [unowned self] in 43 | self.imageView.image = selectedImage 44 | 45 | // Swift 46 | selectedImage.subjectColor({[unowned self] color in 47 | guard let subjectColor = color else { return } 48 | self.view.backgroundColor = subjectColor 49 | }) 50 | 51 | // // OC 52 | // selectedImage.getSubjectColor {[unowned self] color in 53 | // guard let subjectColor = color else { return } 54 | // self.view.backgroundColor = subjectColor 55 | // } 56 | } 57 | } 58 | } 59 | --------------------------------------------------------------------------------