VB.NET Bit manipulation: how to extract byte from short? - vb.net

Given this Short (signed):
&Hxxxx
I want to:
Extract the most right &HxxFF as SByte (signed)
Extract the left &H7Fxx as Byte (unsigned)
Identify if the most left &H8xxx is positive or negative (bool result)

Extract the most right 0xxxff
myShort & 0x00FF
Extract the left 0xffxx
(myShort & 0xFF00) >> 8
Identify if the most left 0xfxxx is
positive or negative (it's a signed
short).
(myShort & 0xF000) >= 0;

Dim test As UInt16 = &HD 'a test value 1101
Dim rb As Byte 'lsb
Dim lb As Byte 'msb - 7 bits
Dim rm As UInt16 = &HFF 'lsb mask
Dim lm As UInt16 = &H7F00 'msb mask
Dim sgn As Byte = &H80 'sign mask
For x As Integer = 0 To 15 'shift the test value one bit at a time
rb = CByte(test And rm) 'get lsb
lb = CByte((test And lm) >> 8) 'get msb
Dim lbS, rbS As Boolean 'sign
'set signs
If (rb And sgn) = sgn Then rbS = True _
Else rbS = False
If (lb And sgn) = sgn Then lbS = True _
Else lbS = False 'should always be false based on mask
Console.WriteLine(String.Format("{0} {1} {2} {3} {4}",
x.ToString.PadLeft(2, " "c),
Convert.ToString(lb, 2).PadLeft(8, "0"c),
Convert.ToString(rb, 2).PadLeft(8, "0"c),
lbS.ToString, rbS.ToString))
test = test << 1
Next

inline char getLsb(short s)
{
return s & 0xff;
}
inline char getMsb(short s)
{
return (s & 0xff00) >> 8;
}
inline bool isBitSet(short s, unsigned pos)
{
return (s & (1 << pos)) > 0;
}

Uh...
value & 0x00ff
(value & 0xff00) >> 8
(value & 0xf000) >= 0
EDIT: I suppose you want the byte value and not just the upper 8 bits.

Extract the most right &HxxFF as SByte (signed)
CType(s AND &H00FF, SByte)
Extract the left &H7Fxx as Byte (unsigned)
CType((s AND &H7F00) >> 8, Byte)
Identify if the most left &H8xxx is positive or negative (bool result)
s AND &H8000 > 0
I think those work, been a while since I have worked in VB

Related

vb.net arithmetic operation resulted in an overflow in decryption

I am working on new decryption functions for password recovery tools. I tried code in c++ and worked:
void poco_pwd(u_char *pwd, int type) {
int len,
tmp;
u_char *out;
short azz;
if(type) azz = 0x2537; // encrypt message
else azz = 0x2a9a; // other passwords
len = strlen(pwd) >> 1;
out = pwd;
while(len--) {
sscanf(pwd, "%02X", &tmp);
pwd += 2;
*out++ = tmp ^ (azz >> 8);
azz = ((tmp + azz) * 0x8141) + 0x3171;
}
*out = 0;
}
I tried to convert this code to vb.net and c# but it throws arithmetic overflow operation. This functions new value is put to "azz" variable. "azz" is a short variable but this these values are very high. Strange is that it works in c++.
I converted this code to vb.net:
Dim encpass As String = "1EF66D8BD3C32476CEC8CF"
Dim encpassByte As Byte() = Encoding.UTF8.GetBytes(HexToString(encpass))
Dim azz As Integer = &H2A9A
Dim len As Integer = encpassByte.Length >> 1
Dim storage(len) As Char
For i = 0 To len
storage(i) = (ChrW(encpassByte(i) Xor (azz >> 8)))
azz = ((encpassByte(i) + azz) * &H8141) + &H3171 //Error: arithmetic operation resulted in an overflow.
Next
Console.WriteLine(storage.ToString)
Console.ReadKey()
Hex to string function:
Function HexToString(ByVal hex As String) As String
Dim text As New System.Text.StringBuilder(hex.Length \ 2)
For i As Integer = 0 To hex.Length - 2 Step 2
text.Append(Chr(Convert.ToByte(hex.Substring(i, 2), 16)))
Next
Return text.ToString
End Function
This code throws this error: arithmetic operation resulted in an overflow.

Converting C# to VB code

