WPF C# Image Source - c#

I'm pretty new to displaying images in WPF forms, and i'm having trouble when it comes to converting and assigning an Image source for my GUI.
System.Drawing.Image testImg = ImageServer.DownloadCharacterImage(charID, ImageServer.ImageSize.Size128px);
byte[] barr = imgToByteArray(testImg);
CharImage.Source = ByteToImage(barr);
public byte[] imgToByteArray(System.Drawing.Image testImg)
{
using (MemoryStream ms = new MemoryStream())
{
testImg.Save(ms,System.Drawing.Imaging.ImageFormat.Jpeg);
return ms.ToArray();
}
}
public System.Drawing.Image ByteToImage(byte[] barr)
{
MemoryStream ms = new MemoryStream(barr);
System.Drawing.Image returnImage = System.Drawing.Image.FromStream(ms);
return returnImage;
}
So i take in an image (JPEG) from the EVE Online C# API Library and then try to convert it to a byte array and back to a proper image. However i always get this error: "Cannot Implicitly convert type 'System.Drawing.Image' to 'System.Windows.Media.ImageSource'" I'm completely dumbfounded on how to solve this.

One possible solution is to save the image files (for example, .jpg) as WPF embedded resource and then use the following code snippet to get BitmapImage:
Listing 1. Get BitmapImage from EmbeddedResource
private string GetAssemblyName()
{
try { return Assembly.GetExecutingAssembly().FullName.Split(',')[0]; }
catch { throw; }
}
private BitmapImage GetEmbeddedBitmapImage(string pathImageFileEmbedded)
{
try
{
// compose full path to embedded resource file
string _fullPath = String.Concat(String.Concat(GetAssemblyName(), "."), pathImageFileEmbedded);
BitmapImage _bmpImage = new BitmapImage();
_bmpImage.BeginInit();
_bmpImage.StreamSource = Assembly.GetExecutingAssembly().GetManifestResourceStream(_fullPath);
_bmpImage.EndInit();
return _bmpImage;
}
catch { throw; }
finally { }
}
Correspondingly, set the Source property of the WPF Image control (for example, Image1) to that BitmapImage returned by function:
Image1.Source = GetEmbeddedBitmapImage(_strEmbeddedPath);
Note: you should reference the following:
using System.Windows.Media.Imaging;
using System.Reflection;
Another possible solution is to get the BitmapImage from image file using Uri object as shown in the following code snippet (Listing 2):
Listing 2. Get BitmapImage from File (use Uri)
private BitmapImage GetBitmapImageFromFile(string ImagePath)
{
Uri BitmapUri;
StreamResourceInfo BitmapStreamSourceInfo;
try
{
// Convert stream to Image.
BitmapImage bi = new BitmapImage();
BitmapUri = new Uri(ImagePath, UriKind.Relative);
BitmapStreamSourceInfo = Application.GetResourceStream(BitmapUri);
bi.BeginInit();
bi.StreamSource = BitmapStreamSourceInfo.Stream;
bi.EndInit();
return bi;
}
catch { throw; }
}
Hope this may help.

