我正在尝试将包含从每像素16位TIFF文件加载的数据的CGImage写入ProRes 44444 QuickTime文件,同时保持位深度。
我正在加载这样的数据:
NSImage* image = [[NSImage alloc] initWithContentsOfFile:@"/whatever/test.tif"];
CGImageRef temp = [image CGImageForProposedRect:nil context:nil hints:nil];
我有一个AVAssetWriterInputPixelBufferAdaptor设置如下:
NSDictionary *sourcePixelBufferAttributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kCVPixelFormatType_64ARGB], kCVPixelBufferPixelFormatTypeKey,
[NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
[NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
nil];
AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:writerInput
sourcePixelBufferAttributes:sourcePixelBufferAttributesDictionary];
然后我将我的图像写入CVPixelBuffer:
CVPixelBufferRef pxbuffer = NULL;
CVReturn status = CVPixelBufferPoolCreatePixelBuffer(NULL, adaptor.pixelBufferPool, &pxbuffer);
CVPixelBufferLockBaseAddress(pxbuffer, 0);
void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGBitmapInfo bitmapInfo = (CGBitmapInfo) kCGImageAlphaPremultipliedLast;
CGContextRef context = CGBitmapContextCreate(pxdata, size.width, size.height, 16, 8*size.width, rgbColorSpace, bitmapInfo);
CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image);
CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
然后将其附加到电影中:
[adaptor appendPixelBuffer:pxbuffer withPresentationTime:CMTimeMake(frame, 24)]
这与8位/像素图像(适当调整值)完美配合,但是对于16位/像素图像,我在生成的QuickTime电影中得到了奇怪的色彩。它看起来有点像某些频道可能被交换,但各种尝试交换它们并没有产生有用的结果。有没有人有一个将超过8位/像素的图像数据写入QuickTime电影的工作示例?
答案 0 :(得分:0)
所以,我找到了一个解决方案,而且我认为我发布了它,因为公共互联网似乎只包含了这个例子,在我点击之前我必须尝试很多东西有用的东西。
以下是如何从CGImage开始获取kCVPixelFormatType_4444AYpCbCr16 CVPixelBuffer(您想要编写ProRes 4444的内容)。这适用于没有alpha的16位/通道RGB源。通过更改bitmapInfo和bitsPerPixel值,可能可以使用alpha通道的图像,但这是未经测试的。
- (CVPixelBufferRef) convertFrame:(CGImageRef) sourceImage {
vImage_Buffer sourceBuffer;
CVPixelBufferRef destBuffer;
vImage_CGImageFormat inFormat = {
.bitsPerComponent = (unsigned int)CGImageGetBitsPerComponent(sourceImage),
.bitsPerPixel = (unsigned int)CGImageGetBitsPerPixel(sourceImage),
.colorSpace = NULL,
.bitmapInfo = (CGBitmapInfo)kCGImageAlphaNone,
.version = 0,
.decode = NULL,
.renderingIntent = kCGRenderingIntentDefault,
};
vImage_Error err = vImageBuffer_InitWithCGImage(&sourceBuffer, &inFormat, NULL, sourceImage, kvImageNoFlags);
if (err == kvImageNoError)
{
CGColorSpaceRef dstColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceITUR_709);
vImage_CGImageFormat format = {
.bitsPerComponent = 16,
.bitsPerPixel = 48,
.bitmapInfo = (CGBitmapInfo)kCGImageAlphaNone,
.colorSpace = dstColorSpace,
};
vImageCVImageFormatRef vformat = vImageCVImageFormat_Create(kCVPixelFormatType_4444AYpCbCr16,
kvImage_ARGBToYpCbCrMatrix_ITU_R_709_2,
kCVImageBufferChromaLocation_Center,
dstColorSpace,
0);
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, CGImageGetWidth(sourceImage), CGImageGetHeight(sourceImage),
kCVPixelFormatType_4444AYpCbCr16, NULL, &destBuffer);
NSParameterAssert(status == kCVReturnSuccess && destBuffer != NULL);
err = vImageBuffer_CopyToCVPixelBuffer(&sourceBuffer, &format, destBuffer, vformat, 0, kvImagePrintDiagnosticsToConsole);
if(err != 0)
NSLog(@"Conversion error: %zi", err);
CGColorSpaceRelease(dstColorSpace);
free(sourceBuffer.data);
}
return destBuffer;
}