如何对像素数据进行位条带化处理?

Ter*_*rry 7 c bit-manipulation interleave

我有3个缓冲区,包含在32位处理器上运行的R,G,B位数据.

我需要以下列方式组合三个字节:

R[0] = 0b r1r2r3r4r5r6r7r8
G[0] = 0b g1g2g3g4g5g6g7g8
B[0] = 0b b1b2b3b4b5b6b7b8

int32_t Out = 0b r1g1b1r2g2b2r3g3 b3r4g4b4r5g5b5r6 g6b6r7g7b7r8g8b8 xxxxxxxx
Run Code Online (Sandbox Code Playgroud)

其中xxxxxxxx继续到缓冲区中的每个下一个字节.

我正在寻找一种最佳的组合方式.我的方法绝对没有效率.

这是我的方法

static void rgbcombineline(uint8_t line)
{
    uint32_t i, bit;
    uint8_t bitMask, rByte, gByte, bByte;
    uint32_t ByteExp, rgbByte;
    uint8_t *strPtr = (uint8_t*)&ByteExp;

    for (i = 0; i < (LCDpixelsCol / 8); i++)
    {
        rByte = rDispbuff[line][i];
        gByte = gDispbuff[line][i];
        bByte = bDispbuff[line][i];

        bitMask = 0b00000001;
        ByteExp = 0;
        for(bit = 0; bit < 8; bit++)
        {
            rgbByte = 0;
            rgbByte |= ((rByte & bitMask) >> bit) << 2;
            rgbByte |= ((gByte & bitMask) >> bit) << 1;
            rgbByte |= ((bByte & bitMask) >> bit);
            ByteExp |= (rgbByte << 3*bit);
            bitMask <<= 1;
        }
        TempLinebuff[((i*3)+0) +2] = *(strPtr + 2);
        TempLinebuff[((i*3)+1) +2] = *(strPtr + 1);
        TempLinebuff[((i*3)+2) +2] = *(strPtr + 0);
    }
}
Run Code Online (Sandbox Code Playgroud)

nne*_*neo 7

如果您可以节省1024个字节,则可以使用单个256个元素的查找表来实现所需的结果:

uint32_t lookup[256] = {
    0, 1, 8, 9, 64, 65, ...
    /* map abcdefgh to a00b00c00d00e00f00g00h */
};

uint32_t result = (lookup[rByte] << 2) | (lookup[gByte] << 1) | lookup[bByte];
Run Code Online (Sandbox Code Playgroud)

这仅使用3次查找,2次移位和2次or操作,这应该提供可接受的加速.

如果你有更多的空间,你可以使用三个查找表来消除转换(虽然这可能导致更糟糕的缓存性能,所以总是要检查配置文件!)


Moh*_*ain 3

您可以使用大小为 64 的表,其中包含 6 位的位剥离值,然后从 r、g 和 b 中分别获取 2 位,并使用表进行更快的查找。使用大小为 512 或 4096 的查找可以更有效。

/* Converts bits abcdefghijkl to adgjbehkcfil */
static const uint32_t bitStripLookUp[4096] = {
  /* Hard coded values, can be generate with some script */
  ...
};

...

rByte = rDispbuff[line][i];  // rByte, gByte, bByte should be unit32
gByte = gDispbuff[line][i];
bByte = bDispbuff[line][i];

uMSB = ((rByte << 4) & 0x0F00) | (gByte & 0x00F0) | ((bByte >> 4) & 0x000F);  // r7r6r5r4g7g6g5g4b7b6b5b4
uLSB = ((rByte << 8) & 0x0F00) | ((gByte << 4) & 0x00F0) | (bByte & 0x000F);  // r3r2r1r0g3g2g1g0b3b2b1b0
stuffed_value = (bitStripLookUp[uMSB] << 12) | bitStripLookUp[uLSB];
Run Code Online (Sandbox Code Playgroud)