Convierta UIImage a CVImageBufferRef

Este código funciona principalmente, pero los datos resultantes parecen perder un canal de color (es lo que estoy pensando) ya que los datos de image resultantes cuando se muestran se tiñen de azul.

Aquí está el código:

UIImage* myImage=[UIImage imageNamed:@"sample1.png"]; CGImageRef imageRef=[myImage CGImage]; CVImageBufferRef pixelBuffer = [self pixelBufferFromCGImage:imageRef]; 

El método pixelBufferFromCGIImage fue capturado de otra publicación en stackoverflow aquí: ¿Cómo exporto UIImage array como una película? (aunque esta aplicación no está relacionada con lo que estoy tratando de hacer) es

 + (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image { CGSize frameSize = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image)); NSDictionary *options = @{ (__bridge NSString *)kCVPixelBufferCGImageCompatibilityKey: @(NO), (__bridge NSString *)kCVPixelBufferCGBitmapContextCompatibilityKey: @(NO) }; CVPixelBufferRef pixelBuffer; CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, frameSize.width, frameSize.height, kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef) options, &pixelBuffer); if (status != kCVReturnSuccess) { return NULL; } CVPixelBufferLockBaseAddress(pixelBuffer, 0); void *data = CVPixelBufferGetBaseAddress(pixelBuffer); CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef context = CGBitmapContextCreate(data, frameSize.width, frameSize.height, 8, CVPixelBufferGetBytesPerRow(pixelBuffer), rgbColorSpace, (CGBitmapInfo) kCGImageAlphaNoneSkipLast); CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image); CGColorSpaceRelease(rgbColorSpace); CGContextRelease(context); CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); return pixelBuffer; } 

Estoy pensando que tiene algo que ver con la relación entre kCVPixelFormatType_32ARGB y kCGImageAlphaNoneSkipLast, aunque he intentado cada combinación y obtuve el mismo resultado o un error de aplicación. Una vez más, esto obtiene los datos UIImage en CVImageBufferRef, pero cuando muestro la image en la pantalla, parece perder un canal de color y aparece en azul. La image es un png.

Parece que podría ser esa relación. ¿Es posible que sea un jpg y RGB en lugar de colors indexados con un png?

La solución es que este código funciona perfectamente como está previsto. 🙂 El problema estaba en usar los datos para crear una textura OpenGL. Completamente sin relación con este código. Cualquier persona que busque cómo convertir UIImage a CVImageBufferRef, su respuesta está en el código anterior.

Si alguien todavía está buscando una solución a este problema, lo solucioné cambiando los BOOL en las opciones de pixelBuffer:

 NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:NO], kCVPixelBufferCGImageCompatibilityKey, [NSNumber numberWithBool:NO], kCVPixelBufferCGBitmapContextCompatibilityKey, nil]; 

De NO a SÍ:

 NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, nil]; 

Me encuentro con el mismo problema y encuentro algunas muestras: http://www.cakesolutions.net/teamblogs/2014/03/08/cmsamplebufferref-from-cgimageref
Trata de cambiar

 CGBitmapInfo bitmapInfo = (CGBitmapInfo)kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst) 

Esto es lo que realmente funciona:

 + (CVPixelBufferRef)pixelBufferFromImage:(CGImageRef)image { CGSize frameSize = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image)); // Not sure why this is even necessary, using CGImageGetWidth/Height in status/context seems to work fine too CVPixelBufferRef pixelBuffer = NULL; CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, frameSize.width, frameSize.height, kCVPixelFormatType_32BGRA, nil, &pixelBuffer); if (status != kCVReturnSuccess) { return NULL; } CVPixelBufferLockBaseAddress(pixelBuffer, 0); void *data = CVPixelBufferGetBaseAddress(pixelBuffer); CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); CGContextRef context = CGBitmapContextCreate(data, frameSize.width, frameSize.height, 8, CVPixelBufferGetBytesPerRow(pixelBuffer), rgbColorSpace, (CGBitmapInfo) kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image); CGColorSpaceRelease(rgbColorSpace); CGContextRelease(context); CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); return pixelBuffer; } 

Puede cambiar el búfer de píxeles a UIImage (y luego mostrarlo o savelo) para confirmar que funciona con este método:

 + (UIImage *)imageFromPixelBuffer:(CVPixelBufferRef)pixelBuffer { CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pixelBuffer]; CIContext *context = [CIContext contextWithOptions:nil]; CGImageRef myImage = [context createCGImage:ciImage fromRect:CGRectMake(0, 0, CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer))]; UIImage *image = [UIImage imageWithCGImage:myImage]; // Uncomment the following lines to say the image to your application's document directory //NSString *imageSavePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"myImageFromPixelBuffer.png"]]; //[UIImagePNGRepresentation(image) writeToFile:imageSavePath atomically:YES]; return image; } 

Solo para aclarar la respuesta anterior: me he topado con el mismo problema porque mi código de sombreador esperaba dos muestras de capas dentro de un búfer de imágenes, mientras utilizaba un búfer de una sola capa

Esta línea tomó los valores de rgb de una muestra y los pasó a (no sé qué), pero el resultado final es una image de color completa.

  gl_FragColor = vec4(texture2D(SamplerY, texCoordVarying).rgb, 1);