Swift 3:获取UIImage(更好的是UIImageView)中像素的颜色

3

我尝试了不同的解决方案(例如this one),但是得到的颜色与实际图像略有不同。我猜这是因为图像只有RGB,而不是RGBA。这可能会有问题吗?

相关问题:如果UIImage具有contentMode = .scaleAspectFill,我是否需要重新计算图像,还是可以直接使用imageView.image

编辑:

我尝试使用此扩展:

extension CALayer {
    func getPixelColor(point: CGPoint) -> CGColor {
        var pixel: [CUnsignedChar] = [0, 0, 0, 0]

        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)

        context!.translateBy(x: -point.x, y: -point.y)

        self.render(in: context!)

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


        let color = UIColor(red:red, green: green, blue:blue, alpha:alpha)

        return color.cgColor
    }
}

但对于一些图像来说,似乎坐标系被翻转了,对于其他图像,我得到的值非常错误...我在这里缺少什么吗?
编辑2:
我尝试使用这些图像:

https://dl.dropboxusercontent.com/u/119600/gradient.png https://dl.dropboxusercontent.com/u/119600/gradient@2x.png

但是我得到了错误的值。它们嵌入在一个 UIImageView 中,但我转换了坐标:
private func convertScreenPointToImage(point: CGPoint) -> CGPoint {
    let widthMultiplier = gradientImage.size.width / UIScreen.main.bounds.width
    let heightMultiplier = gradientImage.size.height / UIScreen.main.bounds.height

    return CGPoint(x: point.x * widthMultiplier, y: point.y * heightMultiplier)
}

这一个

enter image description here

当在iPhone 7模拟器上运行时,给我=== Optional((51, 76, 184, 255)),这是不正确的...

1个回答

3

我在这里写了一个游乐场。我使用指针索引图像数据并获取rgba值:

func pixel(in image: UIImage, at point: CGPoint) -> (UInt8, UInt8, UInt8, UInt8)? {
    let width = Int(image.size.width)
    let height = Int(image.size.height)
    let x = Int(point.x)
    let y = Int(point.y)
    guard x < width && y < height else {
        return nil
    }
    guard let cfData:CFData = image.cgImage?.dataProvider?.data, let pointer = CFDataGetBytePtr(cfData) else {
        return nil
    }
    let bytesPerPixel = 4
    let offset = (x + y * width) * bytesPerPixel
    return (pointer[offset], pointer[offset + 1], pointer[offset + 2], pointer[offset + 3])
}

let image = UIImage(named: "t.png")!
if let (r,g,b,a) = pixel(in: image, at: CGPoint(x: 1, y:2)) {
    print ("Red: \(r), Green: \(g), Blue: \(b), Alpha: \(a)")
}

请注意,如果您在UIImageView的UIImage属性上使用此功能,则像素坐标是实际图像在其原始分辨率下的坐标,而不是缩放后的UIImageView的屏幕坐标。另外,我已经尝试了RGB Jpg和RGBA PNG,它们都作为32位RGBA图像导入,因此两者都可以使用。

我无法使其正常工作,仍然得到错误的值 :( 请查看我的编辑。 - swalkner
代码是正确的,我刚刚用你的第一张图片检查过了。我打开了Photoshop,切换到取色器工具并打开了信息面板。我将鼠标悬停在x = 120,y = 500处的像素上,Photoshop显示r:175 g:146 b 232。我在playground中运行代码,得到红色175,绿色146,蓝色232,Alpha值为255。你的输入是什么,期望输出是什么? - Josh Homann
我得到了不同的值(请参见我的编辑) - 你如何加载图像? - swalkner
在 playground 中加载它,就像这样 let image = UIImage (named: "gradient.png")! 我敢打赌问题就在这里。你是从资源目录中加载,因此获取的是 @2x 图像。而我直接加载了 1X 图像。 - Josh Homann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接