Convert ushort[] into byte[] and back - c#

I have a ushort array that needs converting into a byte array to be transferred over a network.
Once it gets to its destination, I need then reconvert it back into the same ushort array it was to being with.
Ushort Array
Is an array that is of Length 217,088 (1D array of broken down image 512 by 424). It's stored as 16-bit unsigned integers. Each element is 2 bytes.
Byte Array
It needs to be converted into a byte array for network purposes. As each ushort element is worth 2 bytes, I assume the byte array Length needs to be 217,088 * 2?
In terms of converting, and then 'unconverting' correctly, I am unsure on how to do that.
This is for a Unity3D project that is in C#. Could someone point me in the right direction?
Thanks.

You're looking for BlockCopy:
https://msdn.microsoft.com/en-us/library/system.buffer.blockcopy(v=vs.110).aspx
and yes, short as well as ushort is 2 bytes long; and that's why corresponding byte array should be two times longer than initial short one.
Direct (byte to short):
byte[] source = new byte[] { 5, 6 };
short[] target = new short[source.Length / 2];
Buffer.BlockCopy(source, 0, target, 0, source.Length);
Reverse:
short[] source = new short[] {7, 8};
byte[] target = new byte[source.Length * 2];
Buffer.BlockCopy(source, 0, target, 0, source.Length * 2);
using offsets (the second and the fourth parameters of Buffer.BlockCopy) you can have 1D array being broken down (as you've put it):
// it's unclear for me what is the "broken down 1d array", so
// let it be an array of array (say 512 lines, each of 424 items)
ushort[][] image = ...;
// data - sum up all the lengths (512 * 424) and * 2 (bytes)
byte[] data = new byte[image.Sum(line => line.Length) * 2];
int offset = 0;
for (int i = 0; i < image.Length; ++i) {
int count = image[i].Length * 2;
Buffer.BlockCopy(image[i], offset, data, offset, count);
offset += count;
}

Related

Sending a byte array to a serial port using certain formatting

Bit of a weird one here but I'm trying to write a control program for a monitor that uses a serial RS232 port to receive commands in hexadecimal, 0xFF, notation i.e. 0x00.
Problem I have is that I can't seem to find a way of taking a user input, which is a decimal value like 55, and converting it into its byte, hexadecimal, form with the above mentioned format. Using the Convert method that Visual studio has built in gives me the correct value i need but without the required 0x at the beginning.
I'm new to using bytes and byte arrays in C# so forgive me if I've missed out on a simple formatting method that will solve it.
Below is a string to byte array method that I found on here and its helpful but gives me the wrong format for the bytes.
private static byte[] StringToByteArray(String hex)
{
int NumberChars = hex.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
bytes[i / 2] = Convert.ToByte(hex.Substring(i+2, 2), 16);
return bytes;
}
You might just want to convert a hex-string to bytes. See How do you convert a byte array to a hexadecimal string, and vice versa?
simple conversion of one single "hex-string-byte" and send the byte:
MonPort.Write(Convert.ToByte("A6"), 0,1);
Convert content of your textbox to a binary array and send it:
public static byte[] StringToByteArray(String hex)
{
int NumberChars = hex.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
return bytes;
}
public void SendData()
{
byte[] sendBytes = StringToByteArray(YourSendBytesTextbox.Text);
MonPort.Write(sendBytes, 0, sendBytes.Length);
}
See following :
string input = "abcdefghijk";
byte[] data = string.Join(",",input.AsEnumerable()
.Select(x => "0x" + ((byte)x).ToString("X2")))
.Select(x => (byte)x).ToArray();
string str = Encoding.UTF8.GetString(data);

Equivalent C code in C#. (uint8_t *) cast?

I am trying to convert these C piece of code into C#. But I've stumble in some parts that I don't understand exactly what is happening, so I am unable to translate it.
void foo(uint64_t *output, uint64_t *input, uint32_t Length){
uint64_t st[25];
memcpy(st, input, Length);
((uint8_t *)st)[Length] = 0x01;
memset(((uint8_t *)st) + Length + 1, 0x00, 128 - Length - 1);
for(int i = 16; i < 25; ++i) st[i] = 0x00UL;
// Last bit of padding
st[16] = 0x8000000000000000UL;
bar(st);
memcpy(output, st, 200);
}
More specifically in the ((uint8_t *)st)[Length] = 0x01; part. I cannot understand the cast/pointer in this line. Why is the * there for? If somebody could explain what is happening, I would be grateful.
What I got so far in C#:
private void foo(ref ulong[] output, ref ulong[] input, uint Length)
{
ulong[] st = new ulong[25];
//memcpy(st, input, Length);
Buffer.BlockCopy(input, 0, st, 0, (int)Length);
// Help in these line please:
//((uint8_t *)st)[Length] = 0x01;
// Still don't know what to do here too:
//memset(((byte)st) + Length + 1, 0x00, 128 - Length - 1);
for (int i = 16; i < 25; ++i)
{
st[i] = 0x00U;
}
// Last bit of padding
st[16] = 0x8000000000000000U;
bar(st);
//memcpy(output, st, 200);
Buffer.BlockCopy(st, 0, output, 0, 200);
}
Thank you.
What your function does is rather primitive memory manipulation:
void foo(uint64_t *output, uint64_t *input, uint32_t Length)
{
uint64_t st[25];
Your function takes a pointer to 16 elements of uint64_t and prepares a local buffer (st) to store a copy of them.
memcpy(st, input, Length);
((uint8_t *)st)[Length] = 0x01;
memset(((uint8_t *)st) + Length + 1, 0x00, 128 - Length - 1);
Make a copy of the input array into st but insert a byte with value 1 at an offset of Length bytes from the start.
for(int i = 16; i < 25; ++i) st[i] = 0x00UL;
The remaining 8 elements of the buffer are cleared to 0. Writing st[16] is pointless as it will be changed again by the next line...
// Last bit of padding
st[16] = 0x8000000000000000UL;
Now we have 16*8 bytes from the input buffer, 1 extra byte with value 1 inserted somewhere and the remaining elements are filled with 1<<63 and lots of 0 bytes.
bar(st);
memcpy(output, st, 200);
}
Do something we have no clue about and copy the resulting 25 elements into the output buffer

Replacing bits in a Byte Array C#

I want to open a Bitmap File in C# as an array of bytes, and replace certain bytes within that array, and rewrite the Byte array back to disk as a bitmap again.
My current approach is to read into a byte[] array, then convert that array to a list to begin editing individual bytes.
originalBytes = File.ReadAllBytes(path);
List<byte> listBytes = new List<Byte>(originalBytes);
How does one go about replacing every nth byte in the array with a user configured/different byte each time and rewriting back to file?
no need in List<byte>
replaces every n-th byte with customByte
var n = 5;
byte customByte = 0xFF;
var bytes = File.ReadAllBytes(path);
for (var i = 0; i < bytes.Length; i++)
{
if (i%n == 0)
{
bytes[i] = customByte;
}
}
File.WriteAllBytes(path, bytes);
Assuming that you want to replace every nth byte with the same new byte, you could do something like this (shown for every 3rd byte):
int n = 3;
byte newValue = 0xFF;
for (int i = n; i < listBytes.Count; i += n)
{
listBytes[i] = newValue;
}
File.WriteAllBytes(path, listBytes.ToArray());
Of course, you could also do this with a fancy LINQ expression which would be harder to read i guess.
Technically, you can implement something like this:
// ReadAllBytes returns byte[] array, we have no need in List<byte>
byte[] data = File.ReadAllBytes(path);
// starting from 0 - int i = 0 - will ruin BMP header which we must spare
// if n is small, you may want to start from 2 * n, 3 * n etc.
// or from some fixed offset
for (int i = n; i < data.Length; i += n)
data[i] = yourValue;
File.WriteAllBytes(path, data);
Please notice, that Bitmap file has a header
https://en.wikipedia.org/wiki/BMP_file_format
that's why I've started loop from n, not from 0

How to convert an array of signed bytes to float?

I just got confused about how to convert an array of 4 signed bytes to a float number.
I just know for an array of unsigned bytes bts, probably I can use this function
BitConverter.ToSingle(bts, 0);
However, it looks like BitConverter.ToSingle only accepts byte array instead of sbyte array.
Could somebody give me some ideas please?
Thanks!
Maybe this:
float num = 0;
for (int i = 0; i < sbytesArr.Length; i++)
{
num = (num | sbytesArr[i]) << i * 4;
}
Float value = 5000.1234;
//
// Invoke BitConverter.GetBytes to convert double to bytes.
//
byte[] array = BitConverter.GetBytes(value);
foreach (byte element in array)
{
Console.WriteLine(element);
}
//
// You can convert the bytes back to a double.
//
Float result = BitConverter.Tofloat(array, 0);
Console.WriteLine(result);
Assuming that your signed bytes are in an array named sbts you can first of all convert to an unsigned byte array, and then use BitConverter.ToSingle().
byte[] bts = new byte[sbts.Length];
Buffer.BlockCopy(sbts, 0, bts, 0, sbts.Length);
float f = BitConverter.ToSingle(bts, 0);
It is a little known fact that byte and sbyte are interchangeable at the CLR level:
sbyte[] a = new sbyte[1];
byte[] b = (byte[])(object)a;
This code actually works at runtime. So can pass in the array that you have.
BitConverter.ToSingle((byte[])(object)bts, 0);
Call GetFloatValue method passing una array of four sbyte as parameter
public float GetFloatValue(sbyte[] data)
{
return bytesToFloat(data[0], data[1], data[2], data[3]);
}
private static float bytesToFloat(sbyte b0, sbyte b1, sbyte b2, sbyte b3)
{
int mantissa = (byte)b0 + ((byte)b1 << 8) + ((byte)b2 << 16);
return (float)(mantissa * Math.Pow(10, b3));
}

Fast way to swap bytes in array from big endian to little endian in C#

I'm reading from a binary stream which is big-endian. The BitConverter class does this automatically. Unfortunately, the floating point conversion I need is not the same as BitConverter.ToSingle(byte[]) so I have my own routine from a co-worker. But the input byte[] needs to be in little-endian. Does anyone have a fast way to convert endianness of a byte[] array. Sure, I could swap each byte but there has got to be a trick. Thanks.
Here is a fast method for changing endianess for singles in a byte array:
public static unsafe void SwapSingles(byte[] data) {
int cnt = data.Length / 4;
fixed (byte* d = data) {
byte* p = d;
while (cnt-- > 0) {
byte a = *p;
p++;
byte b = *p;
*p = *(p + 1);
p++;
*p = b;
p++;
*(p - 3) = *p;
*p = a;
p++;
}
}
}
I use LINQ:
var bytes = new byte[] {0, 0, 0, 1};
var littleEndianBytes = bytes.Reverse().ToArray();
Single x = BitConverter.ToSingle(littleEndianBytes, 0);
You can also .Skip() and .Take() to your heart's content, or else use an index in the BitConverter methods.
What does the routine from your co-worker look like? If it accesses the bytes explicitly, you could change the code (or rather, create a separate method for big-endian data) instead of reversing the bytes.

Categories

Resources