hex value not writing to image - c#

I am trying to build a larger tool that will take hex strings from .RTF format and dump them to files. This attempt at writing to file from a memory stream is throwing an exception of type 'System.InvalidOperationException' on ReadTimeout and WriteTimeout. I'm a bit in over my head I believe.
the code that I am working with is:
private void button_Click(object sender, RoutedEventArgs e)
{
// Image hex data
string hexImgData = #"FFD8FFE000104A46494600010200006400640000FFFFD9";
// Call function to Convert the hex data to byte array
byte[] newByte = ToByteArray(hexImgData);
MemoryStream memStream = new MemoryStream(newByte);
// Save the memorystream to file
Image image = Image.FromStream(memStream, false, false);
image.Save(#"C:\img.jpg");
memStream.Close();
image.Dispose();
}
// Function converts hex data into byte array
public static byte[] ToByteArray(String HexString)
{
int NumberChars = HexString.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
{
bytes[i / 2] = Convert.ToByte(HexString.Substring(i, 2), 16);
}
return bytes;
}
}
any help would be appreciated

If all you want to do is take a hex string and dump it to a file, there's no need to overcomplicate it by wrapping it in a MemoryStream and then an Image. Just write the bytes directly to a file:
File.WriteAllBytes(#"C:\img.jpg", newByte);
The reason you get the error is as Ron commented; the hex string you gave does not form a valid JPEG image.

Related

Save audio stream float frames as WAV with C#

I am testing an application in C# that receives a live audio stream and then saves it to a WAV file. The audio stream has these characteristics: frequency or sampling rate: 16000, channels: 1, frame Samples Per Channel: 320, play Delay in Ms: 200. The audio frames come as floats, and I am collecting the float frames and storing them into a Memorystream with Binarywriter. After that, I convert the content of the Memorystream into an array, and that array then is converted to a Float array again. With the float array, I start the process to assemble the WAV file.
I have compared the float frames values received with the ones inside the float array that I am using to build the WAV file and are the same. I am having trouble processing the float array to assemble the WAV file. I am not sure if I am doing the data conversion wrong with the ConvertAndWrite() method, or if the WAV header is not well formatted according to the characteristics of the audio stream.
I can see the WAV file being created, but there is no content inside apart from the header I think. Any guidance will be much appreciated. I put together this sample code for you to test what I am doing:
using System;
using System.IO;
using System.Text;
class SaveAudioStreamToWav
{
//Sample as received from stream. Here as a double to avoid altering the sample adding F to each value.
public double[] receivedStreamSample = { 0, -0.003509521, -0.003356934, 0.0002746582, -0.004516602, -0.0027771, -0.0003967285, -0.001739502, 0.004150391, 0.0008544922, 0.002593994, 0.00970459, 0.003631592, 0.001800537, 0.004760742, 0.004272461, -0.002655029, -0.001495361, -0.006835938, -0.004211426, -0.0008239746, 0.001525879, 0.006347656, 0.002532959, -0.002471924, -0.001342773, 0.001159668, 0.0006713867, -0.000793457, 0.001403809, -0.0006713867, -0.0006713867, -0.0007629395, 0.0009460449, -0.003662109, 0.00390625, -0.001312256, -0.001678467, 0.002288818, -0.001831055, -0.00579834, 0.001220703, -0.005096436, -0.003631592, -0.007019043, -0.0001220703, -0.0008850098, -0.0001220703, -0.005371094, 0.004608154, 0.004425049, 0.0027771, 0.005279541, 0.0001525879, 0.0009765625, 0.004150391, -0.002807617, 0.001678467, -0.004577637, -0.002685547, -0.004364014, -0.0008544922, 0.001281738, -0.0009155273, -0.008148193, -0.001983643, 9.155273E-05, 0.0008239746, 0.0004272461, 0.002807617, -0.00289917, 0.002075195, 0.008392334, 0.003479004, 0.005615234, 0.0009460449, 0.002471924, 0.0004272461, -0.006164551, 0.0003967285, -0.0007629395, -0.007476807, -0.002532959, 0.01495361, 0.01382446, 0.002288818, -0.009063721, -0.1129761, -0.05401611, 0.03497314, -0.03027344, 0.08999634, 0.01831055, 0.01037598, 0.03302002, 0.02667236, 0.04309082, -0.01806641, -0.0440979, 0.07125854, 0.00680542, -0.01242065, 0.001983643, -0.03710938, 0.009552002, 0.01013184, 0.002258301, 0.007446289, 0.004486084, -0.009063721, -0.007293701, 0.008239746, -0.0003967285, 0.001556396, 0.001586914, 0.002258301, 0.001281738, 0.001617432, -0.001831055, 0.001556396, -0.001525879, -0.002410889, 0.004516602, 0.000793457, -0.001403809, -0.004882813, -0.0005187988, -0.003540039, -0.004302979, 0.0004272461, 0.004974365, -0.002868652, -0.003875732, -0.0001220703, 0.001617432, 0.002258301, -0.005889893, -0.001068115, 0.003295898, 0.002410889, -0.00201416, 0.001068115, 0.003143311, -0.001464844, 0.000579834, 0.005310059, 0.001434326, 0.001403809, 0.001312256, -0.001617432, 0.0009460449, -0.0009765625, -0.0007324219, -0.001617432, -0.004730225, 0.001373291, -0.001586914, 0.0005187988, 0.001556396, -0.001647949, 0.0008544922, 0.001739502, 0.0027771, 0.001831055, 3.051758E-05, -0.04672241, 0.02276611, 0.02529907, -0.005249023, -0.02285767, -0.0378418, -0.1454468, 0.04385376, -0.04058838, -0.005249023, -3.051758E-05, -0.02166748, -0.006378174, -0.002380371, -0.0368042, 0.04330444, -0.008453369, 0.0300293, -0.01651001, -0.005554199, -0.01828003, 0.008972168, -0.01571655, -0.01202393, 0.01141357, -0.003997803, 0.004119873, -0.002532959, 0.004333496, -0.001495361, -0.001281738, -0.003692627, -0.001647949, -0.001861572, 0.000793457, -0.0003662109, -0.002532959, -0.001342773, 0.0003051758, 0.002075195, 0.002349854, 0.001464844, 0.001678467, -0.0008850098, -0.0001525879, 0.003723145, -0.0009155273, 0.002807617, -0.005157471, -0.001617432, 0.002471924, 0.002166748, -0.0003356934, 0.000213623, -0.000793457, -0.0008544922, -0.00100708, 0.000213623, 0.001037598, -0.003448486, 0.0009460449, -0.0006103516, -0.002655029, -0.009735107, -0.01101685, 0.01937866, 0.00994873, -0.02600098, 0.04592896, 0.1063843, 0.002441406, -0.0100708, 0.002990723, -0.01235962, -0.003448486, 0.01089478, -0.01480103, -0.02902222, 0.02990723, -0.01376343, 0.01275635, -0.008666992, 0.006469727, -0.009857178, 0.002655029, -0.0004882813, 0.003814697, 0.004943848, -0.002990723, -0.0003051758, -0.001678467, 0.003265381, 0.0009460449, -9.155273E-05, -0.001403809, 0.001739502, -0.002685547, -0.0009460449, -0.001281738, 0.0009765625, 0.001312256, 0.002288818, -0.0002746582, -0.001098633, -0.002319336, -0.000793457, 0.001464844, 0.001281738, -0.002319336, 6.103516E-05, 0.0003967285, -0.002532959, 0.0002441406, 0.001861572, 0.0009765625 };
public float[] floatsArray;
public FileStream fileStream;
static void Main(string[] args)
{
var saveAudioStreamToWav = new SaveAudioStreamToWav();
saveAudioStreamToWav.ConvertDoubleToFloat();
saveAudioStreamToWav.CreateEmpty(saveAudioStreamToWav.SetNameAndPath());
saveAudioStreamToWav.ConvertAndWrite();
saveAudioStreamToWav.WriteHeader();
}
public void ConvertDoubleToFloat()
{
floatsArray = new float[receivedStreamSample.Length];
floatsArray = Array.ConvertAll(receivedStreamSample, x => (float)x);
}
public string SetNameAndPath()
{
//Setting the name of the file
string timeStamp = DateTime.Now.ToString("yyyyMMddHHmmssfff");
string filename = "/TestSavingStreamToWav_" + timeStamp + ".wav";
string path = Directory.GetCurrentDirectory();
string filepath = path + filename;
Console.WriteLine(filepath);
return filepath;
}
public void CreateEmpty(string filepath)
{
const int HEADER_SIZE = 44;
fileStream = new FileStream(filepath, FileMode.CreateNew, FileAccess.ReadWrite);
byte emptyByte = new byte();
for (int i = 0; i < HEADER_SIZE; i++) //preparing an empty space for the header
{
fileStream.WriteByte(emptyByte);
}
}
public void ConvertAndWrite()
{
Int16[] intData = new Int16[floatsArray.Length];
Byte[] bytesData = new Byte[floatsArray.Length * 2]; // bytesData array is twice the size of floatsArray array because a float converted in Int16 is 2 bytes.
const float rescaleFactor = 32767; //to convert float to Int16
for (var i = 0; i < floatsArray.Length; i++)
{
intData[i] = (short)(floatsArray[i] * rescaleFactor);
var byteArr = new Byte[2];
byteArr = BitConverter.GetBytes(intData[i]);
byteArr.CopyTo(bytesData, i * 2);
}
fileStream.Write(bytesData, 0, bytesData.Length);
}
public void WriteHeader()
{
int hz = 16000; //frequency or sampling rate
int headerSize = 44; //default for uncompressed wav
fileStream.Seek(0, SeekOrigin.Begin);
Byte[] riff = System.Text.Encoding.UTF8.GetBytes("RIFF"); //RIFF marker. Marks the file as a riff file. Characters are each 1 byte long.
fileStream.Write(riff, 0, 4);
Byte[] chunkSize = BitConverter.GetBytes(fileStream.Length - 8); //file-size (equals file-size - 8). Size of the overall file - 8 bytes, in bytes (32-bit integer). Typically, you'd fill this in after creation.
fileStream.Write(chunkSize, 0, 4);
Byte[] wave = System.Text.Encoding.UTF8.GetBytes("WAVE"); //File Type Header. For our purposes, it always equals "WAVE".
fileStream.Write(wave, 0, 4);
Byte[] fmt = System.Text.Encoding.UTF8.GetBytes("fmt "); //Mark the format section. Format chunk marker. Includes trailing null.
fileStream.Write(fmt, 0, 4);
Byte[] subChunk1 = BitConverter.GetBytes(16); //Length of format data. Always 16.
fileStream.Write(subChunk1, 0, 4);
UInt16 two = 2;
UInt16 one = 1;
Byte[] audioFormat = BitConverter.GetBytes(one); //Type of format (1 is PCM, other number means compression) . 2 byte integer. Wave type PCM
fileStream.Write(audioFormat, 0, 2);
Byte[] numChannels = BitConverter.GetBytes(one); //Number of Channels - 2 byte integer
fileStream.Write(numChannels, 0, 2);
Byte[] sampleRate = BitConverter.GetBytes(hz); //Sample Rate - 32 byte integer. Sample Rate = Number of Samples per second, or Hertz.
fileStream.Write(sampleRate, 0, 4);
Byte[] byteRate = BitConverter.GetBytes(hz * 2 * 1);// sampleRate * bytesPerSample * number of channels, here 16000*2*1.
fileStream.Write(byteRate, 0, 4);
UInt16 blockAlign = (ushort)(1 * 2); //channels * bytesPerSample, here 1 * 2 // Bytes Per Sample: 1=8 bit Mono, 2 = 8 bit Stereo or 16 bit Mono, 4 = 16 bit Stereo
fileStream.Write(BitConverter.GetBytes(blockAlign), 0, 2);
UInt16 sixteen = 16;
Byte[] bitsPerSample = BitConverter.GetBytes(sixteen); //Bits per sample (BitsPerSample * Channels) ?? should be 8???
fileStream.Write(bitsPerSample, 0, 2);
Byte[] dataString = System.Text.Encoding.UTF8.GetBytes("data"); //"data" chunk header. Marks the beginning of the data section.
fileStream.Write(dataString, 0, 4);
Byte[] subChunk2 = BitConverter.GetBytes(fileStream.Length - headerSize); //Size of the data section. data-size (equals file-size - 44). or NumSamples * NumChannels * bytesPerSample ??
fileStream.Write(subChunk2, 0, 4);
fileStream.Close();
}
}//end of class
I have updated your code into an extension method.
The idea was so you could append you data to a stream, like a file stream or memory stream, obviously this won't work for non seekable streams. So you could probably add error checking and validation.
I think I got the header right after looking at the specs, it seems to play at least. Note this is not really cross platform because of the endianness.
I'm not really sure what the rescaleFactor however I'll have to trust you there.
However, you should be able to modify this to accept data in different formats.
Lastly, I am updating the header at the end of the append, you could probably do this separately, i.e keep adding to the stream and then update it once when finished, add pepper and salt to taste.
Usage
using (var stream = new FileStream(GetFileName(), FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
stream.AppendWaveData(receivedStreamSample);
}
Extension
public static class BinaryWriterExtensions
{
private const int HeaderSize = 44;
private const int Hz = 16000; //frequency or sampling rate
private const float RescaleFactor = 32767; //to convert float to Int16
public static void AppendWaveData<T>(this T stream, float[] buffer)
where T : Stream
{
if (stream.Length > HeaderSize)
{
stream.Seek(0, SeekOrigin.End);
}
else
{
stream.SetLength(HeaderSize);
stream.Position = HeaderSize;
}
// rescale
var floats = Array.ConvertAll(buffer, x => (short)(x * RescaleFactor));
// Copy to bytes
var result = new byte[floats.Length * sizeof(short)];
Buffer.BlockCopy(floats, 0, result, 0, result.Length);
// write to stream
stream.Write(result, 0, result.Length);
// Update Header
UpdateHeader(stream);
}
public static void UpdateHeader(Stream stream)
{
var writer = new BinaryWriter(stream);
writer.Seek(0, SeekOrigin.Begin);
writer.Write(Encoding.ASCII.GetBytes("RIFF")); //RIFF marker. Marks the file as a riff file. Characters are each 1 byte long.
writer.Write((int)(writer.BaseStream.Length - 8)); //file-size (equals file-size - 8). Size of the overall file - 8 bytes, in bytes (32-bit integer). Typically, you'd fill this in after creation.
writer.Write(Encoding.ASCII.GetBytes("WAVE")); //File Type Header. For our purposes, it always equals "WAVE".
writer.Write(Encoding.ASCII.GetBytes("fmt ")); //Mark the format section. Format chunk marker. Includes trailing null.
writer.Write(16); //Length of format data. Always 16.
writer.Write((short)1); //Type of format (1 is PCM, other number means compression) . 2 byte integer. Wave type PCM
writer.Write((short)2); //Number of Channels - 2 byte integer
writer.Write(Hz); //Sample Rate - 32 byte integer. Sample Rate = Number of Samples per second, or Hertz.
writer.Write(Hz * 2 * 1); // sampleRate * bytesPerSample * number of channels, here 16000*2*1.
writer.Write((short)(1 * 2)); //channels * bytesPerSample, here 1 * 2 // Bytes Per Sample: 1=8 bit Mono, 2 = 8 bit Stereo or 16 bit Mono, 4 = 16 bit Stereo
writer.Write((short)16); //Bits per sample (BitsPerSample * Channels) ?? should be 8???
writer.Write(Encoding.ASCII.GetBytes("data")); //"data" chunk header. Marks the beginning of the data section.
writer.Write((int)(writer.BaseStream.Length - HeaderSize)); //Size of the data section. data-size (equals file-size - 44). or NumSamples * NumChannels * bytesPerSample ??
}
} //end of class
change
writer.Write((short)2); into writer.Write((short)1);
and the generated file(.wav) will be plays well both on Windows(test against on windows 7) and android device.
otherwise,the Windows Media Player will says:having trouble playing files;android will plays with a quickly speed than expected.

Binary reading from string

I'm writing little decoder. User enter string (hex) that program should decode.
My problem is that int value is not the same as inputed, therefore I don't know how should I advance after reading binary. Am I missing point on how to read binary ?
string input = "0802";
byte[] arr = Encoding.Default.GetBytes(input);
using (MemoryStream stream = new MemoryStream(arr))
{
using (BinaryReader reader = new BinaryReader(stream))
{
int a = reader.ReadInt32();
Console.WriteLine(a);
//output: 842020912
}
}
This is correct. You read 4 bytes from the string so they are interpreted as 4 bytes of your int.
If you check the hex value of your "incorrect" number 842020912 it will give you 0x32303830 and reading every byte as ASCII gives "2080".
The order is reversed as you are reading the value as little-endian.
You are doing it the hard way. I using Bytes but can modify for 1in16, or int32 very easily. :
string input = "0802";
List<byte> bytes = new List<byte>();
for (int i = 0; i < input.Length; i += 2)
{
bytes.Add(byte.Parse(input.Substring(i, 2), System.Globalization.NumberStyles.HexNumber));
}

Stored image on database as bytes does not show as image on table but as bytes

I am trying to save an image to my database in byte array format, but when I look at the database I only see the bytes but not the image! How can I make it so I do not see the byte code but the image? Do I have to reverse the process on client side?
Please help! Thank you!
Byte conversion function:
private byte[] String_To_Bytes2(string strInput)
{
int numBytes = (strInput.Length) / 2;
byte[] bytes = new byte[numBytes];
for (int x = 0; x < numBytes; ++x)
{
bytes[x] = Convert.ToByte(strInput.Substring(x * 2, 2), 16);
}
return bytes;
}
I managed to solve the problem by using the first solution found on the following post:
Displaying database image (bytes[]) in Razor/MVC3?
Model.Content is a byte[] image.
#{
string imageBase64 = Convert.ToBase64String(Model.Content);
string imageSrc = string.Format("data:image/gif;base64,{0}", imageBase64);} <img src="#imageSrc" alt="#Model.Name" width="100" height="100" />

How to speed up writing large byte array to afile?

I need to convert a hex string to byte array, then have to write it to a file. The below code gives 3 seconds of delay. Below hex is an hex string of length 1600. Is there any other way to make this faster ?
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 5000; i++)
{
FileStream objFileStream = new FileStream("E://CRec Correcting Copy//Reader//bin//Debug//Files//Raw Data//a123.txt", FileMode.Append, FileAccess.Write);
objFileStream.Seek(0, SeekOrigin.End);
objFileStream.Write(stringTobyte(hex), 0, stringTobyte(hex).Length);
objFileStream.Close();
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
stringTobyte is a metho to convert the hex string to byte array.
public static byte[] stringTobyte(string hexString)
{
try
{
int bytesCount = (hexString.Length) / 2;
byte[] bytes = new byte[bytesCount];
for (int x = 0; x < bytesCount; ++x)
{
bytes[x] = Convert.ToByte(hexString.Substring(x * 2, 2), 16);
}
return bytes;
}
catch
{
throw;
}
}
Please tell me where the delay is happening ?
You're thinking way to complicated. First of all, no need for your custom function to convert it to a byte array. System.Text.UTF8Encoding.GetBytes(string) will do that for you! Also, no need for streams here, have a look at File.WriteAllBytes(string, byte[]) method.
Then it should look like this:
System.IO.File.WriteAllBytes("E://CRec Correcting Copy//Reader//bin//Debug//Files//Raw Data//a123.txt", new System.Text.UTF8Encoding().GetBytes(hex));
or a multiline version, if you insist:
string filePath = "E://CRec Correcting Copy//Reader//bin//Debug//Files//Raw Data//a123.txt";
System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
byte[] bytes = encoder.GetBytes(hex);
System.IO.File.WriteAllBytes(filePath, bytes);
Wow. For first do this:
objFileStream.Write(stringTobyte(hex), 0, stringTobyte(hex).Length);
byte[] bytes = stringTobyte(hex);
objFileStream.Write(bytes , 0, bytes.Length);

c# bin to hex and hex to bin

I have a problem about converting binary to hex then hex to binary.
For example I have an image file. First I want to convert that image to a hex string, then I want to insert this hex string to database. When a user wants to get that image file, the program has to read the hex string from the databasae, then converts to an image file.
Is it possible in C# ?
I have tried some sample methods from StackOverflow but I can't do that. I did an image file but it can't be shown.
I am waiting for your help.
Thank you
Let us know if this helps you out -
private string GetHexStringFromImage(System.Drawing.Image imageToConvert)
{
//Convert image it to byte-array
byte[] byteArray;
using (MemoryStream ms = new MemoryStream())
{
imageToConvert.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
byteArray = ms.ToArray();
}
//Convert byte-array to Hex-string
StringBuilder hexBuilder = new StringBuilder();
foreach (byte b in byteArray)
{
string hexByte = b.ToString("X");
//make sure each byte is represented by 2 Hex digits
string tempString = hexByte.Length % 2 == 0 ? hexByte : hexByte.PadLeft(2, '0');
hexBuilder.Append(tempString);
}
//return Hex-string to save to DB
return hexBuilder.ToString();
}
private System.Drawing.Image GetImageFromHexString(string hexSting)
{
//Convert Hex-string from DB to byte-array
int length = hexSting.Length;
List<byte> byteList = new List<byte>();
//Take 2 Hex digits at a time
for (int i = 0; i < length; i += 2)
{
byte byteFromHex = Convert.ToByte(hexSting.Substring(i, 2), 16);
byteList.Add(byteFromHex);
}
byte[] byteArray = byteList.ToArray();
//Convert byte-array to image file and return the image
using (MemoryStream stream = new MemoryStream(byteArray))
{
return System.Drawing.Image.FromStream(stream);
}
}
You can use the JSON.NET library to serialize the byte[] into a string which will turn it into hex. Then use the same library to deserialize it back a byte[] when you need to.
I would recommend that you store it as a byte[] in the database though because it will use at least twice the space as a string (one byte in hex is 2 characters, each being a byte at minimum with ASCII or UTF8) and there is a tiny bit of overhead for the JSON format.

Categories