diff --git a/Sora/Views/MediaInfoView/Header/AmbientColor.swift b/Sora/Views/MediaInfoView/Header/AmbientColor.swift deleted file mode 100644 index 6d3f9e2..0000000 --- a/Sora/Views/MediaInfoView/Header/AmbientColor.swift +++ /dev/null @@ -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.. 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) - } - } -} diff --git a/Sora/Views/MediaInfoView/Header/StretchyHeader.swift b/Sora/Views/MediaInfoView/Header/StretchyHeader.swift index 86d623e..db58aa1 100644 --- a/Sora/Views/MediaInfoView/Header/StretchyHeader.swift +++ b/Sora/Views/MediaInfoView/Header/StretchyHeader.swift @@ -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 - } - } - } - } - } } } diff --git a/Sora/Views/MediaInfoView/Header/resized.swift b/Sora/Views/MediaInfoView/Header/resized.swift deleted file mode 100644 index f10969c..0000000 --- a/Sora/Views/MediaInfoView/Header/resized.swift +++ /dev/null @@ -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 - } -} diff --git a/Sulfur.xcodeproj/project.pbxproj b/Sulfur.xcodeproj/project.pbxproj index ce00601..46fd674 100644 --- a/Sulfur.xcodeproj/project.pbxproj +++ b/Sulfur.xcodeproj/project.pbxproj @@ -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 = ""; }; 131845F82D47C62D00CA7A54 /* SettingsViewGeneral.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewGeneral.swift; sourceTree = ""; }; 131BC85A2EC3814700E19F3E /* StretchyHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StretchyHeader.swift; sourceTree = ""; }; - 131BC85C2EC3824700E19F3E /* AmbientColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AmbientColor.swift; sourceTree = ""; }; - 131BC85E2EC3828500E19F3E /* resized.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = resized.swift; sourceTree = ""; }; 1327FBA62D758CEA00FC6689 /* Analytics.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Analytics.swift; sourceTree = ""; }; 1327FBA82D758DEA00FC6689 /* UIDevice+Model.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIDevice+Model.swift"; sourceTree = ""; }; 132AF1202D99951700A0140B /* JSController-Streams.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSController-Streams.swift"; sourceTree = ""; }; @@ -526,9 +522,7 @@ 131BC8602EC3828700E19F3E /* Header */ = { isa = PBXGroup; children = ( - 131BC85E2EC3828500E19F3E /* resized.swift */, 131BC85A2EC3814700E19F3E /* StretchyHeader.swift */, - 131BC85C2EC3824700E19F3E /* AmbientColor.swift */, ); path = Header; sourceTree = ""; @@ -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 */,