C++ to C# Reading Binary File into a two dimensional float array - c#

I have been assigned to convert a C++ app to C#.
I want to convert the following code in C# where rate_buff is a double[3,9876] two dimensional array.
if ((fread((char*) rate_buff,
(size_t) record_size,
(size_t) record_count,
stream)) == (size_t) record_count)

If I correctly guessed your requirements, this is what you want:
int record_size = 9876;
int record_count = 3;
double[,] rate_buff = new double[record_count, record_size];
// open the file
using (Stream stream = File.OpenRead("some file path"))
{
// create byte buffer for stream reading that is record_size * sizeof(double) in bytes
byte[] buffer = new byte[record_size * sizeof(double)];
for (int i = 0; i < record_count; i++)
{
// read one record
if (stream.Read(buffer, 0, buffer.Length) != buffer.Length)
throw new InvalidDataException();
// copy the doubles out of the byte buffer into the two dimensional array
// note this assumes machine-endian byte order
for (int j = 0; j < record_size; j++)
rate_buff[i, j] = BitConverter.ToDouble(buffer, j * sizeof(double));
}
}
Or more concisely with a BinaryReader:
int record_size = 9876;
int record_count = 3;
double[,] rate_buff = new double[record_count, record_size];
// open the file
using (BinaryReader reader = new BinaryReader(File.OpenRead("some file path")))
{
for (int i = 0; i < record_count; i++)
{
// read the doubles out of the byte buffer into the two dimensional array
// note this assumes machine-endian byte order
for (int j = 0; j < record_size; j++)
rate_buff[i, j] = reader.ReadDouble();
}
}

Related

FFT on an image, using butterfly notation with decimation in spatial domain

I'm trying to implement FFT, using butterfly notation with decimation in spatial domain. I have two separated functions, one to calculate the FFT on 1D array, and the other that applies the first function over columns of the image, puts these columns in a temporary array, and then computes the FFT of rows in the temporary array.
Here is the code
public static Complex[] FFT(Complex[] input)
{
// Get the length of the input array
int n = input.Length;
Complex I = new Complex(0, 1);
// Check if the input has a length of 1
if (n == 1)
{
return input;
}
// Split the input into even and odd elements
Complex[] even = new Complex[n / 2];
Complex[] odd = new Complex[n / 2];
for (int i = 0; i < n; i++)
{
if (i % 2 == 0)
{
even[i / 2] = input[i];
}
else
{
odd[(i - 1) / 2] = input[i];
}
}
// Compute the FFT of the even and odd elements
Complex[] evenFFT = FFT(even);
Complex[] oddFFT = FFT(odd);
// Combine the FFT of the even and odd elements using the butterfly notation
Complex[] output = new Complex[n];
for (int i = 0; i < n / 2; i++)
{
Complex w = Complex.Exp(-2 * I * Math.PI * i / n);
output[i] = evenFFT[i] + w * oddFFT[i];
output[i + n / 2] = evenFFT[i] - w * oddFFT[i];
}
return output;
}
public static Complex[,] FFT2D(Complex[,] input)
{
int N = input.GetLength(0);
int M = input.GetLength(1);
Complex[,] output = new Complex[128, 128];
Complex[,] columnsFFT = new Complex[128, 128];
//Perform FFT over the columns of the input
for(int i = 0; i < M; i++)
{
//Put all the values from i'th column in the tempColumn variable
var tempColumn = new Complex[128];
for(int j = 0; j < N; j++)
{
tempColumn[j] = input[j, i];
}
//Calculate the FFT of i'th column
tempColumn = FFT(tempColumn);
//Assign the column to columnsFFT, after calculating its FFT
for(int z = 0; z < 128; z++)
{
columnsFFT[z, i] = tempColumn[z];
}
}
//Perform FFT over the rows of the columnsFFT
for(int i = 0; i < N; i++)
{
//Put the values from i'th row in tempRow, so we can perform the FFT on its entirety
var tempRow = new Complex[128];
for(int j = 0; j < M; j++)
{
tempRow[j] = columnsFFT[i, j];
}
//Calculate the FFT on tempRow
tempRow = FFT(tempRow);
//Assign the tempRow to the output
for(int z = 0; z < M; z++)
{
if (i == 0)
Console.WriteLine(tempRow[z].Real);
output[i, z] = tempRow[z];
}
}
return output;
}
The problem that i have is that it simply doesn't work, or i think it doesn't, based on the image output i get.
Input image
Output
What is it that i'm doing wrong here?

