I have a byte[] that is represented by an Image. I am downloading this Image via a WebClient. When the WebClient has downloaded the picture and I reference it using its URL, I get a byte[]. My question is, how do I load a byte[] into an Image element in WPF? Thank you.
Note: This is complementary to the question I asked here: Generate Image at Runtime. I cannot seem to get that approach to work, so I am trying a different approach.
Create a BitmapImage from the MemoryStream as below:
MemoryStream byteStream = new MemoryStream(bytes);
BitmapImage image = new BitmapImage();
image.BeginInit();
image.StreamSource = byteStream;
image.EndInit();
And in XAML you can create an Image control and set the above image as the Source property.
You can use a BitmapImage, and sets its StreamSource to a stream containing the binary data. If you want to make a stream from a byte[], use a MemoryStream:
MemoryStream stream = new MemoryStream(bytes);
In .Net framework 4.0
using System.Drawing;
using System.Web;
private Image GetImageFile(HttpPostedFileBase postedFile)
{
if (postedFile == null) return null;
return Image.FromStream(postedFile.InputStream);
}
One way that I figured out how to do it so that it was both fast and thread safe was the following:
var imgBytes = value as byte[];
if (imgBytes == null)
return null;
using (var stream = new MemoryStream(imgBytes))
return BitmapFrame.Create(stream,BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
I threw that into a converter for my WPF application after running the images as Varbinary from the DB.
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
Is there any way of converting Stream to Image?
I tried Bitmap, but it states that I don't have System.Drawing... so I tried this:
var bitMap = new BitmapImage();
bitMap.SetSourceAsync(stream);
image.Source = bitMap;
EDIT:
I am trying to build UWP app + using VS 2015.
2 - It just states that System.Drawing does not exist in the namespace.
EDIT2:
Ok, I might have explained it wrong. The idea is: I have an Image, and I want to change its source to something different and then for it to reload, so I can see the image.
The image is effectively a "Stream", so I assume I need to convert it to Bitmap and then load somehow.
EDIT3:
Ok, so I think it will be easier to describe and then use the code above:
There is a picture box and I am using:
var stream = new InMemoryRandomAccessStream();
await mediaCapture.CapturePhotoToStreamAsync(ImageEncodingProperties.CreateJpeg(), stream);
Now I would like this Captured Photo to be displayed as an Image. ( Image "box" is created at the start, so the idea is to change source).
Right, so I managed to fix it:
var bitMap = new BitmapImage();
stream.seek(0); // LINE ADDED
bitMap.SetSourceAsync(stream);
image.Source = bitMap;
I turned out that the error that was being produced was : "The component cannot be found.", so I managed to fix it by using this trick.
I am not sure if this is what you are looking for but if you would like to use stream with BitMapImage you should use:
var image = new BitmapImage();
await image.SetSourceAsync(stream);
For instance when you have your photo stored as a byte[] array you can use the stream to convert it to image:
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
DataWriter writer = new DataWriter(stream.GetOutputStreamAt(0))
writer.WriteBytes(<<here your byte[] array>>);
await writer.StoreAsync();
var image = new BitmapImage();
await image.SetSourceAsync(stream);
}
Is that what you need?
Any executable funtion to convert from base64 to an image using c# windows 8.1************* .
I tried :
public Image byteArrayToImage(byte[] byteArrayIn)
{
Image returnImage = null;
using (MemoryStream ms = new MemoryStream(byteArrayIn))
{
returnImage = Image.FromStream(ms);
}
return returnImage;
}
FromStream not suitable for windows 8.1
First of all, the Windows.UI.Xaml.Controls.Image class is a control object, not an actual bitmap-type object. What you actually want is a BitmapImage. Of course, given this misunderstanding, you're likely to run into other problems with your code; you don't show the caller of this method, but if you've confused the type here, you've probably confused it elsewhere. So that will have to be fixed.
Secondly, as is the case with many things in WinRT, doing what you want is somewhat more complicated than if you were using the desktop API. :(
That said, something like this should work:
public Windows.UI.Xaml.Media.Imaging.BitmapImage byteArrayToImage(byte[] byteArrayIn)
{
using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
{
await stream.WriteAsync(byteArrayIn.AsBuffer(0, byteArrayIn.Length));
stream.Seek(0);
BitmapImage image = new BitmapImage();
await image.SetSourceAsync(stream);
return image;
}
}
Then you can set that object to the Source property of an Image control object.
Some notes:
In your original example, disposing the source stream is at the very least unconventional. My recollection is that in at least some cases, doing so isn't legal, as the Bitmap object returned requires the Stream instance to remain undisposed. For WinRT, AFAIK disposing the stream after the bitmap has been initialized is fine.
The AsBuffer() method is an extension method. You'll need to include a using System.Runtime.InteropServices.WindowsRuntime; in your code if it's not already there for it to work.
See also:
BitmapSource class
InMemoryRandomAccessStream class
WindowsRuntimeBufferExtensions Class
I'm going to convert array of bytes to System.Windows.Media.Imaging.BitmapImage and show the BitmapImage in an image control.
When I'm using the first code, noting happens! no error and no image is displayed. But when I'm using the second one it works fine! can anyone say what is going on?
first code is here:
public BitmapImage ToImage(byte[] array)
{
using (System.IO.MemoryStream ms = new System.IO.MemoryStream(array))
{
BitmapImage image = new BitmapImage();
image.BeginInit();
image.StreamSource = ms;
image.EndInit();
return image;
}
}
second code is here:
public BitmapImage ToImage(byte[] array)
{
BitmapImage image = new BitmapImage();
image.BeginInit();
image.StreamSource = new System.IO.MemoryStream(array);
image.EndInit();
return image;
}
In the first code example the stream is closed (by leaving the using block) before the image is actually loaded. You must also set BitmapCacheOptions.OnLoad to achieve that the image is loaded immediately, otherwise the stream needs to be kept open, as in your second example.
public BitmapImage ToImage(byte[] array)
{
using (var ms = new System.IO.MemoryStream(array))
{
var image = new BitmapImage();
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad; // here
image.StreamSource = ms;
image.EndInit();
return image;
}
}
From the Remarks section in BitmapImage.StreamSource:
Set the CacheOption property to BitmapCacheOption.OnLoad if you wish
to close the stream after the BitmapImage is created.
Besides that, you can also use built-in type conversion to convert from type byte[] to type ImageSource (or the derived BitmapSource):
var bitmap = (BitmapSource)new ImageSourceConverter().ConvertFrom(array);
ImageSourceConverter is called implicitly when you bind a property of type ImageSource (e.g. the Image control's Source property) to a source property of type string, Uri or byte[].
In the first case, you defined your MemoryStream in a using block, which causes the object to be disposed when you go out of the block. So you return a BitmapImage with a disposes (and non-existing) stream.
MemoryStreams keep no unmanaged resources, so you can leave the memory and let the GC handle the freeing process (but that's not a good practice).
Is there a way in C# to do this conversion and back?
I have a WPF app which has a Image control. I'm trying to save the image in that control to a SQL Database.
In my Entity Model, the datatype of the picture column in my database is a byte[]. So I found a method to convert a System.Drawing.Image to a byte[] and back. But I haven't found a method to convert from System.Windows.Controls.Image to a byte[].
So that's why I now need to do the above conversion.
If you have a byte array that represents a file that WPF can decode (bmp, jpg, gif, png, tif, ico), you can do the following:
BitmapSource LoadImage(Byte[] imageData)
{
using (MemoryStream ms = new MemoryStream(imageData))
{
var decoder = BitmapDecoder.Create(ms,
BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.OnLoad);
return decoder.Frames[0];
}
}
Likewise, to convert it back, you can do the following:
byte[] SaveImage(BitmapSource bitmap)
{
using (MemoryStream ms = new MemoryStream())
{
var encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
encoder.Save(ms);
return ms.GetBuffer();
}
}
Well, one is an image and one is a control that shows an image, so I don't think that there's a conversion between the two. But, you could set the Source of the ...Controls.Image to be your ...Drawing.Image.
Edit based on update
Does this do what you need - http://msdn.microsoft.com/en-us/library/ms233764%28VS.100%29.aspx