Update WPF Image issue under SIlverlight 4.0 - c#

When my page loads and I press button1 I can get the image and can see it.
But when I click it second time it doesn't work at all. I debugged it button1_Click(...) and I am sure that imageData != null.
I really can't figure out what's up... Please help me!
private void button1_Click(object button, RoutedEventArgs e)
{
Guid sid = Guid.Parse("087462df-e4b6-484c-879e-cccc37b4c1f4");
EntityQuery<Screenshot> screen = this._myDomainContext.GetScreenshotQuery(sid);
this._myDomainContext.Load(screen).Completed += (sender, args) =>
{
try
{
byte[] imageData = (((LoadOperation<Screenshot>)sender).Entities.FirstOrDefault()).Screen;
if (imageData != null)
{
BitmapImage img = Utilities.Graphics.GetImage(imageData);
img.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
image1.Source = null;
image1.Source = img;
}
}
catch
{
}
};
}
and
public static 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
{
}
return imageSource;
}

Try changing the overload of Load:
this._myDomainContext.Load(screen, LoadBehavior.RefreshCurrent, true).Completed+= ...

I'm not completely sure on the cause if your issue, but I have a few pointers on the code with regards to using BitmapImage's.
There is no need to set the image1.Source property to null before assigning it with an actual source.
Don't dispose the stream you pass to the BitmapImage in case the control is trying to read from it.
I personally make use of BeginInit(...), StreamSource and EndInit(...) when working with BitmapImage's.

Related

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);
}

WPF image control does not update images

I am working on a project that requires me to get bunch of images and display them as a video. Which means, I will update Image control of WPF 30 times a second.
So far no luck.
BitmapImage img = BitmapToImageSource((Bitmap)image);
this.image_box.Dispatcher.Invoke(() =>
{
//this.image_box.Source.Freeze();
this.image_box.Source = img;
});
BitmapImage BitmapToImageSource(Bitmap bitmap)
{
using (MemoryStream memory = new MemoryStream())
{
bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Bmp);
memory.Position = 0;
BitmapImage bitmapimage = new BitmapImage();
bitmapimage.BeginInit();
bitmapimage.StreamSource = memory;
bitmapimage.CacheOption = BitmapCacheOption.OnLoad;
bitmapimage.EndInit();
return bitmapimage;
}
}
image_box is the image control (wpf).
So, I was expecting this code to update image and give an illusion of video being played. Whereas it does nothing. I see waiting cursor on the window.
Edited ---- More Info ----
I created a simple program to check if images can be changed in image control. But the results are same. I see waiting cursor and no image.
private void Window_Loaded(object sender, RoutedEventArgs e)
{
ImageSource s1;
ImageSource s2;
s1 = new BitmapImage(new Uri(#"IMAGE_PATH", UriKind.Absolute));
s2 = new BitmapImage(new Uri(#"IMAGE_PATH", UriKind.Absolute));
while (true)
{
try
{
if (image.Source == s1)
image.Source = s2;
else
image.Source = s1;
System.Threading.Thread.Sleep(1000);
}
catch(Exception ex)
{
MessageBox.Show("Error");
}
}
}
Although I knew this fact, but still made the same mistake.
We are not allowed to update GUI in a loop. If we want to do so, we need to create a separate thread.

WPF C# Image Source

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);

Xaml C# replacing images from an array of images

Ik in windows forms I could add images in resources and then change the images as users click on an event handler not sure whats changed in Xaml but I cant figure it out.
private void guessClick(object sender, RoutedEventArgs e)
{
wrongGuesses++;
hangmanPicture.Image = hangmanImage[wrongGuesses];
}
if I just put hangmanPicture = hangmanImage[wrongGuesses];
I get can not convert. I don't understand why its trying to convert anything.
if your hangmanImage array is an array of ImageSource or BitmapImage, you can use it like this:
private void guessClick(object sender, RoutedEventArgs e)
{
wrongGuesses++;
hangmanPicture.Source = hangmanImage[wrongGuesses];
}
Otherwise, you have to convert anything in hangmanImage into ImageSource or BitmapImage.
If it's Bitmap you can use below converter before that code:
public static BitmapImage ConvertToBitmapImageFromBitmap(Bitmap bitmap)
{
using(var memory = new MemoryStream())
{
BitmapImage bitmapImage;
bitmap.Save(memory, ImageFormat.Png);
memory.Position = 0;
bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = memory;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
return bitmapImage;
}
}
So, then it will be like this:
hangmanPicture.Source = ConvertToBitmapImageFromBitmap(hangmanImage[wrongGuesses]);

Silverlight: Getting image (from OpenFileDialog) width/height

I've been using the BitmapImage.DownloadProgress event to wait until the image is loaded when creating a bitmap from a URI. That was I can use an event handler to check the Image.ActualWidth/ActualHeight after the download is complete. This works fine.
But when I am loading an image that the user has selected from their computer, the DownloadProgress is useless.
This works for URI bitmaps:
private void LoadImage(Uri uri)
{
this.ResetProgressImage();
BitmapImage image = new BitmapImage();
image.DownloadProgress += new EventHandler<DownloadProgressEventArgs>(LoadImageDownloadProgress);
image.UriSource = uri;
this.ImageFull.Source = image;
}
private void LoadImageDownloadProgress(object sender, DownloadProgressEventArgs e)
{
this.Dispatcher.BeginInvoke(delegate
{
this.ProgressImage.Value = e.Progress;
if (e.Progress == 100)
{
ImageHelper.Current.Width = Math.Round(this.ImageFull.ActualWidth);
ImageHelper.Current.Height = Math.Round(this.ImageFull.ActualHeight);
}
});
}
But this doesn't work when getting a BitmapImage from a stream:
private void LoadImage(Stream stream)
{
this.ResetProgressImage();
BitmapImage image = new BitmapImage();
image.DownloadProgress += new EventHandler<DownloadProgressEventArgs>(LoadImageDownloadProgress);
image.SetSource(stream);
this.ImageFull.Source = image;
}
Does anyone know an alternative to DownloadProgress, when using SetSource(stream)?
There is no event in BitmapImage to monitor the loading progress using a stream.
However, if you just need the image dimensions, you can add the image to the hierarchy and wait for the "Loaded" or "LayoutUpdated" event.

Categories

Resources