2014-09-04 597 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