在C中将RGB转换为RGBA

我需要将表示RGB字节顺序的图像的字节数组的内容复制到另一个RGBA(每像素4个字节)缓冲区。 alpha通道稍后会被填充。 实现这一目标的最快方法是什么?

最快的方法是使用一个为您实现转换的库,而不是自己编写。 您定位的是哪个平台?

如果您出于某种原因坚持自己编写,请先写一个简单正确的版本。 用那个。 如果性能不足, 那么您可以考虑优化它。 通常,这种转换最好使用向量置换进行,但确切的最佳序列取决于目标体系结构。

你想要它有多棘手? 您可以将其设置为一次复制一个4字节的字,这在某些32位系统上可能会快一些:

void fast_unpack(char* rgba, const char* rgb, const int count) { if(count==0) return; for(int i=count; --i; rgba+=4, rgb+=3) { *(uint32_t*)(void*)rgba = *(const uint32_t*)(const void*)rgb; } for(int j=0; j<3; ++j) { rgba[j] = rgb[j]; } } 

最后的额外情况是处理rgb数组丢失一个字节的事实。 您还可以使用对齐的移动和SSE指令使其快一点,一次以4个像素的倍数工作。 如果你真的有野心勃勃,你可以尝试更加可怕的模糊处理的东西,例如将缓存行预取到FP寄存器中,然后将其一次性地翻转到另一个图像。 当然,你从这些优化中获得的里程数将高度依赖于你所针对的特定系统配置,而且我真的很怀疑这样做有什么好处而不是简单的事情。

我的简单实validation实,这确实有点快,至少在我的x86机器上。 这是一个基准:

 #include  #include  #include  #include  void fast_unpack(char* rgba, const char* rgb, const int count) { if(count==0) return; for(int i=count; --i; rgba+=4, rgb+=3) { *(uint32_t*)(void*)rgba = *(const uint32_t*)(const void*)rgb; } for(int j=0; j<3; ++j) { rgba[j] = rgb[j]; } } void simple_unpack(char* rgba, const char* rgb, const int count) { for(int i=0; i 

这是结果(用g ++ -O3编译):

图像大小= 262144字节

迭代次数= 10000

测试简单解压....完成

经过的时间:3.830000

平均时间:0.000383

测试棘手解压....完成

经过时间:2.390000

平均时间:0.000239

所以,在美好的一天,也许快40%左右。

 struct rgb { char r; char g; char b; }; struct rgba { char r; char g; char b; char a; } void convert(struct rgba * dst, const struct rgb * src, size_t num) { size_t i; for (i=0; i 

这将是更清晰的解决方案,但是当你提到一个字节数组时,你应该使用这个:

 // num is still the size in pixels. So dst should have space for 4*num bytes, // while src is supposed to be of length 3*num. void convert(char * dst, const char * src, size_t num) { size_t i; for (i=0; i 

只需创建大小为源arrays4/3的数组。 读取整个数组并将其写入RGBA数组,但在每3字节后插入255表示alpha。

我想我会记住一个关于做类似事情的Nehe教程,但很快。

它在这里

有趣的部分在这里:

 void flipIt(void* buffer) // Flips The Red And Blue Bytes (256x256) { void* b = buffer; // Pointer To The Buffer __asm // Assembler Code To Follow { mov ecx, 256*256 // Set Up A Counter (Dimensions Of Memory Block) mov ebx, b // Points ebx To Our Data (b) label: // Label Used For Looping mov al,[ebx+0] // Loads Value At ebx Into al mov ah,[ebx+2] // Loads Value At ebx+2 Into ah mov [ebx+2],al // Stores Value In al At ebx+2 mov [ebx+0],ah // Stores Value In ah At ebx add ebx,3 // Moves Through The Data By 3 Bytes dec ecx // Decreases Our Loop Counter jnz label // If Not Zero Jump Back To Label } } 

它的作用是非常自我解释的,并且应该很容易将其转换为添加alpha字节。