【问题标题】:Getting Pixel Color from an Image using CGPoint in Swift 3在 Swift 3 中使用 CGPoint 从图像中获取像素颜色
【发布时间】:2016-09-17 15:08:40
【问题描述】:

我在 Swift 3 中尝试这个 PixelExtractor 类,得到一个错误; 无法使用类型为“(UnsafeMutableRawPointer?)”的参数列表调用类型“UnsafePointer”的初始化程序

class PixelExtractor: NSObject {

let image: CGImage
let context: CGContextRef?

var width: Int {
    get {
        return CGImageGetWidth(image)
    }
}

var height: Int {
    get {
        return CGImageGetHeight(image)
    }
}

init(img: CGImage) {
    image = img
    context = PixelExtractor.createBitmapContext(img)
}

class func createBitmapContext(img: CGImage) -> CGContextRef {

    // Get image width, height
    let pixelsWide = CGImageGetWidth(img)
    let pixelsHigh = CGImageGetHeight(img)

    let bitmapBytesPerRow = pixelsWide * 4
    let bitmapByteCount = bitmapBytesPerRow * Int(pixelsHigh)

    // Use the generic RGB color space.
    let colorSpace = CGColorSpaceCreateDeviceRGB()

    // Allocate memory for image data. This is the destination in memory
    // where any drawing to the bitmap context will be rendered.
    let bitmapData = malloc(bitmapByteCount)
    let bitmapInfo = CGBitmapInfo(rawValue:   CGImageAlphaInfo.PremultipliedFirst.rawValue)
    let size = CGSizeMake(CGFloat(pixelsWide), CGFloat(pixelsHigh))
    UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
    // create bitmap
    let context = CGBitmapContextCreate(bitmapData, pixelsWide, pixelsHigh, 8,
    bitmapBytesPerRow, colorSpace, bitmapInfo.rawValue)

    // draw the image onto the context
    let rect = CGRect(x: 0, y: 0, width: pixelsWide, height: pixelsHigh)
    CGContextDrawImage(context, rect, img)

    return context!
}

func colorAt(x x: Int, y: Int)->UIColor {

    assert(0<=x && x<width)
    assert(0<=y && y<height)

    let uncastedData = CGBitmapContextGetData(context)
    let data = UnsafePointer<UInt8>(uncastedData)

    let offset = 4 * (y * width + x)

    let alpha: UInt8 = data[offset]
    let red: UInt8 = data[offset+1]
    let green: UInt8 = data[offset+2]
    let blue: UInt8 = data[offset+3]

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

    return color
}

}

修复此错误。

let data = UnsafePointer<UInt8>(uncastedData)

->

let data = UnsafeRawPointer(uncastedData)

得到其他错误; '键入'UnsafeRawPointer?'没有下标成员的

如何修改这个错误?

