swift – 为什么过滤裁剪的图像比过滤尺寸调整的图像慢4倍(两者
|
我一直在努力解决这个问题而没有运气.我有一个非常简单的
Swift命令行应用程序,它接受一个参数 – 图像路径加载.它使用SepiaTone过滤器裁剪图像并过滤该图像片段.
它工作得很好.它将图像裁剪为200×200并使用SepiaTone进行过滤.现在这是我面临的问题 – 我的MacBook Air整个过程需要600毫秒.现在,当我将输入图像调整(而不是裁剪)到相同尺寸(200×200)时,需要150ms. 这是为什么?在这两种情况下,我都会过滤尺寸为200×200的图像.我正在使用this particular image进行测试(5966×3978). 更新: 在处理裁剪图像时,这段特殊代码需要4倍的时间: var ciImage:CIImage = CIImage(cgImage: cgImage) 更新结束 裁剪代码(200×200): // 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)
}
调整大小的代码(200×200): // 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),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,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,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,from: ciImage.extent)
else {
exit(EXIT_FAILURE)
}
解决方法
看起来你正在做两件截然不同的事情.在“慢速”版本中,您正在裁剪(如在原始图像的小CGRect中),而在“快速”版本中,您正在调整大小(如将原始文件缩小为CGRect).
您可以通过添加两个UIImageViews并在每次声明ciImage之后添加这些行来证明这一点: slowImage.image = UIImage(ciImage: ciImage)
fastImage.image = UIImage(ciImage: ciImage)
这是两个模拟器截图,“快速”图像上方的“慢”图像.第一个是您的代码,其中“慢”CGRect原点是(0,0),第二个是将其调整为(2000,2000): 原点是(0,0)
起源是(2000,2000)
知道了这一点,我可以在时间上提出一些事情. 我在Apple的文档中包含了关于裁剪功能的链接.它解释说它正在幕后进行一些CGRect计算,但它没有解释它是如何将像素位从全尺寸CG图像中拉出来的 – 我认为这是真正减速的地方. 最后,看起来时间是由于做了两件完全不同的事情. CGRect.cropping(to:) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |


