Receiving a float as 4 individual bytes then converting it back - vb.net

I am receiving via UDP, 4 byte packets that represent what was a float (from C# code). I now need to turn these bytes back into the single so it's the same number as it was before
I've done a bit of trial and error but I'm not even close to turning it into a single accurately. All I do know is that the number is between 0 and 1, and is in little-endian format.
A few more things that may help
When the float is 1
Byte(0) = 0, Byte(1) = 0, Byte(2) = 128, Byte(3) = 63
When the float is approximately 0.5
Byte(0) = 234, Byte(1) = 111, Byte(2) = 247, Byte(3) = 62
When the float is approximately 0.75
Byte(0) = 178, Byte(1) = 56, Byte(2) = 64, Byte(3) = 63

Related

shape pattern in corel draw vba

I want to make a patern of shapes based on the document size in corel draw. right now I have the four corners taken care of (dot1 to dot4). But, when my document size is bigger than 96" I need to put more than dots 1 to 4 so I've added the if statement but it' not quite what I want.
`
ActivePage.CreateLayer ("CCD")
Dim DOT1 As Shape
Set DOT1 = ActivePage.ActiveLayer.CreateEllipse2(0.225, 0.225, 0.125, 0.125)
DOT1.Fill.UniformColor.RGBAssign 0, 255, 255
DOT1.Outline.SetNoOutline
DOT1.Name = "DOT1"
Dim DOT2 As Shape
Set DOT2 = ActivePage.ActiveLayer.CreateEllipse2(DOCUMENTSIZEX - 0.225, 0.225, 0.125, 0.125)
DOT2.Fill.UniformColor.RGBAssign 0, 255, 255
DOT2.Outline.SetNoOutline
DOT2.Name = "DOT2"
Dim DOT3 As Shape
Set DOT3 = ActivePage.ActiveLayer.CreateEllipse2(0.225, DOCUMENTSIZEY - 0.225, 0.125, 0.125)
DOT3.Fill.UniformColor.RGBAssign 0, 255, 255
DOT3.Outline.SetNoOutline
DOT3.Name = "DOT3"
Dim DOT4 As Shape
Set DOT4 = ActivePage.ActiveLayer.CreateEllipse2(DOCUMENTSIZEX - 0.225, DOCUMENTSIZEY - 0.225, 0.125, 0.125)
DOT4.Fill.UniformColor.RGBAssign 0, 255, 255
DOT4.Outline.SetNoOutline
DOT4.Name = "DOT4"
'check the size of the document, if bigger than 96 inches it will add 2 more dots
If DOCUMENTSIZEX > 96 Then
Dim DOT5 As Shape
Set DOT5 = ActivePage.ActiveLayer.CreateEllipse2(DOCUMENTSIZEX / 2, DOCUMENTSIZEY - 0.225, 0.125, 0.125)
DOT5.Fill.UniformColor.RGBAssign 0, 255, 255
DOT5.Outline.SetNoOutline
DOT5.Name = "DOT5"
Dim DOT6 As Shape
Set DOT6 = ActivePage.ActiveLayer.CreateEllipse2(DOCUMENTSIZEX / 2, 0.225, 0.125, 0.125)
DOT6.Fill.UniformColor.RGBAssign 0, 255, 255
DOT6.Outline.SetNoOutline
DOT6.Name = "DOT6"
End If
`
I've tried the duplicate function "set dot7=dot5.duplicate" type thing which is only doing it once and I'd like to have it make a variable about of dots (only and only if the document is over 96" by multiple of 48). ie: if the document is 144" there would be one every 48"
I've added a portion of the code bellow and I'm mostly looking for a hint at what function I should look at in order to play arround with it and learn it.
thanks

Why AP values decrease after k-means++?

I used k-means++ to size the anchor boxes to give more AP.
As a result, the AP is lower than before applying k-means++.
Please let me know if there is any cause for this.
Thank you in advance.
before: anchor box (10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326)
detections_count = 13032, unique_truth_count = 2164
class_id = 0, name = Can, ap = 90.15% (TP = 240, FP = 25)
class_id = 1, name = Bottle, ap = 96.47% (TP = 898, FP = 60)
class_id = 2, name = Box, ap = 74.26% (TP = 50, FP = 21)
class_id = 3, name = Cigarette, ap = 59.19% (TP = 506, FP = 323) for conf_thresh = 0.25, precision = 0.80, recall = 0.78, F1-score = 0.79
for conf_thresh = 0.25, TP = 1694, FP = 429, FN = 470, average IoU = 66.07 % IoU threshold = 50 %, used Area-Under-Curve for each unique Recall
mean average precision (mAP#0.50) = 0.800176, or 80.02 %
after:anchor box (42, 68, 114, 80, 72,159, 187,149, 128,312, 277,330)
detections_count = 3695, unique_truth_count = 2164
class_id = 0, name = Can, ap = 91.05% (TP = 246, FP = 11)
class_id = 1, name = Bottle, ap = 93.78% (TP = 862, FP = 46)
class_id = 2, name = Box, ap = 76.94% (TP = 42, FP = 11)
class_id = 3, name = Cigarette, ap = 37.37% (TP = 184, FP = 57) for conf_thresh = 0.25, precision = 0.91, recall = 0.62, F1-score = 0.74
for conf_thresh = 0.25, TP = 1334, FP = 125, FN = 830, average IoU = 78.62 % IoU threshold = 50 %, used Area-Under-Curve for each unique Recall
mean average precision (mAP#0.50) = 0.747871, or 74.79 %

Converting bytes to Extended Precision Floating Point not accurate enough

I have some legacy files that need mined for data. The files were created by Lotus123 Release 4 for DOS. I'm trying to read the files faster by parsing the bytes rather than using Lotus to open the files. I have value records of 10 bytes each. They are 80 bit Extended Precision Floating Point.
Debug.Print(ConvertLongDouble80(New Byte() {0, 0, 0, 0, 0, 0, 0, 128, 255, 191})) ' Value = -1
Debug.Print(ConvertLongDouble80(New Byte() {205, 204, 204, 204, 204, 204, 204, 204, 251, 191})) ' Value = -0.1
Debug.Print(ConvertLongDouble80(New Byte() {10, 215, 163, 112, 61, 10, 215, 163, 248, 191})) ' Value = -0.01
Debug.Print(ConvertLongDouble80(New Byte() {59, 223, 79, 141, 151, 110, 18, 131, 245, 191})) ' Value = -0.001
Debug.Print(ConvertLongDouble80(New Byte() {44, 101, 25, 226, 88, 23, 183, 209, 241, 191})) ' Value = -0.0001
Debug.Print(ConvertLongDouble80(New Byte() {35, 132, 71, 27, 71, 172, 197, 167, 238, 191})) ' Value = -0.00001
Debug.Print(ConvertLongDouble80(New Byte() {182, 105, 108, 175, 5, 189, 55, 134, 235, 191})) ' Value = -0.000001
Debug.Print(ConvertLongDouble80(New Byte() {0, 0, 0, 0, 0, 0, 0, 128, 255, 63})) ' Value = 1
Debug.Print(ConvertLongDouble80(New Byte() {205, 204, 204, 204, 204, 204, 204, 204, 251, 63})) ' Value = 0.1
Debug.Print(ConvertLongDouble80(New Byte() {10, 215, 163, 112, 61, 10, 215, 163, 248, 63})) ' Value = 0.01
Debug.Print(ConvertLongDouble80(New Byte() {59, 223, 79, 141, 151, 110, 18, 131, 245, 63})) ' Value = 0.001
Debug.Print(ConvertLongDouble80(New Byte() {44, 101, 25, 226, 88, 23, 183, 209, 241, 63})) ' Value = 0.0001
Debug.Print(ConvertLongDouble80(New Byte() {35, 132, 71, 27, 71, 172, 197, 167, 238, 63})) ' Value = 0.00001
Debug.Print(ConvertLongDouble80(New Byte() {182, 105, 108, 175, 5, 189, 55, 134, 235, 63})) ' Value = 0.000001
Debug.Print(ConvertLongDouble80(New Byte() {188, 66, 122, 229, 213, 148, 191, 214, 231, 63})) ' Value = 0.0000001
Function ConvertLongDouble80(ByVal TenBytes As Byte()) As Double
'https://en.wikipedia.org/wiki/Extended_precision
'get 15 bit exponent; remove the first bit which is the negative sign
Dim arrExp As Byte() = New Byte() {TenBytes(8), (TenBytes(9) << 1) >> 1}
Dim Expo As UInt16 = BitConverter.ToUInt16(arrExp, 0)
'flag bits
Dim Bit63 As UInt16 = Convert.ToUInt16(TenBytes(7) >> 7)
Dim Bits63_62 As UInt16 = Convert.ToUInt16(TenBytes(7) >> 6)
'fractional values
TenBytes(7) = (TenBytes(7) << 1) >> 1
Dim Bits62_0 As UInt64 = BitConverter.ToUInt64(TenBytes, 0)
TenBytes(7) = (TenBytes(7) << 2) >> 2
Dim Bits61_0 As UInt64 = BitConverter.ToUInt64(TenBytes, 0)
If Bit63 = 0 and Bits62_0 = 0 Then
Return 0
Else
Const ExponentBias As Integer = 16383
Dim isNegative As Boolean = (TenBytes(9) And (1 << 7)) <> 0
Dim NegVal As Int16 = IIf(isNegative, -1, 1)
Dim expVal As Double = Math.Pow(2, Expo - ExponentBias)
Dim LBits62 As Int16 = Len(CStr(Bits62_0))
Dim mantissa As Double = CDbl("1." & CStr(Bits62_0))
Dim result As Double = NegVal * expVal * mantissa
Return result
End If
End Function
Value -1 converts to -1
Value -0.1 converts to -0.09708764513821
Value -0.01 converts to -0.00983011263306
Value -0.001 converts to -0.00119273528211
Value -0.0001 converts to -0.00009697388128
Value -0.00001 converts to -0.00000981589215
Value -0.000001 converts to -0.00000138095333
Value 1 converts to 1
Value 0.1 converts to 0.09708764513821
Value 0.01 converts to 0.00983011263306
Value 0.001 converts to 0.00119273528211
Value 0.0001 converts to 0.00009697388128
Value 0.00001 converts to 0.00000981589215
Value 0.000001 converts to 0.00000138095333
Value 0.0000001 converts to 0.00000009686278
What am I doing wrong. My values are not close enough. How do I fix this?
The problem is that you treat the fractional part, which represents the fraction of a binary number as a whole number. I changed your function by interpreting the bits 0 to 63 as an integer number which is 263 too big. It's too big by 263 because bit 63 should be bit 0 (instead of 10110101..., we should have 1.0110101..., i.e., the leading 1 has to move 63 positions to the right). I then subtract 63 the the exponent to take this into account. I didn't check the logic related to the flags handling.
Function ConvertLongDouble80(ByVal TenBytes As Byte()) As Double
'https://en.wikipedia.org/wiki/Extended_precision
' 80-bit extended precision format
' --------------------------------
' bit 0 to 63 fraction, bytes 0 to 7
' bit 64 to 78 exponent (bias 16383, bytes 8 to 9)
' bit 79 sign /
'get 15 bit exponent; remove the first bit which is the negative sign
Dim arrExp As Byte() = New Byte() {TenBytes(8), (TenBytes(9) << 1) >> 1}
Dim Expo As UInt16 = BitConverter.ToUInt16(arrExp, 0)
'flag bits
Dim Bit63 As UInt16 = Convert.ToUInt16(TenBytes(7) >> 7)
Dim Bits63_62 As UInt16 = Convert.ToUInt16(TenBytes(7) >> 6)
Dim fraction = BitConverter.ToUInt64(TenBytes, 0) ' 2 ^ 63 too big
If Bit63 = 0 And fraction = 0 Then
Return 0
Else
Const ExponentBias As Integer = 16383
Dim isNegative As Boolean = (TenBytes(9) And (1 << 7)) <> 0
Dim sign = If(isNegative, -1, 1)
Dim expVal As Double = Math.Pow(2, Expo - ExponentBias - 63)
Dim result As Double = sign * expVal * fraction
Return result
End If
End Function

How do I convert longitude and latitude to GPS Exif byte array

I am trying to put latitude = 8°50'34.46" and longitude = 125° 9'50.82" into the exif file of an image. i'm using vb.net.
I'm not having problem converting the degrees and minutes into bytes because it is a whole number but when i convert the seconds (34.46") which has decimal values into bytes. it gives different result like 0.9856.
Please help me guys how to convert numbers with decimal values into bytes.
here the code:
Private Shared Function intToByteArray(ByVal int As Int32) As Byte()
' a necessary wrapper because of the cast to Int32
Return BitConverter.GetBytes(int)
End Function
Private Shared Function doubleToByteArray(ByVal dbl As Double) As Byte()
Return BitConverter.GetBytes(Convert.ToDecimal(dbl))
End Function
Private Shared Function doubleCoordinateToRationalByteArray(ByVal doubleVal As Double) As Byte()
Dim temp As Double
temp = Math.Abs(doubleVal)
Dim degrees = Math.Truncate(temp)
temp = (temp - degrees) * 60
Dim minutes = Math.Truncate(temp)
temp = (temp - minutes) * 60
Dim seconds = temp
Dim result(24) As Byte
Array.Copy(intToByteArray(degrees), 0, result, 0, 4)
Array.Copy(intToByteArray(1), 0, result, 4, 4)
Array.Copy(intToByteArray(minutes), 0, result, 8, 4)
Array.Copy(intToByteArray(1), 0, result, 12, 4)
Array.Copy(doubleToByteArray(seconds), 0, result, 16, 4)
Array.Copy(intToByteArray(1), 0, result, 20, 4)
Return result
End Function
According to this specification, longitude and latitude are encoded as a
PropertyTagTypeRational
Specifies that the value data member is an array of pairs of unsigned long integers. Each pair represents a fraction; the first integer is the numerator and the second integer is the denominator.
The encoded layout should be (24 bytes total)
Byte Offset Length Encoding Field
0 4 uint Degrees Nominator
4 4 uint Degrees Denominator
8 4 uint Minutes Nominator
12 4 uint Minutes Denominator
16 4 uint Seconds Nominator
20 4 uint Seconds Denominator
Given that your input is using whole degrees and minutes and not fractions, your encoding for those two will work fine, by using the value of 1 as the denominator.
For the seconds, that you have as a floating point value, this is not the case. You will have to encode it as a rational, using a nominator and denominator part.
I am not sure what the precision is that you would like to have, but given your example of 34.46 seconds, it would seem that multiplying by 1000 and using 1000 for the denominator would be more than good enough:
Dim secondsNominator = Math.Truncate(1000 * seconds)
Dim secondsDenoninator = 1000
Then your encoding function becomes:
Private Shared Function doubleCoordinateToRationalByteArray(ByVal doubleVal As Double) As Byte()
Dim temp As Double
temp = Math.Abs(doubleVal)
Dim degrees = Math.Truncate(temp)
temp = (temp - degrees) * 60
Dim minutes = Math.Truncate(temp)
temp = (temp - minutes) * 60
Dim secondsNominator = Math.Truncate(1000 * temp)
Dim secondsDenoninator = 1000
Dim result(24) As Byte
' Degrees (nominator, and 1 for denominator)
Array.Copy(intToByteArray(degrees), 0, result, 0, 4)
Array.Copy(intToByteArray(1), 0, result, 4, 4)
' Minutes (nominator, and 1 for denominator)
Array.Copy(intToByteArray(minutes), 0, result, 8, 4)
Array.Copy(intToByteArray(1), 0, result, 12, 4)
' Seconds (1000 for denominator: ms resolution)
Array.Copy(intToByteArray(secondsNominator), 0, result, 16, 4)
Array.Copy(intToByteArray(secondsDenominator), 0, result, 20, 4)
Return result
End Function
The GPS latitude and longitude for exif data are "rational" data type, or two 32-bit integers. To represent 34.46, for example, you could use the two 32-bit integers 3,446 (numerator) and 100 (denominator), or 344,600 and 10,000. For the integer value of degrees, for example you could use 8 with a denominator of 1.
You can get the exif specification here.

Shifting Byte Array

If have an array of Bytes in visual basic:
Dim data() As Byte = {0, 128, 0, 4, 9, 9, 32, 0, 0, 0, 0, 0, 0, 0, 0}
Is there a quick and easy way to insert two data values to the front of this array, and knock off the last two values?
Dim data() As Byte = {128, 128, 0, 128, 0, 4, 9, 9, 32, 0, 0, 0, 0, 0, 0}
Yes. First you need to move all of the existing values up 2 places in your array. Doing so will overwrite the last 2 values. You'll then want to set the first two values of your array.
'Move data up 2 spots. This needs to be done in reverse order so we don't lose any data
For i as Integer = data.Length - 1 To 2 Step -1
data(i) = data(i - 2)
End
'Assign the new values
data(0) = 128
data(1) = 128
You could load the bytes into a vb.net stack with a loop then use the stack.push then rewrite the data back