2014-09-04 602 views
3

我想将YUV图像转换为CIIMage并最终转换成UIImage。我在这些方面相当新手,并试图找出一个简单的方法来做到这一点。从我所学到的,从iOS6 YUV可以直接用来创建CIImage,但正如我试图创建它,CIImage只保留一个零值。我的代码是这样的 - >如何转换YUV至CIImage for iOS

NSLog(@"Started DrawVideoFrame\n"); 

CVPixelBufferRef pixelBuffer = NULL; 

CVReturn ret = CVPixelBufferCreateWithBytes(
              kCFAllocatorDefault, iWidth, iHeight, kCVPixelFormatType_420YpCbCr8BiPlanarFullRange, 
              lpData, bytesPerRow, 0, 0, 0, &pixelBuffer 
              ); 

if(ret != kCVReturnSuccess) 
{ 
    NSLog(@"CVPixelBufferRelease Failed"); 
    CVPixelBufferRelease(pixelBuffer); 
} 

NSDictionary *opt = @{ (id)kCVPixelBufferPixelFormatTypeKey : 
         @(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange) }; 

CIImage *cimage = [CIImage imageWithCVPixelBuffer:pixelBuffer options:opt]; 
NSLog(@"CURRENT CIImage -> %p\n", cimage); 

UIImage *image = [UIImage imageWithCIImage:cimage scale:1.0 orientation:UIImageOrientationUp]; 
NSLog(@"CURRENT UIImage -> %p\n", image); 

这里的lpData是YUV数据,它是一个无符号字符数组。

这也看起来很有趣:vImageMatrixMultiply,找不到任何这方面的例子。谁能帮我这个?

+1

[This](https://developer.apple.com/library/ios/documentation/graphicsimaging/Conceptual/CoreImaging/ci_performance/ci_performance.html)可能对您有所帮助。 – swiftBoy 2014-09-04 07:34:57

+1

谢谢,我已经检查过这个链接了。我正在关注这一点,并使用这样的选项,但CIImage没有被初始化 – d1xlord 2014-09-04 08:16:40

+0

我发现这个[链接](http://stackoverflow.com/questions/13201084/how-to-convert-a-kcvpixelformattype-420ypcbcr8biplanarfullrange-buffer-到uiimag?RQ = 1)。这可能有帮助。我会尝试一下并发布结果。 – d1xlord 2014-09-04 09:11:26

回答

3

我也遇到过这个类似的问题。我试图将YUV(NV12)格式的数据显示到屏幕上。该解决方案是工作在我的项目...

//YUV(NV12)-->CIImage--->UIImage Conversion 
NSDictionary *pixelAttributes = @{kCVPixelBufferIOSurfacePropertiesKey : @{}}; 
CVPixelBufferRef pixelBuffer = NULL; 

CVReturn result = CVPixelBufferCreate(kCFAllocatorDefault, 
             640, 
             480, 
             kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, 
             (__bridge CFDictionaryRef)(pixelAttributes), 
             &pixelBuffer); 

CVPixelBufferLockBaseAddress(pixelBuffer,0); 
unsigned char *yDestPlane = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0); 

// Here y_ch0 is Y-Plane of YUV(NV12) data. 
memcpy(yDestPlane, y_ch0, 640 * 480); 
unsigned char *uvDestPlane = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1); 

// Here y_ch1 is UV-Plane of YUV(NV12) data. 
memcpy(uvDestPlane, y_ch1, 640*480/2); 
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); 

if (result != kCVReturnSuccess) { 
    NSLog(@"Unable to create cvpixelbuffer %d", result); 
} 

// CIImage Conversion  
CIImage *coreImage = [CIImage imageWithCVPixelBuffer:pixelBuffer]; 

CIContext *MytemporaryContext = [CIContext contextWithOptions:nil]; 
CGImageRef MyvideoImage = [MytemporaryContext createCGImage:coreImage 
                fromRect:CGRectMake(0, 0, 640, 480)]; 

// UIImage Conversion 
UIImage *Mynnnimage = [[UIImage alloc] initWithCGImage:MyvideoImage 
               scale:1.0 
              orientation:UIImageOrientationRight]; 

CVPixelBufferRelease(pixelBuffer); 
CGImageRelease(MyvideoImage); 

我在这里展示的YUV(NV12)数据的数据结构,以及我们如何可以得到y平面(y_ch0)和UV平面(y_ch1),这是用于创建CVPixelBufferRef。让我们来看看在YUV(NV12)数据结构.. enter image description here 如果我们看一下,我们可以得到以下有关YUV(NV12)的信息图片,

  • 总框架尺寸=宽*高* 3/2,
  • y平面尺寸=帧尺寸* 2/3,
  • UV平面尺寸=帧尺寸* 1/3,存储在y平面
  • 数据 - > {Y1,Y2,Y3,Y4, Y5 .....}。
  • 的U-Plane - >(U1,V1,U2,V2,U3,V3,......}

我希望这将有助于所有:)有乐趣。 IOS开发:D

+0

此源代码仅在您仅有YUV(NV12)数据时才有效。如果您有YUV(I420)格式的数据,则需要将YUV(I420)简单转换为YUV(NV12)。 – RajibTheKing 2015-10-17 12:07:30

+2

请提供初始化代码y_ch0和y_ch1 – JULIIncognito 2016-05-31 23:10:53