I have this c# code that creates a CRC code. It works correctly in c#. I converted it to VB but it is not generating the correct CRC code. Could somebody please help me figure out what is wrong with the VB code.
you call GetMessageBytes with a string and get back a bytes array with the CRC added
static byte[] GetMessageBytes(string text)
{
//Get bytes for command
byte[] command = Encoding.ASCII.GetBytes(text);
//Get CRC for command bytes
ushort crc = CalculateCrc(command);
//Append CRC and CR to command
byte[] result = new byte[command.Length + 3];
command.CopyTo(result, 0);
result[result.Length - 3] = (byte)((crc >> 8) & 0xFF);
result[result.Length - 2] = (byte)((crc >> 0) & 0xFF);
result[result.Length - 1] = 0x0d;
return result;
}
static ushort CalculateCrc(byte[] pin)
{
ushort crc;
byte da;
byte ptr;
byte bCRCHign;
byte bCRCLow;
int len = pin.Length;
ushort[] crc_ta = new ushort[]
{
0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef
};
crc = 0;
for (int index = 0; index < len; index++)
{
ptr = pin[index];
da = (byte)(((byte)(crc >> 8)) >> 4);
crc <<= 4;
crc ^= crc_ta[da ^ (ptr >> 4)];
da = (byte)(((byte)(crc >> 8)) >> 4);
crc <<= 4;
crc ^= crc_ta[da ^ (ptr & 0x0f)];
}
//Escape CR,LF,'H' characters
bCRCLow = (byte)(crc & 0x00FF);
bCRCHign = (byte)(crc >> 8);
if (bCRCLow == 0x28 || bCRCLow == 0x0d || bCRCLow == 0x0a)
{
bCRCLow++;
}
if (bCRCHign == 0x28 || bCRCHign == 0x0d || bCRCHign == 0x0a)
{
bCRCHign++;
}
crc = (ushort)(((ushort)bCRCHign) << 8);
crc |= bCRCLow;
return crc;
}
Here is the VB code.
Private Function GetMessageBytes(text As String) As Byte()
'Get bytes for command
Dim command As Byte() = System.Text.Encoding.Unicode.GetBytes(text)
'Get CRC for command bytes
Dim crc As UShort = CalcCrcHalf(command)
'Append CRC and CR to command
Dim result As Byte() = New Byte(command.Length + 3) {}
command.CopyTo(result, 0)
result(result.Length - 3) = CByte((crc >> 8) And &HFF)
result(result.Length - 2) = CByte((crc >> 0) And &HFF)
result(result.Length - 1) = &HD
Return result
End Function
Private Function CalculateCRC(pin As Byte()) As UShort
Dim crc As UShort
Dim da As Byte
Dim ptr As Byte
Dim bCRCHign As Byte
Dim bCRCLow As Byte
Dim len As Integer = pin.Length
Dim crc_ta As UShort() = New UShort() {&H0, &H1021, &H2042, &H3063, &H4084, &H50A5, &H60C6, &H70E7, &H8108, &H9129, &HA14A, &HB16B, &HC18C, &HD1AD, &HE1CE, &HF1EF}
crc = 0
For index As Integer = 0 To len - 1
ptr = pin(index)
da = CByte(CByte(crc >> 8) >> 4)
crc <<= 4
crc = crc Xor crc_ta(da Xor (ptr >> 4))
da = CByte(CByte(crc >> 8) >> 4)
crc <<= 4
crc = crc Xor crc_ta(da Xor (ptr And &HF))
Next
'Escape CR,LF,'H' characters
bCRCLow = CByte(crc And &HFF)
bCRCHign = CByte(crc >> 8)
If bCRCLow = &H28 OrElse bCRCLow = &HD OrElse bCRCLow = &HA Then
bCRCLow += 1
End If
If bCRCHign = &H28 OrElse bCRCHign = &HD OrElse bCRCHign = &HA Then
bCRCHign += 1
End If
crc = CUShort(CUShort(bCRCHign) << 8)
crc = crc Or bCRCLow
Return crc
End Function
Thanks I got it working. It was the encoding.
This is the correct code.
retrun_string = System.Text.Encoding.GetEncoding(1252).GetString(result)
Dim hiByte as byte
Dim LoByter as byte
hiByte = crc \ &H100 And &HFF&
LoByte = crc And &HFF&
At least this worked for me.

Convert Signature Bitmap to Signature String (very strange one)

