Convert byte array to image in wpf
Hi this should be working:
private static BitmapImage LoadImage(byte[] imageData)
{
if (imageData == null || imageData.Length == 0) return null;
var image = new BitmapImage();
using (var mem = new MemoryStream(imageData))
{
mem.Position = 0;
image.BeginInit();
image.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = null;
image.StreamSource = mem;
image.EndInit();
}
image.Freeze();
return image;
}
What is the easiest way to display an image from Byte[]?
The BitmapImage.StreamSource
property only accepts a stream that contains an encoded bitmap buffer, e.g. a PNG or JPEG.
In order to create a BitmapSource
(the base class of BitmapImage
) from raw pixel data, you may use the BitmapSource.Create()
method. Depending on the number of bits per pixel, and the ordering of the alpha and color channels, you would also have to choose an appropriate PixelFormat
.
Assuming an 8-bit grayscale format, you would create a BitmapSource like this:
private BitmapSource LoadImage(int width, int height, byte[] imageData)
{
var format = PixelFormats.Gray8;
var stride = (width * format.BitsPerPixel + 7) / 8;
return BitmapSource.Create(width, height, 96, 96, format, null, imageData, stride);
}
Of course you would also have to change the type of your property to BitmapSource
(which is more flexible anyway, since you can still assign a BitmapImage
).
public BitmapSource Picture { get; set; }
How do I bind a Byte array to an Image in WPF with a value converter?
Thanks for all your help. I've now got it working. I'm still not sure exactly what the problem was.
This is how I put images into my database…
Private Sub ButtonUpload_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
Dim FileOpenStream As Stream = Nothing
Dim FileBox As New Microsoft.Win32.OpenFileDialog()
FileBox.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures)
FileBox.Filter = "Pictures (*.jpg;*.jpeg;*.gif;*.png)|*.jpg;*.jpeg;*.gif;*.png|" & _
"All Files (*.*)|*.*"
FileBox.FilterIndex = 1
FileBox.Multiselect = False
Dim FileSelected As Nullable(Of Boolean) = FileBox.ShowDialog(Me)
If FileSelected IsNot Nothing AndAlso FileSelected.Value = True Then
Try
FileOpenStream = FileBox.OpenFile()
If (FileOpenStream IsNot Nothing) Then
Dim ByteArray As Byte()
Using br As New BinaryReader(FileOpenStream)
ByteArray = br.ReadBytes(FileOpenStream.Length)
End Using
Dim g As New ZackGraphic
g.Id = Guid.NewGuid
g.ImageData = ByteArray
g.FileSize = CInt(ByteArray.Length)
g.FileName = FileBox.FileName.Split("\").Last
g.FileExtension = "." + FileBox.FileName.Split(".").Last.ToLower
g.DateAdded = Now
Dim bmp As New BitmapImage
bmp.BeginInit()
bmp.StreamSource = New MemoryStream(ByteArray)
bmp.EndInit()
bmp.Freeze()
g.PixelWidth = bmp.PixelWidth
g.PixelHeight = bmp.PixelHeight
db.AddToZackGraphic(g)
db.SaveChanges()
End If
Catch Ex As Exception
MessageBox.Show("Cannot read file from disk. " & Ex.Message, "Add a New Image", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK)
Finally
If (FileOpenStream IsNot Nothing) Then
FileOpenStream.Close()
End If
End Try
End If
End Sub
This is my value converter used to bind a Byte array to an Image…
Class BinaryImageConverter
Implements IValueConverter
Private Function Convert(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.Convert
If value IsNot Nothing AndAlso TypeOf value Is Byte() Then
Dim ByteArray As Byte() = TryCast(value, Byte())
Dim bmp As New BitmapImage()
bmp.BeginInit()
bmp.StreamSource = New MemoryStream(ByteArray)
bmp.EndInit()
Return bmp
End If
Return Nothing
End Function
Private Function ConvertBack(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements IValueConverter.ConvertBack
Throw New Exception("The method or operation is not implemented.")
End Function
End Class
This is my XAML that uses the converter display the image…
<Window xmlns:local="clr-namespace:MyProjectName" ... >
<Window.Resources>
<local:BinaryImageConverter x:Key="imgConverter" />
</Window.Resources>
...
<Image Source="{Binding Path=ImageData, Converter={StaticResource imgConverter}}" />
Display image from byte[ ]
Provided that you have a view model class that implements your IFile
interface, and that its FileData
property contains an encoded image buffer like a PNG or JPEG, you could directly bind to the property like this:
<Image Source="{Binding FileData}"/>
This is because WPF provides built-in, automatic type conversion from several source types, including byte[]
, to ImageSource
.
The type conversion is performed by the class ImageSourceConverter
, which is registered as TypeConverter
[TypeConverterAttribute(typeof(ImageSourceConverter))]
public abstract class ImageSource ...
and does something similar to this:
byte[] buffer = ...
ImageSource result;
using (var stream = new MemoryStream(buffer))
{
result = BitmapFrame.Create(
stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
convert array of bytes to bitmapimage
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[]
.
WPF: Byte array to Image on a button in code behind
Try this (without using the WinForms images)
ImageBrush brush;
BitmapImage bi;
using (var ms = new MemoryStream(myByteArray))
{
brush = new ImageBrush();
bi = new BitmapImage();
bi.BeginInit();
bi.CreateOptions = BitmapCreateOptions.None;
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.StreamSource = ms;
bi.EndInit();
}
brush.ImageSource = bi;
button.Background = brush;
Related Topics
Simple Injector Unable to Inject Dependencies in Web API Controllers
Namespace' But Is Used Like a 'Type'
How to Extract a File from an Embedded Resource and Save It to Disk
Url Mapping with C# Httplistener
How to Make My Product as a Trial Version for 30 Days
Selenium Error - the Http Request to the Remote Webdriver Timed Out After 60 Seconds
Why Aren't C# Static Class Extension Methods Supported
Best Way to Determine If Two Path Reference to Same File in C#
Loading Dlls into a Separate Appdomain
How to Put a Task to Sleep (Or Delay) in C# 4.0
Is There Really Any Way to Uniquely Identify Any Computer at All
C# - Winforms - Global Variables
Compare Two Datatables to Determine Rows in One But Not the Other
An Attribute Argument Must Be a Constant Expression, ...- Create an Attribute of Type Array
Main Method Code Entirely Inside Try/Catch: Is It Bad Practice
Modelstate.Isvalid == False, Why
Specified Argument Was Out of the Range of Valid Values. Parameter Name: Site