mirror of
https://github.com/cranci1/Sora.git
synced 2026-01-11 20:10:24 +00:00
Removed unused extensions
This commit is contained in:
parent
a19d47d7e2
commit
2f38763e1a
4 changed files with 6 additions and 227 deletions
|
|
@ -1,160 +0,0 @@
|
|||
//
|
||||
// AmbientColor.swift
|
||||
// Sora
|
||||
//
|
||||
// Created by Francesco on 07/08/25.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SwiftUI
|
||||
import Accelerate
|
||||
|
||||
// How does it work uh? On hopes and beliving on him? Why? Cuz i had to learn HSV, and how to work twith it yayy.
|
||||
extension Color {
|
||||
static func ambientColor(from image: UIImage?, prioritizeBottom: Bool = true) -> Color {
|
||||
guard let image = image else { return .black }
|
||||
|
||||
let targetSize = CGSize(width: 64, height: 64)
|
||||
guard let resizedImage = image.resized(to: targetSize, contentMode: .scaleAspectFill),
|
||||
let cgImage = resizedImage.cgImage else { return .black }
|
||||
|
||||
let width = cgImage.width
|
||||
let height = cgImage.height
|
||||
|
||||
let bytesPerPixel = 4
|
||||
let bytesPerRow = width * bytesPerPixel
|
||||
let totalBytes = height * bytesPerRow
|
||||
|
||||
guard let data = malloc(totalBytes) else { return .black }
|
||||
defer { free(data) }
|
||||
|
||||
let colorSpace = CGColorSpaceCreateDeviceRGB()
|
||||
let bitmapInfo = CGImageAlphaInfo.premultipliedLast.rawValue
|
||||
|
||||
guard let context = CGContext(data: data, width: width, height: height, bitsPerComponent: 8, bytesPerRow: bytesPerRow, space: colorSpace, bitmapInfo: bitmapInfo) else {
|
||||
return .black
|
||||
}
|
||||
|
||||
context.draw(cgImage, in: CGRect(x: 0, y: 0, width: width, height: height))
|
||||
|
||||
let buffer = data.bindMemory(to: UInt8.self, capacity: totalBytes)
|
||||
|
||||
var redSum: Float = 0
|
||||
var greenSum: Float = 0
|
||||
var blueSum: Float = 0
|
||||
var totalWeight: Float = 0
|
||||
|
||||
for y in 0..<height {
|
||||
for x in 0..<width {
|
||||
let pixelIndex = (y * width + x) * bytesPerPixel
|
||||
|
||||
let red = Float(buffer[pixelIndex]) / 255.0
|
||||
let green = Float(buffer[pixelIndex + 1]) / 255.0
|
||||
let blue = Float(buffer[pixelIndex + 2]) / 255.0
|
||||
let alpha = Float(buffer[pixelIndex + 3]) / 255.0
|
||||
|
||||
guard alpha > 0.1 && (red + green + blue) > 0.15 else { continue }
|
||||
|
||||
let brightness = red * 0.2126 + green * 0.7152 + blue * 0.0722
|
||||
let brightnessWeight = 1.0 - abs(brightness - 0.5) * 0.4
|
||||
|
||||
let maxComponent = max(red, max(green, blue))
|
||||
let minComponent = min(red, min(green, blue))
|
||||
let saturation = maxComponent > 0 ? (maxComponent - minComponent) / maxComponent : 0
|
||||
let saturationWeight = 0.5 + saturation * 0.5
|
||||
|
||||
let centerX = Float(width) / 2
|
||||
let centerY = Float(height) / 2
|
||||
let dx = Float(x) - centerX
|
||||
let dy = Float(y) - centerY
|
||||
let distance = sqrt(dx * dx + dy * dy)
|
||||
let maxDistance = sqrt(centerX * centerX + centerY * centerY)
|
||||
let centerWeight = 1.0 - (distance / maxDistance) * 0.3
|
||||
|
||||
let verticalWeight: Float
|
||||
if prioritizeBottom {
|
||||
let normalizedY = Float(y) / Float(height)
|
||||
verticalWeight = 0.3 + 0.7 * (normalizedY * normalizedY)
|
||||
} else {
|
||||
verticalWeight = 1.0
|
||||
}
|
||||
|
||||
let finalWeight = centerWeight * brightnessWeight * saturationWeight * alpha * verticalWeight
|
||||
|
||||
redSum += red * finalWeight
|
||||
greenSum += green * finalWeight
|
||||
blueSum += blue * finalWeight
|
||||
totalWeight += finalWeight
|
||||
}
|
||||
}
|
||||
|
||||
guard totalWeight > 0 else { return .black }
|
||||
|
||||
let avgRed = redSum / totalWeight
|
||||
let avgGreen = greenSum / totalWeight
|
||||
let avgBlue = blueSum / totalWeight
|
||||
|
||||
let (h, s, v) = rgbToHsv(r: Double(avgRed), g: Double(avgGreen), b: Double(avgBlue))
|
||||
|
||||
let adjustedS = min(s * 1.2, 1.0)
|
||||
let adjustedV = v * 0.7
|
||||
|
||||
let (r, g, b) = hsvToRgb(h: h, s: adjustedS, v: adjustedV)
|
||||
|
||||
return Color(red: r, green: g, blue: b)
|
||||
}
|
||||
|
||||
private static func rgbToHsv(r: Double, g: Double, b: Double) -> (h: Double, s: Double, v: Double) {
|
||||
let minVal = min(r, min(g, b))
|
||||
let maxVal = max(r, max(g, b))
|
||||
let delta = maxVal - minVal
|
||||
|
||||
var h: Double = 0
|
||||
var s: Double = 0
|
||||
let v: Double = maxVal
|
||||
|
||||
if delta > 0 {
|
||||
s = delta / maxVal
|
||||
|
||||
if r == maxVal {
|
||||
h = (g - b) / delta
|
||||
} else if g == maxVal {
|
||||
h = 2 + (b - r) / delta
|
||||
} else {
|
||||
h = 4 + (r - g) / delta
|
||||
}
|
||||
|
||||
h *= 60
|
||||
if h < 0 {
|
||||
h += 360
|
||||
}
|
||||
}
|
||||
|
||||
return (h, s, v)
|
||||
}
|
||||
|
||||
private static func hsvToRgb(h: Double, s: Double, v: Double) -> (r: Double, g: Double, b: Double) {
|
||||
if s == 0 {
|
||||
return (v, v, v)
|
||||
}
|
||||
|
||||
var h = h
|
||||
if h >= 360 { h = 0 }
|
||||
h /= 60
|
||||
|
||||
let i = Int(h)
|
||||
let f = h - Double(i)
|
||||
let p = v * (1 - s)
|
||||
let q = v * (1 - s * f)
|
||||
let t = v * (1 - s * (1 - f))
|
||||
|
||||
switch i {
|
||||
case 0: return (v, t, p)
|
||||
case 1: return (q, v, p)
|
||||
case 2: return (p, v, t)
|
||||
case 3: return (p, q, v)
|
||||
case 4: return (t, p, v)
|
||||
default: return (v, p, q)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -37,12 +37,12 @@ struct StretchyHeaderView: View {
|
|||
.fill(Color.gray.opacity(0.3))
|
||||
}
|
||||
}
|
||||
.onCompletion { result in
|
||||
if case .success(let response) = result {
|
||||
let uiImage = response.image
|
||||
backdropImage = uiImage
|
||||
}
|
||||
},
|
||||
.onCompletion { result in
|
||||
if case .success(let response) = result {
|
||||
let uiImage = response.image
|
||||
backdropImage = uiImage
|
||||
}
|
||||
},
|
||||
alignment: .center
|
||||
)
|
||||
.clipped()
|
||||
|
|
@ -51,17 +51,5 @@ struct StretchyHeaderView: View {
|
|||
}
|
||||
}
|
||||
.frame(height: headerHeight)
|
||||
.onAppear {
|
||||
if let backdropURL = backdropURL, let url = URL(string: backdropURL) {
|
||||
Task {
|
||||
let request = ImageRequest(url: url)
|
||||
if let response = try? await ImagePipeline.shared.image(for: request) {
|
||||
await MainActor.run {
|
||||
backdropImage = response
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
//
|
||||
// resized.swift
|
||||
// Sora
|
||||
//
|
||||
// Created by Francesco on 07/08/25.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
extension UIImage {
|
||||
func resized(to size: CGSize, contentMode: ContentMode = .scaleAspectFit) -> UIImage? {
|
||||
let aspectSize: CGSize
|
||||
|
||||
switch contentMode {
|
||||
case .scaleAspectFill:
|
||||
let aspectRatio = self.size.width / self.size.height
|
||||
if size.width / aspectRatio > size.height {
|
||||
aspectSize = CGSize(width: size.width, height: size.width / aspectRatio)
|
||||
} else {
|
||||
aspectSize = CGSize(width: size.height * aspectRatio, height: size.height)
|
||||
}
|
||||
case .scaleAspectFit:
|
||||
let aspectRatio = self.size.width / self.size.height
|
||||
if size.width / aspectRatio < size.height {
|
||||
aspectSize = CGSize(width: size.width, height: size.width / aspectRatio)
|
||||
} else {
|
||||
aspectSize = CGSize(width: size.height * aspectRatio, height: size.height)
|
||||
}
|
||||
}
|
||||
|
||||
let renderer = UIGraphicsImageRenderer(size: aspectSize)
|
||||
return renderer.image { _ in
|
||||
self.draw(in: CGRect(origin: .zero, size: aspectSize))
|
||||
}
|
||||
}
|
||||
|
||||
enum ContentMode {
|
||||
case scaleAspectFit
|
||||
case scaleAspectFill
|
||||
}
|
||||
}
|
||||
|
|
@ -57,8 +57,6 @@
|
|||
131270172DC13A010093AA9C /* DownloadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 131270162DC13A010093AA9C /* DownloadManager.swift */; };
|
||||
131845F92D47C62D00CA7A54 /* SettingsViewGeneral.swift in Sources */ = {isa = PBXBuildFile; fileRef = 131845F82D47C62D00CA7A54 /* SettingsViewGeneral.swift */; };
|
||||
131BC85B2EC3814700E19F3E /* StretchyHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 131BC85A2EC3814700E19F3E /* StretchyHeader.swift */; };
|
||||
131BC85D2EC3824700E19F3E /* AmbientColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 131BC85C2EC3824700E19F3E /* AmbientColor.swift */; };
|
||||
131BC85F2EC3828500E19F3E /* resized.swift in Sources */ = {isa = PBXBuildFile; fileRef = 131BC85E2EC3828500E19F3E /* resized.swift */; };
|
||||
1327FBA72D758CEA00FC6689 /* Analytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1327FBA62D758CEA00FC6689 /* Analytics.swift */; };
|
||||
1327FBA92D758DEA00FC6689 /* UIDevice+Model.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1327FBA82D758DEA00FC6689 /* UIDevice+Model.swift */; };
|
||||
132AF1212D99951700A0140B /* JSController-Streams.swift in Sources */ = {isa = PBXBuildFile; fileRef = 132AF1202D99951700A0140B /* JSController-Streams.swift */; };
|
||||
|
|
@ -191,8 +189,6 @@
|
|||
131270162DC13A010093AA9C /* DownloadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadManager.swift; sourceTree = "<group>"; };
|
||||
131845F82D47C62D00CA7A54 /* SettingsViewGeneral.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewGeneral.swift; sourceTree = "<group>"; };
|
||||
131BC85A2EC3814700E19F3E /* StretchyHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StretchyHeader.swift; sourceTree = "<group>"; };
|
||||
131BC85C2EC3824700E19F3E /* AmbientColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AmbientColor.swift; sourceTree = "<group>"; };
|
||||
131BC85E2EC3828500E19F3E /* resized.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = resized.swift; sourceTree = "<group>"; };
|
||||
1327FBA62D758CEA00FC6689 /* Analytics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Analytics.swift; sourceTree = "<group>"; };
|
||||
1327FBA82D758DEA00FC6689 /* UIDevice+Model.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIDevice+Model.swift"; sourceTree = "<group>"; };
|
||||
132AF1202D99951700A0140B /* JSController-Streams.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSController-Streams.swift"; sourceTree = "<group>"; };
|
||||
|
|
@ -526,9 +522,7 @@
|
|||
131BC8602EC3828700E19F3E /* Header */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
131BC85E2EC3828500E19F3E /* resized.swift */,
|
||||
131BC85A2EC3814700E19F3E /* StretchyHeader.swift */,
|
||||
131BC85C2EC3824700E19F3E /* AmbientColor.swift */,
|
||||
);
|
||||
path = Header;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -1103,7 +1097,6 @@
|
|||
04F08EE22DE10C40006B29D9 /* TabItem.swift in Sources */,
|
||||
04EAC39A2DF9E0DB00BBD483 /* SplashScreenView.swift in Sources */,
|
||||
132AF1212D99951700A0140B /* JSController-Streams.swift in Sources */,
|
||||
131BC85F2EC3828500E19F3E /* resized.swift in Sources */,
|
||||
131845F92D47C62D00CA7A54 /* SettingsViewGeneral.swift in Sources */,
|
||||
04CD76DB2DE20F2200733536 /* AllWatching.swift in Sources */,
|
||||
047F170A2E0C93E10081B5FB /* AllReading.swift in Sources */,
|
||||
|
|
@ -1154,7 +1147,6 @@
|
|||
13DB46922D900BCE008CBC03 /* SettingsViewTrackers.swift in Sources */,
|
||||
7222485F2DCBAA2C00CABE2D /* DownloadModels.swift in Sources */,
|
||||
722248602DCBAA2C00CABE2D /* M3U8StreamExtractor.swift in Sources */,
|
||||
131BC85D2EC3824700E19F3E /* AmbientColor.swift in Sources */,
|
||||
13C0E5EA2D5F85EA00E7F619 /* ContinueWatchingManager.swift in Sources */,
|
||||
13637B8A2DE0EA1100BDA2FC /* UserDefaults.swift in Sources */,
|
||||
7260B66D2E32A8CB00365CDA /* OrphanedDownloadsView.swift in Sources */,
|
||||
|
|
|
|||
Loading…
Reference in a new issue