सी

2016-03-28 6 views
6

में बिट स्ट्राइपिंग में मेरे पास 32 बिट प्रोसेसर पर चल रहे आर, जी, बी बिट डेटा वाले 3 बफर हैं।सी

मैं निम्नलिखित तरीके से तीन बाइट्स गठबंधन करने के लिए की जरूरत है:

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

int32_t Out = 0b r1g1b1r2g2b2r3g3 b3r4g4b4r5g5b5r6 g6b6r7g7b7r8g8b8 xxxxxxxx 

जहां 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); 
    } 
} 
+1

आप (या नहीं) बेहतर प्रतिक्रिया मिल सकता है @ codereview.stackexchange.com –

+0

पर्यावरण पर वहाँ विशेष विचार कर रहे हैं विवरण? यदि आप प्रोसेसर सुविधाओं का फायदा उठा सकते हैं तो एक बहुत तेज़ समाधान हो सकता है। – nneonneo

+0

मुझे उलझन में है कि इस सवाल को तब तक खुला रहने की अनुमति क्यों दी जाती है जब हर दिन प्रश्नों को वोट दिया जाता है और कोड समीक्षा को संदर्भित किया जाता है, भले ही सवाल इस गुणवत्ता का है। क्या कोई समझा सकता है? – Insane

उत्तर

2

आप आकार 64 है कि 6 बिट के लिए bitstripped मान हैं की एक तालिका का उपयोग और उसके बाद आर, जी और ख से 2 बिट्स प्रत्येक लाने और तेजी से देखने के लिए तालिका का उपयोग कर सकते है। आकार 512 या 40 9 6 के लुकअप का उपयोग करना अधिक कुशल हो सकता है।

