Commit c73871a6 by Dmitriy Stepanets

IOS-147: Added new average color calculating logic grabbed from android Palette

parent d0837650
...@@ -23,56 +23,56 @@ ...@@ -23,56 +23,56 @@
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>4</integer> <integer>3</integer>
</dict> </dict>
<key>OneWeatherCorePlayground (Playground) 1.xcscheme</key> <key>OneWeatherCorePlayground (Playground) 1.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>67</integer> <integer>64</integer>
</dict> </dict>
<key>OneWeatherCorePlayground (Playground) 10.xcscheme</key> <key>OneWeatherCorePlayground (Playground) 10.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>21</integer> <integer>23</integer>
</dict> </dict>
<key>OneWeatherCorePlayground (Playground) 11.xcscheme</key> <key>OneWeatherCorePlayground (Playground) 11.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>22</integer> <integer>24</integer>
</dict> </dict>
<key>OneWeatherCorePlayground (Playground) 12.xcscheme</key> <key>OneWeatherCorePlayground (Playground) 12.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>23</integer> <integer>25</integer>
</dict> </dict>
<key>OneWeatherCorePlayground (Playground) 13.xcscheme</key> <key>OneWeatherCorePlayground (Playground) 13.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>30</integer> <integer>93</integer>
</dict> </dict>
<key>OneWeatherCorePlayground (Playground) 14.xcscheme</key> <key>OneWeatherCorePlayground (Playground) 14.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>31</integer> <integer>94</integer>
</dict> </dict>
<key>OneWeatherCorePlayground (Playground) 15.xcscheme</key> <key>OneWeatherCorePlayground (Playground) 15.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>32</integer> <integer>95</integer>
</dict> </dict>
<key>OneWeatherCorePlayground (Playground) 16.xcscheme</key> <key>OneWeatherCorePlayground (Playground) 16.xcscheme</key>
<dict> <dict>
...@@ -100,63 +100,63 @@ ...@@ -100,63 +100,63 @@
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>68</integer> <integer>65</integer>
</dict> </dict>
<key>OneWeatherCorePlayground (Playground) 3.xcscheme</key> <key>OneWeatherCorePlayground (Playground) 3.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>69</integer> <integer>66</integer>
</dict> </dict>
<key>OneWeatherCorePlayground (Playground) 4.xcscheme</key> <key>OneWeatherCorePlayground (Playground) 4.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>65</integer> <integer>11</integer>
</dict> </dict>
<key>OneWeatherCorePlayground (Playground) 5.xcscheme</key> <key>OneWeatherCorePlayground (Playground) 5.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>66</integer> <integer>12</integer>
</dict> </dict>
<key>OneWeatherCorePlayground (Playground) 6.xcscheme</key> <key>OneWeatherCorePlayground (Playground) 6.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>67</integer> <integer>13</integer>
</dict> </dict>
<key>OneWeatherCorePlayground (Playground) 7.xcscheme</key> <key>OneWeatherCorePlayground (Playground) 7.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>18</integer> <integer>17</integer>
</dict> </dict>
<key>OneWeatherCorePlayground (Playground) 8.xcscheme</key> <key>OneWeatherCorePlayground (Playground) 8.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>19</integer> <integer>18</integer>
</dict> </dict>
<key>OneWeatherCorePlayground (Playground) 9.xcscheme</key> <key>OneWeatherCorePlayground (Playground) 9.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>20</integer> <integer>19</integer>
</dict> </dict>
<key>OneWeatherCorePlayground (Playground).xcscheme</key> <key>OneWeatherCorePlayground (Playground).xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>2</integer> <integer>4</integer>
</dict> </dict>
<key>PG (Playground) 1.xcscheme</key> <key>PG (Playground) 1.xcscheme</key>
<dict> <dict>
...@@ -170,42 +170,42 @@ ...@@ -170,42 +170,42 @@
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>24</integer> <integer>26</integer>
</dict> </dict>
<key>PG (Playground) 11.xcscheme</key> <key>PG (Playground) 11.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>25</integer> <integer>27</integer>
</dict> </dict>
<key>PG (Playground) 12.xcscheme</key> <key>PG (Playground) 12.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>26</integer> <integer>28</integer>
</dict> </dict>
<key>PG (Playground) 13.xcscheme</key> <key>PG (Playground) 13.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>27</integer> <integer>89</integer>
</dict> </dict>
<key>PG (Playground) 14.xcscheme</key> <key>PG (Playground) 14.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>28</integer> <integer>90</integer>
</dict> </dict>
<key>PG (Playground) 15.xcscheme</key> <key>PG (Playground) 15.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>29</integer> <integer>91</integer>
</dict> </dict>
<key>PG (Playground) 16.xcscheme</key> <key>PG (Playground) 16.xcscheme</key>
<dict> <dict>
...@@ -247,49 +247,49 @@ ...@@ -247,49 +247,49 @@
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>70</integer> <integer>14</integer>
</dict> </dict>
<key>PG (Playground) 5.xcscheme</key> <key>PG (Playground) 5.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>71</integer> <integer>15</integer>
</dict> </dict>
<key>PG (Playground) 6.xcscheme</key> <key>PG (Playground) 6.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>72</integer> <integer>16</integer>
</dict> </dict>
<key>PG (Playground) 7.xcscheme</key> <key>PG (Playground) 7.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>15</integer> <integer>20</integer>
</dict> </dict>
<key>PG (Playground) 8.xcscheme</key> <key>PG (Playground) 8.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>16</integer> <integer>21</integer>
</dict> </dict>
<key>PG (Playground) 9.xcscheme</key> <key>PG (Playground) 9.xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>17</integer> <integer>22</integer>
</dict> </dict>
<key>PG (Playground).xcscheme</key> <key>PG (Playground).xcscheme</key>
<dict> <dict>
<key>isShown</key> <key>isShown</key>
<false/> <false/>
<key>orderHint</key> <key>orderHint</key>
<integer>3</integer> <integer>2</integer>
</dict> </dict>
</dict> </dict>
</dict> </dict>
......
...@@ -6,19 +6,19 @@ ...@@ -6,19 +6,19 @@
// //
import UIKit import UIKit
import Palette
extension UIImage { extension UIImage {
var averageColor: UIColor? { var averageColor: UIColor? {
guard let inputImage = CIImage(image: self) else { return nil } let palette = self.createPalette()
let extentVector = CIVector(x: inputImage.extent.origin.x, y: inputImage.extent.origin.y, z: inputImage.extent.size.width, w: inputImage.extent.size.height) var vibrantSwatch = palette.mutedSwatch
if nil == vibrantSwatch {
vibrantSwatch = palette.darkMutedSwatch
}
if nil == vibrantSwatch {
vibrantSwatch = palette.lightMutedSwatch
}
guard let filter = CIFilter(name: "CIAreaAverage", parameters: [kCIInputImageKey: inputImage, kCIInputExtentKey: extentVector]) else { return nil } return vibrantSwatch?.color
guard let outputImage = filter.outputImage else { return nil }
var bitmap = [UInt8](repeating: 0, count: 4)
let context = CIContext(options: [.workingColorSpace: kCFNull!])
context.render(outputImage, toBitmap: &bitmap, rowBytes: 4, bounds: CGRect(x: 0, y: 0, width: 1, height: 1), format: .RGBA8, colorSpace: nil)
return UIColor(red: CGFloat(bitmap[0]) / 255, green: CGFloat(bitmap[1]) / 255, blue: CGFloat(bitmap[2]) / 255, alpha: CGFloat(bitmap[3]) / 255)
} }
} }
...@@ -9,6 +9,7 @@ import UIKit ...@@ -9,6 +9,7 @@ import UIKit
import OneWeatherCore import OneWeatherCore
import InMobiShortsSource import InMobiShortsSource
import OneWeatherAnalytics import OneWeatherAnalytics
import Nuke
protocol ShortsManagerDelegate: AnyObject { protocol ShortsManagerDelegate: AnyObject {
func shortsDidChange() func shortsDidChange()
...@@ -24,6 +25,8 @@ class ShortsManager { ...@@ -24,6 +25,8 @@ class ShortsManager {
} }
//Private //Private
private let avgColorQueue = OperationQueue()
private let colorCache = NSCache<NSString, UIColor>()
private let source = InMobiShortSource() private let source = InMobiShortSource()
private let log = Logger(componentName: "ShortsManager") private let log = Logger(componentName: "ShortsManager")
private var isUpdating = false private var isUpdating = false
...@@ -84,4 +87,29 @@ class ShortsManager { ...@@ -84,4 +87,29 @@ class ShortsManager {
self.shorts[sourceIndex].markAsViewed() self.shorts[sourceIndex].markAsViewed()
} }
func backgroundColor(for short:ShortsItem, shortImage: UIImage, completion:@escaping(_ color: UIColor?,_ shortId: String) -> Void) {
if let cachedColor = colorCache.object(forKey: short.id as NSString) {
completion(cachedColor, short.id)
return
}
avgColorQueue.addOperation {
guard let color = shortImage.averageColor else {
completion(nil, short.id)
return
}
self.colorCache.setObject(color, forKey: short.id as NSString)
completion(color, short.id)
}
// shortImage.averageColor { avgColor in
// guard let color = avgColor else {
// completion(nil)
// return
// }
// self.colorCache.setObject(color, forKey: short.id as NSString)
// completion(color)
// }
}
} }
...@@ -18,6 +18,7 @@ class ShortsCollectionViewCell: UICollectionViewCell { ...@@ -18,6 +18,7 @@ class ShortsCollectionViewCell: UICollectionViewCell {
private let imageView = UIImageView() private let imageView = UIImageView()
private let footerView = UIView() private let footerView = UIView()
private let footerLabel = UILabel() private let footerLabel = UILabel()
private var currentShortId: String?
//Public //Public
weak var delegate: ShortsCollectionCellDelegate? weak var delegate: ShortsCollectionCellDelegate?
...@@ -31,30 +32,48 @@ class ShortsCollectionViewCell: UICollectionViewCell { ...@@ -31,30 +32,48 @@ class ShortsCollectionViewCell: UICollectionViewCell {
} }
func configure(shortsItem: ShortsItem) { func configure(shortsItem: ShortsItem) {
self.currentShortId = shortsItem.id
footerLabel.text = shortsItem.title footerLabel.text = shortsItem.title
if let image = self.bestImageForCellSize(images: shortsItem.images) { if let image = self.bestImageForCellSize(images: shortsItem.images) {
let resizeOptions = ImageProcessors.Resize(size: self.bounds.size, crop: true) let resizeOptions = ImageProcessors.Resize(size: self.bounds.size, crop: true)
let cornerRadius = ImageProcessors.RoundedCorners(radius: 12) let cornerRadius = ImageProcessors.RoundedCorners(radius: 12)
let imageRequest = ImageRequest(url: image.url, processors: [resizeOptions, cornerRadius]) let imageRequest = ImageRequest(url: image.url, processors: [resizeOptions, cornerRadius])
Nuke.loadImage(with: imageRequest, into: imageView) {[weak self] result in ImagePipeline.shared.loadImage(with: imageRequest) { result in
switch result { switch result {
case .success(let imageResponse): case .success(let response):
onMain { ShortsManager.shared.backgroundColor(for: shortsItem, shortImage: response.image) {[weak self] avgColor, shortId in
self?.imageView.image = imageResponse.image guard self?.currentShortId == shortId else { return }
if let cachedColor = self?.delegate?.averageColor(forImage: imageResponse.image, onMain {
identifier: image.url.absoluteString) { if let color = avgColor {
self?.footerView.backgroundColor = cachedColor self?.imageView.image = response.image
} self?.footerView.backgroundColor = color
else { }
self?.footerView.backgroundColor = ThemeManager.currentTheme.containerBackgroundColor
} }
} }
default: default:
break break
} }
} }
// Nuke.loadImage(with: imageRequest, into: imageView) {[weak self] result in
// switch result {
// case .success(let imageResponse):
// ShortsManager.shared.backgroundColor(for: shortsItem, shortImage: imageResponse.image) { avgColor, shortId in
// guard self?.currentShortId == shortId else { return }
//
// onMain {
// if let color = avgColor {
// self?.footerView.backgroundColor = color
// }
// }
// }
// default:
// break
// }
// }
} }
else { else {
imageView.image = nil imageView.image = nil
...@@ -68,6 +87,7 @@ class ShortsCollectionViewCell: UICollectionViewCell { ...@@ -68,6 +87,7 @@ class ShortsCollectionViewCell: UICollectionViewCell {
override func prepareForReuse() { override func prepareForReuse() {
super.prepareForReuse() super.prepareForReuse()
self.imageView.image = nil
self.footerView.backgroundColor = .clear self.footerView.backgroundColor = .clear
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment