I'm having some difficulty saving a stream of bytes from an image (in this case, a jpg) to a System.IO.MemoryStream object. The goal is to save the System.Drawing.Image to a MemoryStream, and then use the MemoryStream to write the image to an array of bytes (I ultimately need to insert it into a database). However, inspecting the variable data after the MemoryStream is closed shows that all of the bytes are zero... I'm pretty stumped and not sure where I'm doing wrong...
using (Image image = Image.FromFile(filename))
{
byte[] data;
using (MemoryStream m = new MemoryStream())
{
image.Save(m, image.RawFormat);
data = new byte[m.Length];
m.Write(data, 0, data.Length);
}
// Inspecting data here shows the array to be filled with zeros...
}
Any insights will be much appreciated!
To load data from a stream into an array, you read, not write (and you would need to rewind). But, more simply in this case, ToArray():
using (MemoryStream m = new MemoryStream())
{
image.Save(m, image.RawFormat);
data = m.ToArray();
}
If the purpose is to save the image bytes to a database, you could simply do:
byte[] imgData = System.IO.File.ReadAllBytes(#"path/to/image.extension");
And then plug in your database logic to save the bytes.
I found for another reason this article some seconds ago, maybe you will find it useful:
http://www.codeproject.com/KB/recipes/ImageConverter.aspx
Basically I don't understand why you try to write an empty array over a memory stream that has an image. Is that your way to clean the image?
If that's not the case, read what you have written in your memorystream with ToArray method and assign it to your byte array
And that's all
Try this way, it works for me
MemoryStream ms = new MemoryStream();
Bitmap bmp = new Bitmap(panel1.Width, panel1.Height);
panel1.DrawToBitmap(bmp, panel1.Bounds);
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] Pic_arr = new byte[ms.Length];
ms.Position = 0;
ms.Read(Pic_arr, 0, Pic_arr.Length);
ms.Close();
Well instead of a Image control, I used a Panel Control.
Related
I try converting image data from the database which is already in byte[] back to the image and I'm getting "invalid parameter error" using Image.FileStream.
Please, can anyone help me out with this?
I've tried working around the code using various methods and the last one is below in my code.
byte[] data = validaccount.FingerPrint;
try
{
using (MemoryStream strm = new MemoryStream())
{
strm.Write(data, 0, data.Length);
strm.Position = 0;
System.Drawing.Image img = System.Drawing.Image.FromStream(strm);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
MemoryStream ms = new MemoryStream();
img.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
ms.Seek(0, SeekOrigin.Begin);
bi.StreamSource = ms;
bi.EndInit();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
The code is supposed to convert the byte[] into an image.
According to the docs, Image.FromStream(stream) will throw an argument exception if "The stream does not have a valid image format". Have you verified the data is actually correct? If so, what type of image is it?
You're misusing your streams. You only need 1 memory stream and it has a constructor that takes a byte array (no need to write the bytes yourself). Be sure to wrap it in a using block (like you did for your first stream).
You may not want to use BitmapImage - that's for xaml/wpf apps. You probably want System.Drawing.Bitmap which inherits/extends System.Drawing.Image. Additionally, Bitmap has a constructor which takes a stream - no need to use FromStream.
Finally, Image (and hence Bitmap since Bitmap inherits Image) implements IDisposable, so you should also wrap it in a using block.
P.S. This is a duplicate question.
Though its not memory stream, this method has worked for me and if you browse SO for your question, some times MS does not work.
using System.Drawing;
var converterdImage = (Bitmap)((new ImageConverter()).ConvertFrom(byteArray));
Byte Array to Image Conversion
I have a function that returns an array of bytes containing the data of a bmp img live from a camera (including header).
I write that array in to a MemoryStream object.
That object, I pass to a Image object constructor, which will be passed to a PictureBox.
tl;dr:
byte[] AoB = GetImage();
MemoryStream ms = new MemoryStream();
ms.Write(AoB, 0, AoB.Length);
pictureBoxImage.Image = Image.FromStream(ms);
ms.Dispose();
All of this is done in a timer with a delay of 200 ms (5fps).
It works fine for about a minute or 2 until OutOfMemory exception.
For some reason, even though I dispose of the memory used, it keeps generating new one.
I've also tried to declare ms as global and flush it every time, still no go.
How can I stream the images while using the same memory space?
Try disposing the Image objects when you're done with them as well:
byte[] AoB = GetImage();
using (MemoryStream ms = new MemoryStream()) {
ms.Write(AoB, 0, AoB.Length);
Image old = pictureBoxImage.Image;
pictureBoxImage.Image = Image.FromStream(ms);
if (old != null) {
old.Dispose();
}
}
You definitely should dispose the old images when you are done with them (as adv12 mentioned), however you are also creating two byte[]s in memory. The first one is the one you get from GetImage() the second one is the one stored inside the MemoryStream and that one could be larger than your source array due to its growing algorithms.
Instead use this overload of the MemoryStream constructor to allow you to pass the byte[] directly in and the MemoryStream will reuse that single array for its internal store, reducing the memory requirement.
byte[] AoB = GetImage();
using (MemoryStream ms = new MemoryStream(AoB)) {
Image old = pictureBoxImage.Image;
pictureBoxImage.Image = Image.FromStream(ms);
old.Dispose();
}
Try setting your timer's AutoReset=false and manually starting it over at the end of the last call.
myTimer.AutoReset = false;
Start after image assignment.
byte[] AoB = GetImage();
MemoryStream ms = new MemoryStream();
ms.Write(AoB, 0, AoB.Length);
pictureBoxImage.Image = Image.FromStream(ms);
ms.Dispose();
myTimer.Start().
The timer has the potential to get ahead of the retrieval of the images.
I'm using this function to convert base64 to image.
public Image Base64ToImage(string base64String)
{
// Convert Base64 String to byte[]
byte[] imageBytes = Convert.FromBase64String(base64String);
using (var ms = new MemoryStream(imageBytes, 0,imageBytes.Length))
{
// Convert byte[] to Image
ms.Write(imageBytes, 0, imageBytes.Length);
//Image image = Image.FromStream(ms, true);
Image image = Image.FromStream(ms,true,true);
return image;
}
}
but it is not working. please help me.
I don't thik the ms write call is needed here.
using (var ms = new MemoryStream(imageBytes, 0,imageBytes.Length))
{
// Convert byte[] to Image
ms.Write(imageBytes, 0, imageBytes.Length);
Your are efectively constructing the stream from your byteArray so the ms.Write call will append the data twice in the stream. This might cause issues for your Image object. Either use the default constructor for the stream or delete the Write and test again.
Edit:
Zey deleted his answer but i think he had a good point in there. You might consider dropping the using block as well. My memory might fail me but i think Image objects need the source stream to be kept open. Dispose the Image object when not needed anymore.
How can I upload an image properly from Windows Phone where the image source is
a PhotoResult from a PhotoChooserTask? I'm using RestSharp for this, but it only
uploads a big bunch of zeroes to my server.
Here's the code part I have trobule with:
using (MemoryStream memo = new MemoryStream())
{
appGlobal.appData.selectedPhoto.ChosenPhoto.CopyTo(memo);
byte[] imgArray = new byte[appGlobal.appData.selectedPhoto.ChosenPhoto.Length];
memo.Read(imgArray, 0, imgArray.Length);
request.AddFile("image", imgArray, "image", "image/jpeg");
}
I can't seem to figure out how am I supposed to convert PhotoResult.ChosenPhoto (which is a PhotoStream) to a byte array.
Any thoughts?
Ok I found out what the problem was. It seems that when you get the PhotoResult back from
a chooser task let it be PhotoChooserTask or CameraCaptureTask, the stream's position isn't set to 0. So you'll have to set it manually before reading the bytes out from it. Here's the fixed code for my question:
byte[] imgArray = new byte[(int)appGlobal.appData.selectedPhoto.ChosenPhoto.Length];
appGlobal.appData.selectedPhoto.ChosenPhoto.Position = 0;
appGlobal.appData.selectedPhoto.ChosenPhoto.Read(imgArray, 0, (int)appGlobal.appData.selectedPhoto.ChosenPhoto.Length);
appGlobal.appData.selectedPhoto.ChosenPhoto.Seek(0, SeekOrigin.Begin);
request.AddFile("image", imgArray, "image");
Also thanks for the help KooKiz. :)
You're mixing two approaches in your code.
Either directly read the contents of the stream in a byte array:
byte[] imgArray = new byte[appGlobal.appData.selectedPhoto.ChosenPhoto.Length];
appGlobal.appData.selectedPhoto.ChosenPhoto.Read(imgArray, 0, imgArray.Length);
request.AddFile("image", imgArray, "image", "image/jpeg");
Or copy the stream to a MemoryStream then use the ToArray method:
using (MemoryStream memo = new MemoryStream())
{
appGlobal.appData.selectedPhoto.ChosenPhoto.CopyTo(memo);
byte[] imgArray = memo.ToArray();
request.AddFile("image", imgArray, "image", "image/jpeg");
}
I have an android.graphics.bitmap and an android.net.Uri both of these I can use anyway I want. But I don't know how to take the bitmap and turn it into a byte[] I have tried using a Parcel but I can't initialize it, and when I use it in the writetoparcel method for both the bitmap and uri it throws an error.
I tried the bitmaps ToArray method and that does nothing but create an empty array.
I also tried to use the compress method but I cannot initialize a stream. The text editor throws an error about creating a new Stream inside an abstract class.
Is there some reference that I am missing that allows me to do this.
This is what I ended up using to get it into a byte array and resize.
Bitmap thumb;
Android.Net.Uri val;
this.thumb = MediaStore.Images.Media.GetBitmap(this.ContentResolver, this.val);
Bitmap scaledThumb = Bitmap.CreateScaledBitmap(this.thumb, 1600, 1200, true);
MemoryStream stream = new MemoryStream();
scaledThumb.Compress(Bitmap.CompressFormat.Jpeg, 50, stream);
this.byteArr = stream.ToArray();
This is how you do it.
byte[] bitmapData;
using (var stream = new MemoryStream())
{
bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream);
bitmapData = stream.ToArray();
}
My guess is you would want to use:
Android.Graphics.Bitmap.CopyPixelsToBuffer (Java.Nio.Buffer)
or:
Android.Graphics.Bitmap.GetPixels (int[], int, int, int, int, int, int)