I know there have been lots of posts for how to get the colour of a pixel in a UIImage
given a CGPoint
but they are all outdated as far as I can tell. Most of them contain CGImageGetDataProvider
and CGDataProviderCopyData
which in Swift 4 is an error:
'CGImageGetDataProvider' has been replaced by property 'CGImage.dataProvider' 'CGDataProviderCopyData' has been replaced by property 'CGDataProvider.data'
Xcode suggests these substitutes, but they do not exist so I have been having trouble trying to recreate a Swift 4 function to get the colour of a pixel in a UIImage
.
Here is the typical Swift 3 function:
extension UIImage {
subscript (x: Int, y: Int) -> UIColor? {
if x < 0 || x > Int(size.width) || y < 0 || y > Int(size.height) {
return nil
}
let provider = CGImageGetDataProvider(self.cgImage!)
let providerData = CGDataProviderCopyData(provider!)
let data = CFDataGetBytePtr(providerData)
let numberOfComponents = 4
let pixelData = ((Int(size.width) * y) + x) * numberOfComponents
let r = CGFloat(data![pixelData]) / 255.0
let g = CGFloat(data![pixelData + 1]) / 255.0
let b = CGFloat(data![pixelData + 2]) / 255.0
let a = CGFloat(data![pixelData + 3]) / 255.0
return UIColor(red: r, green: g, blue: b, alpha: a)
}
}
Any suggestions or comments are greatly appreciated. Thank you!
EDIT
I tried @Mukesh 's solution but even though all the build errors are fixed, the program crashes. It says:
The image I give to the function is not nil
, I have checked.
P.S. The image I am using for the function is a snapshot of the camera. I have a live camera and after every frame, this function (below) is called where I turn the current frame into a UIImage
. This UIImage
is what I want to find the pixel colour of:
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
let pixelBuffer: CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!
let ciImg = CIImage(cvPixelBuffer: pixelBuffer)
let cameraImage = UIImage(ciImage: ciImg)
let col = cameraImage.getPixelColor(pos: CGPoint(x: 100, y: 100))
}
I used CGPoint(x: 100, y: 100)
to see if it crashed as an example, and it did. This point is also in the image because if it wasn't, it would have returned nil
here:
if x < 0 || x > Int(size.width) || y < 0 || y > Int(size.height) {
return nil
}
Is there a way to find out why it gets a nil
value? Or maybe a different solution? Thank you :)
But often such sites will often use the hexadecimal system to describe the color. Swift fortunately can represent integers as hex values. Take the first two digits of the hex number as red, the next two as green, and the last two as blue. Write them with 0x prefixed to the number Red for #fde8d7 would be 0xfd for example.
These are not the same type, Swift is very cranky about type so we need to convert red, green and blue with a CGFloat initializer before we do anything else. Next, we checks which segment the user selected.
Thanks in advance! Because image objects are immutable, they also do not provide direct access to their underlying image data. However, you can get an functions.
For example, sRGB is a particular set of intensities for red, green and blue and defines the colors that can be reproduced by mixing those ranges of red, green and blue. How to work with UIColor objects using RGBA and HSBA values in Swift?
Here is the code I get after removing the errors:
extension UIImage {
subscript (x: Int, y: Int) -> UIColor? {
if x < 0 || x > Int(size.width) || y < 0 || y > Int(size.height) {
return nil
}
let provider = self.cgImage!.dataProvider
let providerData = provider!.data
let data = CFDataGetBytePtr(providerData)
let numberOfComponents = 4
let pixelData = ((Int(size.width) * y) + x) * numberOfComponents
let r = CGFloat(data![pixelData]) / 255.0
let g = CGFloat(data![pixelData + 1]) / 255.0
let b = CGFloat(data![pixelData + 2]) / 255.0
let a = CGFloat(data![pixelData + 3]) / 255.0
return UIColor(red: r, green: g, blue: b, alpha: a)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With