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.

Revisions

  1. AllanChen renamed this gist Jun 25, 2018. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  2. AllanChen created this gist Jun 25, 2018.
    90 changes: 90 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,90 @@
    -(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;
    }