首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >获取点的像素颜色对于HEIC图像来说太长了

获取点的像素颜色对于HEIC图像来说太长了
EN

Stack Overflow用户
提问于 2019-06-08 03:07:10
回答 1查看 68关注 0票数 0

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

我想知道为什么会这样,我能做些什么来修复它?为了清楚起见,下面的代码工作,只是需要很长的时间来处理HEIC。

代码语言:javascript
复制
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!
    }
EN

回答 1

Stack Overflow用户

发布于 2019-06-08 14:48:40

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

例如:

代码语言:javascript
复制
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,您可以从中快速检索颜色值。

顺便说一句,我认为使用如下所示的struct来呈现稍微更直观的代码是有用的,而不是单独导航RGBA字节:

代码语言:javascript
复制
struct Pixel {
    let red: UInt8
    let green: UInt8
    let blue: UInt8
    let alpha: UInt8
}

extension Pixel {
    var color: UIColor {
        return UIColor(red: CGFloat(red) / 255,
                       green: CGFloat(green) / 255,
                       blue: CGFloat(blue) / 255,
                       alpha: CGFloat(alpha) / 255)
    }
}

更有趣的问题是,为什么要检索多个像素的颜色。您是否真的需要单个像素的颜色,或者您是否正在根据结果进行一些计算(例如直方图、平均颜色等)?也就是说,如果你真的只需要逐个像素地处理颜色,这是可以的,但如果你试图解决一个更广泛的问题,我们也许能够向你展示比逐个像素处理更有效的方法。其中包括并行化例程、vImage高性能图像处理等。但是,如果不知道如何处理这些重复调用来检索像素颜色,我们就不能说更多了。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56499993

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档