Pixel Array a UIImage en Swift

He estado tratando de averiguar cómo convertir una matriz de datos de píxeles rgb a un UIImage en Swift.

Estoy manteniendo los datos rgb por píxel en una estructura simple:

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

Llegué a la siguiente function, pero la image resultante es incorrecta:

 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)! } 

¿Algún consejo o guía sobre cómo convertir correctamente una matriz rgb en un UIImage?

Su único problema es que los types de datos en su estructura PixelData deben ser UInt8 . Creé una image de testing en un patio con lo siguiente:

 public struct PixelData { var a: UInt8 var r: UInt8 var g: UInt8 var b: UInt8 } var pixels = [PixelData]() let networking = 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(networking) } for _ in 1...300 { pixels.append(green) } for _ in 1...300 { pixels.append(blue) } let image = imageFromARGB32Bitmap(pixels, width: 30, height: 30) 

Actualización para Swift 2.2:

imageFromARGB32Bitmap para trabajar con Swift 2.2:

 func imageFromARGB32Bitmap(pixels:[PixelData], width: Int, height: Int)-> UIImage { let rgbColorSpace = CGColorSpaceCreateDeviceRGB() let bitmapInfo:CGBitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.PremultipliedFirst.rawValue) let bitsPerComponent = 8 let bitsPerPixel = 32 assert(pixels.count == 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, .RenderingIntentDefault ) return UIImage(CGImage: cgim!) } 

Actualización para 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) }