Search code examples
swiftuiimage

RGB values for same image is different between phone and mac or simulator


I'm working on a task where given an image file stored locally (png/ jpg), I have to extract the rgb pixel values and input that to a different function. The problem I have faced is, the rgb values I get from ios simulator environment and on ios device is different resulting the output from next function to be very different as well. Has anyone faced similar issue? What could be the problem for this strange behaviour?

I have used swiftimage library and another different method to extract the rgb values and they both product same output on each device (but different between across each devices)

Using swiftimage library this is how I exract rgbs (from github.com/koher/swift-image)

extension UIImage {
    func extractrgbValues() -> [Float] {
        let swImage = Image<RGB<Float>>(uiImage: self)
        let width = swImage.width
        let height = swImage.height
        
        var reds = [[Float]](repeating: [Float](repeating: 0, count: width), count: height)
        var greens = [[Float]](repeating: [Float](repeating: 0, count: width), count: height)
        var blues = [[Float]](repeating: [Float](repeating: 0, count: width), count: height)
        
        // data is stored columnwise and we have to flip i,j to reconstruct it row-wise
        for i in 0..<width {
            for j in 0..<height {
                let pixel = swImage[i,j]
                reds[j][i] = pixel.red
                greens[j][i] = pixel.green
                blues[j][i] = pixel.blue
            }
        }
        return [reds, greens, blues].flatMap { $0 }.flatMap { $0 }
    }
}

Other reference I've tried is an answer from this post Get Pixel color of UIImage

For the very same image, pixel values on pc/ android environment are almost identical. But on iOS both device and simulator produce very different outcomes and neither is close to pc/android output.


Solution

  • I would expect given this line that it's using a device-calibrated RGB colorspace. When you decode the image, Core Graphics adjusts it to display the correct, calibrated colors on this device's screen. If you want the pixel data to match other platforms, you need to decode it using the same colorspace they do. For PC and Android, the default colorspace is .sRGB (the so-called "standard Red Green Blue" color space defined by IEC 61966-2-1).

    Note that if you then display the image locally, the colors will not match other calibrated displays.

    You can set the colorspace in CIContext using createCGImage(_:from:format:colorSpace:).

    If you already have the CGImage, you can make a new CGImage in a different colorspace using copy(colorSpace:).

    Even with the same color space, JPEG may not decode identically on different systems. This is permitted by spec as long as the results are within a specified tolerance. Lossless formats like PNG or TIFF should always decode identically on all platforms.