2010-10-01 4 views
10

Я хочу преобразовать объект UIImage в объект CVPixelBufferRef, но я абсолютно не знаю. И я не могу найти код примера, делающий что-то подобное.Преобразование UIImage в CVPixelBufferRef

Может кто-нибудь, пожалуйста, помогите мне? THX заранее!

C YA

+0

См https://stackoverflow.com/a/44475334/1418457 – onmyway133

ответ

0

CVPixelBufferRef является то, что видеоядро использует для входа камеры.

Вы можете создавать похожие растровые изображения пикселей из изображений с помощью CGBitmapContextCreate, а затем рисовать изображение в контексте растрового изображения.

+1

То, что я хочу сделать, это добавить отдельные кадры в кино с помощью Фонда AV , Это будет сделано с использованием класса AVAssetWriterInputPixelBufferAdaptor. Но этот класс ожидает объекты CVPixelBufferRef. Итак, как я могу преобразовать UIImage в объект CVPixelBufferRef? – Nuker

1

Google - это всегда ваш друг. Поиск «CVPixelBufferRef» первый результат приводит к this snippet из snipplr:

- (CVPixelBufferRef)fastImageFromNSImage:(NSImage *)image{ 
CVPixelBufferRef buffer = NULL; 

// config 
size_t width = [image size].width; 
size_t height = [image size].height; 
size_t bitsPerComponent = 8; // *not* CGImageGetBitsPerComponent(image); 
CGColorSpaceRef cs = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); 
CGBitmapInfo bi = kCGImageAlphaNoneSkipFirst; // *not* CGImageGetBitmapInfo(image); 
NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, nil]; 

// create pixel buffer 
CVPixelBufferCreate(kCFAllocatorDefault, width, height, k32ARGBPixelFormat, (CFDictionaryRef)d, &buffer); 
CVPixelBufferLockBaseAddress(buffer, 0); 
void *rasterData = CVPixelBufferGetBaseAddress(buffer); 
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(buffer); 

// context to draw in, set to pixel buffer's address 
CGContextRef ctxt = CGBitmapContextCreate(rasterData, width, height, bitsPerComponent, bytesPerRow, cs, bi); 
if(ctxt == NULL){ 
    NSLog(@"could not create context"); 
    return NULL; 
} 

// draw 
NSGraphicsContext *nsctxt = [NSGraphicsContext graphicsContextWithGraphicsPort:ctxt flipped:NO]; 
[NSGraphicsContext saveGraphicsState]; 
[NSGraphicsContext setCurrentContext:nsctxt]; 
[image compositeToPoint:NSMakePoint(0.0, 0.0) operation:NSCompositeCopy]; 
[NSGraphicsContext restoreGraphicsState]; 

CVPixelBufferUnlockBaseAddress(buffer, 0); 
CFRelease(ctxt); 

return buffer; 
} 

Нет идеи, если это вообще работает, хотя. (Ваш пробег может быть осторожным :)

+3

Вопрос был о преобразовании 'UIImage' в' CVPixelBufferRef', а не 'NSImage' – srgtuszy

+1

Строка о size_t bytesPerRow = CVPixelBufferGetBytesPerRow (buffer); вот что сделал трюк для меня.Все остальные образцы кода использовали магическую константу, которая на этом устройстве оказалась неправильной, и возможность определения реального значения была ключом. Благодарю. –

1

Вы можете использовать Core Image, чтобы создать CVPixelBuffer из UIImage.

// 1. Create a CIImage with the underlying CGImage encapsulated by the UIImage (referred to as 'image'): 

CIImage *inputImage = [CIImage imageWithCGImage:image.CGImage]; 

// 2. Create a CIContext: 

Context *ciContext = [CIContext contextWithCGContext:UIGraphicsGetCurrentContext() options:nil]; 

// 3. Render the CIImage to a CVPixelBuffer (referred to as 'outputBuffer'): 

[self.ciContext render:img toCVPixelBuffer:outputBuffer]; 

AVFoundation предоставляет классы, которые считывают видео файлы (так называемые активы), а также от производства других объектов AVFoundation, которые обрабатывают (или уже прочитанные) активы в пиксельные буфера. Если это ваша единственная проблема, вы найдете то, что ищете в примере примера расширения образца для редактирования фотографий.

