如何获取符合当前配色方案的 macOS 壁纸图像 URL?

问题描述 投票:0回答:1

我希望获取 macOS 上当前壁纸图像的 URL,当使用基于活动配色方案的具有不同外观的壁纸时,这也会考虑当前的配色方案。

要获取当前桌面壁纸图像的URL,我使用以下方法:

NSWorkspace.shared.desktopImageURL(for: screen)

这会正确返回 URL,但是,它仅返回当前壁纸的灯光模式变体的 URL。我想获取与当前活动配色方案相匹配的变体的 URL。

这可能吗?

swift xcode macos cocoa appkit
1个回答
0
投票

两个变体都存储在同一 URL 中。 HEIC 文件可以存储许多不同的图像。尝试使用 Preview.app 打开图像:)

要获取亮图和暗图,我们需要读取HEIC文件的元数据,它会告诉我们亮模式图像和暗模式图像各自的索引。

感谢逆向工程师这里,我写了这个函数:

func lightDarkImages(url: URL) throws -> (light: CGImage, dark: CGImage) {
    guard let imageSource = CGImageSourceCreateWithURL(url as CFURL, nil) else {
        throw Errors.notFound
    }
    guard let metadata = CGImageSourceCopyMetadataAtIndex(imageSource, 0, nil) else {
        throw Errors.noMetadata
    }
    let plistDecoder = PropertyListDecoder()
    if let solarTag = CGImageMetadataCopyTagWithPath(metadata, nil, "apple_desktop:solar" as CFString),
        let base64String = CGImageMetadataTagCopyValue(solarTag) as? String,
        let data = Data(base64Encoded: base64String) {
        let indices = try plistDecoder.decode(SolarMetadata.self, from: data)
        return (
            light: CGImageSourceCreateImageAtIndex(imageSource, indices.ap.l, nil)!,
            dark: CGImageSourceCreateImageAtIndex(imageSource, indices.ap.d, nil)!
        )
    } else if let aprTag = CGImageMetadataCopyTagWithPath(metadata, nil, "apple_desktop:apr" as CFString),
              let base64String = CGImageMetadataTagCopyValue(aprTag) as? String,
              let data = Data(base64Encoded: base64String) {
        let indices = try plistDecoder.decode(LightDarkIndex.self, from: data)
        return (
            light: CGImageSourceCreateImageAtIndex(imageSource, indices.l, nil)!,
            dark: CGImageSourceCreateImageAtIndex(imageSource, indices.d, nil)!
        )
    } else {
        throw Errors.invalidMetadata
    }
}

enum Errors: Error {
    case notFound
    case noMetadata
    case invalidMetadata
}

struct LightDarkIndex: Decodable {
    let l: Int
    let d: Int
}

struct SolarMetadata: Decodable {
    let ap: LightDarkIndex
}

这是一个简单的 SwiftUI 视图来显示它们。将

imageFileURL
设置为 HEIC 文件并查看其工作情况。

struct ContentView: View {
    @State var light: Image?
    @State var dark: Image?
    
    var body: some View {
        HStack {
            if let light {
                light
            }
            if let dark {
                dark
            }
        }
        .frame(width: 300)
            .onAppear {
                do {
                    let imageFileURL = ...
                    let images = try lightDarkImages(url: imageFileURL)
                    light = Image(nsImage: NSImage(cgImage: images.light, size: .init(width: 100, height: 100)))
                    dark = Image(nsImage: NSImage(cgImage: images.dark, size: .init(width: 100, height: 100)))
                } catch {
                    print(error)
                }
            }
    }
}

这是“hello Green”壁纸的结果。

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.