import CoreImage import CoreGraphics // MARK: - SATURATION DETECTOR (Unlimited vs Revised) class SaturationDetector { static func analyze(image: CGImage, orientation: CGImagePropertyOrientation = .up) -> Double { // Crop to center 50% to analyze artwork saturation, ignoring borders let ciImage = CIImage(cgImage: image).oriented(orientation) let width = ciImage.extent.width let height = ciImage.extent.height let cropRect = CGRect(x: width * 0.25, y: height * 0.25, width: width * 0.5, height: height * 0.5) let vector = CIVector(cgRect: cropRect) guard let filter = CIFilter(name: "CIAreaAverage", parameters: [kCIInputImageKey: ciImage, kCIInputExtentKey: vector]), let output = filter.outputImage else { return 0 } var bitmap = [UInt8](repeating: 0, count: 4) let context = SharedEngineResources.context context.render(output, toBitmap: &bitmap, rowBytes: 4, bounds: CGRect(x: 0, y: 0, width: 1, height: 1), format: .RGBA8, colorSpace: nil) // Simple Saturation approximation: (Max - Min) / Max let r = Double(bitmap[0]) / 255.0 let g = Double(bitmap[1]) / 255.0 let b = Double(bitmap[2]) / 255.0 let maxC = max(r, max(g, b)) let minC = min(r, min(g, b)) return maxC == 0 ? 0 : (maxC - minC) / maxC } }