Convert Byte Array to Image in Wpf

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



Leave a reply



Submit