1

I have an UIImage made of only 4 types of pixel.

static let black = RGBA32(red: 0, green: 0, blue: 0, alpha: 255)
static let red   = RGBA32(red: 255, green: 0, blue: 0, alpha: 255)
static let green = RGBA32(red: 0, green: 255, blue: 0, alpha: 255)
static let blue  = RGBA32(red: 0, green: 0, blue: 255, alpha: 255)

( reference to the code used to create the Image https://stackoverflow.com/a/40207142/7010252 )

I saved the image in the phone's photo library then I open the image in my app again. I know that the number of pixel is the same.

So how can I get the RGBA data of all the pixels?

CodeBender
  • 35,668
  • 12
  • 125
  • 132
l.b.dev
  • 151
  • 3
  • 10

1 Answers1

1

The first thing done here is to loop through your image and create a map of all the points in it.

func getPixelColor(image: UIImage) {
    let width = image.size.width
    let height = image.size.height

    for x in 0..<Int(width) {
        for y in 0..<Int(height) {
            let color = image.pixelColor(CGPoint(x: CGFloat(x), y: CGFloat(y)))
            print(color.RGBA)
        }
    }
}

Once it has the color it wants, it then calls the RGBA function in the UIColor extension to provide the string you want.

Next, we use an extension of UIImage to then take the points provided by the above function and query the image data for its UIColor data.

extension UIImage {
    func pixelColor(_ point: CGPoint) -> UIColor {
        let pixelData = cgImage?.dataProvider?.data
        let pointerData: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)

        let pixelInfo = Int(((self.size.width * point.y) + point.x)) * 4

        let maxValue: CGFloat = 255.0
        let compare: CGFloat = 0.99

        let r: CGFloat = (CGFloat(pointerData[pixelInfo]) / maxValue) > compare ? 1.0 : 0.0
        let g: CGFloat = (CGFloat(pointerData[pixelInfo + 1]) / maxValue) > compare ? 1.0 : 0.0
        let b: CGFloat = (CGFloat(pointerData[pixelInfo + 2]) / maxValue) > compare ? 1.0 : 0.0
        let a = CGFloat(pointerData[pixelInfo + 3]) / maxValue

        return UIColor(red: r, green: g, blue: b, alpha: a)
    }
}

This extension uses the raw data to determine the RGB values of each pixel. It then performs a crude check to play safe with CGFloats to see if the value is 255.0 for that particular color. If it is, it will return a value of 1.0, otherwise it returns 0.0.

Next, there is an extension for UIColor that will provide the formatted string you are looking for.

extension UIColor {
    var RGBA: String {
        guard let components = cgColor.components, components.count == 4 else {
            return ""
        }

        return "\(components[0])-\(components[1])-\(components[2])-\(components[3])"
    }
}

This should provide the 1-0-0-1 type of values you seek. You can also modify this to include any additional information you need.

CodeBender
  • 35,668
  • 12
  • 125
  • 132
  • but when I use that code there is a problem. I should get either (rgba) 1-0-0-1 (red) / 0-1-0-1 (green) / 0-0-1-1 (blue) / 0-0-0-1 (black) but I get double such as : (rgba) 0.6787878 - 0.823345 - 0.34522 - 1 – l.b.dev Dec 14 '16 at 18:36
  • Updated to address your issue. Hopefully that resolves it. – CodeBender Dec 14 '16 at 19:32
  • nope didn't work, I always get "0.0-0.0-0.0-1.0". It means the pixel is black but actually the picture isn't black. Do you have any Idea how I need to fix it ? @CodeBender – l.b.dev Dec 15 '16 at 19:51
  • it isn't : let r: CGFloat = (CGFloat(pointerData[pixelInfo]) / maxValue) > 254.9 ? 1.0 : 0.0 – l.b.dev Dec 18 '16 at 11:22
  • it is : let r: CGFloat = (CGFloat(pointerData[pixelInfo]) / maxValue) > 0.9 ? 1.0 : 0.0 – l.b.dev Dec 18 '16 at 11:24
  • My bad, I just checked it too late. Updated answer to include that. – CodeBender Dec 18 '16 at 20:26