single byte array to 2d byte array in C#? - c#

I have a byte array of
byte[] d = new byte[64];
now i want to convert it to a 2d byte array like ..
byte[,] data = new byte[8,8];
can any one help me on this

This could be one of method.
byte[] d = new byte[64];
byte[,] data = new byte[8,8];
int row = 0;
int column = 0;
for(i=0; i < d.Length; i++)
{
row = i%8;
column = i/8;
data [row, column] = d[i];
}

You can use the Buffer.BlockCopy Method:
byte[] d = new byte[64];
byte[,] data = new byte[8,8];
Buffer.BlockCopy(d, 0, data, 0, 64);

How about something like
byte[] d = new byte[64];
for (byte i = 0; i < d.Length; i++)
d[i] = i;
byte[,] data = new byte[8, 8];
Enumerable.Range(0, 8).ToList().
ForEach(i => Enumerable.Range(0, 8).ToList().
ForEach(j => data[i, j] = d[i * 8 + j]));

Related

Get frequency spectrum lines of a .wav file C#

I want to display the frequency spectrum of a .wav file.
I don’t know how to do it right. I use C# with naudio nuget to handle the audio data.
When I Insert all spec_data points I only have one-col filled with data. (Picture 1)
what it looks like now (Picture 1)
how it should look like at the end
How can I get all spectrum points of the audio file?
var buffer = new byte[fft_size];
int bytes_read = fileStream.Read(buffer, 0, buffer.Length);
int BYTES_PER_POINT = fileStream.WaveFormat.BitsPerSample / 8; //8Bit = 1Byte
short[] values = new short[buffer.Length / BYTES_PER_POINT];
for (int n = 0; n < BYTES_PER_POINT; n++)
{
for (int i = 0; i < bytes_read; i += BYTES_PER_POINT)
{
values[i / BYTES_PER_POINT] = (short)((buffer[i + 1] << 8) | buffer[i + 0]);
}
}
neanalizir_values.AddRange(values);
short[] data = new short[fft_size];
data = neanalizir_values.GetRange(0, fft_size).ToArray();
spec_data.RemoveAt(0);
List<double> new_data = new List<double>();
Complex[] fft_buffer = new Complex[fft_size];
for (int i = 0; i < fft_size; i++)
{
fft_buffer[i].X = (float)(neanalizir_values[i] * FastFourierTransform.HammingWindow(i, fft_size));
fft_buffer[i].Y = 0;
}
FastFourierTransform.FFT(true, (int)Math.Log(fft_size, 2.0), fft_buffer);
for (int i = 0; i < spec_data[spec_data.Count - 1].Count; i++)
{
double val;
val = (double)fft_buffer[i].X + (double)fft_buffer[i].Y;
val = Math.Abs(val);
new_data.Add(val);
}
new_data.Reverse();
spec_data.Insert(spec_data.Count, new_data);
neanalizir_values.RemoveRange(0, fft_size / pixelsPerBuffer);
Bitmap bitmap = new Bitmap(spec_data.Count, spec_data[0].Count, PixelFormat.Format8bppIndexed);
ColorPalette pal = bitmap.Palette;
for (int i = 0; i < 256; i++)
pal.Entries[i] = Color.FromArgb(255, i, i, i);
bitmap.Palette = pal;
BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
byte[] pixels = new byte[bitmapData.Stride * bitmap.Height];
for (int col = 0; col < spec_data.Count; col++)
{
double scaleFactor = 40;
for (int row = 0; row < spec_data[col].Count; row++)
{
int bytePosition = row * bitmapData.Stride + col;
double pixelVal = spec_data[col][row] * scaleFactor;
pixelVal = Math.Max(0, pixelVal);
pixelVal = Math.Min(255, pixelVal);
pixels[bytePosition] = (byte)(pixelVal);
}
}
Marshal.Copy(pixels, 0, bitmapData.Scan0, pixels.Length);
bitmap.UnlockBits(bitmapData);
pictureBox1.Image = bitmap;

