SwiftUI实现黑白反转且保留颜色的PDF图片深色适配
适配深色模式的PDF转UIImage渲染方案
针对你需要将PDF转换的UIImage在SwiftUI中适配深色模式(地图背景转黑/深灰,保留原色彩)的需求,这里提供几种可行的实现方案:
方案一:优化SwiftUI图层混合(快速调整)
之前的ZStack方案中黄色变绿是因为.color混合模式导致色相偏移,换成.colorBurn并调整滤镜参数可以修正这个问题,同时保留深色背景和原色彩:
ZStack { // 深色灰度底图:反转+去饱和+增强对比度让背景更纯粹 Image(uiImage: self.mapImage!) .resizable() .scaledToFill() .colorInvert() .saturation(0) .contrast(1.2) .brightness(-0.1) // 原色彩层:用colorBurn混合模式保留原色相,增强饱和度让色彩更突出 Image(uiImage: self.mapImage!) .resizable() .scaledToFill() .blendMode(.colorBurn) .saturation(1.1) } .clipped() // 裁剪超出边界的内容
这个方案不需要额外的CoreImage处理,纯SwiftUI API即可实现,调整contrast、brightness和saturation的数值可以适配不同的PDF内容。
方案二:用CoreImage模拟Affinity的图层组合
SwiftUI的blendMode确实没有"Add"模式,但CoreImage提供了CIAdditionCompositing滤镜,可以完全复刻你在Affinity中实现的效果:
1. 先写几个CoreImage工具函数
// 给图片应用单个CoreImage滤镜 private func applyFilter(to image: UIImage, filter: CIFilter) -> UIImage? { guard let ciImage = CIImage(image: image) else { return nil } filter.setValue(ciImage, forKey: kCIInputImageKey) guard let outputCI = filter.outputImage else { return nil } let context = CIContext(options: [.useSoftwareRenderer: false]) guard let outputCG = context.createCGImage(outputCI, from: outputCI.extent) else { return nil } return UIImage(cgImage: outputCG) } // 生成反转+黑白的图片 private func invertedGrayscaleImage(from image: UIImage) -> UIImage? { let invertFilter = CIFilter(name: "CIColorInvert")! let grayFilter = CIFilter(name: "CIColorControls")! grayFilter.setValue(0, forKey: kCIInputSaturationKey) guard let inverted = applyFilter(to: image, filter: invertFilter) else { return nil } return applyFilter(to: inverted, filter: grayFilter) } // 用Add混合模式合成两张图片 private func addComposite(base: UIImage, overlay: UIImage) -> UIImage? { guard let baseCI = CIImage(image: base), let overlayCI = CIImage(image: overlay) else { return nil } let addFilter = CIFilter(name: "CIAdditionCompositing")! addFilter.setValue(baseCI, forKey: kCIInputImageKey) addFilter.setValue(overlayCI, forKey: kCIInputBackgroundImageKey) guard let outputCI = addFilter.outputImage else { return nil } let context = CIContext(options: [.useSoftwareRenderer: false]) guard let outputCG = context.createCGImage(outputCI, from: outputCI.extent) else { return nil } return UIImage(cgImage: outputCG) }
2. 在SwiftUI中处理并渲染
@State private var processedImage: UIImage? var body: some View { Group { if let processedImage = processedImage { Image(uiImage: processedImage) .resizable() .scaledToFill() } else if let mapImage = mapImage { // 加载中可以显示原图或者占位符 Image(uiImage: mapImage) .resizable() .scaledToFill() } } .onAppear { guard let original = mapImage else { return } // 复刻Affinity的三个图层逻辑 guard let layer3 = invertedGrayscaleImage(from: original), let layer2 = addComposite(base: layer3, overlay: layer3), let darkenFilter = CIFilter(name: "CIDarkenBlendMode") else { return } darkenFilter.setValue(CIImage(image: original), forKey: kCIInputImageKey) darkenFilter.setValue(CIImage(image: layer2), forKey: kCIInputBackgroundImageKey) processedImage = applyFilter(to: original, filter: darkenFilter) } }
如果觉得部分文本可读性差,可以在最后给processedImage再叠加一层亮度调整:
// 调整文本可读性 if let processedImage = processedImage { Image(uiImage: processedImage) .resizable() .scaledToFill() .brightness(0.1) .contrast(1.1) }
方案三:极简单图层调整
如果不需要完全复刻Affinity的效果,只想快速适配深色模式,可以用单图层的滤镜组合:
Image(uiImage: mapImage!) .resizable() .scaledToFill() .colorInvert() .saturation(0.3) // 保留少量色彩,同时灰度化背景 .colorMultiply(Color.black.opacity(0.8)) // 加深背景 .brightness(0.1) // 提亮文本 .blendMode(.screen) // 让彩色内容更醒目
内容的提问来源于stack exchange,提问作者Fez Vrasta
相关产品推荐
相关产品推荐