Convert 2D short array to Base64

I have a 2D short array coming from a C++ library. The array contains the pixels of a 16 bit grayscale image. I am trying to convert it to Base64 to display it. My C# code is as follows:
string picture_path = "~/Picture/CT_Axial_Z/CT_Axial-Z_0111.png";
string path = System.Web.Hosting.HostingEnvironment.MapPath(picture_path);
if (File.Exists(path))
{
IntPtr gpget = Open16BitGrayImage(path);
CImage_DLL gget = (CImage_DLL)Marshal.PtrToStructure(gpget, typeof(CImage_DLL));
int short_size = sizeof(short);
int p_s_cursor = 0;
Array pshImageData = Array.CreateInstance(typeof(short), gget.m_nH, gget.m_nW);
for (int i = 0; i < gget.m_nH; i++)
{
for (int j = 0; j < gget.m_nW; j++)
{
short data = (short)Marshal.PtrToStructure(gget.pshImageData + p_s_cursor, typeof(short));
pshImageData.SetValue(data, i, j);
p_s_cursor += short_size;
}
}
}
I need to convert it to Base64 and display it on a canvas. How should I do it?

How do I use a short[] to a BinaryWriter?

short[] sArray = new short[100];
Many 16-bit data in sArray[100], So I want to write using BinaryWriter class.
But BinaryWriter has write(byte[]) and write(char[]) only.
How to write 16-bit(short[]) data to the file?
You need to write each value individually using the BinaryWriter.Write(short) Method.
Writing:
binaryWriter.Write(sArray.Length); // BinaryWriter.Write(Int32) overload
for (int i = 0; i < sArray.Length; i++)
{
binaryWriter.Write(sArray[i]); // BinaryWriter.Write(Int16) overload
}
Reading:
short[] result = new short[binaryReader.ReadInt32()];
for (int i = 0; i < result.Length; i++)
{
result[i] = binaryReader.ReadInt16();
}

C# DeflateStream vs Java DeflaterOutputStream

In Java, this works as expected:
public static void testwrite(String filename) throws IOException {
FileOutputStream fs = new FileOutputStream(new File(filename), false);
DeflaterOutputStream fs2 = new DeflaterOutputStream(fs, new Deflater(3));
for (int i = 0; i < 50; i++)
for (int j = 0; j < 40; j++)
fs2.write((byte) (i + 0x30));
fs2.close();
}
public static void testread(String filename) throws IOException {
FileInputStream fs = new FileInputStream(new File(filename));
InflaterInputStream fs2 = new InflaterInputStream(fs);
int c, n = 0;
while ((c = fs2.read()) >= 0) {
System.out.print((char) c);
if (n++ % 40 == 0) System.out.println("");
}
fs2.close();
}
The first method compresses 2000 chars in a 106 bytes file, the second reads it ok.
The equivalent in C# would seem to be
private static void testwritecs(String filename) {
FileStream fs = new FileStream(filename, FileMode.OpenOrCreate);
DeflateStream fs2 = new DeflateStream(fs,CompressionMode.Compress,false);
for (int i = 0; i < 50; i++) {
for(int j = 0; j < 40; j++)
fs2.WriteByte((byte)(i+0x30));
}
fs2.Flush();
fs2.Close();
}
But it generates a file of 2636 bytes (larger than the raw data, even though it has low entropy) and is not readable with the Java testread() method above. Any ideas?
Edited: The implementation is indeed not standard/portable (this bit of the docs: "an industry standard algorithm" seems a joke), and very crippled. Among other things, its behaviour changes radically if one writes the bytes one at a time or in blocks (which goes against the concept of a "stream"); if I change the above
for(int j = 0; j < 40; j++)
fs2.WriteByte((byte)(i+0x30));
by
byte[] buf = new byte{}[40;
for(int j = 0; j < 40; j++)
buf[j]=(byte)(i+0x30));
fs2.Write(buf,0,buf.Length);
the compression gets (slightly) reasonable. Shame.
Don't use DeflateStream on anything except plain ASCII text, because it uses
statically defined, hardcoded Huffman trees built for plain ASCII text. See my prior answer for more detail, or just use SharpZipLib and forget it.

