2016-09-17 187 views
1

我在Swift 3中尝试这个PixelExtractor类,得到一个错误; 不能调用类型 'UnsafePointer' 初始化与类型的参数列表 '(UnsafeMutableRawPointer?)'在Swift 3中使用CGPoint从图像获取像素颜色

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?'没有下标成员'

如何修改此错误?

回答

4

当你有一个UnsafeRawPointer你可以写这样的事情你data

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) 

否则,你可以从UnsafeMutablePointer<UInt8>uncastedData(假设它是一个UnsafeMutableRawPointer):

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

以下部分取自我用来从图像中采样像素以获取主要色调的一些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,进行重新排序,我曾在订购步骤挑选出对付数据。如果你的颜色不对,你可能想检查一下。

1

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)?

这将是巨大的,如果有人能轻一些添加到神秘...

+0

虽然我仍然有Retina显示屏的问题,我发现这个职位,可以帮助的人:http://stackoverflow.com/questions/25146557/怎么办-I-得到最色的-A-像素IN-A-的UIImage与 - 迅速 – MLBDG

1

斯威夫特-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 和大小是您的ImageView的大小