¿En iOS cómo convertir rápidamente RGB24 a BGR24?

Utilizo vImageConvert_RGB888toPlanar8 y vImageConvert_Planar8toRGB888 desde Accelerate.framework para convertir RGB24 a BGR24, pero cuando los datos necesitan transformarse son muy grandes, como 3M o 4M, el time que se necesita gastar en esto es de unos 10ms. Entonces, ¿alguien conoce alguna idea lo suficientemente rápida? Mi código así:

 - (void)transformRGBToBGR:(const UInt8 *)pict{ rgb.data = (void *)pict; vImage_Error error = vImageConvert_RGB888toPlanar8(&rgb,&networking,&green,&blue,kvImageNoFlags); if (error != kvImageNoError) { NSLog(@"vImageConvert_RGB888toARGB8888 error"); } error = vImageConvert_Planar8toRGB888(&blue,&green,&networking,&bgr,kvImageNoFlags); if (error != kvImageNoError) { NSLog(@"vImagePermuteChannels_ARGB8888 error"); } free((void *)pict); } 

Con una llamada RGB888ToPlanar8, se dispersan los datos y luego se vuelven a reunir. Esto es muy, muy, muy malo. Si la sobrecarga de memory del 33% es asequible, intente usar el formatting RGBA y permute los bytes B / R en el lugar.

Si desea ahorrar un 33% de porcentajes, entonces podría sugerir lo siguiente. Itere todos los píxeles, pero lea solo un múltiplo de 4 bytes (ya que lcm (3,4) es 12, es decir, 3 palabras).

 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; } 

Aún mejor se puede hacer con los intrínsecos NEON.

Vea este enlace desde el website de ARM para ver cómo se realiza el intercambio de 24 bits.

El BGR-to-RGB se puede hacer en el lugar como este:

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

Simplemente cambia los canales: BGRA a 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); } }