2010-05-05 4 views
0

Je cherche un algorithme pour retourner une ligne bitmap 1 bit horizontalement. Rappelez-vous que ces lignes sont alignées DWORD! Je suis actuellement en train de désencoder un flux RLE à un tampon de 8 bits par pixel, puis de le réencoder en une ligne de 1 bit, mais je voudrais essayer de tout conserver dans l'espace de 1 bit dans un effort pour augmenter sa vitesse. Le profilage indique que cette partie du programme est relativement lente par rapport au reste.Inverser horizontalement une ligne bitmap d'un bit

ligne de l'exemple (avant Flip):

FF FF FF FF 77 AE F0 00

ligne de l'exemple (After Flip):

F7 5E EF FF FF FF F0 00
+0

Si pas être '00 01 3A F7 FF FF FF FF' (ou' 3A F7 FF FF FF FF F0 si vous connaissez 00 'la largeur est de 90 bits)? –

+2

90 bits? Il n'y a que 64 bits et la ligne n'a que 52 bits de largeur; les 12 bits restants sont simplement des bits de remplissage. Au moins est-ce que l'exemple suggère - inverser les 52 premiers bits de FF FF FF 77 AE F0 00 rendements F7 5E EF FF FF F0 00. –

Répondre

1

créer une table de conversion pour échanger les bits d'un octet:

byte[] convert = new byte[256]; 
for (int i = 0; i < 256; i++) { 
    int value = 0; 
    for (int bit = 1; bit <= 128; bit<<=1) { 
    value <<= 1; 
    if ((i & bit) != 0) value++; 
    } 
    convert[i] = (byte)value; 
} 

Maintenant, vous pouvez utiliser la table pour échanger un octet, alors il vous suffit de stocker l'octet au bon endroit dans le résultat:

byte[] data = { 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0xAE, 0xF0, 0x00 }; 
int width = 52; 

int shift = data.Length * 8 - width; 
int shiftBytes = data.Length - 1 - shift/8; 
int shiftBits = shift % 8; 

byte[] result = new byte[data.Length]; 
for (int i = 0; i < data.Length; i++) { 
    byte swap = convert[data[i]]; 
    if (shiftBits == 0) { 
    result[shiftBYtes - i] = swap; 
    } else { 
    if (shiftBytes - i >= 0) { 
     result[shiftBytes - i] |= (byte)(swap << shiftBits); 
    } 
    if (shiftBytes - i - 1 >= 0) { 
     result[shiftBytes - i - 1] |= (byte)(swap >> (8 - shiftBits)); 
    } 
    } 
} 

Console.WriteLine(BitConverter.ToString(result)); 

sortie:

F7-5E-EF-FF-FF-FF-F0-00 
+0

semble prometteur, je vais vérifier. Merci. –

1

Le code suivant lit et inverse les données dans des blocs de 32 bits comme des entiers. Le code pour inverser les bits est divisé en deux parties parce que sur une machine peu endian lecture quatre octets comme un entier de 32 bits inverse l'ordre des octets.

private static void Main() 
{  
    var lineLength = 52; 

    var input = new Byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0xAE, 0xF0, 0x00 }; 
    var output = new Byte[input.Length]; 

    UInt32 lastValue = 0x00000000; 

    var numberBlocks = lineLength/32 + ((lineLength % 32 == 0) ? 0 : 1); 
    var numberBitsInLastBlock = lineLength % 32; 

    for (Int32 block = 0; block < numberBlocks; block++) 
    { 
     var rawValue = BitConverter.ToUInt32(input, 4 * block); 

     var reversedValue = (ReverseBitsA(rawValue) << (32 - numberBitsInLastBlock)) | (lastValue >> numberBitsInLastBlock); 

     lastValue = rawValue; 

     BitConverter.GetBytes(ReverseBitsB(reversedValue)).CopyTo(output, 4 * (numberBlocks - block - 1)); 
    } 

    Console.WriteLine(BitConverter.ToString(input).Replace('-', ' ')); 
    Console.WriteLine(BitConverter.ToString(output).Replace('-', ' ')); 
} 

private static UInt32 SwapBitGroups(UInt32 value, UInt32 mask, Int32 shift) 
{ 
    return ((value & mask) << shift) | ((value & ~mask) >> shift); 
} 

private static UInt32 ReverseBitsA(UInt32 value) 
{ 
    value = SwapBitGroups(value, 0x55555555, 1); 
    value = SwapBitGroups(value, 0x33333333, 2); 
    value = SwapBitGroups(value, 0x0F0F0F0F, 4); 

    return value; 
} 

private static UInt32 ReverseBitsB(UInt32 value) 
{ 
    value = SwapBitGroups(value, 0x00FF00FF, 8); 
    value = SwapBitGroups(value, 0x0000FFFF, 16); 

    return value; 
} 

Il est un peu moche et pas robuste contre les erreurs ... mais c'est juste un exemple de code. Et il produit ce qui suit.

FF FF FF FF 77 AE F0 00 
F7 5E EF FF FF FF F0 00 
+0

Très intéressant. Merci pour l'exemple de code. –

Questions connexes