我遇到的问题是无法足够快地迭代UIImage中的所有像素,检查每种颜色与特定的颜色(绿色)。一旦用户启动迭代,就必须立即处理迭代。目前有0.5秒的延迟。
我使用它来创建视图的屏幕截图:
func screenshot() -> UIImage {
UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, UIScreen.main.scale)
view.layer.render(in: UIGraphicsGetCurrentContext()!)
let screenShot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return screenShot!
}
这是为了获得单个像素的颜色:
extension UIImage {
func getPixelColor(pos: CGPoint) -> UIColor {
let pixelData = self.cgImage!.dataProvider!.data
let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)
let pixelInfo: Int = ((Int(self.size.width) * Int(pos.y)) + Int(pos.x)) * 4
let r = CGFloat(data[pixelInfo]) / CGFloat(255.0)
let g = CGFloat(data[pixelInfo+1]) / CGFloat(255.0)
let b = CGFloat(data[pixelInfo+2]) / CGFloat(255.0)
let a = CGFloat(data[pixelInfo+3]) / CGFloat(255.0)
return UIColor(red: r, green: g, blue: b, alpha: a)
}
}
这个循环检查图像的每个像素:
testImage = screenshot()
greenPresent = false
for yCo in 0 ..< Int(testImage.size.height) {
for xCo in 0 ..< Int(testImage.size.width) {
if testImage.getPixelColor(pos: CGPoint(x: xCo, y: yCo)) == UIColor(red: 0, green: 1, blue: 0, alpha: 1) {
greenPresent = true
greenCount += 1
}
}
}
任何建议都将不胜感激。
修改
性能受到0.0的比例因子的影响;我希望能适应这一点。
答案 0 :(得分:4)
这是您发布的代码的更高效版本:
testImage = imageFromView()
var greenCount = 0
if let cfdata = testImage.cgImage?.dataProvider?.data {
let data = cfdata as Data
for i in stride(from: 0, to: data.count, by: 4) {
let r = data[i]
let g = data[i+1]
let b = data[i+2]
if g == 255 && r == 0 && b == 0 {
greenCount += 1
}
}
}
此代码消除了原始代码中的许多低效率。数据只获得一次。没有使用积分。直接访问数据字节。无需创建UIColor
。无法转换为CGFloat
。
答案 1 :(得分:1)
我建议缓存 data
指针:
let data: UnsafePointer<UInt8> = ...
而不是从头开始计算每次一次调用getPixelColor
方法。
另外:考虑创建一个简单的struct Color
,而不是使用标准class UIColor
。创建(和解除分配)许多class
实例可能会很快变得昂贵!
顺便说一句,您还应该在找到所需像素后添加一个简单的break
。当然,假设你的最终算法保持不变; - )
答案 2 :(得分:0)
对于初学者,一找到绿色像素就会突破循环:
yLoop: for yCo in 0 ..< Int(testImage.size.height) {
for xCo in 0 ..< Int(testImage.size.width) {
if testImage.getPixelColor(pos: CGPoint(x: xCo, y: yCo)) == UIColor(red: 0, green: 1, blue: 0, alpha: 1) {
greenPresent = true
break yLoop
}
}
}
由于您只想知道是否有一个绿色像素,所以在找到之后继续没有意义。这将使您的检查平均加速50%(尽管右下方的单个绿色像素将花费的时间一样长。)