Pon*_*ono 5 core-graphics core-image swift
我一直在努力解决这个问题而没有运气.我有一个非常简单的Swift命令行应用程序,它接受一个参数 - 图像路径加载.它使用SepiaTone过滤器裁剪图像并过滤该图像片段.
它工作得很好.它将图像裁剪为200x200并使用SepiaTone进行过滤.现在这是我面临的问题 - 我的MacBook Air 整个过程需要600毫秒.现在,当我将输入图像调整(而不是裁剪)到相同尺寸(200x200)时,需要150ms.
这是为什么?在这两种情况下,我都会过滤尺寸为200x200的图像.我正在使用这个特定的图像进行测试(5966x3978).
更新:
在处理裁剪图像时,这段特殊代码需要4倍的时间:
var ciImage:CIImage = CIImage(cgImage: cgImage)
Run Code Online (Sandbox Code Playgroud)
更新结束
裁剪代码(200x200):
// parse args and get image path
let args:Array = CommandLine.arguments
let inputFile:String = args[CommandLine.argc - 1]
let inputURL:URL = URL(fileURLWithPath: inputFile)
// load the image from path into NSImage
// and convert NSImage into CGImage
guard
let nsImage = NSImage(contentsOf: inputURL),
var cgImage = nsImage.cgImage(forProposedRect: nil, context: nil, hints: nil)
else {
exit(EXIT_FAILURE)
}
// CROP THE IMAGE TO 200x200
// THIS IS THE ONLY BLOCK OF CODE THAT IS DIFFERENT
// IN THOSE TWO EXAMPLES
let rect = CGRect(x: 0, y: 0, width: 200, height: 200)
if let croppedImage = cgImage.cropping(to: rect) {
cgImage = croppedImage
} else {
exit(EXIT_FAILURE)
}
// END CROPPING
// convert CGImage to CIImage
var ciImage:CIImage = CIImage(cgImage: cgImage)
// initiate SepiaTone
guard
let sepiaFilter = CIFilter(name: "CISepiaTone")
else {
exit(EXIT_FAILURE)
}
sepiaFilter.setValue(ciImage, forKey: kCIInputImageKey)
sepiaFilter.setValue(0.5, forKey: kCIInputIntensityKey)
guard
let result = sepiaFilter.outputImage
else {
exit(EXIT_FAILURE)
}
let context:CIContext = CIContext()
// perform filtering in a GPU context
guard
let output = context.createCGImage(sepiaFilter.outputImage!, from: ciImage.extent)
else {
exit(EXIT_FAILURE)
}
Run Code Online (Sandbox Code Playgroud)
调整大小的代码(200x200):
// parse args and get image path
let args:Array = CommandLine.arguments
let inputFile:String = args[CommandLine.argc - 1]
let inputURL:URL = URL(fileURLWithPath: inputFile)
// load the image from path into NSImage
// and convert NSImage into CGImage
guard
let nsImage = NSImage(contentsOf: inputURL),
var cgImage = nsImage.cgImage(forProposedRect: nil, context: nil, hints: nil)
else {
exit(EXIT_FAILURE)
}
// RESIZE THE IMAGE TO 200x200
// THIS IS THE ONLY BLOCK OF CODE THAT IS DIFFERENT
// IN THOSE TWO EXAMPLES
guard let CGcontext = CGContext(data: nil,
width: 200,
height: 200,
bitsPerComponent: cgImage.bitsPerComponent,
bytesPerRow: cgImage.bytesPerRow,
space: cgImage.colorSpace ?? CGColorSpaceCreateDeviceRGB(),
bitmapInfo: cgImage.bitmapInfo.rawValue)
else {
exit(EXIT_FAILURE)
}
CGcontext.draw(cgImage, in: CGRect(x: 0, y: 0, width: 200, height: 200))
if let resizeOutput = CGcontext.makeImage() {
cgImage = resizeOutput
}
// END RESIZING
// convert CGImage to CIImage
var ciImage:CIImage = CIImage(cgImage: cgImage)
// initiate SepiaTone
guard
let sepiaFilter = CIFilter(name: "CISepiaTone")
else {
exit(EXIT_FAILURE)
}
sepiaFilter.setValue(ciImage, forKey: kCIInputImageKey)
sepiaFilter.setValue(0.5, forKey: kCIInputIntensityKey)
guard
let result = sepiaFilter.outputImage
else {
exit(EXIT_FAILURE)
}
let context:CIContext = CIContext()
// perform filtering in a GPU context
guard
let output = context.createCGImage(sepiaFilter.outputImage!, from: ciImage.extent)
else {
exit(EXIT_FAILURE)
}
Run Code Online (Sandbox Code Playgroud)
小智 1
看起来你正在做两件截然不同的事情。在“慢”版本中,您正在裁剪(如获取原始图像的一个小 CGRect),而在“快”版本中,您正在调整大小(如将原始图像缩小为 CGRect)。
您可以通过添加两个 UIImageView 并在每个 ciImage 声明后添加以下行来证明这一点:
slowImage.image = UIImage(ciImage: ciImage)
fastImage.image = UIImage(ciImage: ciImage)
Run Code Online (Sandbox Code Playgroud)
这是两个模拟器屏幕截图,“慢”图像位于“快”图像上方。第一个是您的代码,其中“慢”CGRect 原点是 (0,0),第二个是将其调整为 (2000,2000):
知道了这一点,我就能想出一些发生在时间上的事情。
我提供了有关裁剪功能的 Apple 文档的链接。它解释了它在幕后进行一些 CGRect 计算,但没有解释它如何从全尺寸 CG 图像中提取像素位 - 我认为这才是真正变慢的地方。
但最终,看起来时机是由于做了两件完全不同的事情。
| 归档时间: |
|
| 查看次数: |
187 次 |
| 最近记录: |