Basically I need to convert a bitmap image into a string but it is not a common one.
The dilemma is that this string is composed of two parts:
1) Points
2) Lines
I need to convert the image into two parts delimited by a *.
One example I have been given is:
"221A*221A270A270A2503250320072007171617160D2A0D2A07380738073F073F0B3E0B3E15311531222122212C182C183016301631173117311A311A302230222E272E272D2C2D2C2C2F2C2F2C312C312C2F2C2F2E2B2E2B3126312633223322371D371D381C381C3B1B3B1B3C1C3C1C3D1F3D1F3D243D243C2D3C2D3A333A333A363A36393939393B383B383D363D36412E412E46264626492049204B1B4B1B4E184E184F174F175017501751185118511D511D51225122502450244F294F294F2C4F2C4E2F4E2F4F314F315030503052305230552C552C582958295D225D22601E601E611C611C621B621B621A621A601A601A5D1B5D1B5B1E5B1E5723572353285328512B512B502E502E502F502F513151315231523154305430582E582E592D592D5C2C5C2C5F2A5F2A6428642865286528692669266D246D247122712275207520791D791D7D1B7D1B81198119841884188618861887198719881A881A891B891B881C881C871E871E861F861F852085208421842182228222812481247F257F257E257E257D257D257C247C247C217C217D1F7D1F7E1C7E1C801A801A81198119821782178317831784188418851A851A851C851C86208620862286228625862587278727872B872B882E882E893289328A338A338E348E349033903393329332972F972F9A2D9A2D9F299F29A426A426AB20AB20AF1CAF1CB517B517B716B716B716"
so all I know is that the 221A is the points and the other string is lines but need to be able to achieve that.
Have nay of you come across this before ?
I have tried converting the bitmap to Base64String but that doesn't give my anything near.
If it Helps I only have the reverse in VB i.e. from string to image:
Private Sub unpackBMP(ByVal BITMAP As String)
Dim points As String
Dim lines As String
Dim x As Long
Dim y As Long
Dim x1 As Long
Dim y1 As Long
points = firstItem(BITMAP, "*")
lines = BITMAP
While Len(points) > 0
x = "&H" & Mid(points, 1, 2)
y = "&H" & Mid(points, 3, 2)
points = Mid(points, 5, Len(points) - 4)
'picDraw.PSet (Val(x), Val(y)), vbBlack
'Call picDraw.DrawPoint(CDbl(x), CDbl(y))
'picDraw.Refresh
Wend
While Len(lines) > 0
x = "&H" & Mid(lines, 1, 2)
y = "&H" & Mid(lines, 3, 2)
x1 = "&H" & Mid(lines, 5, 2)
y1 = "&H" & Mid(lines, 7, 2)
lines = Mid(lines, 9, Len(lines) - 8)
'picDraw.Line (Val(x), Val(y))-(Val(x1), Val(y1)), vbBlack
'Call picDraw.DrawLine(CDbl(x), CDbl(y), CDbl(x1), CDbl(y1), 0)
'picDraw.Refresh
Wend
'Call picDraw.DrawLine(lines(1, tmp), lines(2, tmp), lines(3, tmp), lines(4, tmp), 0)
End Sub
Public Function firstItem(pstrItems As String, pstrDelim As String) As String
Dim lngPos As Long
Dim strRes As String
'Dim strDelim As String
strRes = ""
lngPos = InStr(pstrItems, pstrDelim)
If lngPos > 0 Then
strRes = Left$(pstrItems, lngPos - 1)
pstrItems = Mid$(pstrItems, lngPos + 1)
Else
strRes = pstrItems
pstrItems = ""
End If
firstItem = strRes
End Function
Let me know if you require any further details.
Background: This is a signature in a picture box on a windows mobile 6.5 device. Please see below for the image and its related string. Hopefully this helps.
String for SIGNATURE 280172:
3711*371127152715103510351F2C1F2C312231223C1C3C1C3D203D20352D352D333233323D2E3D2E52225222671A671A6C196C196D1A6D1A6D1D6D1D69226922652665266428642864296429652965296E236E23781E781E8718871891179117961896189A199A199B1B9B1B9D1E9D1E9F209F20A021A021A021
Adding the attachment stack makes it a png but it is a bmp file, however it is a 204 x 64 1 bit depth image.
Reordered string (by Spektre)
3711*3711
2715 2715
1035 1035
1F2C 1F2C
3122 3122
3C1C 3C1C
3D20 3D20
352D 352D
3332 3332
3D2E 3D2E
5222 5222
671A 671A
6C19 6C19
6D1A 6D1A
6D1D 6D1D
6922 6922
6526 6526
6428 6428
6429 6429
6529 6529
6E23 6E23
781E 781E
8718 8718
9117 9117
9618 9618
9A19 9A19
9B1B 9B1B
9D1E 9D1E
9F20 9F20
A021 A021 A021
Single horizontal line makes the following string:
101F*101F
1D21 1D21
2121 2121
2820 2820
2C20 2C20
3120 3120
3921 3921
3F21 3F21
4521 4521
4A21 4A21
5122 5122
5822 5822
6121 6121
6421 6421
6721 6721
6A20 6A20
6C20 6C20
6F20 6F20
7220 7220
7520 7520
7720 7720
7920 7920
7D20 7D20
8020 8020
8120 8120
8320 8320
861F 861F
871F 871F
891F 891F
8A1F 8A1F
8D1F 8D1F
8F1F 8F1F
931F 931F
961F 961F
971F 971F
9A1F 9A1F
9C1F 9C1F
9D1E 9D1E
A11E A11E
A31E A31E
A51D A51D
A71D A71D
A91D A91D
AA1C AA1C
AB1C AB1C
AD1C AD1C
AE1C AE1C
B01C B01C
B11B B11B
B21B B21B
B41B B41B
B51A B51A
B61A B61A
B81A B81A
B919 B919
BB19 BB19
BC19 BC19
BD19 BD19
BE19 BE19
BF19 BF19
C019 C019
C11A C11A
C31A C31A
C41A C41A
C51A C51A
C61B C61B
C71B C71B
C81C C81C
C81C
So this is what makes the PictureBox Signature to a string:
'signature
Public gSigPoints() As Long
Public gSigLines() As Long
Public gSigPointCount As Long
Public gSigLinesCount As Long
Public Function PackBMP() As String
Dim tmpStr1 As String
Dim tmpStr2 As String
Dim tmpStr3 As String
Dim tmpStr4 As String
Dim tmp As Long
gJob_Signature = ""
For tmp = 1 To gSigPointCount
tmpStr1 = CStr(Hex(gSigPoints(1, tmp)))
tmpStr2 = CStr(Hex(gSigPoints(2, tmp)))
If Len(tmpStr1) = 2 And Len(tmpStr2) = 2 Then
gJob_Signature = gJob_Signature & tmpStr1 & tmpStr2 '& ";" & ";"
Else
If Len(tmpStr1) = 1 Then tmpStr1 = "0" & tmpStr1
If Len(tmpStr2) = 1 Then tmpStr2 = "0" & tmpStr2
If Len(tmpStr1) = 2 And Len(tmpStr2) = 2 Then
gJob_Signature = gJob_Signature & tmpStr1 & tmpStr2 '& ";"& ";"
End If
End If
Next 'tmp
gJob_Signature = gJob_Signature & "*"
For tmp = 1 To gSigLinesCount
tmpStr1 = CStr(Hex(gSigLines(1, tmp)))
tmpStr2 = CStr(Hex(gSigLines(2, tmp)))
tmpStr3 = CStr(Hex(gSigLines(3, tmp)))
tmpStr4 = CStr(Hex(gSigLines(4, tmp)))
If Len(tmpStr1) = 2 And Len(tmpStr2) = 2 And Len(tmpStr3) = 2 And Len(tmpStr4) = 2 Then
gJob_Signature = gJob_Signature & tmpStr1 & tmpStr2 & tmpStr3 & tmpStr4 '& ";"
Else
If Len(tmpStr1) = 1 Then tmpStr1 = "0" & tmpStr1
If Len(tmpStr2) = 1 Then tmpStr2 = "0" & tmpStr2
If Len(tmpStr3) = 1 Then tmpStr3 = "0" & tmpStr3
If Len(tmpStr4) = 1 Then tmpStr4 = "0" & tmpStr4
If Len(tmpStr1) = 2 And Len(tmpStr2) = 2 And Len(tmpStr3) = 2 And Len(tmpStr4) = 2 Then
gJob_Signature = gJob_Signature & tmpStr1 & tmpStr2 & tmpStr3 & tmpStr4 '& ";"
End If
End If
Next 'tmp
End Function
Public Sub DrawBMP(ByRef pic As PictureBox)
Dim x As Long
pic.Cls
For x = 1 To gSigPointCount
Call pic.DrawPoint(gSigPoints(1, x), gSigPoints(2, x))
Next x
For x = 1 To gSigLinesCount
Call pic.DrawLine(gSigLines(1, x), gSigLines(2, x), gSigLines(3, x), gSigLines(4, x), 0)
Next x
pic.Refresh
End Sub
Public Sub AddPoint(x As Long, Y As Long)
gSigPointCount = gSigPointCount + 1
ReDim Preserve gSigPoints(2, gSigPointCount)
gSigPoints(1, gSigPointCount) = x
gSigPoints(2, gSigPointCount) = Y
End Sub
Public Sub AddLine(x As Long, Y As Long, x1 As Long, y1 As Long)
gSigLinesCount = gSigLinesCount + 1
ReDim Preserve gSigLines(4, gSigLinesCount)
gSigLines(1, gSigLinesCount) = x
gSigLines(2, gSigLinesCount) = Y
gSigLines(3, gSigLinesCount) = x1
gSigLines(4, gSigLinesCount) = y1
End Sub
'********signature
Private miX As Double
Private miY As Double
Private isup As Boolean
'*********end of signature
'## singnatures
Private Sub picDraw_MouseDown(Button As Long, Shift As Long, x As Double, Y As Double)
picDraw.DrawPoint x, Y, 0
picDraw.Refresh
Call AddPoint(x, Y)
miX = x
miY = Y
isup = False
End Sub
Private Sub picDraw_MouseMove(Button As Long, Shift As Long, x As Double, Y As Double)
If isup Then
miX = x
miY = Y
isup = False
Else
If Button = 1 Then
picDraw.DrawLine miX, miY, x, Y, 0
picDraw.Refresh
Call AddLine(miX, miY, x, Y)
miX = x
miY = Y
End If
End If
End Sub
Private Sub picDraw_MouseUp(ByVal Button As Long, ByVal Shift As Long, ByVal x As Double, ByVal Y As Double)
isup = True
End Sub
This is all I can see regarding the signature picture box.
I figured the encoding out from the code you posted (had to port it to C++ though) so the encoding:
string starts with list of points
Each point is present as 4-digit hex number. First 2 hex digits are x coordinate and the second 2 digits are y coordinate of point. (probably marking each mouse down event so it holds the info on how many continuous draws the image was drawn)
then separator * follows
after that list of lines is present
Each line contains 2 points so total of 8-digits hex number per line. The sequence is x0,y0,x1,y1 2-digit hex number per coordinate. If the string contains only 4-digit hex number (the end) it marks the end of signature string.
So when you want to make own signature code then:
clear list of points and list of lines
on mouse down (left button click on or pen hit) event
Add current mouse/pen position to the point list and as a start point to line list
on mouse/pen move event
First find out if the mouse button is still clicked or pen still hitting the pad. If not ignore this event. If yes then add current mouse position to line list twice (that is why they are duplicated the first ends current line and the second starts new line)
on mouse/pen up event
close the actual line so add current mouse position to line list once
before exporting
duplicate last point in lines list to mark end of string
That is all. If you need to convert already drawed image (raster) then you may have problems with comparison because is very unlikely you vectorize the image the same way as the author signs it. Resulting in miss-match of the same images. Also the tripled last point is most likely because of wrong encoding of mouse/pen up event adding the same point inside on mouse move and on mouse up events at once
The images encoded this way are limited to 256x256 pixels.
Here example of decoded image for your first signature string:
signature="221A*221A270A270A2503250320072007171617160D2A0D2A07380738073F073F0B3E0B3E15311531222122212C182C183016301631173117311A311A302230222E272E272D2C2D2C2C2F2C2F2C312C312C2F2C2F2E2B2E2B3126312633223322371D371D381C381C3B1B3B1B3C1C3C1C3D1F3D1F3D243D243C2D3C2D3A333A333A363A36393939393B383B383D363D36412E412E46264626492049204B1B4B1B4E184E184F174F175017501751185118511D511D51225122502450244F294F294F2C4F2C4E2F4E2F4F314F315030503052305230552C552C582958295D225D22601E601E611C611C621B621B621A621A601A601A5D1B5D1B5B1E5B1E5723572353285328512B512B502E502E502F502F513151315231523154305430582E582E592D592D5C2C5C2C5F2A5F2A6428642865286528692669266D246D247122712275207520791D791D7D1B7D1B81198119841884188618861887198719881A881A891B891B881C881C871E871E861F861F852085208421842182228222812481247F257F257E257E257D257D257C247C247C217C217D1F7D1F7E1C7E1C801A801A81198119821782178317831784188418851A851A851C851C86208620862286228625862587278727872B872B882E882E893289328A338A338E348E349033903393329332972F972F9A2D9A2D9F299F29A426A426AB20AB20AF1CAF1CB517B517B716B716B716";
here square example
signature="0808*080820082008202020200820082008080808";
so when reordered:
0808 // point(8h,8h);
* // separator
08 08 20 08 // line( 8h, 8h,20h, 8h)
20 08 20 20 // line(20h, 8h,20h,20h)
20 20 08 20 // line(20h,20h, 8h,20h)
08 20 08 08 // line( 8h,20h, 8h, 8h)
08 08 // not enough points -> end of string
[Edit1] raster image to string conversion
First you need to convert your image to vector form. There are many sophistikated approaches to polygonize raster image to vector form but they are usually using advanced things from math,image processing,structures etc... requiring extensive knowledge on the subject. As I assume you need this just to visualize something on the device so Instead I would use very simple conversion resulting in unreasonable big results (in comparison to the advanced approaches). If your device does not have too small limit on the string size then you should be fine otherwise you would need use something more advanced then this:
clear your vector representation
list of points and list of lines
loop through all horizontal lines of image
process each line
find first set pixel from current position x0
find first unset pixel from current position x1
if x0,x1 found then
add point (x0,y)
add line (x0,y,x1-1,y)
after whole image processed convert vector form to string
clear string
add list of all points to string
add separator * to string
add list of all lines to string
This is how it looks like in C++:
// load input 2D BW (binary) image
backbuffer in;
in.bmp->LoadFromFile("in.bmp");
in.resize(in.bmp->Width,in.bmp->Height);
int x0,x1,x,y;
// clear signature vecor represenytation
gSigPoints.num=0;
gSigLines.num=0;
for (y=0;y<in.ys;y++)
for (x=0;x<in.xs;)
{
for (;(x<in.xs)&&(!in.pyx[y][x]);x++); x0=x; // find start of V-line
for (;(x<in.xs)&&( in.pyx[y][x]);x++) x1=x; // find end of V-line
if (x0<in.xs) // add pnt,line to signature
{
gSigPoints.add(x0);
gSigPoints.add(y );
gSigLines.add(x0);
gSigLines.add(y );
gSigLines.add(x1);
gSigLines.add(y );
}
}
// update string and screen
txt=PackBMP();
draw();
where in.xs,in.ys is input image resolution
in.pyx[y][x] is the image pixel access
txt is the signature string
gSigPoints,gSigLines are lists holding the signature points and lines
these list have .num the number of items and .add(a) adds a to the end of the list
The pack/unpack ported from your VB code looks like this:
//---------------------------------------------------------------------------
#include "list.h"
//---------------------------------------------------------------------------
List<DWORD> gSigPoints;
List<DWORD> gSigLines;
// some test examples:
//AnsiString txt="221A*221A270A270A2503250320072007171617160D2A0D2A07380738073F073F0B3E0B3E15311531222122212C182C183016301631173117311A311A302230222E272E272D2C2D2C2C2F2C2F2C312C312C2F2C2F2E2B2E2B3126312633223322371D371D381C381C3B1B3B1B3C1C3C1C3D1F3D1F3D243D243C2D3C2D3A333A333A363A36393939393B383B383D363D36412E412E46264626492049204B1B4B1B4E184E184F174F175017501751185118511D511D51225122502450244F294F294F2C4F2C4E2F4E2F4F314F315030503052305230552C552C582958295D225D22601E601E611C611C621B621B621A621A601A601A5D1B5D1B5B1E5B1E5723572353285328512B512B502E502E502F502F513151315231523154305430582E582E592D592D5C2C5C2C5F2A5F2A6428642865286528692669266D246D247122712275207520791D791D7D1B7D1B81198119841884188618861887198719881A881A891B891B881C881C871E871E861F861F852085208421842182228222812481247F257F257E257E257D257D257C247C247C217C217D1F7D1F7E1C7E1C801A801A81198119821782178317831784188418851A851A851C851C86208620862286228625862587278727872B872B882E882E893289328A338A338E348E349033903393329332972F972F9A2D9A2D9F299F29A426A426AB20AB20AF1CAF1CB517B517B716B716B716";
//AnsiString txt="3711*371127152715103510351F2C1F2C312231223C1C3C1C3D203D20352D352D333233323D2E3D2E52225222671A671A6C196C196D1A6D1A6D1D6D1D69226922652665266428642864296429652965296E236E23781E781E8718871891179117961896189A199A199B1B9B1B9D1E9D1E9F209F20A021A021A021";
AnsiString txt="0808*08082008200820202020082008200808";
//---------------------------------------------------------------------------
AnsiString Hex(DWORD x,DWORD digits)
{
int i;
char *tab="0123456789ABCDEF";
AnsiString s="";
if (digits>8) digits=8;
s.SetLength(digits);
for (i=digits;i>0;i--,x>>=4) s[i]=tab[x&15];
return s;
}
//---------------------------------------------------------------------------
AnsiString PackBMP()
{
DWORD i;
AnsiString sig="";
// all points
for (i=0;i+1<gSigPoints.num;)
{
sig+=Hex(gSigPoints[i],2); i++; // x
sig+=Hex(gSigPoints[i],2); i++; // y
}
// separator
sig+="*";
// all lines
for (i=0;i+3<gSigLines.num;i++)
{
sig+=Hex(gSigLines[i],2); i++; // x0
sig+=Hex(gSigLines[i],2); i++; // y0
sig+=Hex(gSigLines[i],2); i++; // x1
sig+=Hex(gSigLines[i],2); i++; // y1
}
return sig;
}
//---------------------------------------------------------------------------
void UnpackBMP(AnsiString &sig)
{
DWORD a,x,y;
int i=1,l=sig.Length();
// all points
for(gSigPoints.num=0;(i+3<=l)&&(sig[i]!='*');)
{
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; x =a; i++;
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; x<<=4; x|=a; i++;
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; y =a; i++;
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; y<<=4; y|=a; i++;
gSigPoints.add(x);
gSigPoints.add(y);
}
// separator
i++;
// all lines
for(gSigLines.num=0;i+7<=l;)
{
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; x =a; i++;
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; x<<=4; x|=a; i++;
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; y =a; i++;
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; y<<=4; y|=a; i++;
gSigLines.add(x);
gSigLines.add(y);
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; x =a; i++;
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; x<<=4; x|=a; i++;
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; y =a; i++;
a=sig[i]-'0'; if (a>9) a+='0'-'A'+10; y<<=4; y|=a; i++;
gSigLines.add(x);
gSigLines.add(y);
}
}
//---------------------------------------------------------------------------
void DrawBMP(TCanvas *can)
{
DWORD i,x,y;
// all points
for (i=0;i+1<gSigPoints.num;)
{
x=gSigPoints[i]; i++;
y=gSigPoints[i]; i++;
can->Pixels[x][y]=can->Pen->Color;
}
// all lines
for (i=0;i+3<gSigLines.num;)
{
x=gSigLines[i]; i++;
y=gSigLines[i]; i++;
can->MoveTo(x,y);
x=gSigLines[i]; i++;
y=gSigLines[i]; i++;
can->LineTo(x,y);
}
}
//---------------------------------------------------------------------------
void signature_on_mouse(backbuffer &scr)
{
DWORD x,y;
// mouse left button last and actual
bool q0=scr.sh0.Contains(ssLeft);
bool q1=scr.sh1.Contains(ssLeft);
bool _redraw=false;
// actual mouse position
x=scr.mx1;
y=scr.my1;
// on mouse down event
if ((!q0)&&(q1))
{
gSigPoints.add(x); gSigLines.add(x);
gSigPoints.add(y); gSigLines.add(y);
_redraw=true;
}
// on mouse move event
if ((q0)&&(q1))
{
gSigLines.add(x);
gSigLines.add(y);
gSigLines.add(x);
gSigLines.add(y);
_redraw=true;
}
// mouse mouse up event
if ((q0)&&(!q1))
{
gSigLines.add(x);
gSigLines.add(y);
_redraw=true;
txt=PackBMP();
}
// right mouse button clears signature
if (scr.sh1.Contains(ssRight))
{
gSigPoints.num=0;
gSigLines.num=0;
_redraw=true;
}
if ((_redraw)&&(scr.win)) scr.win->Repaint();
scr.rfs_mouse();
}
//---------------------------------------------------------------------------
where backbuffer is mine class to interface the window backbuffer image and mouse handler events.
So just change List<>,AnsiString,Backbuffer to your platform style.
This can handle any raster binary image not just signatures:
But as you can see the size of signature string is ~ 13.9 KByte

