NetworkStream a thing i don´t understand in my code - c#

I got help in a previous question on how to send an image.
The thing done was to first send the lenght of the image(size), and then the actual image, then it would know when it was done.
IT looks like this:
BinaryWriter writer = new BinaryWriter(netStream);
while (someCondition) {
Image img = SomeImage();
MemoryStream ms = new MemoryStream();
img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
byte[] buffer = new byte[ms.Length];
ms.Seek(0, SeekOrigin.Begin);
ms.Read(buffer, 0, buffer.Length);
writer.Write(buffer.Length);
writer.Write(buffer);
This code is from: Angelo Geels , who helped me in my previous question.
Now, i tried to optimize this in a way. And well, it works. But ONLY when the file is bmp (uncompressed), and i don´t know why.
using (MemoryStream ms = PrintWindow(process))
{
writer.Write((int)ms.Length);
writer.Write(ms.GetBuffer());
}
So PrintWindow save an image to a memorystream and returns it. so ms = memorystream with my image in it.
So for me this should work perfectly, cause form what i can se i do the same thing.
i send the size of the file (length of the memorystream).
Then i send the byte[] data in the memorystream.
So, it´s the same thing.
But, it only works with bmp.
The only thing i can think of is that when i save in a compressed format, the bmp is first written and then encoded, which messes up the getbuffer() or something.
But i still think it should work.

You write too many bytes, use the Write() overload that lets you specify how much to write:
using (MemoryStream ms = PrintWindow(process)) {
writer.Write((int)ms.Length);
writer.Write(ms.GetBuffer(), 0, (int)ms.Length);
}

Don't use GetBuffer. From the documentation:
Note that the buffer contains allocated bytes which might be unused.
For example, if the string "test" is written into the MemoryStream
object, the length of the buffer returned from GetBuffer is 256, not
4, with 252 bytes unused. To obtain only the data in the buffer, use
the ToArray method; however, ToArray creates a copy of the data in
memory.
Use:
writer.Write(ms.ToArray());
Or if you are in 4.0 use the CopyTo method:
ms.CopyTo(netStream);
Check this if you are not in 4.0 for a way to copy streams:
How do I copy the contents of one stream to another?

Related

C# How image is stored in MemoryStream

I work on a project where i need to process a image i receive from a socket and to display it.
I'm getting the image in jpeg format,and i cannot just use the Image.FromStream()); method for retrieving the image,because it contains more data and i want to process it while i'm reading the data-for efficiency reasons.(Basically what i want is to read the image from the stream manually).
Is there any source which explaines how these image are stored in the MemoryStream?
The MemoryStream is built on a byte[] buffer,i resuse the same buffer also and i do not create a new MemoryStream everytime the method called.
A sample of code:
private byte[] BlockToJpeg()
{
Bitmap block=new Bitmap("...");
MemoryStream ms=new MemoryStream();
block.Save(ms, ImageFormat.Jpeg);
return ms.GetBuffer();
}
So the call would look like this
byte[] buffer=BlockToJpeg();
sck.Send(buffer);//sending the buffer...not the full code because this is not our problem.
Now in the Reciver side,when i'll get that buffer:
Byte[] RecieveBuffer=sck.Recieve();//again,kind of pseudo code,because this is not the relevant part.
i have to processes it's pixels,so i'll prefer to read them from the byte[] array one by one manually...
Is there any structure for reading this(in our case-reading a jpeg image stored as byte array)?
For example- first 4 bytes are width,second are height...3rd are PixelFormat and the rest are the pixels values...or somthing...?
Thanks.
jpeg is type of compression method usually on images.
you can read more about it here:http://www.ams.org/samplings/feature-column/fcarc-image-compression

Image.GetThumbnailImage throws OutOfMemoryException

The following C# 3.5 code throws an exception in GetThumbnailImage:
Image img = null;
Image scaledImg = null;
byte[] imageData = File.ReadAllBytes("11001.jpg");
MemoryStream stream = new MemoryStream(imageData);
img = Image.FromStream(stream);
stream.Close();
stream.Dispose();
scaledImg = img.GetThumbnailImage(64, 64, null, IntPtr.Zero);
The problem is the disposing of the stream. If I remove the Close() and Dispose() statement, everything works fine. Does anyone know why this exception is thrown? Using a callback instead of null as parameter does not change the behavior.
I don't need a solution, I can use new Bitmap(img, new Size(width, height) for scaling. This is probably better and shoud have been used from the beginning.
Edit: Sorry, I forgot to mention that the exception only occurs in WindowsXP. Win7 and Win8 seem to handle the above code just fine.
GetThumbnailImage is a native method, using the same stream you passed while creating the Image. Only the .NET methods are using the actual data from the stream (it's loaded as the last thing while creating the image from a stream).
It's a pretty typical leaky abstraction. You thought you have an Image object that already has its data loaded, but the data is only loaded in the .NET part. Any method that works directly with the GDI+ image handle will still need the stream to be live.
Another example of the same problem is while trying to save the image in a different format. When you try to save with the same format, .NET just saves the byte data it has in memory, simple. If it's not the same, it will use the GDI+ method SaveImageToFile, which again requires the original stream to be preserved.
If you don't mind having the stream alive, you can just move the Dispose after everything you do with the images produced from that stream:
using (var stream = new MemoryStream(imageData))
{
var img = Image.FromStream(stream);
var scaledImg = img.GetThumbnailImage(64, 64, null, IntPtr.Zero);
scaledImg.Save(...);
}
If you do mind, the easiest thing you can do is this:
var bmp = new Bitmap(Image.FromStream(stream));
The Bitmap constructor will copy the image data, and you no longer need to keep the stream.
I think that GetThumbnailImage uses the stream to do its job so it needs it to be open.You can do it like this :
Image img = null;
Image scaledImg = null;
byte[] imageData = File.ReadAllBytes("11001.jpg");
using(MemoryStream stream = new MemoryStream(imageData))
{
img = Image.FromStream(stream);
scaledImg = img.GetThumbnailImage(64, 64, null, IntPtr.Zero);
}
(using closes and disposes the MemoryStream but it also handles exceptional situations to avoid memory leaks)
The Image object uses lazy evaluation. As you have already closed the stream, when it actually tries to read the image in order to get the thumbnail, it's not there anymore. Hence the error.

Loading saved byte array to memory stream causes out of memory exception

At some point in my program the user selects a bitmap to use as the background image of a Panel object. When the user does this, the program immediately draws the panel with the background image and everything works fine. When the user clicks "Save", the following code saves the bitmap to a DataTable object.
MyDataSet.MyDataTableRow myDataRow = MyDataSet.MyDataTableRow.NewMyDataTableRow(); //has a byte[] column named BackgroundImageByteArray
using (MemoryStream stream = new MemoryStream())
{
this.Panel.BackgroundImage.Save(stream, ImageFormat.Bmp);
myDataRow.BackgroundImageByteArray = stream.ToArray();
}
Everything works fine, there is no out of memory exception with this stream, even though it contains all the image bytes. However, when the application launches and loads saved data, the following code throws an Out of Memory Exception:
using (MemoryStream stream = new MemoryStream(myDataRow.BackGroundImageByteArray))
{
this.Panel.BackgroundImage = Image.FromStream(stream);
}
The streams are the same length. I don't understand how one throws an out of memory exception and the other doesn't. How can I load this bitmap?
P.S. I've also tried
using (MemoryStream stream = new MemoryStream(myDataRow.BackgroundImageByteArray.Length))
{
stream.Write(myDataRow.BackgroundImageByteArray, 0, myDataRow.BackgroundImageByteArray.Length); //throw OoM exception here.
}
The issue I think is here:
myDataRow.BackgroundImageByteArray = stream.ToArray();
Stream.ToArray() . Be advised, this will convert the stream to an array of bytes with length = stream.Length. Stream.Legnth is size of the buffer of the stream, which is going to be larger than the actual data that is loaded into it. You can solve this by using Stream.ReadByte() in a while loop until it returns a -1, indicating the end of the data within the stream.
You might give this library a look.
http://arraysegments.codeplex.com/
Project Description
Lightweight extension methods for ArraySegment, particularly useful for byte arrays.
Supports .NET 4.0 (client and full), .NET 4.5, Metro/WinRT, Silverlight 4 and 5, Windows Phone 7 and 7.5, all portable library profiles, and XBox.

Convert 64base byte array to PDF and show in webBroswer compont

This is what i would like to do:
Get a 64base byte array from database (which is actually in pdf format). This works.
Then i would like to show the pdf in a webbrowser component.
I first started with saving the pdf to a file.pdf and then open it:
byte[] bitjes = isc.GetFileById(fileid); // Getting the bytes
FileStream stream = new FileStream(#"C:\NexusPDF\" + filename, FileMode.CreateNew);
BinaryWriter writer = new BinaryWriter(stream);
writer.Write(bitjes, 0, bitjes.Length);
writer.Close();
webBrowser.Navigate(#"C:\NexusPDF\" + filename);
But that gave me all sorts of problems involving read/write acces. So i figured i have to use the memorystream class to solve this problem.
byte[] bitjes = isc.GetFileById(fileid);
MemoryStream memstream = new MemoryStream(bitjes);
BinaryWriter writer = new BinaryWriter(memstream);
writer.Write(bitjes, 0, bitjes.Length);
writer.Close();
But here's where i'm stuck! I can't just show this in a webBrowser component can i?
Do i have to use the binaryreader before i can show the pdf?
Am i approaching this problem the right way, or are there better alternatives?
Main thing is that i don't want to save the file on disk.
Any help will be appreciated.
You may be able to use the data URL scheme. This URL scheme specifies the content inline.
webBrowser.Navigate("data:application/pdf;base64," + X);
Where X is the base 64 string.
No need to convert the base 64 PDF string into a byte array!
See http://www.ietf.org/rfc/rfc2397.txt for more details.

How to convert byte array to image file?

I have browsed and uploaded a png/jpg file in my MVC web app.
I have stored this file as byte[] in my database.
Now I want to read and convert the byte[] to original file.
How can i achieve this?
Create a MemoryStream passing the array in the constructor.
Read the image from the stream using Image.FromStream.
Call theImg.Save("theimage.jpg", ImageFormat.Jpeg).
Remember to reference System.Drawing.Imaging and use a using block for the stream.
Create a memory stream from the byte[] array in your database and then use Image.FromStream.
byte[] image = GetImageFromDatabase();
MemoryStream ms = new MemoryStream(image);
Image i = Image.FromStream(ms);
May you have trouble with the mentioned solutions on DotNet Core 3.0 or higher
so my solution is:
using(var ms = new MemoryStream(yourByteArray)) {
using(var fs = new FileStream("savePath", FileMode.Create)) {
ms.WriteTo(fs);
}
}
Or just use this:
System.IO.File.WriteAllBytes(string path, byte[] bytes)
File.WriteAllBytes(String, Byte[]) Method (System.IO) | Microsoft Docs

Categories

Resources