我希望获取 macOS 上当前壁纸图像的 URL,当使用基于活动配色方案的具有不同外观的壁纸时,这也会考虑当前的配色方案。
要获取当前桌面壁纸图像的URL,我使用以下方法:
NSWorkspace.shared.desktopImageURL(for: screen)
这会正确返回 URL,但是,它仅返回当前壁纸的灯光模式变体的 URL。我想获取与当前活动配色方案相匹配的变体的 URL。
这可能吗?
两个变体都存储在同一 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”壁纸的结果。