Robert Harvey
Robert Harvey

Reputation: 180788

Bit manipulation in C# using a mask

I need a little help with bitmap operations in C#

I want to take a UInt16, isolate an arbitrary number of bits, and set them using another UInt16 value.

Example:

10101010  -- Original Value
00001100  -- Mask - Isolates bits 2 and 3

Input        Output
00000000  -- 10100010
00000100  -- 10100110
00001000  -- 10101010
00001100  -- 10101110
                 ^^

Upvotes: 7

Views: 20294

Answers (5)

Martin Weihrauch
Martin Weihrauch

Reputation: 310

If you want to do bitwise manipulations, I have written a very versatile method to copy any number of bits from one byte (source byte) to another byte (target byte). The bits can be put to another starting bit in the target byte.

In this example, I want to copy 3 bits (bitCount=3) from bit #4 (sourceStartBit) to bit #3 (destinationStartBit). Please note that the numbering of bits starts with "0" and that in my method, the numbering starts with the most significant bit = 0 (reading from left to right).

byte source = 0b10001110;
byte destination = 0b10110001;

byte result = CopyByteIntoByte(source, destination, 4, 1, 3);
Console.WriteLine("The binary result: " + Convert.ToString(result, toBase: 2));
//The binary result: 11110001

byte CopyByteIntoByte(byte sourceByte, byte destinationByte, int sourceStartBit, int destStartBit, int bitCount)
{
    int[] mask = { 0, 1, 3, 7, 15, 31, 63, 127, 255 };
    byte sourceMask = (byte)(mask[bitCount] << (8 - sourceStartBit - bitCount));
    byte destinationMask = (byte)(~(mask[bitCount] << (8-destStartBit - bitCount)));
    byte destinationToCopy = (byte)(destinationByte & destinationMask);
    int diff = destStartBit - sourceStartBit;
    byte sourceToCopy;
    if(diff > 0)
    {
        sourceToCopy = (byte)((sourceByte & sourceMask) >> (diff));
    }
    else
    {
        sourceToCopy = (byte)((sourceByte & sourceMask) << (diff * (-1)));
    }
    return (byte)(sourceToCopy | destinationToCopy);
}

Upvotes: 0

Paul Sasik
Paul Sasik

Reputation: 81459

A number of the terser solutions here look plausible, especially JS Bangs', but don't forget that you also have a handy BitArray collection to use in the System.Collections namespace: http://msdn.microsoft.com/en-us/library/system.collections.bitarray.aspx

Upvotes: 1

Chris Taylor
Chris Taylor

Reputation: 53699

newValue = (originalValue & ~mask) | (inputValue & mask);

originalValue -> 10101010
inputValue    -> 00001000  
mask          -> 00001100 
~mask         -> 11110011

(originalValue & ~mask)
  10101010
& 11110011
----------
  10100010
      ^^
      Cleared isolated bits from the original value

(inputValue & mask)
  00001000  
& 00001100 
----------
  00001000


newValue =      
  10100010
| 00001000
----------
  10101010

Upvotes: 5

P Daddy
P Daddy

Reputation: 29527

Something like this?

static ushort Transform(ushort value){
    return (ushort)(value & 0x0C/*00001100*/ | 0xA2/*10100010*/);
}

This will convert all your sample inputs to your sample outputs. To be more general, you'd want something like this:

static ushort Transform(ushort input, ushort mask, ushort bitsToSet){
    return (ushort)(input & mask | bitsToSet & ~mask);
}

And you would call this with:

Transform(input, 0x0C, 0xA2);

For the equivalent behavior of the first function.

Upvotes: 1

JSBձոգչ
JSBձոգչ

Reputation: 41378

It seems like you want:

(orig & ~mask) | (input & mask)

The first half zeroes the bits of orig which are in mask. Then you do a bitwise OR against the bits from input that are in mask.

Upvotes: 9

Related Questions