austintt austintt - 6 months ago 110
Swift Question

Pixel Array to UIImage in Swift

I've been trying to figure out how to convert an array of rgb pixel data to a UIImage in Swift.

I'm keeping the rgb data per pixel in a simple struct:

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


I've 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 how to properly convert an rgb array to an UIImage?

Answer

Your only problem is that the data types in your PixelData structure need to be UInt8. I created a test image in a 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 2.2:

I updated imageFromARGB32Bitmap to work with 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!)
}
Comments