How to convert a numerical data array into RAW image data in Swift?

913 views Asked by At

I have a data array of Int16 or Int32 numerical values that are the raw image data from a 11MP camera chip with an RGGB pixel layout (CFA). The data are exported by the camera driver as FITS data, which is basically a vector or long string of bytes or 16bit/pixel data in my case.

I like to convert these data into a raw image format in Swift in order to use the powerful debayering and demosaicing features and algorithms in iOS/Swift. I do not intend to demosaic myself, since iOS has a great library for this already (see WWDC2016 keynote on Raw Processing with Core Image).

I need to make iOS “believe” my data are actual raw image data.

I tried using CreatePixelBufferWithBytes in Swift and then CIImage from pixelbuffer but to no avail. The CIImage.cgimage is not an RGB color image.

Is there a simple way to create a raw or DNG image in Swift from raw numerical data?

Here is what I tried with the CVPixelBuffer approach, but I do not get any color image out of this:

imgRawData is a [Int32] or [Float32] array with width*height number of elements.

var pixelBuffer: CVPixelBuffer?
let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue,
            kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue ]
    
CVPixelBufferCreateWithBytes(kCFAllocatorDefault, width, height, kCVPixelFormatType_14Bayer_RGGB, &imgRawData, 2*width, nil, nil, attrs as CFDictionary, &pixelBuffer)

let dummyImg = UIImage(systemName: "star.fill")?.cgImage
    
let ciiraw = CIImage(cvPixelBuffer: pixelBuffer!)
    
let cif = CIFilter.lanczosScaleTransform()
cif.scale = 0.25
cif.inputImage  = ciiraw
let cii = cif.outputImage
    
let context: CIContext = CIContext.init(options: nil)
guard let cgi = context.createCGImage(cii!, from: cii!.extent) else { return dummyImg! }

Quickview of Xcode shows me only black&white or grayscale images. So does the SwiftUI View of the CGImage...

1

There are 1 answers

9
Ctibor Šebák On

You can use CGContext and pass your raw values in as bitmapinfo, see init:

init?(data: UnsafeMutableRawPointer?, width: Int, height: Int, bitsPerComponent: Int, bytesPerRow: Int, space: CGColorSpace, bitmapInfo: UInt32)

And for space parameter, which takes CGColorSpace you would use CGColorSpaceCreateDeviceRGB().

You will then use your image with a code similar to this one:

let imageRef = CGContext.makeImage(context!)
let imageRep = NSBitmapImageRep(cgImage: imageRef()!)

Play around with it for a bit, I think you will find what you are looking for.