iOS 转换RGB24 为 RGBA
昨晚完成了一篇转换RGB24为BGR24的文章,今天续写如何将RGB24转换为RGBA。一点显著的不同是RGB占有3个字节,而RGBA则占有4个字节,相比RGB TO BGR的简单性,RGB TO RGBA一定需要为RGBA另外分配存储空间。类似于昨天的第一中方法这里就不再提供了,一是简单,二呢效率太低。
1.使用ACCERLERATE.FRAMEWORK提供的库函数 vImageConvert_RGB888toARGB8888 和 vImagePermuteChannels_ARGB8888
- (void)transformRGBToRGBA:(const UInt8 *)pict width:(int)width height:(int)height { const uint8_t permuteMap[4] = {1,2,3,0}; rgb.data = (void *)pict; vImage_Error error = vImageConvert_RGB888toARGB8888(&rgb,NULL,0,&argb,NO,kvImageNoFlags); if (error != kvImageNoError) { NSLog(@"vImageConvert_RGB888toARGB8888 error"); } error = vImagePermuteChannels_ARGB8888(&argb,&rgba,permuteMap,kvImageNoFlags); if (error != kvImageNoError) { NSLog(@"vImagePermuteChannels_ARGB8888 error"); } free((void *)pict); }
这里的rgb,rgba,argb为 vImage_Buffer类型,表示具体的像素数据,是为数据源。可以看出首先使用 vImageConvert_RGB888toARGB8888 将 rgb 转换为 argb,然后使用 vImagePermuteChannels_ARGB8888 将argb 转换为 rgba。之所以经过两次转换,是因为iOS目前不支持argb格式。整个accerlerate.framework都是经过neon优化的,效率相当高。
2.第一种方法固然很快,但是要经过两次转换,少费周折。因此,这里我们祭出了终极杀器。
- (void) neon_asm_convert_RGB_TO_RGBA:(const UInt8 *) img toRGBABuffer:(const UInt8 *)bytes numPixel:(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" "# store 4 64-bit regs: \n" "vst4.8 {d0,d1,d2,d3}, [%2]! \n" "subs %1, %1, #1 \n" "bne 0b \n" : : "r"(img), "r"(numPixels24), "+r"(bytes) : "r6", "r7","r8" ); free((void *)img); }
直接使用neon汇编节省了内存,避免了中间状态的转换,效率提升明显相比第一中方法。