2016年5月17日 星期二

把 OpenGL 畫面轉換為 UIImage


在開發拍照畫面時,又遇到另一個問題。鏡頭圖案數據會綁定到 OpenGL 的介面來顯示,當點擊「拍照」按鈕後,程式會把本來從 AVCaptureVideoDataOutput 取得相片的數據,轉為經 AVCaptureStillImageOutput 取得;再進行 CIFilter 加工,得出結果圖案。可是拍出來的照片在加工後變了樣。起初以為是數據來源的問題,於是修改了程式,把兩個來源的數據都儲存起來。打開來看,發現除了解像度的分別外,沒有其他。後來又想到會不會是 OpenGL 的繪畫問題?於是嘗試從 OpenGL 中抓下畫面:
   CGFloat width = _previewView.frame.size.width;
   CGFloat height = _previewView.frame.size.height;
   NSInteger length = 4*width*height;

   GLubyte *buffer = (GLubyte *)malloc(length);
   glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);

   GLubyte *buffer2 = (GLubyte *)malloc(length);
   for (int y=0; y<height; y++)  {
      for (int x=0; x<height*4; x++)  {
         int offset = ((4*width)*y)+x;
         int offset2 = (height-1-y)*width*4+x;
         buffer2[offset2] = buffer[offset];
      }
   }

   int bitsPerComponent = 8;
   int bitsPerPixel = 32;
   int bytesPerRow = 4*width;
   CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
   CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
   CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

   CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, length, NULL);
   CGImageRef imageRef = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

   UIImage *image = [UIImage imageWithCGImage:imageRef];
這個方法無法解決問題。看來在 OpenGL 用的喧染方法 (GL_ONE, GL_ONE_MINUS_SRC_ALPHA) 是正常。這樣的話,剩下的可能性會是 CIImage 及 UIImage 的問題...。

沒有留言: