LiveApple/LiveApple/Frame+CV.swift

76 lines
2.7 KiB
Swift

//
// Frame+CV.swift
// LiveApple
//
// Created by Shadowfacts on 9/24/22.
//
import Foundation
import CoreVideo
import Accelerate
extension Frame {
init(pixelBuffer buf: CVPixelBuffer) {
let inputHeight = CVPixelBufferGetHeight(buf)
let inputWidth = CVPixelBufferGetWidth(buf)
let width = inputWidth / 8
let height = inputHeight / 8
precondition(width <= 64)
// something is wonky with the format, sourceBuffer comes out green/white instead of white/black
// but whatever, we can work with that
let inputCVImageFormat = vImageCVImageFormat_CreateWithCVPixelBuffer(buf).takeRetainedValue()
vImageCVImageFormat_SetColorSpace(inputCVImageFormat, CGColorSpaceCreateDeviceRGB())
var error = kvImageNoError
var sourceFormat = vImage_CGImageFormat(
bitsPerComponent: 8,
bitsPerPixel: 32,
colorSpace: nil,
bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.last.rawValue),
version: 0,
decode: nil,
renderingIntent: .defaultIntent
)
var sourceBuffer = vImage_Buffer()
error = vImageBuffer_InitWithCVPixelBuffer(&sourceBuffer, &sourceFormat, buf, inputCVImageFormat, nil, vImage_Flags(kvImageNoFlags))
defer { sourceBuffer.free() }
precondition(error == kvImageNoError)
var destBuffer = vImage_Buffer()
error = vImageBuffer_Init(&destBuffer, vImagePixelCount(height), vImagePixelCount(width), sourceFormat.bitsPerPixel, vImage_Flags(kvImageNoFlags))
defer { destBuffer.free() }
precondition(error == kvImageNoError)
error = vImageScale_ARGB8888(&sourceBuffer, &destBuffer, nil, vImage_Flags(kvImageNoFlags))
precondition(error == kvImageNoError)
let cgImage = vImageCreateCGImageFromBuffer(&destBuffer, &sourceFormat, nil, nil, vImage_Flags(kvImageNoFlags), &error).takeRetainedValue()
precondition(error == kvImageNoError)
let dataRef = cgImage.dataProvider!.data!
let data = dataRef as Data
var enc = [UInt64](repeating: 0, count: height)
for row in 0..<height {
let start = row * cgImage.bytesPerRow
var rowEnc: UInt64 = 0
// this could probably be faster with simd
// note: the individual UInt64s end up being reversed here
for col in 0..<width {
// 4 bytes per pixel
if data[start + (col * 4)] > 127 {
rowEnc |= (1 << col)
}
}
enc[row] = rowEnc
}
self.width = width
self.data = enc
}
}