加快 UIImage 处理速度 Swift
Accelerate UIImage processing speed in Swift
我正在尝试应用下一个代码来为从图库中截取的图像着色:
func zoeFilter() -> UIImage? {
let brownColor = UIColor (red: 128/255, green: 0, blue: 0, alpha: 1)
let colorRect = CGRect (origin: .zero, size: self.size)
let renderer = UIGraphicsImageRenderer (bounds: colorRect)
let brownColoredImage = renderer.image { ctx in
ctx.cgContext.setFillColor(greyColor.cgColor)
ctx.fill(colorRect)
}
let outBrown0Image = renderer.image { ctx in
ctx.cgContext.setFillColor(UIColor.white.cgColor)
ctx.fill(colorRect)
self.draw(in: colorRect, blendMode: .normal, alpha: 1)
brownColoredImage.draw(in: colorRect, blendMode: .colorDodge, alpha: 1)
}
let outBrownImage = renderer.image { ctx in
self.draw(in: colorRect, blendMode: .normal, alpha: 1)
outBrown0Image.draw(in: colorRect, blendMode: .multiply, alpha: 1)
}
return outBrownImage
}
但是处理图像需要大约 14 秒,这对用户体验来说不是很好...
你知道我怎样才能得到相同的结果但加速图像处理吗?
你有什么建议吗?
提前致谢!
最终解决方案
func zoeFilter() -> UIImage? {
let inImage = CIImage (image: self)
let SRGBImage = inImage?.applyingFilter("CILinearToSRGBToneCurve")
let brownColor = CIColor (red: 128/255, green: 0, blue: 0, alpha: 1)
let colorRect = CGRect (origin: .zero, size: self.size)
dynamic let colorFilter = CIFilter(name: "CIConstantColorGenerator")
dynamic let colorizeFilter = CIFilter (name: "CIColorDodgeBlendMode")
dynamic let multiplyFilter = CIFilter (name: "CIMultiplyBlendMode")
colorFilter?.setValue(brownColor, forKey: kCIInputColorKey)
let brownSolidImage = colorFilter?.outputImage?.cropped(to: colorRect)
colorizeFilter?.setValue(SRGBImage, forKey: kCIInputBackgroundImageKey)
colorizeFilter?.setValue(brownSolidImage, forKey: kCIInputImageKey)
let outBrown0Image = colorizeFilter?.outputImage
multiplyFilter?.setValue(SRGBImage, forKey: kCIInputBackgroundImageKey)
multiplyFilter?.setValue(outBrown0Image, forKey: kCIInputImageKey)
let outBrownImage = multiplyFilter?.outputImage
let linearImage = outBrownImage?.applyingFilter("CISRGBToneCurveToLinear")
let cgImage = CIContext().createCGImage(linearImage!, from: linearImage!.extent)
return UIImage (cgImage: cgImage!)
}
最简单的尝试是将这 3 个 renderer.image { ... }
调用合并为一个调用。您应该能够将第二个调用的内容移动到第一个调用中。这应该会产生巨大的性能差异。
除此之外,您真的需要对相机胶卷中的全尺寸图像执行此操作吗?如果不是,请在执行所有不需要的渲染之前调整您在渲染器上设置的大小。
通常,当您尝试以高性能方式进行此类过滤时,您会使用 CoreImage
。有了它,您可以以非常高的速度处理图像。像 60 fps 过滤实时视频。
我将从查看 Apple 的内置过滤器列表开始:
https://developer.apple.com/library/archive/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html
这是一个很好的过滤器使用示例:
https://www.hackingwithswift.com/articles/204/how-to-use-core-image-filters-the-type-safe-way
如果您发现无法组合内置过滤器来获得效果,您始终可以自己编写非常简单的 Metal backed 过滤器:
https://flexmonkey.blogspot.com/2016/01/metal-kernel-functions-as-core-image.html
我正在尝试应用下一个代码来为从图库中截取的图像着色:
func zoeFilter() -> UIImage? {
let brownColor = UIColor (red: 128/255, green: 0, blue: 0, alpha: 1)
let colorRect = CGRect (origin: .zero, size: self.size)
let renderer = UIGraphicsImageRenderer (bounds: colorRect)
let brownColoredImage = renderer.image { ctx in
ctx.cgContext.setFillColor(greyColor.cgColor)
ctx.fill(colorRect)
}
let outBrown0Image = renderer.image { ctx in
ctx.cgContext.setFillColor(UIColor.white.cgColor)
ctx.fill(colorRect)
self.draw(in: colorRect, blendMode: .normal, alpha: 1)
brownColoredImage.draw(in: colorRect, blendMode: .colorDodge, alpha: 1)
}
let outBrownImage = renderer.image { ctx in
self.draw(in: colorRect, blendMode: .normal, alpha: 1)
outBrown0Image.draw(in: colorRect, blendMode: .multiply, alpha: 1)
}
return outBrownImage
}
但是处理图像需要大约 14 秒,这对用户体验来说不是很好...
你知道我怎样才能得到相同的结果但加速图像处理吗?
你有什么建议吗?
提前致谢!
最终解决方案
func zoeFilter() -> UIImage? {
let inImage = CIImage (image: self)
let SRGBImage = inImage?.applyingFilter("CILinearToSRGBToneCurve")
let brownColor = CIColor (red: 128/255, green: 0, blue: 0, alpha: 1)
let colorRect = CGRect (origin: .zero, size: self.size)
dynamic let colorFilter = CIFilter(name: "CIConstantColorGenerator")
dynamic let colorizeFilter = CIFilter (name: "CIColorDodgeBlendMode")
dynamic let multiplyFilter = CIFilter (name: "CIMultiplyBlendMode")
colorFilter?.setValue(brownColor, forKey: kCIInputColorKey)
let brownSolidImage = colorFilter?.outputImage?.cropped(to: colorRect)
colorizeFilter?.setValue(SRGBImage, forKey: kCIInputBackgroundImageKey)
colorizeFilter?.setValue(brownSolidImage, forKey: kCIInputImageKey)
let outBrown0Image = colorizeFilter?.outputImage
multiplyFilter?.setValue(SRGBImage, forKey: kCIInputBackgroundImageKey)
multiplyFilter?.setValue(outBrown0Image, forKey: kCIInputImageKey)
let outBrownImage = multiplyFilter?.outputImage
let linearImage = outBrownImage?.applyingFilter("CISRGBToneCurveToLinear")
let cgImage = CIContext().createCGImage(linearImage!, from: linearImage!.extent)
return UIImage (cgImage: cgImage!)
}
最简单的尝试是将这 3 个 renderer.image { ... }
调用合并为一个调用。您应该能够将第二个调用的内容移动到第一个调用中。这应该会产生巨大的性能差异。
除此之外,您真的需要对相机胶卷中的全尺寸图像执行此操作吗?如果不是,请在执行所有不需要的渲染之前调整您在渲染器上设置的大小。
通常,当您尝试以高性能方式进行此类过滤时,您会使用 CoreImage
。有了它,您可以以非常高的速度处理图像。像 60 fps 过滤实时视频。
我将从查看 Apple 的内置过滤器列表开始: https://developer.apple.com/library/archive/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html
这是一个很好的过滤器使用示例: https://www.hackingwithswift.com/articles/204/how-to-use-core-image-filters-the-type-safe-way
如果您发现无法组合内置过滤器来获得效果,您始终可以自己编写非常简单的 Metal backed 过滤器: https://flexmonkey.blogspot.com/2016/01/metal-kernel-functions-as-core-image.html