I'm currently reading a file and wanted to be able to convert the array of bytes obtained from the file into a short array.
How would I go about doing this?
Use Buffer.BlockCopy.
Create the short array at half the size of the byte array, and copy the byte data in:
short[] sdata = new short[(int)Math.Ceiling(data.Length / 2)];
Buffer.BlockCopy(data, 0, sdata, 0, data.Length);
It is the fastest method by far.
One possibility is using Enumerable.Select:
byte[] bytes;
var shorts = bytes.Select(b => (short)b).ToArray();
Another is to use Array.ConvertAll:
byte[] bytes;
var shorts = Array.ConvertAll(bytes, b => (short)b);
A shorthard is a compound of two bytes. If you are writing all the shorts to the file as true shorts then those conversions are wrong. You must use two bytes to get the true short value, using something like:
short s = (short)(bytes[0] | (bytes[1] << 8))
short value = BitConverter.ToInt16(bytes, index);
I dont know, but I would have expected another aproach to this question.
When converting a sequence of bytes into a sequence of shorts, i would have it done like #Peter did
short s = (short)(bytes[0] | (bytes[1] << 8))
or
short s = (short)((bytes[0] << 8) | bytes[1])
depending on endianess of the bytes in the file.
But the OP didnt mention his usage of the shorts or the definition of the shorts in the file.
In his case it would make no sense to convert the byte array to a short array, because it would take twice as much memory, and i doubt if a byte would be needed to be converted to a short when used elsewhere.
short[] wordArray = Array.ConvertAll(byteArray, (b) => (short)b);
byte[] bytes;
var shorts = bytes.Select(n => System.Convert.ToInt16(n)).ToArray();
Related
I'm trying to parse a JPEG file. This page says that the format is the following :
0xFF+Marker Number(1 byte)+Data size(2 bytes)+Data(n bytes)
So, when I encounter a 0xFF, I read the data like this (s is the JPEG file stream) :
int marker, size;
byte[] data;
//marker number (1 byte)
marker = s.ReadByte();
//size (2 bytes)
byte[] b = new byte[2];
s.Read(b, 0, 2);
size = BitConverter.ToInt16(b, 0);
Problem is, size's value after that is -7937 (which causes the next lines to raise an exception because I try to allow a -7937-long byte[]). b[0] == 255 and b[1] == 224.
I suspect I don't use BitConverter.ToInt16 properly, but I can't find what I did wrong.
The BitConverter doc page says that "The order of bytes in the array must reflect the endianness of the computer system's architecture", but when I do this :
byte a = b[0]; b[0] = b[1]; b[1] = a;
size = BitConverter.ToInt16(b, 0);
...I get size == -32 which is not really better.
What's the problem ?
Integers are stored in Big Endian order in JPEG. If you are on a little endian system (e.g. Intel) you need to reverse the order of the bytes in the length field. Length fields are unsigned.
The data in question was an unsigned int. Using the uint type and BitConverter.ToUInt16 fixed it.
I need to combine two Bytes into one int value.
I receive from my camera a 16bit Image were two successive bytes have the intensity value of one pixel. My goal is to combine these two bytes into one "int" vale.
I manage to do this using the following code:
for (int i = 0; i < VectorLength * 2; i = i + 2)
{
NewImageVector[ImagePointer] = ((int)(buffer.Array[i + 1]) << 8) | ((int)(buffer.Array[i]));
ImagePointer++;
}
My image is 1280*960 so VectorLength==1228800 and the incomming buffer size is 2*1228800=2457600 elements...
Is there any way that I can speed this up?
Maybe there is another way so I don't need to use a for-loop.
Thank you
You could use the equivalent to the union of c. Im not sure if faster, but more elegant:
[StructLayout(LayoutKind.Explicit)]
struct byte_array
{
[FieldOffset(0)]
public byte byte1;
[FieldOffset(1)]
public byte byte2;
[FieldOffset(0)]
public short int0;
}
use it like this:
byte_array ba = new byte_array();
//insert the two bytes
ba.byte1 = (byte)(buffer.Array[i]);
ba.byte2 = (byte)(buffer.Array[i + 1]);
//get the integer
NewImageVector[ImagePointer] = ba.int1;
You can fill your two bytes and use the int. To find the faster way take the StopWatch-Class and compare the two ways like this:
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
//The code
stopWatch.Stop();
MessageBox.Show(stopWatch.ElapsedTicks.ToString()); //Or milliseconds ,...
Assuming you can (re-)define NewImageVector as a short[], and every two consecutive bytes in Buffer should be transformed into a short (which basically what you're doing now, only you cast to an int afterwards), you can use Buffer.BlockCopy to do it for you.
As the documentation tells, you Buffer.BlockCopy copies bytes from one array to another, so in order to copy your bytes in buffer you need to do the following:
Buffer.BlockCopy(Buffer, 0, NewImageVector, 0, [NumberOfExpectedShorts] * 2)
This tells BlockCopy that you want to start copying bytes from Buffer, starting at index 0, to NewImageVector starting at index 0, and you want to copy [NumberOfExpectedShorts] * 2 bytes (since every short is two bytes long).
No loops, but it does depend on the ability of using a short[] array instead of an int[] array (and indeed, on using an array to begin with).
Note that this also requires the bytes in Buffer to be in little-endian order (i.e. Buffer[index] contains the low byte, buffer[index + 1] the high byte).
You can achieve a small performance increase by using unsafe pointers to iterate the arrays. The following code assumes that source is the input byte array (buffer.Array in your case). It also assumes that source has an even number of elements. In production code you would obviously have to check these things.
int[] output = new int[source.Length / 2];
fixed (byte* pSource = source)
fixed (int* pDestination = output)
{
byte* sourceIterator = pSource;
int* destIterator = pDestination;
for (int i = 0; i < output.Length; i++)
{
(*destIterator) = ((*sourceIterator) | (*(sourceIterator + 1) << 8));
destIterator++;
sourceIterator += 2;
}
}
return output;
I want to convert a given byte array to an int. Then I want to reverse the process. That is I want to get back the original byte array from that int.
I thought something like this would have worked:
byte[] myBytes = { 0, 0, 0, 32 };
if (BitConverter.IsLittleEndian)
Array.Reverse(myBytes);
int i = BitConverter.ToInt32(myBytes, 0);
Console.WriteLine("int: {0}", i); // Output: 32
byte[] newBytes = BitConverter.GetBytes(i);
Console.WriteLine("byte array: " + BitConverter.ToString(newBytes));
// Outputs: 20-00-00-00
So it doesn't give me back the original byte array. What am I doing wrong?
You're reversing the bytes with Array.Reverse for no obvious reason - given that you're using BitConverter for both conversion to an int and from an int, you don't need the Array.Reverse call at all.
If you want to treat the byte array as big-endian and you're faced with a little-endian BitConverter, you have to reverse the array in both cases, not just one. Basically you should regard BitConverter as providing a reversible conversion, but it may not be the exact conversion you want.
You might want to use my EndianBitConverter in my MiscUtil project if you want to specify endianness for this kind of conversion.
I have a file containing some data (for example, "00927E2B112DB958......"). This data is a representation of bytes in ASCII form. The bytes are 8 bit, so 2 ASCII chars map to each byte that needs to go into the final output buffer array.
What is the best way to do this?
EDIT: What I am trying to do is go from a string that looks like "00DFFF" to a byte array of {0x00, 0xDF, 0xFF}, for example. I guess this wasn't clear.
Thanks!
private ICollection<byte> HexString2Ascii(string hexString)
{
var bytes = new List<byte>(hexString.Length / 2);
for (int i = 0; i <= hexString.Length - 2; i += 2)
bytes.Add(byte.Parse(hexString.Substring(i, 2), System.Globalization.NumberStyles.HexNumber));
return bytes;
}
I'm looking for a smooth/fast way to retrieve every nth short in a byte array and copy it to a new array.
l = lowerbyte
u = upperbyte
My data is of the following form:
byte[] bytes= {a0l, a0u, b0l, b0u, c0l, ..., n0l, n0l, a1l, a1u, b1l, ..., nXl, nXu}
What I need is to get get n byte arrays of length X (e.g., a[0..X], b[0..X], ... or M[a..n][0..X])
I was thinking of the following two steps:
convert values to short (=> short[] shorts= { a0, b0, c0, ... n0, a1, .. nX})
by using something like
short[] shorts= new short[(int)(Math.Ceiling(bytes.Length / 2.0)];
Buffer.BlockCopy(bytes, 0, shorts, 0, bytes.Length);
retrieve every second value from shorts
I'm looking for some fast code here... something like blockcopy with skip
I am completely aware that I could use a loop - but maybe there's a better
solution to it as I need to do this task for 80MB/s...
convert it back to byte arrays (same same - using blockcopy)
byte[] arrayX = new byte[shorts.Length * 2];
Buffer.BlockCopy(shorts, 0, arrayX , 0, arrayX .Length);
Thank you so much!
I think you might as just well copy the bytes directly to the new byte array, having calculated the correct offset for each short.
Converting it all to a separate short array and back to a byte array is a waste of time IMO.