【问题讨论】:

    标签: image pixel swift3 cgpoint


    【解决方案1】:

    当您的data 中有UnsafeRawPointer 时,您可以这样写:

        let alpha = data.load(fromByteOffset: offset, as: UInt8.self)
        let red = data.load(fromByteOffset: offset+1, as: UInt8.self)
        let green = data.load(fromByteOffset: offset+2, as: UInt8.self)
        let blue = data.load(fromByteOffset: offset+3, as: UInt8.self)
    

    否则,您可以从您的uncastedData 获取UnsafeMutablePointer&lt;UInt8&gt;(假设它是UnsafeMutableRawPointer):

        let data = uncastedData.assumingMemoryBound(to: UInt8.self)
    

    【讨论】:

      【解决方案2】:

      SWIFT 3(2017 年 3 月更新)Xcode 8 / IOS 10

      重要:注意返回值对应数据中的红色:b,绿色:r和蓝色:r它们向后存储

      • 首先,创建扩展程序(您可以复制并粘贴到您的 代码)

        extension UIImage {
        
            func getPixelColor(pos: CGPoint) -> UIColor {
        
                if 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+0]) / 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: b, green: g, blue: r, alpha: a)
                } else {
                //IF something is wrong I returned WHITE, but change as needed
                    return UIColor.white
                }
            }
        }
        
      • 那么就叫它:

        let colorAtPixel : UIColor = (theView.image?.getPixelColor(pos: CGPoint(x: 2, y: 2)))!
        

      虽然代码返回准确的颜色,但似乎没有为不同的 CGPoints 返回正确的颜色。

      可能是因为屏幕分辨率? (x1,x2,x3)?

      如果有人能为这个谜团增添一些光,那就太好了……

      【讨论】:

      • 虽然我仍然遇到视网膜显示器的问题,但我发现这篇文章可能对某人有所帮助:stackoverflow.com/questions/25146557/…
      • 我只是想知道,UIImage 的点使用什么坐标系?是 UIKit - 例如点 (0,0) 在左上角?谢谢!
      【解决方案3】:

      Swift-3 (IOS 10.3)

      extension UIImage {
      
          func getPixelColor(atLocation location: CGPoint, withFrameSize size: CGSize) -> UIColor {
              let x: CGFloat = (self.size.width) * location.x / size.width
              let y: CGFloat = (self.size.height) * location.y / size.height
      
              let pixelPoint: CGPoint = CGPoint(x: x, y: y)
      
              let pixelData = self.cgImage!.dataProvider!.data
              let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)
      
              let pixelIndex: Int = ((Int(self.size.width) * Int(pixelPoint.y)) + Int(pixelPoint.x)) * 4
      
              let r = CGFloat(data[pixelIndex]) / CGFloat(255.0)
              let g = CGFloat(data[pixelIndex+1]) / CGFloat(255.0)
              let b = CGFloat(data[pixelIndex+2]) / CGFloat(255.0)
              let a = CGFloat(data[pixelIndex+3]) / CGFloat(255.0)
      
              return UIColor(red: r, green: g, blue: b, alpha: a)
          }
      
      }
      

      用法:-

      let color = yourImageView.image!.getPixelColor(atLocation: location, withFrameSize: yourImageView.frame.size)
      

      位置是一个CGPoint size 是 imageView 的大小

      【讨论】:

        【解决方案4】:

        以下部分取自一些 Swift 3 代码,我用于从图像中采样像素以获得主要色调,用于为 tableView 行生成背景。色调选择过程的机制不适用于您的问题,所以我只是提供相关片段。

        let colorSpace = CGColorSpaceCreateDeviceRGB() //  UIExtendedSRGBColorSpace
        let newImage = image.cgImage?.copy(colorSpace: colorSpace)
        
        let pixelData = newImage?.dataProvider!.data
        let data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)
        
        var hueFrequency = [Int: Double]()
        hueFrequency[1] = 1                 // Add one entry so this serves as a default if no hues from the image pass the filters
        
        let nStart = 1
        let mStart = 1
        
        for n in nStart...Int(image.size.width / samplingFactor) {
            for m in mStart...Int(image.size.height / samplingFactor) {
                let pixelInfo: Int = ((Int(image.size.width) * m * Int(samplingFactor)) + n * Int(samplingFactor)) * 4 // bytesPerPixel
        
                let b = CGFloat(data[pixelInfo]) / CGFloat(255.0)           // cgImage bitmapinfo = rawValue 8194 -> BGRA ordering
                let g = CGFloat(data[pixelInfo+1]) / CGFloat(255.0)
                let r = CGFloat(data[pixelInfo+2]) / CGFloat(255.0)
                let a = CGFloat(data[pixelInfo+3]) / CGFloat(255.0)
        

        另外,请注意,我发现 bitmapInfo 值(使用我的参数的 image.cgImage!.bitmapInfo)表明将 RGBA 序列重新排序为 BGRA,我必须在排序步骤以挑选数据时进行处理。如果您的颜色不正确,您可能需要检查一下。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-07-21
          • 2019-07-27
          • 1970-01-01
          • 2014-12-06
          • 1970-01-01
          • 1970-01-01
          • 2013-07-11
          • 1970-01-01
          相关资源
          最近更新 更多