mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Add IconImage to encapsulate our icon processing logic
This commit is contained in:
66
Shared/Extensions/IconImage.swift
Normal file
66
Shared/Extensions/IconImage.swift
Normal file
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// IconImage.swift
|
||||
// NetNewsWire
|
||||
//
|
||||
// Created by Maurice Parker on 11/5/19.
|
||||
// Copyright © 2019 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RSCore
|
||||
|
||||
final class IconImage {
|
||||
|
||||
lazy var isDark: Bool = {
|
||||
return image.isDark()
|
||||
}()
|
||||
|
||||
let image: RSImage
|
||||
|
||||
init(_ image: RSImage) {
|
||||
self.image = image
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if os(macOS)
|
||||
extension NSImage {
|
||||
func isDark() -> Bool {
|
||||
return self.cgImage(forProposedRect: nil, context: nil, hints: nil)?.isDark() ?? false
|
||||
}
|
||||
}
|
||||
#else
|
||||
extension UIImage {
|
||||
func isDark() -> Bool {
|
||||
return self.cgImage?.isDark() ?? false
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
extension CGImage {
|
||||
|
||||
func isDark() -> Bool {
|
||||
guard let imageData = self.dataProvider?.data else { return false }
|
||||
guard let ptr = CFDataGetBytePtr(imageData) else { return false }
|
||||
|
||||
let length = CFDataGetLength(imageData)
|
||||
var pixelCount = 0
|
||||
var totalLuminance = 0.0
|
||||
|
||||
for i in stride(from: 0, to: length, by: 4) {
|
||||
|
||||
let r = ptr[i]
|
||||
let g = ptr[i + 1]
|
||||
let b = ptr[i + 2]
|
||||
let luminance = (0.299 * Double(r) + 0.587 * Double(g) + 0.114 * Double(b))
|
||||
|
||||
totalLuminance += luminance
|
||||
pixelCount += 1
|
||||
|
||||
}
|
||||
|
||||
let avgLuminance = totalLuminance / Double(pixelCount)
|
||||
return avgLuminance < 37.5
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,19 +11,19 @@ import RSCore
|
||||
|
||||
extension RSImage {
|
||||
|
||||
static let avatarSize = 48
|
||||
static let maxIconSize = 48
|
||||
|
||||
static func scaledForAvatar(_ data: Data, imageResultBlock: @escaping (RSImage?) -> Void) {
|
||||
static func scaledForIcon(_ data: Data, imageResultBlock: @escaping (RSImage?) -> Void) {
|
||||
DispatchQueue.global(qos: .default).async {
|
||||
let image = RSImage.scaledForAvatar(data)
|
||||
let image = RSImage.scaledForIcon(data)
|
||||
DispatchQueue.main.async {
|
||||
imageResultBlock(image)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static func scaledForAvatar(_ data: Data) -> RSImage? {
|
||||
let scaledMaxPixelSize = Int(ceil(CGFloat(RSImage.avatarSize) * RSScreen.mainScreenScale))
|
||||
static func scaledForIcon(_ data: Data) -> RSImage? {
|
||||
let scaledMaxPixelSize = Int(ceil(CGFloat(RSImage.maxIconSize) * RSScreen.mainScreenScale))
|
||||
guard var cgImage = RSImage.scaleImage(data, maxPixelSize: scaledMaxPixelSize) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user