How to do RLE (run length encoding) in C# on a byte array?

I am trying to XOR two bitmap files (their byte arrays) to produce a byte array that can be used to change image A into image B or vice versa. I am sending this over the network so I would like to do some basic compression before this happens.
Is there a way to do RLE (run length encoding) in C# (using a built-in, or fast reliable 3rd party library) on a byte array for this purpose?
Notes:
If you are going to suggest an alternative to my approach please keep in mind that the decompression and transformation on the remote machine has to be as quick and efficient as possible.
I usually use GZipStream. It's fast enough and works fine.
class Compressor
{
public static byte[] compress(byte[] buffer)
{
MemoryStream ms = new MemoryStream();
GZipStream zip = new GZipStream(ms, CompressionMode.Compress, true);
zip.Write(buffer, 0, buffer.Length);
zip.Close();
ms.Position = 0;
byte[] compressed = new byte[ms.Length];
ms.Read(compressed, 0, compressed.Length);
byte[] gzBuffer = new byte[compressed.Length + 4];
Buffer.BlockCopy(compressed, 0, gzBuffer, 4, compressed.Length);
Buffer.BlockCopy(BitConverter.GetBytes(buffer.Length), 0, gzBuffer, 0, 4);
return gzBuffer;
}
public static byte[] decompress(byte[] gzBuffer)
{
MemoryStream ms = new MemoryStream();
int msgLength = BitConverter.ToInt32(gzBuffer, 0);
ms.Write(gzBuffer, 4, gzBuffer.Length - 4);
byte[] buffer = new byte[msgLength];
ms.Position = 0;
GZipStream zip = new GZipStream(ms, CompressionMode.Decompress);
zip.Read(buffer, 0, buffer.Length);
return buffer;
}
}
Here are two methods of RLE string packing/unpacking. The best result will be seen on a big text.
public string PackText()
{
try
{
StringBuilder str1 = new StringBuilder(Text);
StringBuilder str = new StringBuilder();
char ch;
int i, k, j;
for (i = 0; i < str1.Length; ) // from 0 to length of unpackedtext
{
ch = str1[i]; // get current char from str1
k = 0; //count the number of repeated characters
if (i == str1.Length - 1) // If this is the last character
{
str.Append(ch);
break; //exit the loop
}
if (str1[i + 1] == ch) //if current symbol is next
{
for (j = i; j < str1.Length; j++) //packing the characters
{
if (str1[j] == ch) //if current symbol is next
{
if (k == 9) break; //the maximum number of characters packed 9,
//or there might be problems with unpacking is not packed numeric characters
k++;
}
else break;
}
i = j;
}
else if ("0123456789".Contains(ch)) //if this digit and it is not repeated, then it must be escaped,
//so when unpacking to understand that this is not the number of repeated characters
{
k = 1;
i++;
}
else i++;
if (k != 0)
str.AppendFormat("{0}{1}", k, ch); //forming packed string
else
str.Append(ch);
}
return str.ToString();
}
catch
{
return null;
}
}
public string UnpackText()
{
try
{
StringBuilder str1 = new StringBuilder(Text);
StringBuilder str = new StringBuilder();
char ch;
char symb = 'a';
int s = 0;
int i, j;
for (i = 0; i < str1.Length; ) // from 0 to length of packedtext
{
ch = str1[i]; // get current char from str1
s = 0;
if ("123456789".Contains(ch)) //if this digit
{
if (i == str1.Length - 1) // If this is the last character
{
symb = ch;
s = 1;
i++;
}
else
{
symb = str1[i + 1]; // get packed symbol
i += 2;
s = Convert.ToInt32(ch) - 48; //get the number of repetitions
}
}
else
{
s = 0;
i++;
}
if (s > 0)
{
for (j = 0; j < s; j++) // write the decompressed symbol
str.Append(symb);
}
else
str.Append(ch);
}
return str.ToString();
}
catch
{
return null;
}
}
You can use the RLE encoding/decoding tool from CodePlex: http://rle.codeplex.com/ ( C# )
You may build as .net dll and its lib

Categories

Resources