2016-05-07 11 views
4

Я получаю пиксели методом OpenGLES (glReadPixels) или другим способом, а затем создаю CVPixelBuffer (с или без CGImage) для видеозаписи, но окончательное изображение искажено. Это происходит на iPhone6, когда я проверить на iPhone 5с, 5с и 6.Создайте CVPixelBuffer с данными пикселей, но окончательное изображение искажено

Это выглядит следующим образом:

enter image description here

Вот код:

CGSize viewSize=self.glView.bounds.size; 
NSInteger myDataLength = viewSize.width * viewSize.height * 4; 

// allocate array and read pixels into it. 
GLubyte *buffer = (GLubyte *) malloc(myDataLength); 
glReadPixels(0, 0, viewSize.width, viewSize.height, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 

// gl renders "upside down" so swap top to bottom into new array. 
// there's gotta be a better way, but this works. 
GLubyte *buffer2 = (GLubyte *) malloc(myDataLength); 
for(int y = 0; y < viewSize.height; y++) 
{ 
    for(int x = 0; x < viewSize.width* 4; x++) 
    { 
     buffer2[(int)((viewSize.height-1 - y) * viewSize.width * 4 + x)] = buffer[(int)(y * 4 * viewSize.width + x)]; 
    } 
} 

free(buffer); 

// make data provider with data. 
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL); 

// prep the ingredients 
int bitsPerComponent = 8; 
int bitsPerPixel = 32; 
int bytesPerRow = 4 * viewSize.width; 
CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault; 
CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault; 

// make the cgimage 
CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB(); 
CGImageRef imageRef = CGImageCreate(viewSize.width , viewSize.height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent); 

//UIImage *photo = [UIImage imageWithCGImage:imageRef]; 

int width = CGImageGetWidth(imageRef); 
int height = CGImageGetHeight(imageRef); 

CVPixelBufferRef pixelBuffer = NULL; 
CVReturn status = CVPixelBufferPoolCreatePixelBuffer(NULL, _recorder.pixelBufferAdaptor.pixelBufferPool, &pixelBuffer); 

NSAssert((status == kCVReturnSuccess && pixelBuffer != NULL), @"create pixel buffer failed."); 

CVPixelBufferLockBaseAddress(pixelBuffer, 0); 
void *pxdata = CVPixelBufferGetBaseAddress(pixelBuffer); 
NSParameterAssert(pxdata != NULL);//CGContextRef 
CGContextRef context = CGBitmapContextCreate(pxdata, 
              width, 
              height, 
              CGImageGetBitsPerComponent(imageRef), 
              CGImageGetBytesPerRow(imageRef), 
              colorSpaceRef, 
              kCGImageAlphaPremultipliedLast); 
NSParameterAssert(context); 

CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); 

CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); 

CGColorSpaceRelease(colorSpaceRef); 
CGContextRelease(context); 
CGImageRelease(imageRef); 

free(buffer2); 

//CIImage *image = [CIImage imageWithCVPixelBuffer:pixelBuffer]; 

// ... 

CVPixelBufferRelease(pixelBuffer); 
+0

также сталкиваются с этой проблемой ... :( – jamesfzhang

+0

я был в состоянии решить эту проблему, гарантируя, что каждый кадр точно такие же размеры Оказалось, что некоторые фреймы были немного другого размера, что привело к искажению. – jamesfzhang

ответ

0

Примечание - этот ответ связывающее общая проблема с изображением, а не с конкретным кодом.

Такого рода проблемы, как правило, «шаг» и относится к компоновке памяти, используемой для хранения изображения, где каждая строка пикселей не плотно упакованы вместе

В качестве примера исходное изображение может быть широким 240 пикселей , CMPixelBuffer может выделять 320 пикселей для каждой строки, где первые 240 пикселей содержат изображение, а дополнительные 80 пикселей - это отступы. В этом случае ширина составляет 240 пикселей, шаг - 320 пикселей.

Strides обычно означает, что вы должны скопировать на каждый ряд пикселей одного в цикле

+0

Любые другие советы? Можете ли вы объяснить «шаг» и как он связан с кодом CGContext? – jamesfzhang