Ответ 1
Похоже, что это могут быть отношения. Возможно, это будет jpg и RGB вместо индексированных цветов с помощью png?
Этот код работает в основном, но результирующие данные, похоже, теряют цветной канал (это то, что я думаю), поскольку результирующие данные изображения при отображении окрашены в синий цвет!
Вот код:
UIImage* myImage=[UIImage imageNamed:@"sample1.png"];
CGImageRef imageRef=[myImage CGImage];
CVImageBufferRef pixelBuffer = [self pixelBufferFromCGImage:imageRef];
Метод pixelBufferFromCGIImage был схвачен из другого сообщения в stackoverflow здесь: Как экспортировать массив UIImage как фильм? (хотя это приложение не связано с тем, что я пытаюсь делать)
+ (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;
}
Я думаю, что это имеет какое-то отношение к отношениям между kCVPixelFormatType_32ARGB и kCGImageAlphaNoneSkipLast, хотя я пробовал каждую комбинацию и получал либо тот же результат, либо сбой приложения. Еще раз, это получает данные UIImage в CVImageBufferRef, но когда я показываю изображение на экране, он, похоже, потеряет цветной канал и отображает оттенок синего. Изображение представляет собой png.
Похоже, что это могут быть отношения. Возможно, это будет jpg и RGB вместо индексированных цветов с помощью png?
Решение состоит в том, что этот код работает идеально, как предполагалось.:) Проблема заключалась в использовании данных при создании текстуры OpenGL. Полностью не связан с этим кодом. Любой, кто ищет, как преобразовать UIImage в CVImageBufferRef, ваш ответ указан в приведенном выше коде!
Если кто-то все еще ищет решение этой проблемы, я решил это, переключив BOOLs в опции pixelBuffer:
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:NO], kCVPixelBufferCGImageCompatibilityKey,
[NSNumber numberWithBool:NO], kCVPixelBufferCGBitmapContextCompatibilityKey,
nil];
От NO до YES:
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
[NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
nil];
Я сталкиваюсь с той же проблемой и нахожу несколько примеров: http://www.cakesolutions.net/teamblogs/2014/03/08/cmsamplebufferref-from-cgimageref
попробуйте изменить
CGBitmapInfo bitmapInfo = (CGBitmapInfo)kCGBitmapByteOrder32Little |
kCGImageAlphaPremultipliedFirst)
Вот что действительно работает:
+ (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;
}
Вы можете изменить буфер пикселей обратно на UIImage (а затем отобразить или сохранить его), чтобы подтвердить, что он работает с этим методом:
+ (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 document directory
//NSString *imageSavePath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"myImageFromPixelBuffer.png"]];
//[UIImagePNGRepresentation(image) writeToFile:imageSavePath atomically:YES];
return image;
}
Только для того, чтобы прояснить ответ выше: я столкнулся с той же проблемой, потому что мой шейдерный код ожидал двухслойных выборок в буфере изображения, тогда как я использовал буфер одного уровня
Эта строка взяла значения rgb из одного образца и передала их (я не знаю, что), но конечным результатом является полноцветное изображение.
gl_FragColor = vec4(texture2D(SamplerY, texCoordVarying).rgb, 1);