2014-07-13 28 views
1

我需要一個例程,它可以快速複製一個緩衝區的矩形區域之間的原始32位像素數據。仿真Apple的drawInRect:用於離屏像素緩衝區

所以...下面是我試圖效仿Apple的drawInRect:fromRect:operation:fraction方法blitting數據輸出到NSView。這兩個例程通常存在於NSImageNSBitmapImageRep類中。我忽略了operation:模式或fraction: alpha混合。

可以假設x/y/w/h值已被測試&被截斷以確保源/目標矩形位於提供的兩個緩衝區內,並且矩形區域是非零的並且尺寸相同(即不縮放)。

我的測試表明覆制全HD(1920×1080)在我的特定硬件區域圖像是

  • 殼體1:32位傳送:6.74ms
  • 殼體2:64位傳送:5.30ms
  • 殼體3:memcpy的傳輸:3.20ms

不幸的是,一些這些緩衝器由外部API提供,我沒有保證,緩衝器是64位或128位對齊。話雖如此,我有一種預感他們在我的情況 - memcpy正在測試,看看是否緩衝區地址說對齊,並正在做一些SSE3內部函數來做生意(_platform_memmove$VARIANT$Ivybridge)。

有沒有關於改善這一切的建議?

或者也許在Cocoa API中有一些神奇的例程已經這樣做了嗎?

typedef struct copyRect 
{ 
    u_int32_t *data; 
    u_int32_t x; 
    u_int32_t y; 
    u_int32_t w; 
    u_int32_t h; 
    u_int32_t canvasWidth; // ie. rowBytes/4 
} copyRect; 

-(void)copyRectFromSrc:(copyRect *)srcImage toTarget:(copyRect *)dstImage 
{ 
    u_int32_t h = srcImage->h; 
    u_int32_t w = srcImage->w; 

    u_int32_t srcDelta = srcImage->y*srcImage->canvasWidth + srcImage->x; 
    u_int32_t dstDelta = dstImage->y*dstImage->canvasWidth + dstImage->x; 
    u_int32_t *srcPtr = srcImage->data+srcDelta; 
    u_int32_t *dstPtr = dstImage->data+dstDelta; 
    u_int32_t w2 = w/2; 

    // scan top-to-bottom in buffer 
    for (u_int32_t y=0; y<h; y++) { 

// case 1: this would work in all cases (single pixel = 32 bits) 
//  u_int32_t *srcXptr = srcPtr; 
//  u_int32_t *dstXptr = dstPtr; 
//  for (u_int32_t x=0; x<w; x++) 
//   *dstXptr++ = *srcXptr++; 

// case 2: this would work if src/dst image were even-width 
//  u_int64_t *srcXptr = (u_int64_t *)srcPtr; 
//  u_int64_t *dstXptr = (u_int64_t *)dstPtr; 
//  for (u_int32_t x=0; x<w2; x++) 
//   *dstXptr++ = *srcXptr++; 

// case 3: this seems to have the best performance (all cases) 
     memcpy(dstPtr,srcPtr,w*4); 

     srcPtr += srcImage->canvasWidth; 
     dstPtr += dstImage->canvasWidth; 
    } 
} 

回答

2
#include <Accelerate/Accelerate.h> // see vImage/Conversion.h 

vImage_Error vImageCopyBuffer(const vImage_Buffer *src, const vImage_Buffer *dest, size_t pixelSize, vImage_Flags flags) VIMAGE_NON_NULL(1,2) __OSX_AVAILABLE_STARTING(__MAC_10_10, __IPHONE_8_0); 

對於阿爾法合成,見在VIMAGE/Alpha.h各種α混合例程。

+0

vImageCopyBufer特定於OSX 10.10。 – zzyzy