System.Drawing.Image is WinForms, not WPF. Your ByteToImage method should return BitmapSource instead.
The probably easiest way to create a BitmapSource from a byte array is BitmapFrame.Create:
public BitmapSource ByteArrayToImage(byte[] buffer)
{
using (var stream = new MemoryStream(buffer))
{
return BitmapFrame.Create(stream,
BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
}
You would assign the return value of the above method to the Source property of an Image control:
image.Source = ByteArrayToImage(barr);

Related

Converting ImageSource to String on C# WPF

ESRI Symbology library is slow and sometimes take longer time than expected.
I wish to serialize a selected range of ImageSource to a cache, string in the memory or file.
I have searched the web but not much on ImageSource.
An interesting thing I have found is "ImageSourceValueSerializer".
Being a 3 months old baby in WPF, I am not so sure how to go about this.
here's how I got the ImageSource:
MultilayerPointSymbol multiLayerSym = await result.GetSymbolAsync() as MultilayerPointSymbol;
RuntimeImage swatch = await multiLayerSym.CreateSwatchAsync();
ImageSource symbolImage = await swatch.ToImageSourceAsync();
Tested Clemen's, the routine:
MultilayerPointSymbol multiLayerSym = await result.GetSymbolAsync() as MultilayerPointSymbol;
RuntimeImage swatch = await multiLayerSym.CreateSwatchAsync();
ImageSource symbolImage = await swatch.ToImageSourceAsync();
byte[] b = ImageSourceBinary(symbolImage);
ImageSource test = BinaryImageSource(b);
In the class:
private byte[] ImageSourceBinary(ImageSource imageSrc)
{
if (imageSrc is BitmapSource bitmapSource)
{
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
using (MemoryStream stream = new MemoryStream())
{
encoder.Save(stream);
return stream.ToArray();
}
}
return null;
}
private ImageSource BinaryImageSource(byte[] bytes)
{
using (MemoryStream stream = new MemoryStream(bytes))
{
PngBitmapDecoder decoder = new PngBitmapDecoder(stream, BitmapCreateOptions.IgnoreImageCache, BitmapCacheOption.Default);
BitmapFrame bf = decoder.Frames[0];
if (bf is ImageSource imagesource)
return imagesource;
return null;
}
}
The outcome, no image! :(
Check if the ImageSource is a BitmapSource and encode the BitmapSource by one of the BitmapEncoders. Encode into a MemoryStream or a FileStream.
private byte[] ImageSourceToByteArray(ImageSource imageSrc)
{
if (symbolImage is BitmapSource bitmapSource)
{
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
using (var stream = new MemoryStream())
{
encoder.Save(stream);
return stream.ToArray();
}
}
return null;
}
In order to decode an image from a byte array, do not explictly use a specific BitmapDecoder. Better rely on automatic decoder selection, like shown below. It is also important to set BitmapCacheOption.OnLoad when the stream is closed right after decoding.
private ImageSource ByteArrayToImageSource(byte[] bytes)
{
using (var stream = new MemoryStream(bytes))
{
return BitmapFrame.Create(
stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
}

How to override(use) BitmapFrame.Thumbnail property in WPF C#?

Hello! The problem is? that I've got a multipage Tiff file to show, and I use
BitmapFrame.Thumbnail property to show small size thumbnail of every frame(page) of my multipage Tiff file. But< for some reason? the property returns null. Please, give step by step description, of how this should be done?
I've already tried to create my own BitmapSource thumbnail with this method:
public static BitmapImage GetThumbnail(BitmapFrame bitmapFrame)
{
try
{
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
MemoryStream memorystream = new MemoryStream();
BitmapImage tmpImage = new BitmapImage();
encoder.Frames.Add(bitmapFrame);
encoder.Save(memorystream);
tmpImage.BeginInit();
tmpImage.CacheOption = BitmapCacheOption.OnLoad;
tmpImage.StreamSource = new MemoryStream(memorystream.ToArray());
File.WriteAllBytes( $"{Path.GetTempFileName()}.jpg", memorystream.ToArray());
tmpImage.UriSource = new Uri($"{Path.GetTempFileName()}.jpg");
tmpImage.DecodePixelWidth = 80;
tmpImage.DecodePixelHeight = 120;
tmpImage.EndInit();
memorystream.Close();
return tmpImage;
}
catch (Exception ex)
{
return null;
throw ex;
}
}
then I convert the result to BitmapSource and create a list of BitmapFrames using:
List<BitmapFrame> tiffImageList = new List<BitmapFrame>();
tiffImageList.Add(new TiffImage() { index = imageIndex, image = BitmapFrame.Create(frame, (BitmapSource)GetThumbnail(frame))});
In the end I try to get property, but it returns null:
foreach (var tiffImage in tiffImageList)
{
Image image = new Image();
image.Source = tiffImage.image.Thumbnail;
}
I ran into a similar issue, modifying with the SDK PhotoViewerDemo example. Some valid jpg's are shown as white square thumbnails.
I think I found why the question code does not work. Ivan's question provides a correct constructor of BitmapFrame, but the functions have to create a BitmapSource, not a BitmapImage.
C# BitmapFrame.Thumbnail property is null for some images
I got it working with the function provided in that topic, using Ivan's call to the constructor, using the two bitmapsource arguments.
Code in the SDK example I now use is..
private BitmapSource CreateBitmapSource(Uri path)
{
BitmapImage bmpImage = new BitmapImage();
bmpImage.BeginInit();
bmpImage.UriSource = path;
bmpImage.EndInit();
return bmpImage;
}
private BitmapSource CreateThumbnail(Uri path)
{
BitmapImage bmpImage = new BitmapImage();
bmpImage.BeginInit();
bmpImage.UriSource = path;
bmpImage.DecodePixelWidth = 120;
bmpImage.EndInit();
return bmpImage;
}
// it has to be plugged in here,
public Photo(string path)
{
Source = path;
_source = new Uri(path);
// replaced.. Image = BitmapFrame.Create(_source);
// with this:
Image = BitmapFrame.Create(CreateBitmapSource(_source),CreateThumbnail(_source));
Metadata = new ExifMetadata(_source);
}

How can I decode a byte array using a JpegBitmapDecoder

I cannot decode images back from their encoded form as a (Jpeg) byte array retrieved from my database to be used as image sources for my WPF application.
The code I am using to encode them as a Jpeg byte array is as follows:
public byte[] bytesFromBitmap(BitmapImage bit)
{
byte[] data;
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bit));
using (MemoryStream ms = new MemoryStream())
{
encoder.Save(ms);
data = ms.ToArray();
}
return data;
}
This is taking my Image taken directly from a webpage and assigned to an Image control like so:
var img = new BitmapImage(new Uri(entity.Image.ImageSrc)); //the entity has been saved in my DB, having been parsed from html
pbImage.Source = img;
This works just fine, I encode the BitmapImage and it saves just fine. But when I retrieve it from the DB and try to display it in another window, I cannot get it to work after trying every example I can see online - all either render nothing, or a black box or a visual mess not at all similar to the image I encoded.
Neither of the following have worked for me:
public BitmapSource GetBMImage(byte[] data)
{
using (var ms = new MemoryStream(data))
{
JpegBitmapDecoder decoder = new JpegBitmapDecoder(ms, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource frame = decoder.Frames[0];
return frame;
}
}
public static BitmapImage ImageFromBytes(byte[] imageData)
{
if (imageData == null)
{
return null;
}
else
{
var image = new BitmapImage();
using (var mem = new MemoryStream())
{
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;
}
} //this throws a 'No imaging component suitable to complete this operation was found' exception
Among other uses of memory streams and decoders I just can't get this to work - can anyone help?

Need to bind ISO Stores file in a ListBox

I am trying to store some soundclips which are tagged with Images chosen from ISO Storage through a PhotoChooserTask.
I can successfully display the image in a standalone Image box but when I am setting the Imagebox source inside a listbox It does not shows the image.
Currently what I am doing is something like this:
public ImageSource Image
{
get {
try
{
BitmapImage image;
if(Category == 11)
{
image = new BitmapImage(new Uri(this.ImageLocation));
}
return image;
}
catch (Exception)
{
return null;
}
}
I don't understand what is missing
BitmapImage can't load image from Isolated Storage. You need to read file image manually
BitmapImage bi = new BitmapImage();
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream fileStream = myIsolatedStorage.OpenFile(this.ImageLocation, FileMode.Open, FileAccess.Read))
{
bi.SetSource(fileStream);
}
}
return bi;
Also, if this won't work, check CreateOptions and set it to None

byte[] to BitmapImage in silverlight

For the purpose of a game, I need to serialize some pictures in a binary file through a WPF application, using bitmapEncoder and its child classes.
But these class are not available in silverlight, so I can't load them into the browser from the same binary file.
Does someone know how to convert a byte[] to BitmapImage in silverlight?
Thanks,
KiTe
Try something like this:
BitmapImage GetImage( byte[] rawImageBytes )
{
BitmapImage imageSource = null;
try
{
using ( MemoryStream stream = new MemoryStream( rawImageBytes ) )
{
stream.Seek( 0, SeekOrigin.Begin );
BitmapImage b = new BitmapImage();
b.SetSource( stream );
imageSource = b;
}
}
catch ( System.Exception ex )
{
}
return imageSource;
}
use this method
first use
using System.IO;
using System.Windows.Media.Imaging;
then
public Image Base64ToImage(byte[] imageBytes)
{
Image img = new Image();
using (MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length))
{
BitmapImage im = new BitmapImage();
im.SetSource(ms);
img.Source = im;
}
return img;
}

Categories

Resources