Performance loss in VB.net equivalent of light weight conversion from hex to byte

I have read through the answers here https://stackoverflow.com/a/14332574/44080
I've also tried to produce equivalent VB.net code:
Option Strict ON
Public Function ParseHex(hexString As String) As Byte()
If (hexString.Length And 1) <> 0 Then
Throw New ArgumentException("Input must have even number of characters")
End If
Dim length As Integer = hexString.Length \ 2
Dim ret(length - 1) As Byte
Dim i As Integer = 0
Dim j As Integer = 0
Do While i < length
Dim high As Integer = ParseNybble(hexString.Chars(j))
j += 1
Dim low As Integer = ParseNybble(hexString.Chars(j))
j += 1
ret(i) = CByte((high << 4) Or low)
i += 1
Loop
Return ret
End Function
Private Function ParseNybble(c As Char) As Integer
If c >= "0"C AndAlso c <= "9"C Then
Return c - "0"C
End If
c = ChrW(c And Not &H20)
If c >= "A"C AndAlso c <= "F"C Then
Return c - ("A"C - 10)
End If
Throw New ArgumentException("Invalid nybble: " & c)
End Function
Can we remove the compile errors in ParseNybble without introducing data conversions?
Return c - "0"c Operator '-' is not defined for types 'Char' and 'Char'
c = ChrW(c And Not &H20) Operator 'And' is not defined for types 'Char' and 'Integer'
As it stands, no.
However, you could change ParseNybble to take an integer and pass AscW(hexString.Chars(j)) to it, so that the data conversion takes place outside of ParseNybble.
This solution is much much faster than all the alternative i have tried. And it avoids any ParseNybble lookup.
Function hex2byte(s As String) As Byte()
Dim l = s.Length \ 2
Dim hi, lo As Integer
Dim b(l - 1) As Byte
For i = 0 To l - 1
hi = AscW(s(i + i))
lo = AscW(s(i + i + 1))
hi = (hi And 15) + ((hi And 64) >> 6) * 9
lo = (lo And 15) + ((lo And 64) >> 6) * 9
b(i) = CByte((hi << 4) Or lo)
Next
Return b
End Function

