0

这是我想出的将 24 位 BGR 图像传送到 NSView 的最佳方法。

通过确保 NSWindow 主机也具有相同的颜色空间,我确实减少了大量的 CPU 时间。

我认为这里有 4 或 5 个像素的副本:

  1. vImage转换中(必填)
  2. 打电话CGDataProviderCreateWithData
  3. 打电话CGImageCreate
  4. 创建NSBitmapImageRep位图
  5. 在最后的 blit 中drawInRect(必需)

任何人都想参与改进它?

任何帮助将非常感激。

{
   // one-time setup code
   CGColorSpaceRef useColorSpace = nil; 
   int w = 1920;
   int h = 1080;
   [theWindow setColorSpace: [NSColorSpace genericRGBColorSpace]];
   // setup vImage buffers (not listed here)
   // srcBuffer is my 24-bit BGR image (malloc-ed to be w*h*3)
   // dstBuffer is for the resulting 32-bit RGBA image (malloc-ed to be w*h*4)

   ...
   // this is called @ 30-60fps
   if (!useColorSpace)
      useColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
   vImage_Error err = vImageConvert_BGR888toRGBA8888(srcBuffer, NULL, 0xff, dstBuffer, NO, 0);

   CGDataProviderRef newProvider = CGDataProviderCreateWithData(NULL,dstBuffer->data,w*h*4,myReleaseProvider);
   CGImageRef myImageRGBA = CGImageCreate(w, h, 8, 32, w*4, useColorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaLast, newProvider, NULL, false, kCGRenderingIntentDefault);
   CGDataProviderRelease(newProvider);
   // store myImageRGBA in an array of frames (using NSObject wrappers) for later access (setNeedsDisplay:)
   ... 
}

- (void)drawRect:(NSRect)dirtyRect
{
   // this is called @ 30-60fps
   CGImageRef storedImage = ...;  // retrieve from array
   NSBitmapImageRep *repImg = [[NSBitmapImageRep alloc] initWithCGImage:storedImage];
   CGRect myFrame = CGRectMake(0,0,CGImageGetWidth(storedImage),CGImageGetHeight(storedImage));
   [repImg drawInRect:myFrame fromRect:myFrame operation:NSCompositeCopy fraction:1.0 respectFlipped:TRUE hints:nil];

   // free image from array (not listed here)
}

// this is called when the CGDataProvider is ready to release its data
void myReleaseProvider (void *info, const void *data, size_t size)
{
    if (data)  {
        free((void *)data);
        data=nil;
    }
}
4

1 回答 1

2

使用 CGColorSpaceCreateDeviceRGB 而不是 genericRGB 来避免 CG 内部的颜色空间转换。使用 kCGImageAlphaNoneSkipLast 而不是 kCGImageAlphaLast,因为我们知道 alpha 是不透明的,以允许复制而不是混合。

进行这些更改后,在其上运行 Instruments 时间配置文件以显示时间的去向会很有用。

于 2014-07-09T20:43:08.183 回答