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:

example image of current implementation

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

Popular posts from this blog

resizing Telegram inline keyboard -

command line - How can a Python program background itself? -

php - "cURL error 28: Resolving timed out" on Wordpress on Azure App Service on Linux -