2015-12-16 1 views
1

Je collecte des données d'image de l'appareil photo en utilisant ce code:Création d'annonce l'affichage d'un UIImage à partir des données BGRA premières

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 
{ 
    // Called when a frame arrives 
    // Should be in BGRA format 
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    CVPixelBufferLockBaseAddress(imageBuffer, 0); 

    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 
    unsigned char *raw = (unsigned char *)CVPixelBufferGetBaseAddress(imageBuffer); 

    // Copy memory into allocated buffer 
    unsigned char *buffer = malloc(sizeof(unsigned char) * bytesPerRow * height); 
    memcpy(buffer, raw, bytesPerRow * height); 
    [self processVideoData:buffer width:width height:height bytesPerRow:bytesPerRow]; 

    CVPixelBufferUnlockBaseAddress(imageBuffer, 0); 
} 

La méthode processVideoData: ressemble à ceci:

- (void)processVideoData:(unsigned char *)data width:(size_t)width height:(size_t)height bytesPerRow:(size_t)bytesPerRow 
{ 
    dispatch_sync(dispatch_get_main_queue(), ^{ 

     CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, data, bytesPerRow * height, NULL); 
     CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
     CGImageRef image = CGImageCreate(width, height, 8, 32, bytesPerRow, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaLast, dataProvider, NULL, NO, kCGRenderingIntentDefault); 

     // Set layer contents??? 
     UIImage *objcImage = [UIImage imageWithCGImage:image]; 
     self.imageView.image = objcImage; 

     free(data); 
     CGDataProviderRelease(dataProvider); 
     CGColorSpaceRelease(colorSpace); 
     CGImageRelease(image); 
    }); 
} 

Aucune plainte, aucune fuites mais rien n'apparaît dans la vue de l'image il reste juste vide (oui j'ai vérifié la connexion de sortie). Auparavant, j'avais le bitmapInfo réglé juste à kCGBitmapByteOrderDefault qui provoquait un plantage lors de la définition de la propriété d'image de la vue de l'image, mais la vue de l'image deviendrait sombre, ce qui était prometteur juste avant le crash.

J'ai résumé que l'accident était dû à l'image étant dans BGRA pas BGR donc j'ai mis le bitmapInfo à kCGBitmapByteOrderDefault | kCGImageAlphaLast et cela a résolu le crash mais aucune image.

Je me rends compte que l'image semblera étrange car le CGImageRef attend une image RVB et je la passe BGR mais cela devrait seulement donner une image bizarre à cause de la permutation des canaux. J'ai également déconnecté les données que je reçois et il semble être dans l'ordre quelque chose comme: b:65 g:51 r:42 a:255 et le canal alpha est toujours 255 comme prévu.

Je suis désolé si c'est évident mais je n'arrive pas à comprendre ce qui ne va pas.

Répondre

0

Il s'avère que les données étaient juste dans le mauvais format et je ne l'ai pas introduit correctement dans la fonction CGImageCreate.

Les données sont dans le format BGRA donc je nourris ces données dans une structure IplImage (j'utilise OpenCV v 2.4.9) comme ceci:

// Pack IplImage with data 
IplImage *img = cvCreateImage(cvSize((int)width, (int)height), 8, 4); 
img->imageData = (char *)data; 

puis converti je en RVB comme ceci:

IplImage *converted = cvCreateImage(cvSize((int)width, (int)height), 8, 3); 
cvCvtColor(img, converted, CV_BGRA2RGB); 

I ensuite introduit les données de l'IplImage converti en une fonction CGImageCreate et il fonctionne bien.

2

Vous pouvez utiliser cette combinaison de drapeau pour obtenir le format BGRA:

kCGBitmapByteOrder32Little | kCGImageAlphaSkipFirst 

Vous devriez préférer utiliser cette solution, il sera plus moyen par rapport à performante conversion OpenCV.

est ici de façon plus commune pour convertir sourcePixelFormat à bitmapInfo:

sourcePixelFormat = CVPixelBufferGetPixelFormatType(pixelBuffer); 
bitmapInfo = @{ 
    @(kCVPixelFormatType_32ARGB) : @(kCGBitmapByteOrder32Big | kCGImageAlphaNoneSkipFirst), 
    @(kCVPixelFormatType_32BGRA) : @(kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst), 
}[@(sourcePixelFormat)].unsignedIntegerValue;