Search code examples
iosswiftuiimageswift3rgba

change an UI Image into a String array


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?


Solution

  • 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.