2016-09-17 201 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的大小