How to implement murmurhash3 in VBNET

I'm trying to implement murmurhash3 in vb.net and trying to convert from this C# implementation
first part of the function in c#
public static SqlInt32 MurmurHash3(SqlBinary data)
{
const UInt32 c1 = 0xcc9e2d51;
const UInt32 c2 = 0x1b873593;
int curLength = data.Length; /* Current position in byte array */
int length = curLength; /* the const length we need to fix tail */
UInt32 h1 = seed;
UInt32 k1 = 0;
/* body, eat stream a 32-bit int at a time */
Int32 currentIndex = 0;
while (curLength >= 4)
{
/* Get four bytes from the input into an UInt32 */
k1 = (UInt32)(data[currentIndex++]
| data[currentIndex++] << 8
| data[currentIndex++] << 16
| data[currentIndex++] << 24);
/* bitmagic hash */
k1 *= c1;
k1 = rotl32(k1, 15);
k1 *= c2;
h1 ^= k1;
h1 = rotl32(h1, 13);
h1 = h1 * 5 + 0xe6546b64;
curLength -= 4;
}
And same in VB.net:
Public Shared Function MurmurHash3(data As Byte()) As Int32
Const c1 As UInt32 = &HCC9E2D51UI
Const c2 As UInt32 = &H1B873593
Dim curLength As Integer = data.Length
' Current position in byte array
Dim length As Integer = curLength
' the const length we need to fix tail
Dim h1 As UInt32 = seed
Dim k1 As UInt32 = 0
' body, eat stream a 32-bit int at a time
Dim dBytes As Byte()
Dim currentIndex As Int32 = 0
While curLength >= 4
' Get four bytes from the input into an UInt32
dBytes = New Byte() {data(currentIndex), data(currentIndex + 1), data(currentIndex + 2), data(currentIndex + 3)}
k1 = BitConverter.ToUInt32(dBytes, 0)
currentIndex += 4
' bitmagic hash
k1 *= c1
k1 = rotl32(k1, 15)
k1 *= c2
h1 = h1 Xor k1
h1 = rotl32(h1, 13)
h1 = h1 * 5 + &HE6546B64UI
curLength -= 4
End While
Private Shared Function rotl32(x As UInt32, r As Byte) As UInt32
Return (x << r) Or (x >> (32 - r))
End Function
k1 *= c1
Throws error Arithmetic operation resulted in an overflow.
Any suggestions how this should be implemented? I'm Not sure how to do the Get four bytes from the input into an UInt32 part if that is the problem or is it related to something else since there are some differences in bitwise operations between C# and VB.
For the reference Java implementation also exists
https://github.com/yonik/java_util/blob/master/src/util/hash/MurmurHash3.java
I'd first convert the 32-bit k1 to a 64-bit variant first, e.g:
k1_64 = CType(k1, UInt64)
for modulo-32bit calculation, do
k1_64 = (k1_64 * c1) And &HFFFFFFFFUI
finally, recast back to 32-bit
k1 = CType(k1_64 And $HFFFFFFFFUI, UInt32)
to add more performance, you might want to consider replacing the BitConverter.ToUInt call with something else.
EDIT : Here's a simpler version without additional variable (but with a 'helper constant')
Const LOW_32 as UInt32 = &HFFFFFFFFUI
' ... intervening code ...
k1 = (1L * k1 * c1) And LOW_32
' ... later on ...
h1 = (h1 * 5L + &HE6546B64UL) And LOW_32
the 1L forces the calculation within the parens to be performed as Long (Int64). The And LOW_32 pares down the number of non-zero bits to 32, and the overall result is then automatically casted to UInt32. Similar thing happens on the h1 line.
Reference: http://www.undermyhat.org/blog/2009/08/secrets-and-lies-of-type-suffixes-in-c-and-vb-net/ (scroll down to the section "Secrets of constants and type suffixes")
Unfortunately, it possible to do the equivalent of unchecked {} in VB.NET? You could use a try/catch blocked and do the shift manually if you overflow. Just be careful, putting an error handler in there will slow down the hash calculation.