对于HEIC图像,获取像素颜色花费的时间太长

时间:2019-06-07 19:07:09

标签: ios swift core-graphics

以下方法获取所选照片中特定点的像素颜色。选择JPG时,以下图像处理很快。 选择HEIC照片时,以下图像处理很慢。大约慢40倍(7秒vs 5分钟)。

我想知道为什么会这样,如何解决?为清楚起见,下面的代码有效,处理HEIC需要很长时间。

class func getPixelColorAtPoint(point:CGPoint, sourceView: UIView) -> UIColor{

        let pixel = UnsafeMutablePointer<CUnsignedChar>.allocate(capacity: 4)
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
        let context = CGContext(data: pixel, width: 1, height: 1, bitsPerComponent: 8, bytesPerRow: 4, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)
        var color: UIColor? = nil

        if let context = context {
            context.translateBy(x: -point.x, y: -point.y)
            sourceView.layer.render(in: context)

            color = UIColor(red: CGFloat(pixel[0])/255.0,
                            green: CGFloat(pixel[1])/255.0,
                            blue: CGFloat(pixel[2])/255.0,
                            alpha: CGFloat(pixel[3])/255.0)

            pixel.deallocate(capacity: 4)
        }
        return color!
    }

1 个答案:

答案 0 :(得分:0)

如果要花费5分钟,我假设您必须重复调用此例程,每次渲染此0.5。您应该一次又一次地将整个视图渲染到一个完整的像素缓冲区中,然后可以从该缓冲区中有效地检索多个像素的颜色。

例如:

sourceView

很显然,可以根据需要将其渲染到缓冲区,但是基本思想是将像素缓冲区保存到某个var data: Data? var width: Int! var height: Int! func pixelColor(at point: CGPoint, for sourceView: UIView) -> UIColor? { if data == nil { fillBuffer(for: sourceView) } return data?.withUnsafeBytes { rawBufferPointer in let pixels = rawBufferPointer.bindMemory(to: Pixel.self) let pixel = pixels[Int(point.y) * width + Int(point.x)] return pixel.color } } func fillBuffer(for sourceView: UIView) { // get image snapshot let bounds = sourceView.bounds let format = UIGraphicsImageRendererFormat() format.scale = 1 let image = UIGraphicsImageRenderer(bounds: bounds, format: format).image { _ in sourceView.drawHierarchy(in: bounds, afterScreenUpdates: false) } guard let cgImage = image.cgImage else { return } // prepare to get pixel buffer let colorSpace = CGColorSpaceCreateDeviceRGB() let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue) width = Int(bounds.width) height = Int(bounds.height) // populate and save pixel buffer if let context = CGContext(data: nil, width: width, height: height, bitsPerComponent: 8, bytesPerRow: 4 * width, space: colorSpace, bitmapInfo: bitmapInfo.rawValue) { context.draw(cgImage, in: bounds) data = context.data.flatMap { Data(bytes: $0, count: 4 * width * height) } } } 中,您可以从中快速检索颜色值。

顺便说一句,我认为使用Data(如下所示)来渲染稍微更直观的代码是有用的,而不是分别导航RGBA字节:

struct

更有趣的问题,恕我直言,是为什么要检索多个像素的颜色。您是否真的需要单个像素的颜色,还是根据结果(例如直方图,平均颜色等)进行一些计算?即如果您确实只需要逐像素地设置颜色,那很好,但是如果您要解决一个更广泛的问题,我们可能会向您展示比逐像素处理更有效的方法。这些范围包括并行例程,vImage高性能图像处理等。但是,如果不知道您对这些重复调用以获取像素颜色所做的工作,我们就不能说更多。