Я хочу преобразовать объект UIImage в объект CVPixelBufferRef, но я абсолютно не знаю. И я не могу найти код примера, делающий что-то подобное.Преобразование UIImage в CVPixelBufferRef
Может кто-нибудь, пожалуйста, помогите мне? THX заранее!
C YA
Я хочу преобразовать объект UIImage в объект CVPixelBufferRef, но я абсолютно не знаю. И я не могу найти код примера, делающий что-то подобное.Преобразование UIImage в CVPixelBufferRef
Может кто-нибудь, пожалуйста, помогите мне? THX заранее!
C YA
CVPixelBufferRef является то, что видеоядро использует для входа камеры.
Вы можете создавать похожие растровые изображения пикселей из изображений с помощью CGBitmapContextCreate, а затем рисовать изображение в контексте растрового изображения.
То, что я хочу сделать, это добавить отдельные кадры в кино с помощью Фонда AV , Это будет сделано с использованием класса AVAssetWriterInputPixelBufferAdaptor. Но этот класс ожидает объекты CVPixelBufferRef. Итак, как я могу преобразовать UIImage в объект CVPixelBufferRef? – Nuker
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;
}
Нет идеи, если это вообще работает, хотя. (Ваш пробег может быть осторожным :)
Вопрос был о преобразовании 'UIImage' в' CVPixelBufferRef', а не 'NSImage' – srgtuszy
Строка о size_t bytesPerRow = CVPixelBufferGetBytesPerRow (buffer); вот что сделал трюк для меня.Все остальные образцы кода использовали магическую константу, которая на этом устройстве оказалась неправильной, и возможность определения реального значения была ключом. Благодарю. –
Вы можете использовать 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 заботится о вас.
Существуют различные способы сделать это, эти функции преобразуют буфер пикселей из 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;
}
Зачем вам переворачивать вертикально и горизонтально? –
@MaxiMus Поскольку UIKit и core grphics имеют разные системы координат https://developer.apple.com/library/content/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/GraphicsDrawingOverview/GraphicsDrawingOverview.html – Andrea
Координаты y да, но не x. ..? –
Очень поздно, но для тех, кто нуждается.
// 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;
}
См https://stackoverflow.com/a/44475334/1418457 – onmyway133