zhz*_*zhy 7 rgb assembly neon ios accelerate-framework
我使用vImageConvert_RGB888toPlanar8和vImageConvert_Planar8toRGB888来自Accelerate.framework将RGB24转换为BGR24,但是当需要转换的数据非常大时,例如3M或4M,需要花费的时间大约是10ms.所以有人知道一些足够快的想法吗?.我的代码如下:
- (void)transformRGBToBGR:(const UInt8 *)pict{
rgb.data = (void *)pict;
vImage_Error error = vImageConvert_RGB888toPlanar8(&rgb,&red,&green,&blue,kvImageNoFlags);
if (error != kvImageNoError) {
NSLog(@"vImageConvert_RGB888toARGB8888 error");
}
error = vImageConvert_Planar8toRGB888(&blue,&green,&red,&bgr,kvImageNoFlags);
if (error != kvImageNoError) {
NSLog(@"vImagePermuteChannels_ARGB8888 error");
}
free((void *)pict);
}
Run Code Online (Sandbox Code Playgroud)
使用RGB888ToPlanar8调用,您可以分散数据,然后再次收集数据.这非常非常糟糕.如果33%的内存开销是可以承受的,请尝试使用RGBA格式并就地置换B/R字节.
如果你想节省33%的百分比,那么我可能会建议如下.迭代所有像素,但只读取4个字节的倍数(因为lcm(3,4)是12,即3个双字).
uint8_t* src_image;
uint8_t* dst_image;
uint32_t* src = (uint32_t*)src_image;
uint32_t* dst = (uint32_t*)dst_image;
uint32_t v1, v2, v3;
uint32_t nv1, nv2, nv3;
for(int i = 0 ; i < num_pixels / 12 ; i++)
{
// read 12 bytes
v1 = *src++;
v2 = *src++;
v3 = *src++;
// shuffle bits in the pixels
// [R1 G1 B1 R2 | G2 B2 R3 G3 | B3 R4 G4 B4]
nv1 = // [B1 G1 R1 B2]
((v1 >> 8) & 0xFF) | (v1 & 0x00FF0000) | ((v1 >> 16) & 0xFF) | ((v2 >> 24) & 0xFF);
nv2 = // [G2 R2 B3 G3]
...
nv3 = // [R3 B4 G4 R4]
...
// write 12 bytes
*dst++ = nv1;
*dst++ = nv2;
*dst++ = nv3;
}
Run Code Online (Sandbox Code Playgroud)
使用NEON内在函数可以做得更好.
BGR-to-RGB可以就地完成,如下所示:
void neon_asm_convert_BGR_TO_RGB(uint8_t* img, int numPixels24)
{
// numPixels is divided by 24
__asm__ volatile(
"0: \n"
"# load 3 64-bit regs with interleave: \n"
"vld3.8 {d0,d1,d2}, [%0] \n"
"# swap d0 and d2 - R and B\n"
"vswp d0, d2 \n"
"# store 3 64-bit regs: \n"
"vst3.8 {d0,d1,d2}, [%0]! \n"
"subs %1, %1, #1 \n"
"bne 0b \n"
:
: "r"(img), "r"(numPixels24)
: "r4", "r5"
);
}
Run Code Online (Sandbox Code Playgroud)