/* 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]; 
6

आप 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]; 

यह केवल 3 लुकअप, 2 परिवर्तन और 2 or संचालन, का उपयोग करता है जो एक स्वीकार्य गति प्रदान करना चाहिए।

आप अधिक स्थान है, तो आप भी बदलाव को खत्म करने के तीन देखने तालिकाओं का उपयोग कर सकते हैं (हालांकि यह भी बदतर कैश प्रदर्शन में हो सकता है, इसलिए हमेशा की जांच करने के प्रोफ़ाइल!)

+0

अच्छा विचार है, लेकिन यह नहीं होना चाहिए: 'uint32_t परिणाम = (लुकअप [आरबीटीई] << 2) | (लुकअप [gByte] << 1) | लुकअप [बीबीटीई]; ' –

+0

@ माइकलबुर: गुड कॉल; मैं अपने एंडियन फिसल गया। फिक्स्ड। – nneonneo

3

आप से एक गुणा उपयोग कर सकते हैं एक " जादुई "बिट्स को दोहराने के लिए निरंतर। फिर आवश्यक बिट्स निकालने के लिए बिट-शिफ्ट का उपयोग करें, और उन्हें गठबंधन करने के लिए बिट-वार मास्किंग का उपयोग करें। "जादुई" निरंतर एक 17-बिट बाइनरी 10000000100000001 है। जब इसके द्वारा गुणा किया जाता है, तो 8-बिट संख्या स्वयं को 3 बार समेकित की जाती है।

 
r1r2r3r4r5r6r7r8 * M  = r1r2r3r4r5r6r7r8r1r2r3r4r5r6r7r8r1r2r3r4r5r6r7r8 
r1r2r3r4r5r6r7r8 * M shr 2 = 0 0 r1r2r3r4r5r6r7r8r1r2r3r4r5r6r7r8r1r2r3r4r5r6 
r1r2r3r4r5r6r7r8 * M shr 4 = 0 0 0 0 r1r2r3r4r5r6r7r8r1r2r3r4r5r6r7r8r1r2r3r4 
r1r2r3r4r5r6r7r8 * M shr 6 = 0 0 0 0 0 0 r1r2r3r4r5r6r7r8r1r2r3r4r5r6r7r8r1r2 

बोल्ड में चिह्नित बिट्स सही जगह पर हैं।

आप इस मास्किंग कोड का उपयोग करते हैं

R * M  & 0b100000000000100000000000 | 
(R * M >> 2) & 0b000100000000000100000000 | 
(R * M >> 4) & 0b000000100000000000100000 | 
(R * M >> 6) & 0b000000000100000000000100 

आप सही तरीके से संयुक्त "लाल" बिट्स मिल जाएगा:

r1 0 0 r2 0 0 r3 0 0 r4 0 0 r5 0 0 r6 0 0 r7 0 0 r8 0 0 

फिर में "नीले" और "हरी" बिट्स गठबंधन एक समान तरीका


संचालन की संख्या का मोटे तौर पर अनुमान:

  • गुणा: 3
  • बिट बदलाव: 9
  • बिट के लिहाज से और: 12
  • बिट के लिहाज से या: 11
0

Interleaving with bitwise operators

inline int interleave(int n) 
{ 
    n = ((n << 18) | (n << 9) | n) & 0007007007; // 000000111 000000111 000000111 
    n = ((n << 6) | (n << 3) | n) & 0444444444; // 100100100 100100100 100100100 
    return n; 
} 

r = interleave(r); 
g = interleave(g); 
b = interleave(b); 

rgb = r | (g >> 1) | (b >> 2); 

TempLinebuff[((i*3)+0) +2] = (rgb >> 16) & 0xFF; 
TempLinebuff[((i*3)+1) +2] = (rgb >> 8) & 0xFF; 
TempLinebuff[((i*3)+2) +2] = rgb  & 0xFF; 

एक और तरीका है

इस packing technique

साथ magic number multiplication का उपयोग कर मान देता है rByte 8 बिट गिने 12345678 है interleaving है। अंतिम परिणाम में डालने के बाद उन आर बिट्स इस तरह दिखेगा, हाइफ़न डॉन-केयर बिट्स नहीं हैं।

1--2--3--4--5--6--7--8------------------------------------------ 

हम

unsigned long long r = (rByte * 0x0101010101010101ULL) * 0x8040201008040201ULL; 

द्वारा समान रूप से 8 बाइट्स में बिट्स वितरित करेंगे अब आर

1--------2--------3--------4--------5--------6--------7--------8 

हाइफ़न के साथ के रूप में rByte में बिट्स शामिल सभी शून्य हैं


स्पष्टीकरण

........................................................12345678 (rByte) 
x ..............1......1......1......1......1......1......1......1 (Magic number, dots are 0s) 
__________________________________________________________________ 
    ........................................................12345678 
    ................................................12345678.......↓ 
    ........................................12345678......↓........↓ 
    ................................12345678.....↓........↓........↓ 
+ ........................12345678....↓........↓........↓........↓ 
    ................12345678...↓........↓........↓........↓........↓ 
    ........12345678..↓........↓........↓........↓........↓........↓ 
    12345678.↓........↓........↓........↓........↓........↓........↓ 
__________________________________________________________________  
= 1........2........3........4........5........6........7........8 

उनके अंतिम पदों के लिए r में बिट्स ले जाने के लिए हम r 2 में भागों विभाजित है और उनके सही स्थिति में प्रत्येक भाग में बिट्स मिल जाएगा। पहला भाग बिट्स 1, 4, 5 और 8 को जादू संख्या 0x40001040001 के साथ ले जाएगा और दूसरा भाग शेष संख्याओं को जादू संख्या 0x01040001040 के साथ ले जाएगा। उन जादू संख्याओं की गणना उपरोक्त के समान ही की जा सकती है। इसके लिए 32-बिट गुणा पर्याप्त है लेकिन मैंने इसे चेक नहीं किया है।

#define RBIT(n)  (1ULL << (8-n)*9) 
#define RMASK_1458 (RBIT(1) | RBIT(4) | RBIT(5) | RBIT(8)) 
#define RMASK_2367 (RBIT(2) | RBIT(3) | RBIT(6) | RBIT(7)) 

#define BIT(n)  ((1ULL << 63) >> ((n-1)*3)) 
#define MASK_BIT1458 (BIT(1) | BIT(4) | BIT(5) | BIT(8)) 
#define MASK_BIT2367 (BIT(2) | BIT(3) | BIT(6) | BIT(7)) 

#define MAGIC_1458 0x40001040001ULL 
#define MAGIC_2367 0x01040001040ULL 

uint64_t resultR = (((r & RMASK_1458) * MAGIC_1458) & MASK_BIT1458) 
       | (((r & RMASK_2367) * MAGIC_2367) & MASK_BIT2367); 

जी और बी के लिए बिट्स की गणना इसी प्रकार की जा सकती है। वेक्टर निर्देश की उपलब्धता, एम्बेडेड प्रोसेसर सीमाओं, या वास्तुकला - उसके बाद परिणामों के लिए बस एक साथ जोड़ा जा सकता है

result = (resultR >> 32) | (resultG >> 33) | (resultB >> 34);