Если ваш источник создан из серии объектов UIImage (возможно, не было исходного файла, и вы создаете новый файл из созданного пользователем контента), то пример кода, приведенный выше, будет достаточным.

ПРИМЕЧАНИЕ. Это не самые эффективные средства и не единственное средство преобразования UIImage в CVPixelBuffer; но, это БЫСТРОЕ самое легкое средство. Использование Core Graphics для преобразования UIImage в CVPixelBuffer требует гораздо больше кода для настройки атрибутов, таких как размер буфера пикселей и цветовое пространство, которые Core Image заботится о вас.

6

Существуют различные способы сделать это, эти функции преобразуют буфер пикселей из CGImage. UImage - обертка вокруг CGImage, таким образом, чтобы получить CGImage, вам просто нужно вызвать метод .CGImage.
Другие способы также создают CIImage из буфера (уже размещены) или используют фреймворк Accelerate, который, вероятно, является самым быстрым, а также самым сложным.

- (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image 
{ 
    NSDictionary *options = @{ 
           (NSString*)kCVPixelBufferCGImageCompatibilityKey : @YES, 
           (NSString*)kCVPixelBufferCGBitmapContextCompatibilityKey : @YES, 
           }; 

    CVPixelBufferRef pxbuffer = NULL; 
    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, CGImageGetWidth(image), 
         CGImageGetHeight(image), kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef) options, 
         &pxbuffer); 
    if (status!=kCVReturnSuccess) { 
     NSLog(@"Operation failed"); 
    } 
    NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL); 

    CVPixelBufferLockBaseAddress(pxbuffer, 0); 
    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer); 

    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(pxdata, CGImageGetWidth(image), 
               CGImageGetHeight(image), 8, 4*CGImageGetWidth(image), rgbColorSpace, 
               kCGImageAlphaNoneSkipFirst); 
    NSParameterAssert(context); 

    CGContextConcatCTM(context, CGAffineTransformMakeRotation(0)); 
    CGAffineTransform flipVertical = CGAffineTransformMake(1, 0, 0, -1, 0, CGImageGetHeight(image)); 
    CGContextConcatCTM(context, flipVertical); 
    CGAffineTransform flipHorizontal = CGAffineTransformMake(-1.0, 0.0, 0.0, 1.0, CGImageGetWidth(image), 0.0); 
    CGContextConcatCTM(context, flipHorizontal); 

    CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), 
              CGImageGetHeight(image)), image); 
    CGColorSpaceRelease(rgbColorSpace); 
    CGContextRelease(context); 

    CVPixelBufferUnlockBaseAddress(pxbuffer, 0); 
    return pxbuffer; 
} 
+0

Зачем вам переворачивать вертикально и горизонтально? –

+0

@MaxiMus Поскольку UIKit и core grphics имеют разные системы координат https://developer.apple.com/library/content/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html – Andrea

+0

Координаты y да, но не x. ..? –

0

Очень поздно, но для тех, кто нуждается.

// call like this 
    CVPixelBufferRef videobuffer = [self pixelBufferFromCGImage:yourImage.CGImage]; 

// метод, который преобразует

-(CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image{ 

    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 
          [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, 
          [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, nil]; 
    CVPixelBufferRef pxbuffer = NULL; 
    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, videoSize.width, videoSize.height, 
              kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef)options, &pxbuffer); 
    NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL); 

    CVPixelBufferLockBaseAddress(pxbuffer, 0); 
    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer); 
    NSParameterAssert(pxdata != NULL); 

    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef context = CGBitmapContextCreate(pxdata, videoSize.width, videoSize.height, 8, 4*videoSize.width, rgbColorSpace, kCGImageAlphaNoneSkipFirst); 
    NSParameterAssert(context); 
    CGContextConcatCTM(context, CGAffineTransformIdentity); 
    CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image); 
    CGColorSpaceRelease(rgbColorSpace); 
    CGContextRelease(context); 
    CVPixelBufferUnlockBaseAddress(pxbuffer, 0); 

    return pxbuffer; 
}