【问题标题】:Creating ad displaying a UIImage from raw BGRA data从原始 BGRA 数据创建显示 UIImage 的广告
【发布时间】:2015-12-16 15:40:36
【问题描述】:

我正在使用此代码从相机收集图像数据:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
    // Called when a frame arrives
    // Should be in BGRA format
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    CVPixelBufferLockBaseAddress(imageBuffer, 0);

    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
    size_t width = CVPixelBufferGetWidth(imageBuffer);
    size_t height = CVPixelBufferGetHeight(imageBuffer);
    unsigned char *raw = (unsigned char *)CVPixelBufferGetBaseAddress(imageBuffer);

    // Copy memory into allocated buffer
    unsigned char *buffer = malloc(sizeof(unsigned char) * bytesPerRow * height);
    memcpy(buffer, raw, bytesPerRow * height);
    [self processVideoData:buffer width:width height:height bytesPerRow:bytesPerRow];

    CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
}

processVideoData: 方法如下所示:

- (void)processVideoData:(unsigned char *)data width:(size_t)width height:(size_t)height bytesPerRow:(size_t)bytesPerRow
{
    dispatch_sync(dispatch_get_main_queue(), ^{

        CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, data, bytesPerRow * height, NULL);
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        CGImageRef image = CGImageCreate(width, height, 8, 32, bytesPerRow, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaLast, dataProvider, NULL, NO, kCGRenderingIntentDefault);

        // Set layer contents???
        UIImage *objcImage = [UIImage imageWithCGImage:image];
        self.imageView.image = objcImage;

        free(data);
        CGDataProviderRelease(dataProvider);
        CGColorSpaceRelease(colorSpace);
        CGImageRelease(image);
    });
}

没有投诉,没有泄漏,但图像视图中没有任何显示,它只是保持空白(是的,我已经检查了插座连接)。以前我将bitmapInfo 设置为kCGBitmapByteOrderDefault,这在设置图像视图的图像属性时会导致崩溃,但是图像视图会变暗,这在崩溃之前很有希望。

我总结说崩溃是由于图像在 BGRA 而不是 BGR 所以我将bitmapInfo 设置为kCGBitmapByteOrderDefault | kCGImageAlphaLast 并且解决了崩溃但没有图像。

我意识到图像看起来会很奇怪,因为CGImageRef 期望的是 RGB 图像,而我将其传递给 BGR,但由于通道交换,这只会导致图像看起来很奇怪。我还注销了我得到的数据,它似乎是这样的:b:65 g:51 r:42 a:255 并且 alpha 通道始终为 255,正如预期的那样。

很抱歉,如果这很明显,但我无法弄清楚出了什么问题。

【问题讨论】:

    标签: objective-c image avfoundation cgimage


    【解决方案1】:

    你可以使用这个标志组合来实现BGRA格式:

    kCGBitmapByteOrder32Little | kCGImageAlphaSkipFirst
    

    您应该更喜欢使用此解决方案,与 OpenCV 转换相比,它会更高效。

    这是将sourcePixelFormat 转换为bitmapInfo 的更常见方法:

    sourcePixelFormat = CVPixelBufferGetPixelFormatType(pixelBuffer);
    bitmapInfo = @{
        @(kCVPixelFormatType_32ARGB) : @(kCGBitmapByteOrder32Big | kCGImageAlphaNoneSkipFirst),
        @(kCVPixelFormatType_32BGRA) : @(kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst),
    }[@(sourcePixelFormat)].unsignedIntegerValue;
    

    【讨论】:

      【解决方案2】:

      事实证明数据格式错误,我没有正确地将其输入CGImageCreate 函数。

      数据以 BGRA 格式输出,因此我将这些数据输入到 IplImage 结构中(我使用的是 OpenCV v 2.4.9),如下所示:

      // Pack IplImage with data
      IplImage *img = cvCreateImage(cvSize((int)width, (int)height), 8, 4);
      img->imageData = (char *)data;
      

      然后我将其转换为 RGB,如下所示:

      IplImage *converted = cvCreateImage(cvSize((int)width, (int)height), 8, 3);
      cvCvtColor(img, converted, CV_BGRA2RGB);
      

      然后我将转换后的IplImage 中的数据输入到CGImageCreate 函数中,它运行良好。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-07-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-02
        相关资源
        最近更新 更多