Fastest way to accomplish a lookup in C# and how to deal with imprecision of double values?

I have an array of doubles (from a calculation) with 327,680 values. I need to translate those values into a color 8 bit per color image. I need to have a lookup table that holds the double values as an index with a byte[3] array for the RGB values to be used as the visual representation of that temperature value. I have up to 15 ms to do this, no more.
The best idea I have come up with is using a dictionary for the colors. Here is minimal, complete and verifiable code that I have used for testing:
//Create lookup table
Dictionary<int, byte[]> Lookup = new Dictionary<int, byte[]>();
for (int i = 0; i < 1200; i++)
{
byte bValue = (byte)i;
byte[] b = new byte[3] { bValue, bValue, bValue };
Lookup.Add(i, b);
}
//Make proto temp readings
int[] temps = new int[640 * 512];
Random r = new Random();
for (int i = 0; i < 640 * 512; i++)
{
temps[i] = r.Next(0, 255);
}
int size = 640 * 512 * 3;
byte[] imageValues = new byte[size];
for (int i = 0; i < 50; i++)
{
Stopwatch sw = new Stopwatch();
sw.Start();
int index = 0;
foreach (int item in temps)
{
byte[] pixel = new byte[3];
if (Lookup.TryGetValue(item, out pixel))
{
imageValues[index] = pixel[0];
imageValues[index + 1] = pixel[1];
imageValues[index + 2] = pixel[2];
index += 3;
}
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}
First question: When I run this I get times in the 10ms - 14ms range depending on if the lookup table has 1200 items or 256 items. Is there a way to speed this up?
Second question: My actual key values will be temperatures (double) that are the result of a calculation. For some reason doubles seem to have a little imprecision in the least significant digits. I have noticed that a result that should have turned out as 25 ends up being 25.00000000012 or something like that. If I am using doubles as the search value then I have the real risk of looking for 25 when the actual key value is 25.00000000012 or vice versa.
I can truncate or something when I am creating the doubles but I am worried about the time to do that.
What are some good strategies for dealing with the double imprecision issue when using the double as a key?
First question: Is there a way to speed this up?
You have unneccesary memory allocation
byte[] pixel = new byte[3];
You can either leave the empty variable declaration
byte[] pixel;
or use inline variable declaration
if (Lookup.TryGetValue(item, out byte[] pixel))
This change improves performance in my tests.
Like Ivan said move the memory allocation which will save you ~20%
You can save another 50% if you create a lookup array with all possible temperature values (just use the resolution of your sensor).
//Create array lookup table
List<byte[]> array = new List<byte[]>(25500);
for (int i = 0; i < 25500; i++)
{
byte bValue = (byte)i;
byte[] b = new byte[3] { bValue, bValue, bValue };
array.Add(b);
}
This will give you temperatures from 0 to 255.00
Then you can access the desired value like so
int size = 640 * 512 * 3;
byte[] imageValues = new byte[size];
var sw = new Stopwatch();
byte[] pixel = new byte[3];
for (int i = 0; i < 50; i++)
{
sw.Start();
int index = 0;
foreach (var item in temps)
{
pixel = array[item * 100];
imageValues[index] = pixel[0];
imageValues[index + 1] = pixel[1];
imageValues[index + 2] = pixel[2];
index += 3;
}
}
sw.Stop();
Console.WriteLine($"{sw.ElapsedMilliseconds}/{sw.ElapsedMilliseconds / 50.0}");
This will bring you below 5ms for a single lookup
You can solve both problems by replacing the Dictionary<T,byte[]> with a byte[][], and mapping each temperature double to an int index into the color array.
So take the range of temperatures, divide it into N equal partitions, where N is the number of elements in your color array. Take each measured temperature and map it to a partition number, which is also an array index into the colors.
The function to map a temperature to an array index would be something like:
temp => (int)(pixelValues * (temp - minTemp) / (maxTemp - minTemp));
EG
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace ConsoleApp21
{
class Program
{
static void Main(string[] args)
{
double maxTemp = 255;
double minTemp = -35;
int pixelValues = 1200;
byte[][] Lookup = new byte[pixelValues][];
for (int i = 0; i < Lookup.Length; i++)
{
byte bValue = (byte)i;
byte[] b = new byte[3] { bValue, bValue, bValue };
Lookup[i] = b;
}
//Make proto temp readings
double[] temps = new double[640 * 512];
Random r = new Random();
for (int i = 0; i < 640 * 512; i++)
{
temps[i] = r.NextDouble() * maxTemp;
}
int size = 640 * 512 * 3;
byte[] imageValues = new byte[size];
var timings = new List<long>(50);
for (int i = 0; i < 50; i++)
{
Stopwatch sw = new Stopwatch();
sw.Start();
int index = 0;
for (int j = 0; j < temps.Length; j++)
{
var lookupVal = (int)(pixelValues * (temps[j] - minTemp) / (maxTemp - minTemp));
byte[] pixel = Lookup[lookupVal];
imageValues[index] = pixel[0];
imageValues[index + 1] = pixel[1];
imageValues[index + 2] = pixel[2];
index += 3;
}
sw.Stop();
var ms = sw.ElapsedMilliseconds;
timings.Add(ms);
//Console.WriteLine(sw.ElapsedMilliseconds);
}
Console.WriteLine($"Max {timings.Max()} Avg {timings.Average()}");
Console.ReadKey();
}
}
}
outputs
Max 7 Avg 3.2
This may be a bit unfair, as it optimizes your example and not your real problem, but perhaps can be applied. You know you are looking up ints, so just use a jagged array: byte[][]. This averages 0.66ms on my PC versus 5.4ms for your original.
Note: Using a Dictionary<int,(byte,byte,byte)> is about a 4ms with a ValueTuple holding the 3 bytes.
var repeats = 50;
Console.WriteLine();
Console.WriteLine("byte[][3]");
//Create lookup table
var lookups = 1200;
var Lookup = new byte[lookups][];
for (int i = 0; i < lookups; i++) {
byte bValue = (byte)i;
var b = new byte[3] { bValue, bValue, bValue };
Lookup[i] = b;
}
//Make proto temp readings
int[] temps = new int[640 * 512];
Random r = new Random();
for (int i = 0; i < 640 * 512; i++) {
temps[i] = r.Next(0, 255);
}
int size = 640 * 512 * 3;
byte[] imageValues = new byte[size];
long totalMS = 0;
Stopwatch sw = new Stopwatch();
for (int i = 0; i < repeats; i++) {
sw.Restart();
int index = 0;
foreach (int item in temps) {
if (item < lookups) {
var pixel = Lookup[item];
imageValues[index] = pixel[0];
imageValues[index + 1] = pixel[1];
imageValues[index + 2] = pixel[2];
index += 3;
}
}
sw.Stop();
totalMS += sw.ElapsedMilliseconds;
//Console.WriteLine(sw.ElapsedMilliseconds);
}
Console.WriteLine($"Average: {totalMS / (double)repeats} ms");
You can utilize more cores of your machine, assuming that it has more than one. Probably it is a good idea to not utilize all of them, and leave one free for the OS and other apps. The code below uses Parallel.ForEach with a range partitioner, and speeds up the execution from 21 msec to 8 msec in my machine.
ParallelOptions options = new ParallelOptions()
{
MaxDegreeOfParallelism = Math.Max(1, Environment.ProcessorCount - 1)
};
Parallel.ForEach(Partitioner.Create(0, temps.Length), options, range =>
{
for (int item = range.Item1; item < range.Item2; item++)
{
byte[] pixel = new byte[3];
if (Lookup.TryGetValue(item, out pixel))
{
int updatedIndex = Interlocked.Add(ref index, 3);
int localIndex = updatedIndex - 3;
imageValues[localIndex] = pixel[0];
imageValues[localIndex + 1] = pixel[1];
imageValues[localIndex + 2] = pixel[2];
//index += 3;
}
}
});
I made no other changes to your code. I didn't optimize the unnecessary array allocation for example.
Btw multithreading creates issues with thread safety. For this reason I edited my answer to increment index using Interlocked.Add instead of +=. Shared access to the imageValues array is probably safe.

Convert List<Byte> with hex values to decimal

I've a List with either 1, 2 or 4 hex values saved as decimal values. I want to convert them into one decimal number.
Example:
List<Byte> values: 1 and 95 (= 0x01, 0x5F)
I want to convert the list into one decimal number:
0x015F = 351
How can I do that?
var result = 0;
var i = 0;
foreach (var val in values)
{
result = (result << i) + (int)val;
i += 8;
}
Modern, LINQ-based way (old-fashined C-programmers can turn in one's grave):
List<Byte> list = new List<byte>() { 0x01, 0x5F };
var output = list.Select(x => (int)x)
.Reverse()
.Aggregate((x, y) => (int)0x100 * y + (int)x);
With BitConverter class, you can do:
var values = new List<byte> { 0x01, 0x5F, };
byte[] arr = new byte[4];
for (int i = 0; i < values.Count; ++i)
arr[values.Count - 1 - i] = values[i];
int result = BitConverter.ToInt32(arr, 0);
You fill the array arr backwards from the middle, as seen.
If the numbers can be greater (i.e. the List<> can be up to 8 bytes long), use ulong (never negative), for example:
var values = new List<byte> { 0x01, 0x5F, };
byte[] arr = new byte[8];
for (int i = 0; i < values.Count; ++i)
arr[values.Count - 1 - i] = values[i];
ulong result = BitConverter.ToUInt64(arr, 0);
If the List<> can be arbitrarily long, use new BigInteger(arr) (requires csproj reference to System.Numerics.dll assembly).

Is there a way to convert an image into a multidimensional array of 0's and 1's

I want to convert an image into a multidimensional array with 0's and 1's.
The image would be:
I wan't to store this image into an array with 'black' being stored as 1 and 'white' being stored as 0 in the array. The array would be of 8 rows and 6 columns:
int[,] imgArray = new int[8,6];
Is there a way to achieve this in C#?
If you are using a Bitmap, you can populate the array like this:
var bitmap = new Bitmap(#"C:\MyImage.png");
var imgArray = new int[bitmap.Width,bitmap.Height];
var blackArgb = Color.Black.ToArgb();
var whiteArgb = Color.White.ToArgb();
for (var i = 0; i < bitmap.Width; ++i)
{
for (var j = 0; j < bitmap.Height; ++j)
{
var pixelCol = bitmap.GetPixel(i, j);
if (pixelCol.ToArgb() == blackArgb)
{
imgArray[i, j] = 1;
}
else if (pixelCol.ToArgb() == whiteArgb)
{
imgArray[i, j] = 0;
}
else
throw new InvalidOperationException("Pixel color must be black or white");
}
}

Assigning the whole array values to another variable in c#?

I have an array and i want to assign it to another array variable. Here is the code
for (int i = 0; i < length; i++)
{
arr1[i] = Convert.ToByte(Tag_uid.Substring(2 * i, 2), 16);
}
//Create an array to hold the Command Packet
byte[] CommandPacket = new byte[9];
CommandPacket[0] = arr1; //ERROR: cannot convert type byte[] to byte
How can i assign the whole array values to commandpacket[0]?
How about
for (int i = 0; i < length; i++)
{
arr1[i] = Convert.ToByte(Tag_uid.Substring(2 * i, 2), 16);
}
byte[][] CommandPacket = new byte[9][];
CommandPacket[0] = arr1;

Categories