├── .gitignore ├── .swift-version ├── LICENSE ├── NSImageColors ├── Info.plist └── NSImageColors.h ├── Package.swift ├── README.md ├── UIImageColors.podspec ├── UIImageColors.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ ├── NSImageColors.xcscheme │ └── UIImageColors.xcscheme ├── UIImageColors ├── Sources │ ├── UIImageColors.h │ └── UIImageColors.swift └── Supporting Files │ └── Info.plist ├── UIImageColorsExample ├── Album.swift ├── AlbumViewCell.swift ├── AppDelegate.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Blue Nude II - Henri Matisse.imageset │ │ ├── Blue Nude II - Henri Matisse.jpg │ │ └── Contents.json │ ├── Cafe Terrace at Night - Vincent Van Gogh.imageset │ │ ├── Cafe Terrace at Night - Vincent Van Gogh.jpg │ │ └── Contents.json │ ├── Calvin Klein - Kaws.imageset │ │ ├── Calvin Klein - Kaws.jpg │ │ └── Contents.json │ ├── Contents.json │ ├── Le Reve - Pablo Picasso.imageset │ │ ├── Contents.json │ │ └── Le Reve - Pablo Picasso.jpg │ ├── Les Demoiselles d'Avignon - Picasso.imageset │ │ ├── Contents.json │ │ └── Les Demoiselles d'Avignon - Picasso.jpg │ ├── Mona Lisa - Leonardo da Vinci.imageset │ │ ├── Contents.json │ │ └── Mona Lisa - Leonardo da Vinci.jpg │ ├── Nighthawks - Edward Hopper.imageset │ │ ├── Contents.json │ │ └── Nighthawks - Edward Hopper.jpg │ ├── No. 210:No. 211 - Mark Rothko.imageset │ │ ├── Contents.json │ │ └── No. 210:No. 211 - Mark Rothko.jpg │ ├── Number 1A - Jackson Pollock.imageset │ │ ├── Contents.json │ │ └── Number 1A - Jackson Pollock.jpg │ ├── Self-portrait Spring 1887 - Vincent Van Gogh.imageset │ │ ├── Contents.json │ │ └── Self-portrait Spring 1887 - Vincent Van Gogh.jpg │ ├── Skull - Jean-Michel Basquiat.imageset │ │ ├── Contents.json │ │ └── Skull - Jean-Michel Basquiat.jpg │ ├── Woman I - Willem de Kooning.imageset │ │ ├── Contents.json │ │ └── Woman I - Willem de Kooning.jpg │ └── play.imageset │ │ ├── Contents.json │ │ ├── play@1x.png │ │ ├── play@2x.png │ │ └── play@3x.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist └── ViewController.swift └── preview.png /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | **/xcuserdata 4 | *.pbxuser 5 | *.mode1v3 6 | .swiftpm 7 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 3.0 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2015 Jathu Satkunarajah 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /NSImageColors/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 2.2.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSHumanReadableCopyright 22 | Copyright © 2019 Jathu Satkunarajah. All rights reserved. 23 | 24 | 25 | -------------------------------------------------------------------------------- /NSImageColors/NSImageColors.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSImageColors.h 3 | // NSImageColors 4 | // 5 | // Created by Boy van Amstel on 20/01/2019. 6 | // Copyright © 2019 Jathu Satkunarajah. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for NSImageColors. 12 | FOUNDATION_EXPORT double NSImageColorsVersionNumber; 13 | 14 | //! Project version string for NSImageColors. 15 | FOUNDATION_EXPORT const unsigned char NSImageColorsVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "UIImageColors", 7 | products: [ 8 | .library(name: "UIImageColors", targets: ["UIImageColors"]) 9 | ], 10 | targets: [ 11 | .target(name: "UIImageColors", path: "UIImageColors") 12 | ] 13 | ) 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Swift](https://img.shields.io/badge/Swift-5.0-orange.svg) 2 | ![platform: iOS, tvOS and macOS](https://img.shields.io/badge/platform-iOS%20%7C%20tvOS%20%7C%20macOS-lightgrey.svg) 3 | 4 | # UIImageColors 5 | 6 | iTunes style color fetcher for `UIImage` and `NSImage`. It fetches the most dominant and prominent colors. 7 | 8 | ![preview](preview.png) 9 | 10 | ## Installation 11 | 12 | ### Manual 13 | 14 | Copy [UIImageColors.swift](UIImageColors/Sources/UIImageColors.swift) into your project. 15 | 16 | ### [Cocoapods](https://cocoapods.org) 17 | 18 | Add UIImageColors to your [`Podfile`](https://cocoapods.org/pods/UIImageColors): 19 | 20 | ``` 21 | pod 'UIImageColors' 22 | ``` 23 | 24 | ### [Carthage](https://github.com/Carthage/Carthage) 25 | 26 | Add UIImageColors to your `Cartfile`: 27 | 28 | ``` 29 | github "jathu/UIImageColors" 30 | ``` 31 | 32 | ## Example 33 | 34 | Asynchronous example: 35 | 36 | ```swift 37 | let image = UIImage(named: "yeezus.png") 38 | 39 | image.getColors { colors in 40 | backgroundView.backgroundColor = colors.background 41 | mainLabel.textColor = colors.primary 42 | secondaryLabel.textColor = colors.secondary 43 | detailLabel.textColor = colors.detail 44 | } 45 | ``` 46 | 47 | Synchronous example: 48 | 49 | ```swift 50 | let colors = UIImage(named: "yeezus.png").getColors() 51 | 52 | backgroundView.backgroundColor = colors.background 53 | mainLabel.textColor = colors.primary 54 | secondaryLabel.textColor = colors.secondary 55 | detailLabel.textColor = colors.detail 56 | ``` 57 | 58 | ## Image Methods 59 | 60 | ```swift 61 | getColors() -> UIImageColors? 62 | getColors(quality: ImageColorsQuality) -> UIImageColors? 63 | getColors(_ completion: (UIImageColors?) -> Void) -> Void 64 | getColors(quality: UIImageColorsQuality, _ completion: (UIImageColors?) -> Void) -> Void 65 | ``` 66 | 67 | ## UIImageColors Objects 68 | 69 | `UIImageColors` is struct that contains four different `UIColor` (or `NSColor` on macOS) variables. 70 | 71 | ```swift 72 | public struct UIImageColors { 73 | public var background: UIColor! 74 | public var primary: UIColor! 75 | public var secondary: UIColor! 76 | public var detail: UIColor! 77 | } 78 | ``` 79 | 80 | `UIImageColorsQuality` is a enum with four different qualities. The qualities refer to how much the original image is scaled down. `Lowest` implies smaller size and faster performance at the cost of quality colors. `High` implies larger size with slower performance with good colors. `Highest` implies no downscaling and very good colors, but it is very slow. 81 | 82 | The default is set to `high`. 83 | 84 | ```swift 85 | public enum UIImageColorsQuality: CGFloat { 86 | case lowest = 50 // 50px 87 | case low = 100 // 100px 88 | case high = 250 // 250px 89 | case highest = 0 // No scale 90 | } 91 | ``` 92 | 93 | ## License 94 | 95 | The [license](https://github.com/jathu/UIImageColors/blob/master/LICENSE) is provided in the project folder. This is based on Panic's [OS X ColorArt](https://github.com/panicinc/ColorArt/#license). 96 | 97 | ------ 98 | June 2015 - Toronto 99 | -------------------------------------------------------------------------------- /UIImageColors.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = "UIImageColors" 3 | spec.version = "2.3.0" 4 | spec.license = "MIT" 5 | spec.summary = "iTunes style color fetcher for UIImage and NSImage." 6 | spec.homepage = "https://github.com/jathu/UIImageColors" 7 | spec.authors = { "Jathu Satkunarajah" => "https://twitter.com/jathu" } 8 | spec.source = { :git => "https://github.com/jathu/UIImageColors.git", :tag => spec.version } 9 | 10 | spec.ios.deployment_target = "8.0" 11 | spec.tvos.deployment_target = "9.0" 12 | spec.macos.deployment_target = "10.10" 13 | spec.source_files = "UIImageColors/Sources/*.swift" 14 | spec.requires_arc = true 15 | spec.pod_target_xcconfig = { 16 | "SWIFT_VERSION" => "5.0" 17 | } 18 | end 19 | -------------------------------------------------------------------------------- /UIImageColors.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 035BC84A1DABA020006CA9BE /* UIImageColors.h in Headers */ = {isa = PBXBuildFile; fileRef = 035BC8491DABA020006CA9BE /* UIImageColors.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 035BC84C1DABA027006CA9BE /* UIImageColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 035BC84B1DABA027006CA9BE /* UIImageColors.swift */; }; 12 | 8709D06E1FDC762E0007E717 /* AlbumViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8709D06D1FDC762E0007E717 /* AlbumViewCell.swift */; }; 13 | 871ED4461FD0B2E50062BC12 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 871ED4451FD0B2DC0062BC12 /* Foundation.framework */; }; 14 | 871ED4471FD0B2EF0062BC12 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 871ED4451FD0B2DC0062BC12 /* Foundation.framework */; }; 15 | 871ED4481FD0C12F0062BC12 /* UIImageColors.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 035BC83D1DAB9FED006CA9BE /* UIImageColors.framework */; }; 16 | 871ED4491FD0C12F0062BC12 /* UIImageColors.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 035BC83D1DAB9FED006CA9BE /* UIImageColors.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 17 | 87A73EC81FD0913A00EE147D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87A73EC71FD0913A00EE147D /* AppDelegate.swift */; }; 18 | 87A73ECA1FD0913A00EE147D /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87A73EC91FD0913A00EE147D /* ViewController.swift */; }; 19 | 87A73ECD1FD0913A00EE147D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 87A73ECB1FD0913A00EE147D /* Main.storyboard */; }; 20 | 87A73ECF1FD0913A00EE147D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 87A73ECE1FD0913A00EE147D /* Assets.xcassets */; }; 21 | 87A73ED21FD0913A00EE147D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 87A73ED01FD0913A00EE147D /* LaunchScreen.storyboard */; }; 22 | 87A73ED81FD092CD00EE147D /* Album.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87A73ED71FD092CD00EE147D /* Album.swift */; }; 23 | B57E060F21F484E0001D5009 /* NSImageColors.h in Headers */ = {isa = PBXBuildFile; fileRef = B57E060D21F484E0001D5009 /* NSImageColors.h */; settings = {ATTRIBUTES = (Public, ); }; }; 24 | B57E061721F48517001D5009 /* UIImageColors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 035BC84B1DABA027006CA9BE /* UIImageColors.swift */; }; 25 | B57E061821F4851B001D5009 /* UIImageColors.h in Headers */ = {isa = PBXBuildFile; fileRef = 035BC8491DABA020006CA9BE /* UIImageColors.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26 | /* End PBXBuildFile section */ 27 | 28 | /* Begin PBXContainerItemProxy section */ 29 | 871ED44A1FD0C12F0062BC12 /* PBXContainerItemProxy */ = { 30 | isa = PBXContainerItemProxy; 31 | containerPortal = 035BC8341DAB9FED006CA9BE /* Project object */; 32 | proxyType = 1; 33 | remoteGlobalIDString = 035BC83C1DAB9FED006CA9BE; 34 | remoteInfo = UIImageColors; 35 | }; 36 | /* End PBXContainerItemProxy section */ 37 | 38 | /* Begin PBXCopyFilesBuildPhase section */ 39 | 871ED44C1FD0C12F0062BC12 /* Embed Frameworks */ = { 40 | isa = PBXCopyFilesBuildPhase; 41 | buildActionMask = 2147483647; 42 | dstPath = ""; 43 | dstSubfolderSpec = 10; 44 | files = ( 45 | 871ED4491FD0C12F0062BC12 /* UIImageColors.framework in Embed Frameworks */, 46 | ); 47 | name = "Embed Frameworks"; 48 | runOnlyForDeploymentPostprocessing = 0; 49 | }; 50 | /* End PBXCopyFilesBuildPhase section */ 51 | 52 | /* Begin PBXFileReference section */ 53 | 035BC83D1DAB9FED006CA9BE /* UIImageColors.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = UIImageColors.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 035BC8491DABA020006CA9BE /* UIImageColors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIImageColors.h; sourceTree = ""; }; 55 | 035BC84B1DABA027006CA9BE /* UIImageColors.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImageColors.swift; sourceTree = ""; }; 56 | 035BC84E1DABA02E006CA9BE /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 57 | 8709D06D1FDC762E0007E717 /* AlbumViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlbumViewCell.swift; sourceTree = ""; }; 58 | 871ED4451FD0B2DC0062BC12 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 59 | 87A73EC51FD0913A00EE147D /* UIImageColorsExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UIImageColorsExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 60 | 87A73EC71FD0913A00EE147D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 61 | 87A73EC91FD0913A00EE147D /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 62 | 87A73ECC1FD0913A00EE147D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 63 | 87A73ECE1FD0913A00EE147D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 64 | 87A73ED11FD0913A00EE147D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 65 | 87A73ED31FD0913A00EE147D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 66 | 87A73ED71FD092CD00EE147D /* Album.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Album.swift; sourceTree = ""; }; 67 | B57E060B21F484E0001D5009 /* NSImageColors.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = NSImageColors.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 68 | B57E060D21F484E0001D5009 /* NSImageColors.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSImageColors.h; sourceTree = ""; }; 69 | B57E060E21F484E0001D5009 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 70 | /* End PBXFileReference section */ 71 | 72 | /* Begin PBXFrameworksBuildPhase section */ 73 | 035BC8391DAB9FED006CA9BE /* Frameworks */ = { 74 | isa = PBXFrameworksBuildPhase; 75 | buildActionMask = 2147483647; 76 | files = ( 77 | 871ED4461FD0B2E50062BC12 /* Foundation.framework in Frameworks */, 78 | ); 79 | runOnlyForDeploymentPostprocessing = 0; 80 | }; 81 | 87A73EC21FD0913A00EE147D /* Frameworks */ = { 82 | isa = PBXFrameworksBuildPhase; 83 | buildActionMask = 2147483647; 84 | files = ( 85 | 871ED4481FD0C12F0062BC12 /* UIImageColors.framework in Frameworks */, 86 | 871ED4471FD0B2EF0062BC12 /* Foundation.framework in Frameworks */, 87 | ); 88 | runOnlyForDeploymentPostprocessing = 0; 89 | }; 90 | B57E060821F484E0001D5009 /* Frameworks */ = { 91 | isa = PBXFrameworksBuildPhase; 92 | buildActionMask = 2147483647; 93 | files = ( 94 | ); 95 | runOnlyForDeploymentPostprocessing = 0; 96 | }; 97 | /* End PBXFrameworksBuildPhase section */ 98 | 99 | /* Begin PBXGroup section */ 100 | 035BC8331DAB9FED006CA9BE = { 101 | isa = PBXGroup; 102 | children = ( 103 | B57E05F121F48157001D5009 /* UIImageColors */, 104 | 87A73EC61FD0913A00EE147D /* UIImageColorsExample */, 105 | B57E060C21F484E0001D5009 /* NSImageColors */, 106 | 035BC83E1DAB9FED006CA9BE /* Products */, 107 | 871ED4441FD0B2DC0062BC12 /* Frameworks */, 108 | ); 109 | sourceTree = ""; 110 | }; 111 | 035BC83E1DAB9FED006CA9BE /* Products */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 035BC83D1DAB9FED006CA9BE /* UIImageColors.framework */, 115 | 87A73EC51FD0913A00EE147D /* UIImageColorsExample.app */, 116 | B57E060B21F484E0001D5009 /* NSImageColors.framework */, 117 | ); 118 | name = Products; 119 | sourceTree = ""; 120 | }; 121 | 035BC8481DABA020006CA9BE /* Sources */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 035BC8491DABA020006CA9BE /* UIImageColors.h */, 125 | 035BC84B1DABA027006CA9BE /* UIImageColors.swift */, 126 | ); 127 | name = Sources; 128 | path = UIImageColors/Sources; 129 | sourceTree = SOURCE_ROOT; 130 | }; 131 | 035BC84D1DABA02E006CA9BE /* Supporting Files */ = { 132 | isa = PBXGroup; 133 | children = ( 134 | 035BC84E1DABA02E006CA9BE /* Info.plist */, 135 | ); 136 | name = "Supporting Files"; 137 | path = "UIImageColors/Supporting Files"; 138 | sourceTree = SOURCE_ROOT; 139 | }; 140 | 871ED4441FD0B2DC0062BC12 /* Frameworks */ = { 141 | isa = PBXGroup; 142 | children = ( 143 | 871ED4451FD0B2DC0062BC12 /* Foundation.framework */, 144 | ); 145 | name = Frameworks; 146 | sourceTree = ""; 147 | }; 148 | 87A73EC61FD0913A00EE147D /* UIImageColorsExample */ = { 149 | isa = PBXGroup; 150 | children = ( 151 | 87A73EC71FD0913A00EE147D /* AppDelegate.swift */, 152 | 87A73EC91FD0913A00EE147D /* ViewController.swift */, 153 | 8709D06D1FDC762E0007E717 /* AlbumViewCell.swift */, 154 | 87A73ED71FD092CD00EE147D /* Album.swift */, 155 | 87A73ECB1FD0913A00EE147D /* Main.storyboard */, 156 | 87A73ECE1FD0913A00EE147D /* Assets.xcassets */, 157 | 87A73ED01FD0913A00EE147D /* LaunchScreen.storyboard */, 158 | 87A73ED31FD0913A00EE147D /* Info.plist */, 159 | ); 160 | path = UIImageColorsExample; 161 | sourceTree = ""; 162 | }; 163 | B57E05F121F48157001D5009 /* UIImageColors */ = { 164 | isa = PBXGroup; 165 | children = ( 166 | 035BC8481DABA020006CA9BE /* Sources */, 167 | 035BC84D1DABA02E006CA9BE /* Supporting Files */, 168 | ); 169 | path = UIImageColors; 170 | sourceTree = ""; 171 | }; 172 | B57E060C21F484E0001D5009 /* NSImageColors */ = { 173 | isa = PBXGroup; 174 | children = ( 175 | B57E060D21F484E0001D5009 /* NSImageColors.h */, 176 | B57E060E21F484E0001D5009 /* Info.plist */, 177 | ); 178 | path = NSImageColors; 179 | sourceTree = ""; 180 | }; 181 | /* End PBXGroup section */ 182 | 183 | /* Begin PBXHeadersBuildPhase section */ 184 | 035BC83A1DAB9FED006CA9BE /* Headers */ = { 185 | isa = PBXHeadersBuildPhase; 186 | buildActionMask = 2147483647; 187 | files = ( 188 | 035BC84A1DABA020006CA9BE /* UIImageColors.h in Headers */, 189 | ); 190 | runOnlyForDeploymentPostprocessing = 0; 191 | }; 192 | B57E060621F484E0001D5009 /* Headers */ = { 193 | isa = PBXHeadersBuildPhase; 194 | buildActionMask = 2147483647; 195 | files = ( 196 | B57E061821F4851B001D5009 /* UIImageColors.h in Headers */, 197 | B57E060F21F484E0001D5009 /* NSImageColors.h in Headers */, 198 | ); 199 | runOnlyForDeploymentPostprocessing = 0; 200 | }; 201 | /* End PBXHeadersBuildPhase section */ 202 | 203 | /* Begin PBXNativeTarget section */ 204 | 035BC83C1DAB9FED006CA9BE /* UIImageColors */ = { 205 | isa = PBXNativeTarget; 206 | buildConfigurationList = 035BC8451DAB9FED006CA9BE /* Build configuration list for PBXNativeTarget "UIImageColors" */; 207 | buildPhases = ( 208 | 035BC8381DAB9FED006CA9BE /* Sources */, 209 | 035BC8391DAB9FED006CA9BE /* Frameworks */, 210 | 035BC83A1DAB9FED006CA9BE /* Headers */, 211 | 035BC83B1DAB9FED006CA9BE /* Resources */, 212 | ); 213 | buildRules = ( 214 | ); 215 | dependencies = ( 216 | ); 217 | name = UIImageColors; 218 | productName = UIImageColors; 219 | productReference = 035BC83D1DAB9FED006CA9BE /* UIImageColors.framework */; 220 | productType = "com.apple.product-type.framework"; 221 | }; 222 | 87A73EC41FD0913A00EE147D /* UIImageColorsExample */ = { 223 | isa = PBXNativeTarget; 224 | buildConfigurationList = 87A73ED61FD0913A00EE147D /* Build configuration list for PBXNativeTarget "UIImageColorsExample" */; 225 | buildPhases = ( 226 | 87A73EC11FD0913A00EE147D /* Sources */, 227 | 87A73EC21FD0913A00EE147D /* Frameworks */, 228 | 87A73EC31FD0913A00EE147D /* Resources */, 229 | 871ED44C1FD0C12F0062BC12 /* Embed Frameworks */, 230 | ); 231 | buildRules = ( 232 | ); 233 | dependencies = ( 234 | 871ED44B1FD0C12F0062BC12 /* PBXTargetDependency */, 235 | ); 236 | name = UIImageColorsExample; 237 | productName = UIImageColorsExample; 238 | productReference = 87A73EC51FD0913A00EE147D /* UIImageColorsExample.app */; 239 | productType = "com.apple.product-type.application"; 240 | }; 241 | B57E060A21F484E0001D5009 /* NSImageColors */ = { 242 | isa = PBXNativeTarget; 243 | buildConfigurationList = B57E061421F484E0001D5009 /* Build configuration list for PBXNativeTarget "NSImageColors" */; 244 | buildPhases = ( 245 | B57E060621F484E0001D5009 /* Headers */, 246 | B57E060721F484E0001D5009 /* Sources */, 247 | B57E060821F484E0001D5009 /* Frameworks */, 248 | B57E060921F484E0001D5009 /* Resources */, 249 | ); 250 | buildRules = ( 251 | ); 252 | dependencies = ( 253 | ); 254 | name = NSImageColors; 255 | productName = NSImageColors; 256 | productReference = B57E060B21F484E0001D5009 /* NSImageColors.framework */; 257 | productType = "com.apple.product-type.framework"; 258 | }; 259 | /* End PBXNativeTarget section */ 260 | 261 | /* Begin PBXProject section */ 262 | 035BC8341DAB9FED006CA9BE /* Project object */ = { 263 | isa = PBXProject; 264 | attributes = { 265 | LastSwiftUpdateCheck = 1010; 266 | LastUpgradeCheck = 1010; 267 | ORGANIZATIONNAME = "Jathu Satkunarajah"; 268 | TargetAttributes = { 269 | 035BC83C1DAB9FED006CA9BE = { 270 | CreatedOnToolsVersion = 8.0; 271 | LastSwiftMigration = 1010; 272 | ProvisioningStyle = Automatic; 273 | }; 274 | 87A73EC41FD0913A00EE147D = { 275 | CreatedOnToolsVersion = 9.1; 276 | LastSwiftMigration = 1010; 277 | ProvisioningStyle = Automatic; 278 | }; 279 | B57E060A21F484E0001D5009 = { 280 | CreatedOnToolsVersion = 10.1; 281 | ProvisioningStyle = Automatic; 282 | }; 283 | }; 284 | }; 285 | buildConfigurationList = 035BC8371DAB9FED006CA9BE /* Build configuration list for PBXProject "UIImageColors" */; 286 | compatibilityVersion = "Xcode 3.2"; 287 | developmentRegion = English; 288 | hasScannedForEncodings = 0; 289 | knownRegions = ( 290 | English, 291 | en, 292 | Base, 293 | ); 294 | mainGroup = 035BC8331DAB9FED006CA9BE; 295 | productRefGroup = 035BC83E1DAB9FED006CA9BE /* Products */; 296 | projectDirPath = ""; 297 | projectRoot = ""; 298 | targets = ( 299 | 035BC83C1DAB9FED006CA9BE /* UIImageColors */, 300 | B57E060A21F484E0001D5009 /* NSImageColors */, 301 | 87A73EC41FD0913A00EE147D /* UIImageColorsExample */, 302 | ); 303 | }; 304 | /* End PBXProject section */ 305 | 306 | /* Begin PBXResourcesBuildPhase section */ 307 | 035BC83B1DAB9FED006CA9BE /* Resources */ = { 308 | isa = PBXResourcesBuildPhase; 309 | buildActionMask = 2147483647; 310 | files = ( 311 | ); 312 | runOnlyForDeploymentPostprocessing = 0; 313 | }; 314 | 87A73EC31FD0913A00EE147D /* Resources */ = { 315 | isa = PBXResourcesBuildPhase; 316 | buildActionMask = 2147483647; 317 | files = ( 318 | 87A73ED21FD0913A00EE147D /* LaunchScreen.storyboard in Resources */, 319 | 87A73ECF1FD0913A00EE147D /* Assets.xcassets in Resources */, 320 | 87A73ECD1FD0913A00EE147D /* Main.storyboard in Resources */, 321 | ); 322 | runOnlyForDeploymentPostprocessing = 0; 323 | }; 324 | B57E060921F484E0001D5009 /* Resources */ = { 325 | isa = PBXResourcesBuildPhase; 326 | buildActionMask = 2147483647; 327 | files = ( 328 | ); 329 | runOnlyForDeploymentPostprocessing = 0; 330 | }; 331 | /* End PBXResourcesBuildPhase section */ 332 | 333 | /* Begin PBXSourcesBuildPhase section */ 334 | 035BC8381DAB9FED006CA9BE /* Sources */ = { 335 | isa = PBXSourcesBuildPhase; 336 | buildActionMask = 2147483647; 337 | files = ( 338 | 035BC84C1DABA027006CA9BE /* UIImageColors.swift in Sources */, 339 | ); 340 | runOnlyForDeploymentPostprocessing = 0; 341 | }; 342 | 87A73EC11FD0913A00EE147D /* Sources */ = { 343 | isa = PBXSourcesBuildPhase; 344 | buildActionMask = 2147483647; 345 | files = ( 346 | 87A73ECA1FD0913A00EE147D /* ViewController.swift in Sources */, 347 | 87A73EC81FD0913A00EE147D /* AppDelegate.swift in Sources */, 348 | 8709D06E1FDC762E0007E717 /* AlbumViewCell.swift in Sources */, 349 | 87A73ED81FD092CD00EE147D /* Album.swift in Sources */, 350 | ); 351 | runOnlyForDeploymentPostprocessing = 0; 352 | }; 353 | B57E060721F484E0001D5009 /* Sources */ = { 354 | isa = PBXSourcesBuildPhase; 355 | buildActionMask = 2147483647; 356 | files = ( 357 | B57E061721F48517001D5009 /* UIImageColors.swift in Sources */, 358 | ); 359 | runOnlyForDeploymentPostprocessing = 0; 360 | }; 361 | /* End PBXSourcesBuildPhase section */ 362 | 363 | /* Begin PBXTargetDependency section */ 364 | 871ED44B1FD0C12F0062BC12 /* PBXTargetDependency */ = { 365 | isa = PBXTargetDependency; 366 | target = 035BC83C1DAB9FED006CA9BE /* UIImageColors */; 367 | targetProxy = 871ED44A1FD0C12F0062BC12 /* PBXContainerItemProxy */; 368 | }; 369 | /* End PBXTargetDependency section */ 370 | 371 | /* Begin PBXVariantGroup section */ 372 | 87A73ECB1FD0913A00EE147D /* Main.storyboard */ = { 373 | isa = PBXVariantGroup; 374 | children = ( 375 | 87A73ECC1FD0913A00EE147D /* Base */, 376 | ); 377 | name = Main.storyboard; 378 | sourceTree = ""; 379 | }; 380 | 87A73ED01FD0913A00EE147D /* LaunchScreen.storyboard */ = { 381 | isa = PBXVariantGroup; 382 | children = ( 383 | 87A73ED11FD0913A00EE147D /* Base */, 384 | ); 385 | name = LaunchScreen.storyboard; 386 | sourceTree = ""; 387 | }; 388 | /* End PBXVariantGroup section */ 389 | 390 | /* Begin XCBuildConfiguration section */ 391 | 035BC8431DAB9FED006CA9BE /* Debug */ = { 392 | isa = XCBuildConfiguration; 393 | buildSettings = { 394 | ALWAYS_SEARCH_USER_PATHS = NO; 395 | CLANG_ANALYZER_NONNULL = YES; 396 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 397 | CLANG_CXX_LIBRARY = "libc++"; 398 | CLANG_ENABLE_MODULES = YES; 399 | CLANG_ENABLE_OBJC_ARC = YES; 400 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 401 | CLANG_WARN_BOOL_CONVERSION = YES; 402 | CLANG_WARN_COMMA = YES; 403 | CLANG_WARN_CONSTANT_CONVERSION = YES; 404 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 405 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 406 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 407 | CLANG_WARN_EMPTY_BODY = YES; 408 | CLANG_WARN_ENUM_CONVERSION = YES; 409 | CLANG_WARN_INFINITE_RECURSION = YES; 410 | CLANG_WARN_INT_CONVERSION = YES; 411 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 412 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 413 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 414 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 415 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 416 | CLANG_WARN_STRICT_PROTOTYPES = YES; 417 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 418 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 419 | CLANG_WARN_UNREACHABLE_CODE = YES; 420 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 421 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 422 | COPY_PHASE_STRIP = NO; 423 | CURRENT_PROJECT_VERSION = 1; 424 | DEBUG_INFORMATION_FORMAT = dwarf; 425 | ENABLE_STRICT_OBJC_MSGSEND = YES; 426 | ENABLE_TESTABILITY = YES; 427 | GCC_C_LANGUAGE_STANDARD = gnu99; 428 | GCC_DYNAMIC_NO_PIC = NO; 429 | GCC_NO_COMMON_BLOCKS = YES; 430 | GCC_OPTIMIZATION_LEVEL = 0; 431 | GCC_PREPROCESSOR_DEFINITIONS = ( 432 | "DEBUG=1", 433 | "$(inherited)", 434 | ); 435 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 436 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 437 | GCC_WARN_UNDECLARED_SELECTOR = YES; 438 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 439 | GCC_WARN_UNUSED_FUNCTION = YES; 440 | GCC_WARN_UNUSED_VARIABLE = YES; 441 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 442 | MTL_ENABLE_DEBUG_INFO = YES; 443 | ONLY_ACTIVE_ARCH = YES; 444 | SDKROOT = iphoneos; 445 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 446 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 447 | SWIFT_VERSION = 5.0; 448 | TARGETED_DEVICE_FAMILY = "1,2"; 449 | VERSIONING_SYSTEM = "apple-generic"; 450 | VERSION_INFO_PREFIX = ""; 451 | }; 452 | name = Debug; 453 | }; 454 | 035BC8441DAB9FED006CA9BE /* Release */ = { 455 | isa = XCBuildConfiguration; 456 | buildSettings = { 457 | ALWAYS_SEARCH_USER_PATHS = NO; 458 | CLANG_ANALYZER_NONNULL = YES; 459 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 460 | CLANG_CXX_LIBRARY = "libc++"; 461 | CLANG_ENABLE_MODULES = YES; 462 | CLANG_ENABLE_OBJC_ARC = YES; 463 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 464 | CLANG_WARN_BOOL_CONVERSION = YES; 465 | CLANG_WARN_COMMA = YES; 466 | CLANG_WARN_CONSTANT_CONVERSION = YES; 467 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 468 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 469 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 470 | CLANG_WARN_EMPTY_BODY = YES; 471 | CLANG_WARN_ENUM_CONVERSION = YES; 472 | CLANG_WARN_INFINITE_RECURSION = YES; 473 | CLANG_WARN_INT_CONVERSION = YES; 474 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 475 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 476 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 477 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 478 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 479 | CLANG_WARN_STRICT_PROTOTYPES = YES; 480 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 481 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 482 | CLANG_WARN_UNREACHABLE_CODE = YES; 483 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 484 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 485 | COPY_PHASE_STRIP = NO; 486 | CURRENT_PROJECT_VERSION = 1; 487 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 488 | ENABLE_NS_ASSERTIONS = NO; 489 | ENABLE_STRICT_OBJC_MSGSEND = YES; 490 | GCC_C_LANGUAGE_STANDARD = gnu99; 491 | GCC_NO_COMMON_BLOCKS = YES; 492 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 493 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 494 | GCC_WARN_UNDECLARED_SELECTOR = YES; 495 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 496 | GCC_WARN_UNUSED_FUNCTION = YES; 497 | GCC_WARN_UNUSED_VARIABLE = YES; 498 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 499 | MTL_ENABLE_DEBUG_INFO = NO; 500 | SDKROOT = iphoneos; 501 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 502 | SWIFT_VERSION = 5.0; 503 | TARGETED_DEVICE_FAMILY = "1,2"; 504 | VALIDATE_PRODUCT = YES; 505 | VERSIONING_SYSTEM = "apple-generic"; 506 | VERSION_INFO_PREFIX = ""; 507 | }; 508 | name = Release; 509 | }; 510 | 035BC8461DAB9FED006CA9BE /* Debug */ = { 511 | isa = XCBuildConfiguration; 512 | buildSettings = { 513 | CLANG_ENABLE_MODULES = YES; 514 | CODE_SIGN_IDENTITY = ""; 515 | DEFINES_MODULE = YES; 516 | DEVELOPMENT_TEAM = ""; 517 | DYLIB_COMPATIBILITY_VERSION = 1; 518 | DYLIB_CURRENT_VERSION = 1; 519 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 520 | INFOPLIST_FILE = "$(SRCROOT)/UIImageColors/Supporting Files/Info.plist"; 521 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 522 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 523 | PRODUCT_BUNDLE_IDENTIFIER = me.jathu.UIImageColors; 524 | PRODUCT_NAME = "$(TARGET_NAME)"; 525 | SKIP_INSTALL = YES; 526 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 527 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 528 | SWIFT_VERSION = 5.0; 529 | }; 530 | name = Debug; 531 | }; 532 | 035BC8471DAB9FED006CA9BE /* Release */ = { 533 | isa = XCBuildConfiguration; 534 | buildSettings = { 535 | CLANG_ENABLE_MODULES = YES; 536 | CODE_SIGN_IDENTITY = ""; 537 | DEFINES_MODULE = YES; 538 | DEVELOPMENT_TEAM = ""; 539 | DYLIB_COMPATIBILITY_VERSION = 1; 540 | DYLIB_CURRENT_VERSION = 1; 541 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 542 | INFOPLIST_FILE = "$(SRCROOT)/UIImageColors/Supporting Files/Info.plist"; 543 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 544 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 545 | PRODUCT_BUNDLE_IDENTIFIER = me.jathu.UIImageColors; 546 | PRODUCT_NAME = "$(TARGET_NAME)"; 547 | SKIP_INSTALL = YES; 548 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 549 | SWIFT_VERSION = 5.0; 550 | }; 551 | name = Release; 552 | }; 553 | 87A73ED41FD0913A00EE147D /* Debug */ = { 554 | isa = XCBuildConfiguration; 555 | buildSettings = { 556 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 557 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 558 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 559 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 560 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 561 | CLANG_WARN_COMMA = YES; 562 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 563 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 564 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 565 | CLANG_WARN_STRICT_PROTOTYPES = YES; 566 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 567 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 568 | CODE_SIGN_IDENTITY = "iPhone Developer"; 569 | CODE_SIGN_STYLE = Automatic; 570 | DEVELOPMENT_TEAM = ""; 571 | GCC_C_LANGUAGE_STANDARD = gnu11; 572 | INFOPLIST_FILE = UIImageColorsExample/Info.plist; 573 | IPHONEOS_DEPLOYMENT_TARGET = 11.1; 574 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 575 | PRODUCT_BUNDLE_IDENTIFIER = com.jathu.UIImageColorsExample; 576 | PRODUCT_NAME = "$(TARGET_NAME)"; 577 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 578 | SWIFT_VERSION = 5.0; 579 | TARGETED_DEVICE_FAMILY = "1,2"; 580 | }; 581 | name = Debug; 582 | }; 583 | 87A73ED51FD0913A00EE147D /* Release */ = { 584 | isa = XCBuildConfiguration; 585 | buildSettings = { 586 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 587 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 588 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 589 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 590 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 591 | CLANG_WARN_COMMA = YES; 592 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 593 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 594 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 595 | CLANG_WARN_STRICT_PROTOTYPES = YES; 596 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 597 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 598 | CODE_SIGN_IDENTITY = "iPhone Developer"; 599 | CODE_SIGN_STYLE = Automatic; 600 | DEVELOPMENT_TEAM = ""; 601 | GCC_C_LANGUAGE_STANDARD = gnu11; 602 | INFOPLIST_FILE = UIImageColorsExample/Info.plist; 603 | IPHONEOS_DEPLOYMENT_TARGET = 11.1; 604 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 605 | PRODUCT_BUNDLE_IDENTIFIER = com.jathu.UIImageColorsExample; 606 | PRODUCT_NAME = "$(TARGET_NAME)"; 607 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 608 | SWIFT_VERSION = 5.0; 609 | TARGETED_DEVICE_FAMILY = "1,2"; 610 | }; 611 | name = Release; 612 | }; 613 | B57E061521F484E0001D5009 /* Debug */ = { 614 | isa = XCBuildConfiguration; 615 | buildSettings = { 616 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 617 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 618 | CLANG_ENABLE_OBJC_WEAK = YES; 619 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 620 | CODE_SIGN_IDENTITY = "-"; 621 | CODE_SIGN_STYLE = Automatic; 622 | COMBINE_HIDPI_IMAGES = YES; 623 | DEFINES_MODULE = YES; 624 | DYLIB_COMPATIBILITY_VERSION = 1; 625 | DYLIB_CURRENT_VERSION = 1; 626 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 627 | FRAMEWORK_VERSION = A; 628 | GCC_C_LANGUAGE_STANDARD = gnu11; 629 | INFOPLIST_FILE = NSImageColors/Info.plist; 630 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 631 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 632 | MACOSX_DEPLOYMENT_TARGET = 10.11; 633 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 634 | MTL_FAST_MATH = YES; 635 | PRODUCT_BUNDLE_IDENTIFIER = com.jathu.NSImageColors; 636 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 637 | SDKROOT = macosx; 638 | SKIP_INSTALL = YES; 639 | SWIFT_VERSION = 5.0; 640 | }; 641 | name = Debug; 642 | }; 643 | B57E061621F484E0001D5009 /* Release */ = { 644 | isa = XCBuildConfiguration; 645 | buildSettings = { 646 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 647 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 648 | CLANG_ENABLE_OBJC_WEAK = YES; 649 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 650 | CODE_SIGN_IDENTITY = "-"; 651 | CODE_SIGN_STYLE = Automatic; 652 | COMBINE_HIDPI_IMAGES = YES; 653 | DEFINES_MODULE = YES; 654 | DYLIB_COMPATIBILITY_VERSION = 1; 655 | DYLIB_CURRENT_VERSION = 1; 656 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 657 | FRAMEWORK_VERSION = A; 658 | GCC_C_LANGUAGE_STANDARD = gnu11; 659 | INFOPLIST_FILE = NSImageColors/Info.plist; 660 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 661 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 662 | MACOSX_DEPLOYMENT_TARGET = 10.11; 663 | MTL_FAST_MATH = YES; 664 | PRODUCT_BUNDLE_IDENTIFIER = com.jathu.NSImageColors; 665 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 666 | SDKROOT = macosx; 667 | SKIP_INSTALL = YES; 668 | SWIFT_VERSION = 5.0; 669 | }; 670 | name = Release; 671 | }; 672 | /* End XCBuildConfiguration section */ 673 | 674 | /* Begin XCConfigurationList section */ 675 | 035BC8371DAB9FED006CA9BE /* Build configuration list for PBXProject "UIImageColors" */ = { 676 | isa = XCConfigurationList; 677 | buildConfigurations = ( 678 | 035BC8431DAB9FED006CA9BE /* Debug */, 679 | 035BC8441DAB9FED006CA9BE /* Release */, 680 | ); 681 | defaultConfigurationIsVisible = 0; 682 | defaultConfigurationName = Release; 683 | }; 684 | 035BC8451DAB9FED006CA9BE /* Build configuration list for PBXNativeTarget "UIImageColors" */ = { 685 | isa = XCConfigurationList; 686 | buildConfigurations = ( 687 | 035BC8461DAB9FED006CA9BE /* Debug */, 688 | 035BC8471DAB9FED006CA9BE /* Release */, 689 | ); 690 | defaultConfigurationIsVisible = 0; 691 | defaultConfigurationName = Release; 692 | }; 693 | 87A73ED61FD0913A00EE147D /* Build configuration list for PBXNativeTarget "UIImageColorsExample" */ = { 694 | isa = XCConfigurationList; 695 | buildConfigurations = ( 696 | 87A73ED41FD0913A00EE147D /* Debug */, 697 | 87A73ED51FD0913A00EE147D /* Release */, 698 | ); 699 | defaultConfigurationIsVisible = 0; 700 | defaultConfigurationName = Release; 701 | }; 702 | B57E061421F484E0001D5009 /* Build configuration list for PBXNativeTarget "NSImageColors" */ = { 703 | isa = XCConfigurationList; 704 | buildConfigurations = ( 705 | B57E061521F484E0001D5009 /* Debug */, 706 | B57E061621F484E0001D5009 /* Release */, 707 | ); 708 | defaultConfigurationIsVisible = 0; 709 | defaultConfigurationName = Release; 710 | }; 711 | /* End XCConfigurationList section */ 712 | }; 713 | rootObject = 035BC8341DAB9FED006CA9BE /* Project object */; 714 | } 715 | -------------------------------------------------------------------------------- /UIImageColors.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /UIImageColors.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /UIImageColors.xcodeproj/xcshareddata/xcschemes/NSImageColors.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /UIImageColors.xcodeproj/xcshareddata/xcschemes/UIImageColors.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /UIImageColors/Sources/UIImageColors.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageColors.h 3 | // UIImageColors 4 | // 5 | // Created by Suyeol Jeon on 10/10/2016. 6 | // Copyright © 2016 Jathu Satkunarajah (@jathu) - Toronto. All rights reserved. 7 | // 8 | 9 | #if TARGET_OS_MAC 10 | #import 11 | #else 12 | #import 13 | #endif 14 | 15 | //! Project version number for UIImageColors. 16 | FOUNDATION_EXPORT double UIImageColorsVersionNumber; 17 | 18 | //! Project version string for UIImageColors. 19 | FOUNDATION_EXPORT const unsigned char UIImageColorsVersionString[]; 20 | 21 | // In this header, you should import all the public headers of your framework using statements like #import 22 | 23 | 24 | -------------------------------------------------------------------------------- /UIImageColors/Sources/UIImageColors.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageColors.swift 3 | // https://github.com/jathu/UIImageColors 4 | // 5 | // Created by Jathu Satkunarajah (@jathu) on 2015-06-11 - Toronto 6 | // Based on Cocoa version by Panic Inc. - Portland 7 | // 8 | 9 | #if os(OSX) 10 | import AppKit 11 | public typealias UIImage = NSImage 12 | public typealias UIColor = NSColor 13 | #else 14 | import UIKit 15 | #endif 16 | 17 | public struct UIImageColors { 18 | public var background: UIColor! 19 | public var primary: UIColor! 20 | public var secondary: UIColor! 21 | public var detail: UIColor! 22 | 23 | public init(background: UIColor, primary: UIColor, secondary: UIColor, detail: UIColor) { 24 | self.background = background 25 | self.primary = primary 26 | self.secondary = secondary 27 | self.detail = detail 28 | } 29 | } 30 | 31 | public enum UIImageColorsQuality: CGFloat { 32 | case lowest = 50 // 50px 33 | case low = 100 // 100px 34 | case high = 250 // 250px 35 | case highest = 0 // No scale 36 | } 37 | 38 | fileprivate struct UIImageColorsCounter { 39 | let color: Double 40 | let count: Int 41 | init(color: Double, count: Int) { 42 | self.color = color 43 | self.count = count 44 | } 45 | } 46 | 47 | /* 48 | Extension on double that replicates UIColor methods. We DO NOT want these 49 | exposed outside of the library because they don't make sense outside of the 50 | context of UIImageColors. 51 | */ 52 | fileprivate extension Double { 53 | 54 | private var r: Double { 55 | return fmod(floor(self/1000000),1000000) 56 | } 57 | 58 | private var g: Double { 59 | return fmod(floor(self/1000),1000) 60 | } 61 | 62 | private var b: Double { 63 | return fmod(self,1000) 64 | } 65 | 66 | var isDarkColor: Bool { 67 | return (r*0.2126) + (g*0.7152) + (b*0.0722) < 127.5 68 | } 69 | 70 | var isBlackOrWhite: Bool { 71 | return (r > 232 && g > 232 && b > 232) || (r < 23 && g < 23 && b < 23) 72 | } 73 | 74 | func isDistinct(_ other: Double) -> Bool { 75 | let _r = self.r 76 | let _g = self.g 77 | let _b = self.b 78 | let o_r = other.r 79 | let o_g = other.g 80 | let o_b = other.b 81 | 82 | return (fabs(_r-o_r) > 63.75 || fabs(_g-o_g) > 63.75 || fabs(_b-o_b) > 63.75) 83 | && !(fabs(_r-_g) < 7.65 && fabs(_r-_b) < 7.65 && fabs(o_r-o_g) < 7.65 && fabs(o_r-o_b) < 7.65) 84 | } 85 | 86 | func with(minSaturation: Double) -> Double { 87 | // Ref: https://en.wikipedia.org/wiki/HSL_and_HSV 88 | 89 | // Convert RGB to HSV 90 | 91 | let _r = r/255 92 | let _g = g/255 93 | let _b = b/255 94 | var H, S, V: Double 95 | let M = fmax(_r,fmax(_g, _b)) 96 | var C = M-fmin(_r,fmin(_g, _b)) 97 | 98 | V = M 99 | S = V == 0 ? 0:C/V 100 | 101 | if minSaturation <= S { 102 | return self 103 | } 104 | 105 | if C == 0 { 106 | H = 0 107 | } else if _r == M { 108 | H = fmod((_g-_b)/C, 6) 109 | } else if _g == M { 110 | H = 2+((_b-_r)/C) 111 | } else { 112 | H = 4+((_r-_g)/C) 113 | } 114 | 115 | if H < 0 { 116 | H += 6 117 | } 118 | 119 | // Back to RGB 120 | 121 | C = V*minSaturation 122 | let X = C*(1-fabs(fmod(H,2)-1)) 123 | var R, G, B: Double 124 | 125 | switch H { 126 | case 0...1: 127 | R = C 128 | G = X 129 | B = 0 130 | case 1...2: 131 | R = X 132 | G = C 133 | B = 0 134 | case 2...3: 135 | R = 0 136 | G = C 137 | B = X 138 | case 3...4: 139 | R = 0 140 | G = X 141 | B = C 142 | case 4...5: 143 | R = X 144 | G = 0 145 | B = C 146 | case 5..<6: 147 | R = C 148 | G = 0 149 | B = X 150 | default: 151 | R = 0 152 | G = 0 153 | B = 0 154 | } 155 | 156 | let m = V-C 157 | 158 | return (floor((R + m)*255)*1000000)+(floor((G + m)*255)*1000)+floor((B + m)*255) 159 | } 160 | 161 | func isContrasting(_ color: Double) -> Bool { 162 | let bgLum = (0.2126*r)+(0.7152*g)+(0.0722*b)+12.75 163 | let fgLum = (0.2126*color.r)+(0.7152*color.g)+(0.0722*color.b)+12.75 164 | if bgLum > fgLum { 165 | return 1.6 < bgLum/fgLum 166 | } else { 167 | return 1.6 < fgLum/bgLum 168 | } 169 | } 170 | 171 | var uicolor: UIColor { 172 | return UIColor(red: CGFloat(r)/255, green: CGFloat(g)/255, blue: CGFloat(b)/255, alpha: 1) 173 | } 174 | 175 | var pretty: String { 176 | return "\(Int(self.r)), \(Int(self.g)), \(Int(self.b))" 177 | } 178 | } 179 | 180 | extension UIImage { 181 | #if os(OSX) 182 | private func resizeForUIImageColors(newSize: CGSize) -> UIImage? { 183 | let frame = CGRect(origin: .zero, size: newSize) 184 | guard let representation = bestRepresentation(for: frame, context: nil, hints: nil) else { 185 | return nil 186 | } 187 | let result = NSImage(size: newSize, flipped: false, drawingHandler: { (_) -> Bool in 188 | return representation.draw(in: frame) 189 | }) 190 | 191 | return result 192 | } 193 | #else 194 | private func resizeForUIImageColors(newSize: CGSize) -> UIImage? { 195 | UIGraphicsBeginImageContextWithOptions(newSize, false, 0) 196 | defer { 197 | UIGraphicsEndImageContext() 198 | } 199 | self.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)) 200 | guard let result = UIGraphicsGetImageFromCurrentImageContext() else { 201 | fatalError("UIImageColors.resizeForUIImageColors failed: UIGraphicsGetImageFromCurrentImageContext returned nil.") 202 | } 203 | 204 | return result 205 | } 206 | #endif 207 | 208 | public func getColors(quality: UIImageColorsQuality = .high, _ completion: @escaping (UIImageColors?) -> Void) { 209 | DispatchQueue.global().async { 210 | let result = self.getColors(quality: quality) 211 | DispatchQueue.main.async { 212 | completion(result) 213 | } 214 | } 215 | } 216 | 217 | public func getColors(quality: UIImageColorsQuality = .high) -> UIImageColors? { 218 | var scaleDownSize: CGSize = self.size 219 | if quality != .highest { 220 | if self.size.width < self.size.height { 221 | let ratio = self.size.height/self.size.width 222 | scaleDownSize = CGSize(width: quality.rawValue/ratio, height: quality.rawValue) 223 | } else { 224 | let ratio = self.size.width/self.size.height 225 | scaleDownSize = CGSize(width: quality.rawValue, height: quality.rawValue/ratio) 226 | } 227 | } 228 | 229 | guard let resizedImage = self.resizeForUIImageColors(newSize: scaleDownSize) else { return nil } 230 | 231 | #if os(OSX) 232 | guard let cgImage = resizedImage.cgImage(forProposedRect: nil, context: nil, hints: nil) else { return nil } 233 | #else 234 | guard let cgImage = resizedImage.cgImage else { return nil } 235 | #endif 236 | 237 | let width: Int = cgImage.width 238 | let height: Int = cgImage.height 239 | 240 | let threshold = Int(CGFloat(height)*0.01) 241 | var proposed: [Double] = [-1,-1,-1,-1] 242 | 243 | guard let data = CFDataGetBytePtr(cgImage.dataProvider!.data) else { 244 | fatalError("UIImageColors.getColors failed: could not get cgImage data.") 245 | } 246 | 247 | let imageColors = NSCountedSet(capacity: width*height) 248 | for x in 0.. ComparisonResult in 258 | let m = main as! UIImageColorsCounter, o = other as! UIImageColorsCounter 259 | if m.count < o.count { 260 | return .orderedDescending 261 | } else if m.count == o.count { 262 | return .orderedSame 263 | } else { 264 | return .orderedAscending 265 | } 266 | } 267 | 268 | var enumerator = imageColors.objectEnumerator() 269 | var sortedColors = NSMutableArray(capacity: imageColors.count) 270 | while let K = enumerator.nextObject() as? Double { 271 | let C = imageColors.count(for: K) 272 | if threshold < C { 273 | sortedColors.add(UIImageColorsCounter(color: K, count: C)) 274 | } 275 | } 276 | sortedColors.sort(comparator: sortedColorComparator) 277 | 278 | var proposedEdgeColor: UIImageColorsCounter 279 | if 0 < sortedColors.count { 280 | proposedEdgeColor = sortedColors.object(at: 0) as! UIImageColorsCounter 281 | } else { 282 | proposedEdgeColor = UIImageColorsCounter(color: 0, count: 1) 283 | } 284 | 285 | if proposedEdgeColor.color.isBlackOrWhite && 0 < sortedColors.count { 286 | for i in 1.. 0.3 { 289 | if !nextProposedEdgeColor.color.isBlackOrWhite { 290 | proposedEdgeColor = nextProposedEdgeColor 291 | break 292 | } 293 | } else { 294 | break 295 | } 296 | } 297 | } 298 | proposed[0] = proposedEdgeColor.color 299 | 300 | enumerator = imageColors.objectEnumerator() 301 | sortedColors.removeAllObjects() 302 | sortedColors = NSMutableArray(capacity: imageColors.count) 303 | let findDarkTextColor = !proposed[0].isDarkColor 304 | 305 | while var K = enumerator.nextObject() as? Double { 306 | K = K.with(minSaturation: 0.15) 307 | if K.isDarkColor == findDarkTextColor { 308 | let C = imageColors.count(for: K) 309 | sortedColors.add(UIImageColorsCounter(color: K, count: C)) 310 | } 311 | } 312 | sortedColors.sort(comparator: sortedColorComparator) 313 | 314 | for color in sortedColors { 315 | let color = (color as! UIImageColorsCounter).color 316 | 317 | if proposed[1] == -1 { 318 | if color.isContrasting(proposed[0]) { 319 | proposed[1] = color 320 | } 321 | } else if proposed[2] == -1 { 322 | if !color.isContrasting(proposed[0]) || !proposed[1].isDistinct(color) { 323 | continue 324 | } 325 | proposed[2] = color 326 | } else if proposed[3] == -1 { 327 | if !color.isContrasting(proposed[0]) || !proposed[2].isDistinct(color) || !proposed[1].isDistinct(color) { 328 | continue 329 | } 330 | proposed[3] = color 331 | break 332 | } 333 | } 334 | 335 | let isDarkBackground = proposed[0].isDarkColor 336 | for i in 1...3 { 337 | if proposed[i] == -1 { 338 | proposed[i] = isDarkBackground ? 255255255:0 339 | } 340 | } 341 | 342 | return UIImageColors( 343 | background: proposed[0].uicolor, 344 | primary: proposed[1].uicolor, 345 | secondary: proposed[2].uicolor, 346 | detail: proposed[3].uicolor 347 | ) 348 | } 349 | } 350 | 351 | -------------------------------------------------------------------------------- /UIImageColors/Supporting Files/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 2.3.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /UIImageColorsExample/Album.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Album.swift 3 | // UIImageColorsExample 4 | // 5 | // Created by Jathu Satkunarajah on 2017-11-30 - Toronto 6 | // Copyright © 2017 Jathu Satkunarajah. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | struct Album { 12 | let albumImage: UIImage? 13 | let albumName: String 14 | let artistName: String 15 | let year: Int 16 | 17 | public init(albumImage: UIImage?, albumName: String, artistName: String, year: Int) { 18 | self.albumImage = albumImage 19 | self.albumName = albumName 20 | self.artistName = artistName 21 | self.year = year 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /UIImageColorsExample/AlbumViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AlbumViewCell.swift 3 | // UIImageColorsExample 4 | // 5 | // Created by Jathu Satkunarajah on 2017-11-30 - Toronto 6 | // Copyright © 2017 Jathu Satkunarajah. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class AlbumViewCell: UICollectionViewCell { 12 | 13 | let imageView: UIImageView = { 14 | let i = UIImageView() 15 | i.translatesAutoresizingMaskIntoConstraints = false 16 | i.contentMode = .scaleAspectFill 17 | i.layer.masksToBounds = true 18 | return i 19 | }() 20 | 21 | override init(frame: CGRect) { 22 | super.init(frame: frame) 23 | 24 | // Add subview 25 | self.contentView.addSubview(self.imageView) 26 | 27 | // Constraints 28 | NSLayoutConstraint.activate([ 29 | self.imageView.topAnchor.constraint(equalTo: self.contentView.topAnchor), 30 | self.imageView.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor), 31 | self.imageView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor), 32 | self.imageView.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor), 33 | ]) 34 | } 35 | 36 | required init?(coder aDecoder: NSCoder) { 37 | fatalError("init(coder:) has not been implemented") 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /UIImageColorsExample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // UIImageColorsExample 4 | // 5 | // Created by Jathu Satkunarajah on 2017-11-30 - Toronto 6 | // Copyright © 2017 Jathu Satkunarajah. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | 18 | // Override storyboard 19 | self.window = UIWindow(frame: UIScreen.main.bounds) 20 | self.window?.makeKeyAndVisible() 21 | self.window?.rootViewController = ViewController() 22 | 23 | return true 24 | } 25 | 26 | 27 | } 28 | 29 | -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Blue Nude II - Henri Matisse.imageset/Blue Nude II - Henri Matisse.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jathu/UIImageColors/f064be8ee0b03158e61135e6c384aee18d7a5414/UIImageColorsExample/Assets.xcassets/Blue Nude II - Henri Matisse.imageset/Blue Nude II - Henri Matisse.jpg -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Blue Nude II - Henri Matisse.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Blue Nude II - Henri Matisse.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Cafe Terrace at Night - Vincent Van Gogh.imageset/Cafe Terrace at Night - Vincent Van Gogh.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jathu/UIImageColors/f064be8ee0b03158e61135e6c384aee18d7a5414/UIImageColorsExample/Assets.xcassets/Cafe Terrace at Night - Vincent Van Gogh.imageset/Cafe Terrace at Night - Vincent Van Gogh.jpg -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Cafe Terrace at Night - Vincent Van Gogh.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Cafe Terrace at Night - Vincent Van Gogh.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Calvin Klein - Kaws.imageset/Calvin Klein - Kaws.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jathu/UIImageColors/f064be8ee0b03158e61135e6c384aee18d7a5414/UIImageColorsExample/Assets.xcassets/Calvin Klein - Kaws.imageset/Calvin Klein - Kaws.jpg -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Calvin Klein - Kaws.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Calvin Klein - Kaws.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Le Reve - Pablo Picasso.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Le Reve - Pablo Picasso.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Le Reve - Pablo Picasso.imageset/Le Reve - Pablo Picasso.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jathu/UIImageColors/f064be8ee0b03158e61135e6c384aee18d7a5414/UIImageColorsExample/Assets.xcassets/Le Reve - Pablo Picasso.imageset/Le Reve - Pablo Picasso.jpg -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Les Demoiselles d'Avignon - Picasso.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Les Demoiselles d'Avignon - Picasso.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Les Demoiselles d'Avignon - Picasso.imageset/Les Demoiselles d'Avignon - Picasso.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jathu/UIImageColors/f064be8ee0b03158e61135e6c384aee18d7a5414/UIImageColorsExample/Assets.xcassets/Les Demoiselles d'Avignon - Picasso.imageset/Les Demoiselles d'Avignon - Picasso.jpg -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Mona Lisa - Leonardo da Vinci.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Mona Lisa - Leonardo da Vinci.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Mona Lisa - Leonardo da Vinci.imageset/Mona Lisa - Leonardo da Vinci.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jathu/UIImageColors/f064be8ee0b03158e61135e6c384aee18d7a5414/UIImageColorsExample/Assets.xcassets/Mona Lisa - Leonardo da Vinci.imageset/Mona Lisa - Leonardo da Vinci.jpg -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Nighthawks - Edward Hopper.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Nighthawks - Edward Hopper.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Nighthawks - Edward Hopper.imageset/Nighthawks - Edward Hopper.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jathu/UIImageColors/f064be8ee0b03158e61135e6c384aee18d7a5414/UIImageColorsExample/Assets.xcassets/Nighthawks - Edward Hopper.imageset/Nighthawks - Edward Hopper.jpg -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/No. 210:No. 211 - Mark Rothko.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "No. 210:No. 211 - Mark Rothko.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/No. 210:No. 211 - Mark Rothko.imageset/No. 210:No. 211 - Mark Rothko.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jathu/UIImageColors/f064be8ee0b03158e61135e6c384aee18d7a5414/UIImageColorsExample/Assets.xcassets/No. 210:No. 211 - Mark Rothko.imageset/No. 210:No. 211 - Mark Rothko.jpg -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Number 1A - Jackson Pollock.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Number 1A - Jackson Pollock.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Number 1A - Jackson Pollock.imageset/Number 1A - Jackson Pollock.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jathu/UIImageColors/f064be8ee0b03158e61135e6c384aee18d7a5414/UIImageColorsExample/Assets.xcassets/Number 1A - Jackson Pollock.imageset/Number 1A - Jackson Pollock.jpg -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Self-portrait Spring 1887 - Vincent Van Gogh.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Self-portrait Spring 1887 - Vincent Van Gogh.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Self-portrait Spring 1887 - Vincent Van Gogh.imageset/Self-portrait Spring 1887 - Vincent Van Gogh.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jathu/UIImageColors/f064be8ee0b03158e61135e6c384aee18d7a5414/UIImageColorsExample/Assets.xcassets/Self-portrait Spring 1887 - Vincent Van Gogh.imageset/Self-portrait Spring 1887 - Vincent Van Gogh.jpg -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Skull - Jean-Michel Basquiat.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Skull - Jean-Michel Basquiat.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Skull - Jean-Michel Basquiat.imageset/Skull - Jean-Michel Basquiat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jathu/UIImageColors/f064be8ee0b03158e61135e6c384aee18d7a5414/UIImageColorsExample/Assets.xcassets/Skull - Jean-Michel Basquiat.imageset/Skull - Jean-Michel Basquiat.jpg -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Woman I - Willem de Kooning.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Woman I - Willem de Kooning.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/Woman I - Willem de Kooning.imageset/Woman I - Willem de Kooning.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jathu/UIImageColors/f064be8ee0b03158e61135e6c384aee18d7a5414/UIImageColorsExample/Assets.xcassets/Woman I - Willem de Kooning.imageset/Woman I - Willem de Kooning.jpg -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/play.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "play@1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "play@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "play@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/play.imageset/play@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jathu/UIImageColors/f064be8ee0b03158e61135e6c384aee18d7a5414/UIImageColorsExample/Assets.xcassets/play.imageset/play@1x.png -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/play.imageset/play@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jathu/UIImageColors/f064be8ee0b03158e61135e6c384aee18d7a5414/UIImageColorsExample/Assets.xcassets/play.imageset/play@2x.png -------------------------------------------------------------------------------- /UIImageColorsExample/Assets.xcassets/play.imageset/play@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jathu/UIImageColors/f064be8ee0b03158e61135e6c384aee18d7a5414/UIImageColorsExample/Assets.xcassets/play.imageset/play@3x.png -------------------------------------------------------------------------------- /UIImageColorsExample/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 | -------------------------------------------------------------------------------- /UIImageColorsExample/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /UIImageColorsExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UIViewControllerBasedStatusBarAppearance 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /UIImageColorsExample/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // UIImageColorsExample 4 | // 5 | // Created by Jathu Satkunarajah on 2017-11-30 - Toronto 6 | // Copyright © 2017 Jathu Satkunarajah. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import UIImageColors 11 | 12 | class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { 13 | 14 | let albums: [Album] = [ 15 | Album(albumImage: #imageLiteral(resourceName: "Calvin Klein - Kaws"), albumName: "Calvin Klein", artistName: "Kaws", year: 1999), 16 | Album(albumImage: #imageLiteral(resourceName: "Cafe Terrace at Night - Vincent Van Gogh"), albumName: "Cafe Terrace at Night", artistName: "Vincent Van Gogh", year: 1888), 17 | Album(albumImage: #imageLiteral(resourceName: "Woman I - Willem de Kooning"), albumName: "Woman I", artistName: "Willem de Kooning", year: 1952), 18 | Album(albumImage: #imageLiteral(resourceName: "Skull - Jean-Michel Basquiat"), albumName: "Skull", artistName: "Jean-Michel Basquiat", year: 1981), 19 | Album(albumImage: #imageLiteral(resourceName: "Les Demoiselles d'Avignon - Picasso"), albumName: "Les Demoiselles d'Avignon", artistName: "Pablo Picasso", year: 1907), 20 | Album(albumImage: #imageLiteral(resourceName: "Le Reve - Pablo Picasso"), albumName: "Le Rêve", artistName: "Pablo Picasso", year: 1932), 21 | Album(albumImage: #imageLiteral(resourceName: "Mona Lisa - Leonardo da Vinci"), albumName: "Mona Lisa", artistName: "Leonardo da Vinci", year: 1503), 22 | Album(albumImage: #imageLiteral(resourceName: "No. 210:No. 211 - Mark Rothko"), albumName: "No. 210/211 Orange", artistName: "Mark Rothko", year: 1960), 23 | Album(albumImage: #imageLiteral(resourceName: "Blue Nude II - Henri Matisse"), albumName: "Blue Nude II", artistName: "Henri Matisse", year: 1952), 24 | Album(albumImage: #imageLiteral(resourceName: "Nighthawks - Edward Hopper"), albumName: "Nighthawks", artistName: "Edward Hopper", year: 1942), 25 | Album(albumImage: #imageLiteral(resourceName: "Number 1A - Jackson Pollock"), albumName: "Number 1A", artistName: "Jackson Pollock", year: 1948), 26 | Album(albumImage: #imageLiteral(resourceName: "Self-portrait Spring 1887 - Vincent Van Gogh"), albumName: "Self-Portrait", artistName: "Vincent Van Gogh", year: 1887), 27 | ] 28 | 29 | private let cellID = "cellID" 30 | private let cellSizeFactor: CGFloat = 0.8 31 | private lazy var cellSize: CGSize = { 32 | let w = self.view.frame.width 33 | return CGSize(width: w*self.cellSizeFactor, height: w) 34 | }() 35 | private lazy var cellSpacing: CGFloat = { 36 | return self.view.frame.width*((1-self.cellSizeFactor)/4) 37 | }() 38 | private lazy var collectionView: UICollectionView = { 39 | let l = UICollectionViewFlowLayout() 40 | l.scrollDirection = .horizontal 41 | l.minimumInteritemSpacing = 0 42 | l.minimumLineSpacing = self.cellSpacing 43 | let c = UICollectionView(frame: .zero, collectionViewLayout: l) 44 | c.translatesAutoresizingMaskIntoConstraints = false 45 | c.isScrollEnabled = true 46 | c.isPagingEnabled = false 47 | c.showsHorizontalScrollIndicator = false 48 | c.showsVerticalScrollIndicator = false 49 | c.backgroundColor = .clear 50 | c.register(AlbumViewCell.self, forCellWithReuseIdentifier: self.cellID) 51 | c.dataSource = self 52 | c.delegate = self 53 | return c 54 | }() 55 | 56 | private let mainLabel: UILabel = { 57 | let l = UILabel() 58 | l.translatesAutoresizingMaskIntoConstraints = false 59 | l.textAlignment = .left 60 | l.numberOfLines = 2 61 | l.font = UIFont.systemFont(ofSize: 25, weight: UIFont.Weight.regular) 62 | return l 63 | }() 64 | 65 | private let secondaryLabel: UILabel = { 66 | let l = UILabel() 67 | l.translatesAutoresizingMaskIntoConstraints = false 68 | l.textAlignment = .left 69 | l.numberOfLines = 1 70 | l.font = UIFont.systemFont(ofSize: 20, weight: UIFont.Weight.regular) 71 | return l 72 | }() 73 | 74 | private let detailLabel: UILabel = { 75 | let l = UILabel() 76 | l.translatesAutoresizingMaskIntoConstraints = false 77 | l.textAlignment = .left 78 | l.numberOfLines = 1 79 | l.font = UIFont.systemFont(ofSize: 15, weight: UIFont.Weight.regular) 80 | return l 81 | }() 82 | 83 | private var selectedIndex: IndexPath? 84 | private var timer: Timer? 85 | private let playButton: UIButton = { 86 | let b = UIButton() 87 | b.translatesAutoresizingMaskIntoConstraints = false 88 | b.setImage(#imageLiteral(resourceName: "play").withRenderingMode(.alwaysTemplate), for: .normal) 89 | b.tintColor = .white 90 | return b 91 | }() 92 | 93 | override var prefersStatusBarHidden: Bool { 94 | return true 95 | } 96 | 97 | override func viewDidLoad() { 98 | super.viewDidLoad() 99 | self.view.backgroundColor = .white 100 | 101 | // Add subviews 102 | self.view.addSubview(self.collectionView) 103 | self.view.addSubview(self.mainLabel) 104 | self.view.addSubview(self.secondaryLabel) 105 | self.view.addSubview(self.detailLabel) 106 | self.view.addSubview(self.playButton) 107 | 108 | // Constraints 109 | NSLayoutConstraint.activate([ 110 | self.collectionView.widthAnchor.constraint(equalTo: self.view.widthAnchor), 111 | self.collectionView.heightAnchor.constraint(equalTo: self.view.heightAnchor, multiplier: 0.6), 112 | self.collectionView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor), 113 | self.collectionView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor), 114 | 115 | self.mainLabel.widthAnchor.constraint(equalTo: self.view.widthAnchor, multiplier: self.cellSizeFactor), 116 | self.mainLabel.centerXAnchor.constraint(equalTo: self.view.centerXAnchor), 117 | self.mainLabel.bottomAnchor.constraint(equalTo: self.collectionView.topAnchor), 118 | 119 | self.secondaryLabel.widthAnchor.constraint(equalTo: self.mainLabel.widthAnchor), 120 | self.secondaryLabel.centerXAnchor.constraint(equalTo: self.view.centerXAnchor), 121 | self.secondaryLabel.topAnchor.constraint(equalTo: self.collectionView.bottomAnchor), 122 | 123 | self.detailLabel.widthAnchor.constraint(equalTo: self.mainLabel.widthAnchor), 124 | self.detailLabel.centerXAnchor.constraint(equalTo: self.view.centerXAnchor), 125 | self.detailLabel.topAnchor.constraint(equalTo: self.secondaryLabel.bottomAnchor), 126 | 127 | self.playButton.widthAnchor.constraint(equalToConstant: 24), 128 | self.playButton.heightAnchor.constraint(equalToConstant: 24), 129 | self.playButton.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -12), 130 | self.playButton.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -12), 131 | ]) 132 | 133 | // Set up play button 134 | self.playButton.addTarget(self, action: #selector(setupPlayTimer), for: .touchUpInside) 135 | 136 | // Update view 137 | self.selectedIndex = IndexPath(item: 0, section: 0) 138 | self.updateView(with: self.albums[0]) 139 | } 140 | 141 | @objc func setupPlayTimer() { 142 | if self.timer == nil { 143 | self.timer = Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(startPlaying), userInfo: nil, repeats: true) 144 | self.playButton.isHidden = true 145 | } 146 | } 147 | 148 | @objc func startPlaying() { 149 | if let index = self.selectedIndex { 150 | self.selectedIndex = IndexPath(item: (index.item+1)%self.albums.count, section: 0) 151 | self.goTo(indexPath: self.selectedIndex) 152 | } 153 | } 154 | 155 | func goTo(indexPath: IndexPath?) { 156 | if let index = indexPath { 157 | self.collectionView.scrollToItem(at: index, at: .centeredHorizontally, animated: true) 158 | self.updateView(with: self.albums[index.item]) 159 | } 160 | } 161 | 162 | // Mark: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout 163 | 164 | func numberOfSections(in collectionView: UICollectionView) -> Int { 165 | return 1 166 | } 167 | 168 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 169 | return self.albums.count 170 | } 171 | 172 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 173 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: self.cellID, for: indexPath) as! AlbumViewCell 174 | cell.imageView.image = self.albums[indexPath.item].albumImage 175 | return cell 176 | } 177 | 178 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { 179 | return self.cellSize 180 | } 181 | 182 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { 183 | return UIEdgeInsets(top: 0, left: self.cellSpacing*2, bottom: 0, right: self.cellSpacing*2) 184 | } 185 | 186 | func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { 187 | if let _ = self.timer { 188 | self.timer?.invalidate() 189 | self.timer = nil 190 | self.playButton.isHidden = false 191 | } 192 | } 193 | 194 | func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { 195 | let rect = CGRect(origin: self.collectionView.contentOffset, size: self.collectionView.bounds.size) 196 | let mid = CGPoint(x: rect.midX, y: rect.midY) 197 | DispatchQueue.main.async { 198 | var smallestDiff = CGFloat.greatestFiniteMagnitude 199 | for index in self.collectionView.indexPathsForVisibleItems { 200 | if let cell = self.collectionView.cellForItem(at: index) { 201 | let diff = abs((cell.frame.origin.x+(cell.frame.width/2))-mid.x) 202 | if diff < smallestDiff { 203 | smallestDiff = diff 204 | self.selectedIndex = index 205 | } 206 | } 207 | } 208 | 209 | self.goTo(indexPath: self.selectedIndex) 210 | } 211 | } 212 | 213 | private func updateView(with album: Album) { 214 | album.albumImage?.getColors(quality: .high) { colors in 215 | guard let colors = colors else { return } 216 | 217 | UIView.animate(withDuration: 0.15, animations: { 218 | self.view.backgroundColor = colors.background 219 | 220 | self.mainLabel.text = album.albumName 221 | self.mainLabel.textColor = colors.primary 222 | 223 | self.secondaryLabel.text = album.artistName 224 | self.secondaryLabel.textColor = colors.secondary 225 | 226 | self.detailLabel.text = "\(album.year)" 227 | self.detailLabel.textColor = colors.detail 228 | 229 | self.playButton.tintColor = colors.detail 230 | }) 231 | } 232 | } 233 | } 234 | 235 | -------------------------------------------------------------------------------- /preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jathu/UIImageColors/f064be8ee0b03158e61135e6c384aee18d7a5414/preview.png --------------------------------------------------------------------------------