Reputation: 365
I am trying to combine three Byte values to one Long value, like System.Drawing.Color.ToArgb() does.
I've looked up reference source code to find it and converted it to VB .NET:
Return CLng((CInt(red) << 16 Or CInt(green) << 8 Or blue Or CInt(alpha) << 24) And -1)
It works fine of course, but I don't really understand why alpha shifted by 24 is last, not first (so it would be in nice order 24, 16, 8). I don't really understand bitwise operations a lot. Also, this code snippet works for 4 bytes, which is redundant for me, I need just three bytes and I wonder if Long is still required when bytes are only three, wouldn't Integer do just fine in this case?
So, my question is, how do I rewrite this code to work with just 3 parameters? Do I need to use Long? And, I know this is silly, but is it possible to make byte shifting in order 16,8,0 instead of 16,8,0,24? It's really just aesthetics, but I am awful perfectionist.
Thanks in advance!
Aaron
Upvotes: 0
Views: 1848
Reputation: 884
I'm not familiar with VB.NET, but in general there is no right or wrong order of the shift count. It can be 24, 16, 8, 0 or 16, 24, 0, 8 or any other order.
And regrading the variable type: There are 8-bit, 16-bit and 32-bit variables. That means you must define a 32-bit type (long) in order to have room for your three bytes. For easy access, leave the 8 MSB bits as 0 so you can use it as a 24-bit value (0x00YYYYYY).
Upvotes: 1
Reputation: 941605
It doesn't matter, a OR b is the same value as b OR a. The OR operator is commutative, just like the + and * operators.
An Integer can store the value just fine, it has 32 bits. Using UInteger instead can be useful to deal with alpha values larger than 127 turning the value negative. Which will give you a bit of a headache when you try to read the alpha value back. Sign extension produces a large value, fixed by AND-ing with 255. Long was common in VB6 code since its Integer type had only 16 bits, not an issue in vb.net.
Upvotes: 1
Reputation: 11773
Here are some different ways. The order of the OR's does not matter. I added some debugs so you can see the results as you go.
Private Sub Button1_Click(sender As System.Object, _
e As System.EventArgs) Handles Button1.Click
Dim bar As Integer '32 bits
'three byte values
Dim x As Byte = 66
Dim y As Byte = 65
Dim z As Byte = 82
'desired byte order
'0xyz
'one byte at a time
bar = 0
bar = bar Or (CInt(x) << 16)
Debug.WriteLine(Convert.ToString(bar, 2).PadLeft(32, "0"c))
bar = bar Or (CInt(y) << 8)
Debug.WriteLine(Convert.ToString(bar, 2).PadLeft(32, "0"c))
bar = bar Or (CInt(z) << 0) 'bar Or CInt(z)
Debug.WriteLine(Convert.ToString(bar, 2).PadLeft(32, "0"c))
'or as single statement
bar = 0 Or (CInt(x) << 16) Or (CInt(y) << 8) Or CInt(z)
Debug.WriteLine(Convert.ToString(bar, 2).PadLeft(32, "0"c))
'in any order
bar = 0 Or CInt(z) Or (CInt(y) << 8) Or (CInt(x) << 16)
Debug.WriteLine(Convert.ToString(bar, 2).PadLeft(32, "0"c))
'check results
Dim foo() As Byte = BitConverter.GetBytes(bar) 'get the individual bytes
Array.Reverse(foo) 'reverse
Debug.WriteLine(System.Text.ASCIIEncoding.ASCII.GetChars(foo, 1, 3))
End Sub
Upvotes: 1