在iOS如何快速转换为RGB24 BGR24? [英] On iOS how to quickly convert RGB24 to BGR24?
问题描述
我用 vImageConvert_RGB888toPlanar8
和 vImageConvert_Planar8toRGB888
从Accelerate.framework到RGB24转换为BGR24,但是当数据需要变换是非常大的,比如3M或4M,时间需要花费上,这是约10ms。因此,一些人知道一些足够快的想法。我的code是这样的:
- (无效)transformRGBToBGR:(常量UINT8 *){PICT
rgb.data =(无效*)PICT;vImage_Error错误= vImageConvert_RGB888toPlanar8(安培; RGB,&安培,红色,和放大器;绿,和蓝光,kvImageNoFlags);
如果(错误!= kvImageNoError){
的NSLog(@vImageConvert_RGB888toARGB8888错误);
}错误= vImageConvert_Planar8toRGB888(和蓝光,和放大器;绿色&安培,红色,和放大器; BGR,kvImageNoFlags);
如果(错误!= kvImageNoError){
的NSLog(@vImagePermuteChannels_ARGB8888错误);
}免费的((无效*)PICT);
}
随着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;我++)
{
//读取12个字节
V1 = * SRC ++;
V2 = * SRC ++;
V3 = * SRC ++;
中的像素//洗牌位
// [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和GT;> 24)及为0xFF);
NV2 = // [G2 R2 B3 G3]
...
NV3 = // [R3 B4 G4 R4]
...
//写12个字节
* DST ++ = NV1;
* DST ++ = NV2;
* DST ++ = NV3;
}
更妙的是可以与NEON内在函数来完成。
请参阅此链接从ARM的网站看到24位交换是如何完成的。
在BGR到RGB可以就地就像这样:
无效neon_asm_convert_BGR_TO_RGB(uint8_t有* IMG,INT numPixels24)
{
// numPixels被除以24
__asm__挥发性(
0:\\ n
#负载3交错64位暂存器:\\ n
vld3.8 {D0,D1,D2},[%0] \\ n上
#交换D0和D2 - R和B \\ N
VSWP D0,D2 \\ n
#3店64位暂存器:\\ n
vst3.8 {D0,D1,D2},[%0]!\\ N
潜艇%1%1,#1 \\ n
BNE 0B \\ n
:
:R(IMG),R(numPixels24)
R 4,R 5
);
}
I use vImageConvert_RGB888toPlanar8
and vImageConvert_Planar8toRGB888
from Accelerate.framework to convert RGB24 to BGR24, but when the data need to transform is very big, such as 3M or 4M, the time need to spend on this is about 10ms. So some one know some fast enough idea?.My code like this:
- (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);
}
With a RGB888ToPlanar8 call you scatter the data and then gather it once again. This is very-very-very bad. If the memory overhead of 33% is affordable, try using the RGBA format and permute the B/R bytes in-place.
If you want to save 33% percents, then I might suggest the following. Iterate all the pixels, but read only a multiple of 4 bytes (since lcm(3,4) is 12, that is 3 dwords).
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;
}
Even better can be done with NEON intrinsics.
See this link from ARM's website to see how the 24-bit swapping is done.
The BGR-to-RGB can be done in-place like this:
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"
);
}
这篇关于在iOS如何快速转换为RGB24 BGR24?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!