Skip to content

Instantly share code, notes, and snippets.

@AllanChen
Last active May 20, 2024 08:53
Show Gist options
  • Save AllanChen/94bb2a0f418af25bdfd408076408516d to your computer and use it in GitHub Desktop.
Save AllanChen/94bb2a0f418af25bdfd408076408516d to your computer and use it in GitHub Desktop.
UIImage to YUV420f NV12 (iOS)
-(CVPixelBufferRef)imageToYUVPixelBuffer:(UIImage *)image{
// convert to CGImage & dump to bitmapData
CGImageRef imageRef = [image CGImage];
int width = (int)CGImageGetWidth(imageRef);
int height = (int)CGImageGetHeight(imageRef);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
NSUInteger bytesPerPixel = 4;
NSUInteger bytesPerRow = ((bytesPerPixel*width+255)/256)*256;
NSUInteger bitsPerComponent = 8;
GLubyte* bitmapData = (GLubyte *)malloc(bytesPerRow*height); // if 4 components per pixel (RGBA)
CGContextRef context = CGBitmapContextCreate(bitmapData, width, height,
bitsPerComponent, bytesPerRow, colorSpace,
kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
CGContextRelease(context);
// 创建YUV pixelbuffer
CVPixelBufferRef yuvPixelBuffer;
CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(attrs, kCVPixelBufferIOSurfacePropertiesKey, (void*)[NSDictionary dictionary]);
CFDictionarySetValue(attrs, kCVPixelBufferOpenGLESCompatibilityKey, (void*)[NSNumber numberWithBool:YES]);
////420YpCbCr8BiPlanar是半 plannar
CVReturn err = CVPixelBufferCreate(kCFAllocatorDefault, (int)image.size.width, (int)image.size.height, kCVPixelFormatType_420YpCbCr8BiPlanarFullRange, attrs, &yuvPixelBuffer);
if (err) {
return NULL;
}
CFRelease(attrs);
CVPixelBufferLockBaseAddress(yuvPixelBuffer, 0);
uint8_t * yPtr = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(yuvPixelBuffer, 0);
size_t strideY = CVPixelBufferGetBytesPerRowOfPlane(yuvPixelBuffer, 0);
uint8_t * uvPtr = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(yuvPixelBuffer, 1);
size_t strideUV = CVPixelBufferGetBytesPerRowOfPlane(yuvPixelBuffer, 1);
for (int j = 0; j < image.size.height; j++) {
for (int i = 0; i < image.size.width; i++) {
float r = bitmapData[j*bytesPerRow + i*4 + 0];
float g = bitmapData[j*bytesPerRow + i*4 + 1];
float b = bitmapData[j*bytesPerRow + i*4 + 2];
int16_t y = (0.257*r + 0.504*g + 0.098*b) + 16;
if (y > 255) {
y = 255;
} else if (y < 0) {
y = 0;
}
yPtr[j*strideY + i] = (uint8_t)y;
}
}
for (int j = 0; j < image.size.height/2; j++) {
for (int i = 0; i < image.size.width/2; i++) {
float r = bitmapData[j*2*bytesPerRow + i*2*4 + 0];
float g = bitmapData[j*2*bytesPerRow + i*2*4 + 1];
float b = bitmapData[j*2*bytesPerRow + i*2*4 + 2];
int16_t u = (-0.148*r - 0.291*g + 0.439*b) + 128;
int16_t v = (0.439*r - 0.368*g - 0.071*b) + 128;
if (u > 255) {
u = 255;
} else if (u < 0) {
u = 0;
}
if (v > 255) {
v = 255;
} else if (v < 0) {
v = 0;
}
uvPtr[j*strideUV + i*2 + 0] = (uint8_t)u;
uvPtr[j*strideUV + i*2 + 1] = (uint8_t)v;
}
}
free(bitmapData);
CVPixelBufferUnlockBaseAddress(yuvPixelBuffer, 0);
return yuvPixelBuffer;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment