Byte Array to Bitmap Image - c#

I made this code to receive an image and convert it to bitmap image but it doesn't work.
Here is the code:
public void ReceiveImage()
{
NetworkStream stream = new NetworkStream(socket);
byte[] data = new byte[4];
stream.read(data,0,data.length,0)
int size = BitConverter.ToInt32(data,0);
data = new byte[size];
stream.read(data,0,data.length)
MemoryStream imagestream = new MemoryStream(data);
Bitmap bmp = new Bitmap(imagestream);
picturebox1.Image = bmp;
}
It gets to:
Bitmap bmp = new Bitmap(imagestream);
And gives me this error:
Parameter is not valid

This is an alternative method
int w= 100;
int h = 200;
int ch = 3; //number of channels (ie. assuming 24 bit RGB in this case)
byte[] imageData = new byte[w*h*ch]; //you image data here
Bitmap bitmap = new Bitmap(w,h,PixelFormat.Format24bppRgb);
BitmapData bmData = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
IntPtr pNative = bmData.Scan0;
Marshal.Copy(imageData,0,pNative,w*h*ch);
bitmap.UnlockBits(bmData);

You are probably not receiving enough bytes in stream.read(data,0,data.length) since Read does not ensure that it will read data.length bytes. you have to check its return value and continue to read till data.Length bytes are read.
See : Stream.Read Method's return value
int read = 0;
while (read != data.Length)
{
read += stream.Read(data, read, data.Length - read);
}
PS: I am assuming lengths and reads are typos.

I assume you have a table and want to receive the picture from database.
int cout = ds.Tables["TableName"].Rows.Count;
if (cout > 0)
{
if (ds.Tables["TableName"].Rows[cout - 1]["Image"] != DBNull.Value)
{
var data = (byte[])(ds.Tables["TableName"].Rows[cout - 1]["Image"]);
var stream = new MemoryStream(data);
pictureBox1.Image = Image.FromStream(stream);
}
else
{
pictureBox1.Image = null;
}
}

Try this:
int size = BitConverter.ToInt32(data.Reverse().ToArray(),0);

Related

Using SharpAvi to convert images to video

I'm using SharpAvi .dll to convert a serie of images to video, everything looks fine, but when I try to play the video in windows media player I only get a black screen for one second, nothing else.
This is the code I wrote, (frames is a list of images as base64)
private void CreateMovie(List<string> frames)
{
int width = 320;
int height = 240;
var framRate = 2;
var writer = new AviWriter("C:\\test.avi")
{
FramesPerSecond = framRate,
EmitIndex1 = true
};
var stream = writer.AddVideoStream();
stream.Width = width;
stream.Height = height;
stream.Codec = KnownFourCCs.Codecs.DivX;
stream.BitsPerPixel = BitsPerPixel.Bpp32;
foreach (var frame in frames)
{
byte[] arr = Convert.FromBase64String(frame);
stream.WriteFrame(true, arr, 0, arr.Length);
}
writer.Close();
}
I can't see what the error could be. Does anyone have an idea?
So, i've found the errors:
the line:
stream.Codec = KnownFourCCs.Codecs.DivX;
should be:
stream.Codec = KnownFourCCs.Codecs.Uncompressed;
and all the frames of the video should be the same size as video, in order to do that i've use this block of code:
foreach (var frame in frames)
{
byte[] arr = Convert.FromBase64String(frame);
var bm = ToBitmap(arr);
var rbm = ReduceBitmap(bm, 320, 240);
byte[] fr = BitmapToByteArray(rbm);
stream.WriteFrame(true, fr, 0, fr.Length);
}
and here the helper functions:
public Bitmap ToBitmap(byte[] byteArrayIn)
{
var ms = new MemoryStream(byteArrayIn);
var returnImage = Image.FromStream(ms);
var bitmap = new Bitmap(returnImage);
return bitmap;
}
public Bitmap ReduceBitmap(Bitmap original, int reducedWidth, int reducedHeight)
{
var reduced = new Bitmap(reducedWidth, reducedHeight);
using (var dc = Graphics.FromImage(reduced))
{
dc.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
dc.DrawImage(original, new Rectangle(0, 0, reducedWidth, reducedHeight), new Rectangle(0, 0, original.Width, original.Height), GraphicsUnit.Pixel);
}
return reduced;
}
public static byte[] BitmapToByteArray(Bitmap bitmap)
{
BitmapData bmpdata = null;
try
{
bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
int numbytes = bmpdata.Stride * bitmap.Height;
byte[] bytedata = new byte[numbytes];
IntPtr ptr = bmpdata.Scan0;
Marshal.Copy(ptr, bytedata, 0, numbytes);
return bytedata;
}
finally
{
if (bmpdata != null)
{
bitmap.UnlockBits(bmpdata);
}
}
}

c# - memory usage during filestream.seek and marshal.copy

I have a running code, which gets any filetypes and show that file in a picturebox full of black and white pixels representing opened file bits
////////////////
int bmpWidth = 128000;
int startIndex = 0;
Int64 tempz = Convert.ToInt64(bmpWidth);
long tmp2 = fs.Length / tempz + 1;
int bmpHeight = Convert.ToInt32(tmp2);
Bitmap bmp = new Bitmap(bmpWidth, bmpHeight, PixelFormat.Format1bppIndexed);
////////////////
long all = 0;
byte[] array = new byte[bmpWidth];
int read = 0;
fs.Seek(startIndex, SeekOrigin.Begin);
all += startIndex;
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat);
Int64 ptrFirstPixel = bmpData.Scan0.ToInt64();
int y = 0;
while ((read = fs.Read(array, 0, array.Length)) > 0)
{
if (read < array.Length)
{
byte[] arrayNew = new byte[read];
Array.Copy(array, arrayNew, read);
array = arrayNew;
}
Marshal.Copy(array, 0, new IntPtr(ptrFirstPixel + y * bmpData.Stride), array.Length/8);
y++;
all += read;
}
bmp.UnlockBits(bmpData);
imageBox.Image = bmp;
I have a 4GB ram, how its possible that I'm opening a 4.5GB file?
And also, when I try opening 2 or 4 GB file, only 200MB of memory is used, where are the rest of the data coming from?
During marshal.copy and filestream.seek the system use memory for byte by byte for hole filestream and bitmap or its coming from hard disk?
I have a logical and semantic misunderstanding in my mind, any help!?

Bitmap Image from Hex string - extra bytes being added

I have a Hex string that's coming from postscript file.
<< /ImageType 1
/Width 986 /Height 1
/BitsPerComponent 8
/Decode [0 1 0 1 0 1]
/ImageMatrix [986 0 0 -1 0 1]
/DataSource <
803fe0503824160d0784426150b864361d0f8844625138a4562d178c466351b8e4763d1f904864523924964d27944a6552b964b65d2f984c665339a4d66d379c4e6753b9e4f67d3fa05068543a25168d47a4526954ba648202
> /LZWDecode filter >> image } def
Below are the methods that I am using. I have commented out the method for updating color.
public static void ProcessImageColourMapping()
{
string imageDataSource = "803fe0503824160d0784426150b864361d0f8844625138a4562d178c466351b8e4763d1f904864523924964d27944a6552b964b65d2f984c665339a4d66d379c4e6753b9e4f67d3fa05068543a25168d47a4526954ba648202";
string imageDataSourceUpdated = GetUpdatedImage(imageDataSource);
}
public static string GetUpdatedImage(string strImageDataSource)
{
string imageDataSourceUpdated = "";
byte[] imageBytes = StringToByteArray(strImageDataSource);
Bitmap bitmapImage = ByteArrayToBitmap(imageBytes);
//UpdateColour(bitmapImage);
byte[] imageBytesUpdated = BitmapToByteArray(bitmapImage);
imageDataSourceUpdated = ByteArrayToString(imageBytesUpdated);
return imageDataSourceUpdated;
}
public static byte[] StringToByteArray(String imageHexString)
{
int numberOfChars = imageHexString.Length / 2;
byte[] byteArray = new byte[numberOfChars];
using (var sr = new StringReader(imageHexString))
{
for (int i = 0; i < numberOfChars; i++)
byteArray[i] = Convert.ToByte(new string(new char[2] { (char)sr.Read(), (char)sr.Read() }), 16);
}
return byteArray;
}
public static Bitmap ByteArrayToBitmap(byte[] byteArray)
{
int width = 986; //width and height are taken from postscript file for testing a single hex string.
int height = 1;
Bitmap bitmapImage = new Bitmap(width, height, PixelFormat.Format32bppPArgb);
BitmapData bmpData = bitmapImage.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format32bppPArgb);
try
{
Marshal.Copy(byteArray, 0, bmpData.Scan0, byteArray.Length);
}
finally
{
bitmapImage.UnlockBits(bmpData);
}
return bitmapImage;
}
public static byte[] BitmapToByteArray(Bitmap bitmap)
{
BitmapData bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat);
int numbytes = bmpdata.Stride * bitmap.Height;
byte[] bytedata = new byte[numbytes];
try
{
Marshal.Copy(bmpdata.Scan0, bytedata, 0, numbytes);
}
finally
{
bitmap.UnlockBits(bmpdata);
}
return bytedata;
}
public static string ByteArrayToString(byte[] byteArray)
{
StringBuilder hex = new StringBuilder(byteArray.Length * 2);
foreach (byte b in byteArray)
{
hex.AppendFormat("{0:x2}", b);
}
return hex.ToString();
}
Issue:
In below code, I am not updating anything for incoming Hex string imageDataSource.
Converting it to byte[] - then to Bitmap - Back to byte[] - and finally back to Hex string.
So, imageDataSourceUpdated should have same value as imageDataSource.
However, when I finally check the value for imageDataSourceUpdated, it comes out as:
803fe0503824160d0784426150b864361d0f8844625138a4562d178c466351b8e4763d1f904864523924964d27944a6552b964b65d2f984c665339a4d66d379c4e6753b9e4f67d3fa05068543a25168d47a4526954ba64820200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.....
So many zeros being appended.
Can please guide what I am missing here.
You are passing some input string, but the width of the image (and so 1/4 of the size of the byte array) is set to 986 in your sample, which would yield the behaviour you observe - you're not actually passing 986 * 4 bytes of data, but the Bitmap does have that many. So you'll get the first X bytes you actually copied to the bitmap, and then all zeros. In other words, it seems your issue is with your sample data, not with the methods themselves - those work just fine.

Image.FromStream() issue C# at the time of image manipulation

I'm working with JPG image type and this line image = Image.FromStream(ms); is giving an error Parameter is not valid.
What is wrong with this code?
private void button3_Click(object sender, EventArgs e)
{
Image partial=null;
Rectangle bounds;
Guid id;
if (diff != null)
{
ImageConverter converter = new ImageConverter();
var data = (byte[])converter.ConvertTo(diff, typeof(byte[]));
UnpackScreenCaptureData(data, out partial, out bounds,out id);
Image imgfirst = (Image)firstImg;
UpdateScreen(ref imgfirst, partial, bounds);
}
}
public static void UnpackScreenCaptureData(byte[] data, out Image image, out Rectangle bounds, out Guid id)
{
// Unpack the data that is transferred over the wire.
// Create byte arrays to hold the unpacked parts.
const int numBytesInInt = sizeof(int);
int idLength = Guid.NewGuid().ToByteArray().Length;
int imgLength = data.Length - 4 * numBytesInInt - idLength;
byte[] topPosData = new byte[numBytesInInt];
byte[] botPosData = new byte[numBytesInInt];
byte[] leftPosData = new byte[numBytesInInt];
byte[] rightPosData = new byte[numBytesInInt];
byte[] imgData = new byte[imgLength];
byte[] idData = new byte[idLength];
// Fill the byte arrays.
Array.Copy(data, 0, topPosData, 0, numBytesInInt);
Array.Copy(data, numBytesInInt, botPosData, 0, numBytesInInt);
Array.Copy(data, 2 * numBytesInInt, leftPosData, 0, numBytesInInt);
Array.Copy(data, 3 * numBytesInInt, rightPosData, 0, numBytesInInt);
Array.Copy(data, 4 * numBytesInInt, imgData, 0, imgLength);
Array.Copy(data, 4 * numBytesInInt + imgLength, idData, 0, idLength);
// Create the bitmap from the byte array.
MemoryStream ms = new MemoryStream(imgData, 0, imgData.Length);
ms.Write(imgData, 0, imgData.Length);
image = Image.FromStream(ms);
....
}
I think you have to reset your MemoryStream to position 0.
You can accomplish this by calling the Seek() method on the memory stream:
MemoryStream ms = new MemoryStream(imgData, 0, imgData.Length);
ms.Write(imgData, 0, imgData.Length);
ms.Seek(0, SeekOrigin.Begin); // Set stream position to 0.
image = Image.FromStream(ms);

C# Problems With Sending/Receiving Size of bytes (Sockets)

I've made these codes to send and receive an Image with a TCP socket but the receive code didn't work.
This is the send code:
public void SendImage()
{
int ScreenWidth = Screen.GetBounds(new Point(0, 0)).Width;
int ScreenHeight = Screen.GetBounds(new Point(0, 0)).Height;
Bitmap bmpScreenShot = new Bitmap(ScreenWidth, ScreenHeight);
Graphics gfx = Graphics.FromImage((Image)bmpScreenShot);
gfx.CopyFromScreen(0, 0, 0, 0, new Size(ScreenWidth, ScreenHeight));
bmpScreenShot.Save(Application.StartupPath + "/ScreenShot.jpg", ImageFormat.Jpeg);
byte[] image = new byte[1];
bmpScreenShot = ResizeBitmap(bmpScreenShot, 300, 300);
image = ImageToByte(bmpScreenShot);
//get the length of image (length of bytes)
int NumberOfBytes = image.Length;
//put the size into a byte array
byte[] numberofbytesArray = BitConverter.GetBytes(NumberOfBytes);
//send the size to the Client
int sizesend = sck.Send(numberofbytesArray, 0, numberofbytesArray.Length, 0);
if (sizesend > 0)
{
MessageBox.Show("Size Sent");
}
//send the image to the Client
int imagesend =sck.Send(image, 0, NumberOfBytes, 0);
if (imagesend > 0)
{
MessageBox.Show("Image Sent");
}
}
And here is the receive code:
public void ReceiveImage()
{
if (sck.Connected)
{
{
NetworkStream stream = new NetworkStream(sck);
byte[] data = new byte[4];
//Read The Size
stream.Read(data, 0, data.Length);
int size = (BitConverter.ToInt32(data,0));
// prepare buffer
data = new byte[size];
//Load Image
int read = 0;
while (read != data.Length)
{
read += stream.Read(data, read, data.Length - read);
}
//stream.Read(data, 0, data.Length);
//Convert Image Data To Image
MemoryStream imagestream = new MemoryStream(data);
Bitmap bmp = new Bitmap(imagestream);
pictureBox1.Image = bmp;
}
}
}
The problem is when i send the size, its sent as 5kb but when i receive it i find it 2GB and this error comes up:
Unable to read data from the transport connection. An operation on a socket could be performed because the system lacked sufficient buffer space or because a queue was full.
The error is at this statement read += stream.Read(data, read, data.Length - read);
I would try getting smaller chunks of data. In your code you're starting off with all the data (2GB at a time in the case that fails. Drop that down to something smaller--the data is sent in chunks anyway. For example:
read += stream.Read(buffer, read, 20480);
this will read about 2k at a time so as to not be larger than the buffer space or be too large for the queue.
If you've allocated a buffer of 2GB in size, your application likely has very little memory left. The underlying framework is probably unable to allocated 2GB of data for itself (4GB total allocated) to transfer data.

Categories