iOS 图片转yuv与CVPixelBufferRef转image

图片转yuv

//很奇怪不知道为啥红色和橙色等亮色都成了蓝色... 难道说只能用libyuv去转?
- (CVPixelBufferRef)convertYUVWithImage:(UIImage *)image{
    CGImageRef imageRef = image.CGImage;
    CGDataProviderRef provider = CGImageGetDataProvider(imageRef);
    CFDataRef pixelData = CGDataProviderCopyData(provider);
    const unsigned char *data = CFDataGetBytePtr(pixelData);
        
    size_t bitsPerPixel = CGImageGetBitsPerPixel(imageRef);
    size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
    size_t frameWidth = CGImageGetWidth(imageRef);
    size_t frameHeight = CGImageGetHeight(imageRef);
    size_t bytesPerRow = CGImageGetBytesPerRow(imageRef);
//    NSLog(@"bytesPerRow:%lu ==:%lu",bytesPerRow,bytesPerRow/4);
    CFRelease(pixelData);
    
    NSDictionary *options = @{(id)kCVPixelBufferIOSurfacePropertiesKey : @{}};
    CVPixelBufferRef pixelBuffer = NULL;
    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault,
                                          frameWidth,
                                          frameHeight,
                                          kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange,
                                          (__bridge CFDictionaryRef)(options),
                                          &pixelBuffer);
    NSParameterAssert(status == kCVReturnSuccess && pixelBuffer != NULL);
        
    CVPixelBufferLockBaseAddress(pixelBuffer, 0);
    size_t width = CVPixelBufferGetWidth(pixelBuffer);
    size_t height = CVPixelBufferGetHeight(pixelBuffer);
    size_t wh = width * height;
//    size_t bpr = CVPixelBufferGetBytesPerRow(pixelBuffer);
//    size_t size = CVPixelBufferGetDataSize(pixelBuffer);
//    size_t count = CVPixelBufferGetPlaneCount(pixelBuffer);
    //plane0
    size_t width0 = CVPixelBufferGetWidthOfPlane(pixelBuffer, 0);
    size_t height0 = CVPixelBufferGetHeightOfPlane(pixelBuffer, 0);
    size_t bpr0 = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0);
    //plane1
//    size_t width1 = CVPixelBufferGetWidthOfPlane(pixelBuffer, 1);
    size_t height1 = CVPixelBufferGetHeightOfPlane(pixelBuffer, 1);
    size_t bpr1 = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1);
        
    unsigned char *bufY = malloc(wh);
    unsigned char *bufUV = malloc(wh/2);
    size_t offset,p;
    

    int r,g,b,y,u,v;
    int a=255;
    for (int row = 0; row < height; ++row) {
      for (int col = 0; col < width; ++col) {
        //
        offset = ((width * row) + col);
        p = offset*4;
        //
        r = data[p + 0];
        g = data[p + 1];
        b = data[p + 2];
        a = data[p + 3];
        //yuv
        y = 0.299*r + 0.587*g + 0.114*b;
        u = -0.1687*r - 0.3313*g + 0.5*b + 128;
        v = 0.5*r - 0.4187*g - 0.0813*b + 128;
        
        //
        bufY[offset] = y;
        bufUV[(row/2)*width + (col/2)*2] = u;
        bufUV[(row/2)*width + (col/2)*2 + 1] = v;
      }
    }
    uint8_t *yPlane = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);
    memset(yPlane, 0x80, height0 * bpr0);
    for (int row=0; row<height0; ++row) {
      memcpy(yPlane + row*bpr0, bufY + row*width0, width0);
    }
    uint8_t *uvPlane = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1);
    memset(uvPlane, 0x80, height1 * bpr1);
    for (int row=0; row<height1; ++row) {
      memcpy(uvPlane + row*bpr1, bufUV + row*width, width);
    }
        
    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
    free(bufY);
    free(bufUV);
    return pixelBuffer;
}

CVPixelBufferRef转image

- (UIImage *)bufferConvertToImage:(CVPixelBufferRef)pixelBuffer {
    CIImage *cImage = [CIImage imageWithCVPixelBuffer:pixelBuffer];
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef videoImage = [context
        createCGImage:cImage
             fromRect:CGRectMake(0, 0, CVPixelBufferGetWidth(pixelBuffer), CVPixelBufferGetHeight(pixelBuffer))];
    UIImage *uiImage = [UIImage imageWithCGImage:videoImage];
    CGImageRelease(videoImage);
    return uiImage;
}
posted @ 2022-11-22 20:23  CoderWGB  阅读(268)  评论(0)    收藏  举报