Are algorithm questions allowed here? Well here goes anyway.
I am loading a large dataset into an array, doing some data processing to generate an array of pixel data which I then save as a PNG file.
For the original data, the reference point for the data is the bottom-left corner, but when saving to a PNG file the reference point is the top-left corner - so I have to do a vertical flip.
To add a little complication, I am not able to use CoreGraphics
image handling as my code will run on a RaspberryPi, so I am using PureSwift/PNG (https://github.com/PureSwift/png) instead.
The code I have works but my method could be a bit slow - the typical images that I am generating being 7200x7200px (~52M pixels).
Redesigning my implementation such that the pixelData
is [UInt8][UInt8]
might allow me to process the pixels a line at a time, but that would require a big rewrite of other code - which I am trying to avoid.!
import Foundation
import PNG
func writePixelstoFilePNG(_ pixelData: [UInt8], height: Int, width: Int, to destinationURL: URL) -> Bool {
let size: (x: Int, y: Int) = (width, height)
let layout: (rgb: PNG.Layout, v: PNG.Layout) = (
rgb: .init(format: .rgb8(palette: [], fill: nil, key: nil)),
v: .init(format: .v8( fill: nil, key: nil))
)
var px = pixelData
vFlipImagePixels(&px, height: height, width: width)
let image: PNG.Data.Rectangular = .init(packing: px, size: size, layout: layout.v)
do {
try image.compress(path: destinationURL.path, level: 0)
} catch {
return false
}
return true
}
func vFlipImagePixels(_ px: inout [UInt8], height: Int, width: Int) {
for r in 0 ..< ((height >> 1)) {
for c in 0 ..< width {
px.swapAt((height * r) + c, (height - 1 - r) * width + c)
}
}
}