On iOS, how to quickly convert RGB24 to BGR24?

I use vImageConvert_RGB888toPlanar8 and vImageConvert_Planar8toRGB888 from Accelerate.framework to convert RGB24 to BGR24, but when the data needs to be converted very large, like 3M or 4M, the time it takes is about 10 ms. So, does anyone know a pretty quick idea ?. My code is:

 - (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); } 
+7
source share
2 answers

By calling RGB888ToPlanar8, you scatter data and then collect it again. This is very, very, very bad. If the memory overhead is 33%, try using the RGBA format and rearrange the B / R bytes.

If you want to keep 33% percent, I can suggest the following. Iterate all the pixels, but only read a multiple of 4 bytes (since lcm (3,4) is 12, i.e. 3 words).

 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.

See the link from the ARM website for how 24-bit swap is performed.

BGR-to-RGB can be done as follows:

 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" ); } 
+6
source

Just swap channels - BGRA to RGBA

 - (void)convertBGRAFrame:(const CLPBasicVideoFrame &)bgraFrame toRGBA:(CLPBasicVideoFrame &)rgbaFrame { vImage_Buffer bgraImageBuffer = { .width = bgraFrame.width, .height = bgraFrame.height, .rowBytes = bgraFrame.bytesPerRow, .data = bgraFrame.rawPixelData }; vImage_Buffer rgbaImageBuffer = { .width = rgbaFrame.width, .height = rgbaFrame.height, .rowBytes = rgbaFrame.bytesPerRow, .data = rgbaFrame.rawPixelData }; const uint8_t byteSwapMap[4] = { 2, 1, 0, 3 }; vImage_Error error; error = vImagePermuteChannels_ARGB8888(&bgraImageBuffer, &rgbaImageBuffer, byteSwapMap, kvImageNoFlags); if (error != kvImageNoError) { NSLog(@"%s, vImage error %zd", __PRETTY_FUNCTION__, error); } } 
0
source

All Articles