2016-09-17 2 views
1

Я пытаюсь использовать этот класс PixelExtractor в Swift 3, получить сообщение об ошибке; Не может вызвать инициализатор для типа 'UnsafePointer' со списком аргументов типа '(UnsafeMutableRawPointer?)'Получение пикселя от изображения с помощью CGPoint в Swift 3

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) Xcode 8/IOS 10

Важно: обратите внимание, что возвращаемое значение соответствует красный цвет: б, зеленый: г и синий: г как в данных, которые они хранятся в обратном направлении

  • Во-первых, создать расширение (вы можете скопировать & вставить где-нибудь в вашем коде)

    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

Хотя я до сих пор проблемы с сетчаткой дисплеев я нашел этот пост, который может помочь кому-то: http://stackoverflow.com/questions/25146557/ как-ду-я-получить по-цвет-в-а-пиксель-в-а-UIImage-с-скор – MLBDG

1

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 и размер является размер вашего ImageView

Смежные вопросы