Pixel Array for UIImage in Swift

I was trying to figure out how to convert an array of rgb pixel data in UIImage to Swift.

I save rgb data per pixel in a simple structure:

public struct PixelData { var a: Int var r: Int var g: Int var b: Int } 

I made my way to the following function, but the resulting image is incorrect:

 func imageFromARGB32Bitmap(pixels:[PixelData], width: Int, height: Int)-> UIImage { let rgbColorSpace = CGColorSpaceCreateDeviceRGB() let bitmapInfo:CGBitmapInfo = CGBitmapInfo(CGImageAlphaInfo.PremultipliedFirst.rawValue) let bitsPerComponent:Int = 8 let bitsPerPixel:Int = 32 assert(pixels.count == Int(width * height)) var data = pixels // Copy to mutable [] let providerRef = CGDataProviderCreateWithCFData( NSData(bytes: &data, length: data.count * sizeof(PixelData)) ) let cgim = CGImageCreate( width, height, bitsPerComponent, bitsPerPixel, width * Int(sizeof(PixelData)), rgbColorSpace, bitmapInfo, providerRef, nil, true, kCGRenderingIntentDefault ) return UIImage(CGImage: cgim)! } 

Any tips or pointers on the proper conversion of the rgb array to UIImage?

+7
arrays ios swift uiimage cgimage
source share
2 answers

Your only problem is that the data types in your PixelData structure must be UInt8 . I created a test image on the playground with the following:

 public struct PixelData { var a: UInt8 var r: UInt8 var g: UInt8 var b: UInt8 } var pixels = [PixelData]() let red = PixelData(a: 255, r: 255, g: 0, b: 0) let green = PixelData(a: 255, r: 0, g: 255, b: 0) let blue = PixelData(a: 255, r: 0, g: 0, b: 255) for _ in 1...300 { pixels.append(red) } for _ in 1...300 { pixels.append(green) } for _ in 1...300 { pixels.append(blue) } let image = imageFromARGB32Bitmap(pixels, width: 30, height: 30) 

Update for Swift 4:

I updated imageFromARGB32Bitmap to work with Swift 4. Now the function returns UIImage? and guard used to return nil if something goes wrong.

 func imageFromARGB32Bitmap(pixels: [PixelData], width: Int, height: Int) -> UIImage? { guard width > 0 && height > 0 else { return nil } guard pixels.count == width * height else { return nil } let rgbColorSpace = CGColorSpaceCreateDeviceRGB() let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue) let bitsPerComponent = 8 let bitsPerPixel = 32 var data = pixels // Copy to mutable [] guard let providerRef = CGDataProvider(data: NSData(bytes: &data, length: data.count * MemoryLayout<PixelData>.size) ) else { return nil } guard let cgim = CGImage( width: width, height: height, bitsPerComponent: bitsPerComponent, bitsPerPixel: bitsPerPixel, bytesPerRow: width * MemoryLayout<PixelData>.size, space: rgbColorSpace, bitmapInfo: bitmapInfo, provider: providerRef, decode: nil, shouldInterpolate: true, intent: .defaultIntent ) else { return nil } return UIImage(cgImage: cgim) } 
+5
source share

Update for Swift 3

 struct PixelData { var a: UInt8 = 0 var r: UInt8 = 0 var g: UInt8 = 0 var b: UInt8 = 0 } func imageFromBitmap(pixels: [PixelData], width: Int, height: Int) -> UIImage? { assert(width > 0) assert(height > 0) let pixelDataSize = MemoryLayout<PixelData>.size assert(pixelDataSize == 4) assert(pixels.count == Int(width * height)) let data: Data = pixels.withUnsafeBufferPointer { return Data(buffer: $0) } let cfdata = NSData(data: data) as CFData let provider: CGDataProvider! = CGDataProvider(data: cfdata) if provider == nil { print("CGDataProvider is not supposed to be nil") return nil } let cgimage: CGImage! = CGImage( width: width, height: height, bitsPerComponent: 8, bitsPerPixel: 32, bytesPerRow: width * pixelDataSize, space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedFirst.rawValue), provider: provider, decode: nil, shouldInterpolate: true, intent: .defaultIntent ) if cgimage == nil { print("CGImage is not supposed to be nil") return nil } return UIImage(cgImage: cgimage) } 
+7
source share

All Articles