概要
我有一个图像缓冲区,需要将其转换为另一种格式。原始图像缓冲区是四个通道,每个通道8位,包括Alpha、Red、Green和Blue。目标缓冲区是三个通道,每个通道8位,包括Blue、Green和Red。
所以暴力方法是:
// Assume a 32 x 32 pixel image
#define IMAGESIZE (32*32)
typedef struct{ UInt8 Alpha; UInt8 Red; UInt8 Green; UInt8 Blue; } ARGB;
typedef struct{ UInt8 Blue; UInt8 Green; UInt8 Red; } BGR;
ARGB orig[IMAGESIZE];
BGR dest[IMAGESIZE];
for(x = 0; x < IMAGESIZE; x++)
{
dest[x].Red = orig[x].Red;
dest[x].Green = orig[x].Green;
dest[x].Blue = orig[x].Blue;
}
然而,我需要比循环和三个字节复制提供的速度更快。我希望有一些技巧可以用来减少内存读写的次数,因为我在32位机器上运行。附加信息
每个图像至少是4个像素的倍数。所以我们可以处理16个ARGB字节并将它们移动到每个循环的12个RGB字节中。也许这个事实可以用来加速处理,尤其是它刚好落在32位边界上。
我可以使用OpenCL——虽然这需要将整个缓冲区移动到GPU内存中,然后再将结果移回来,但OpenCL可以同时处理图像的许多部分,而且大块内存移动实际上非常高效,这可能是值得探索的。
虽然我上面给出了小缓冲区的例子,但我实际上正在移动高清视频(1920x1080)和有时更大,大多数情况下是较小的缓冲区,因此尽管32x32的情况可能微不足道,但逐字节复制8.3MB的图像数据确实非常糟糕。
在Intel处理器(Core 2及以上)上运行,因此我知道存在流式传输和数据处理命令,但我不知道它们在哪里-也许指向寻找专门的数据处理指令的指针将是有益的。
这将进入一个OS X应用程序,我正在使用XCode 4。如果汇编语言很简单并且是显而易见的方法,我很愿意走上这条路,但是在这个设置上没有这样做让我担心会浪费太多时间。
伪代码也可以-我不需要完整的解决方案,只需要算法和任何可能不明显的花招的解释。
for(x = 0; x < IMAGESIZE; x++) { dest[x].Red = orig[x].Red; } for(x = 0; x < IMAGESIZE; x++) { dest[x].Green = orig[x].Green; } for(x = 0; x < IMAGESIZE; x++) { dest[x].Blue = orig[x].Blue; }
的可能性。在这种情况下,简单的循环是否超过了位操作? - Mark Hurd