swift - CMSampleBuffer frame converted to vImage has wrong colors -
i’m trying convert cmsamplebuffer
camera output vimage
, later apply processing. unfortunately, without further editing, frame buffer has wrong colors:
implementation (memory management , errors not considered in question):
configuring video output device:
videodataoutput = avcapturevideodataoutput() videodataoutput.videosettings = [string(kcvpixelbufferpixelformattypekey): kcvpixelformattype_32bgra] videodataoutput.alwaysdiscardslatevideoframes = true videodataoutput.setsamplebufferdelegate(self, queue: capturequeue) videoconnection = videodataoutput.connection(withmediatype: avmediatypevideo) capturesession.sessionpreset = avcapturesessionpreset1280x720 let videodevice = avcapturedevice.defaultdevice(withmediatype: avmediatypevideo) guard let videodeviceinput = try? avcapturedeviceinput(device: videodevice) else { return }
creating vimage
casamplebuffer
received camera:
// convert `casamplebuffer` `cvimagebuffer` guard let pixelbuffer = cmsamplebuffergetimagebuffer(samplebuffer) else { return } var buffer: vimage_buffer = vimage_buffer() buffer.data = cvpixelbuffergetbaseaddress(pixelbuffer) buffer.rowbytes = cvpixelbuffergetbytesperrow(pixelbuffer) buffer.width = vimagepixelcount(cvpixelbuffergetwidth(pixelbuffer)) buffer.height = vimagepixelcount(cvpixelbuffergetheight(pixelbuffer)) let vformat = vimagecvimageformat_createwithcvpixelbuffer(pixelbuffer) let bitmapinfo:cgbitmapinfo = cgbitmapinfo(rawvalue: cgimagealphainfo.last.rawvalue | cgbitmapinfo.byteorder32little.rawvalue) var cgformat = vimage_cgimageformat(bitspercomponent: 8, bitsperpixel: 32, colorspace: nil, bitmapinfo: bitmapinfo, version: 0, decode: nil, renderingintent: .defaultintent) // create vimage vimagebuffer_initwithcvpixelbuffer(&buffer, &cgformat, pixelbuffer, vformat!.takeretainedvalue(), cgcolor, vimage_flags(kvimagenoflags))
converting buffer uiimage:
for sake of tests cvpixelbuffer exported uiimage, adding video buffer has same result.
var dstpixelbuffer: cvpixelbuffer? let status = cvpixelbuffercreatewithbytes(nil, int(buffer.width), int(buffer.height), kcvpixelformattype_32bgra, buffer.data, int(buffer.rowbytes), releasecallback, nil, nil, &dstpixelbuffer) let destcgimage = vimagecreatecgimagefrombuffer(&buffer, &cgformat, nil, nil, numericcast(kvimagenoflags), nil)?.takeretainedvalue() // create uiimage let exportedimage = destcgimage.flatmap { uiimage(cgimage: $0, scale: 0.0, orientation: uiimageorientation.right) } dispatchqueue.main.async { self.previewview.image = exportedimage }
the call vimagebuffer_initwithcvpixelbuffer
performing modifying vimage_buffer
, cvpixelbuffer
's contents, bit naughty because in (linked) code promise not modify pixels when say
cvpixelbufferlockbaseaddress(pixelbuffer, .readonly)
the correct way initialise cgbitmapinfo
bgra8888 alpha first, 32bit little endian, non obvious, covered in header file vimage_cgimageformat
in vimage_utilities.h:
let bitmapinfo = cgbitmapinfo(rawvalue: cgimagealphainfo.first.rawvalue | cgimagebyteorderinfo.order32little.rawvalue)
what don't why vimagebuffer_initwithcvpixelbuffer
modifying buffer, cgformat
(desiredformat
) should match vformat
, although documented modify buffer, maybe should copy data first.
Comments
Post a Comment