I am trying to save and load an ImageSource (or BitmapSource) to and from an XML file. A quick look on SO gave me this answer.
It looked ok so I tried it out but I am getting a strange result.
When I try this code everything works:
BitmapSource testImgSrc = new WriteableBitmap(new BitmapImage(new Uri("pack://application:,,,/MyNameSpace;component/Images/MyImg.png")));
BackgroundImage = testImgSrc;
But when I try this code the image just does not appear at all:
BitmapSource testImgSrc = new WriteableBitmap(new BitmapImage(new Uri("pack://application:,,,/MyNameSpace;component/Images/MyImg.png")));
string testImgStr = ImageToBase64(testImgSrc);
BitmapSource testImg = Base64ToImage(testImgStr);
BackgroundImage = testImg;
There don't seem to be any errors or exceptions. When steping through the code BackgroundImage looks like it gets set to a valid image object.
My WPF form has an image control that has it's source bound to a property that returns the result of the BackgroundImage property. I am guessing the binding is working ok because the first test works as expected.
Can anyone help me to understand why the second test is not displaying my image?
There's a problem with Base64ToImage method from this answer. The documentation states that with the default OnDemand cache option the stream must not be closed before the image is actually used. In your case this means that the Image element is trying to access the already disposed stream.
The fix is pretty simple, you just need to change the cache option to OnLoad and the problem is gone:
BitmapSource Base64ToImage(string base64)
{
byte[] bytes = Convert.FromBase64String(base64);
using (var stream = new MemoryStream(bytes))
{
return BitmapFrame.Create(stream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
}
}
Related
I am writing an application in Avalonia and using OpenCvSharp to get frames from the camera. This worked with WPF - there I just called
Image.Source = Mat.ToBitmapSource();
but this doesn't work in Avalonia, because there is a different type of Image control, and a different type of its Source property.
I tried doing this via a MemoryStream, but then the Bitmap constructor crashes with an ArgumentNullException (although the stream is not null).
Of course, as soon as I asked you that, I found a solution. Load the image into memory and then call it back.
I was getting the same type of error but that was fixed after I implemented the using statement.
//Place this in your class to create a class variable and create the System.Drawing.Bitmap Bitmap
private System.Drawing.Bitmap irBitmap = new System.Drawing.Bitmap(256, 192, PixelFormat.Format24bppRgb);
//Add this using statement to the function you're converting inside of
//to convert the System.Drawing.Bitmap to Avalonia compatible image for view/viewmodel
using (MemoryStream memory = new MemoryStream())
{
irBitmap.Save(memory, ImageFormat.Png);
memory.Position = 0;
//AvIrBitmap is our new Avalonia compatible image. You can pass this to your view
Avalonia.Media.Imaging.Bitmap AvIrBitmap = new Avalonia.Media.Imaging.Bitmap(memory);
}
Let me know if you have questions or how to specifically tie this into your app. There wasn't a lot of code provided earlier so I didn't have any idea what to name variables for your specific use case.
I have copied some data in Clipboard using MS-Word Com API
Range.CopyAsPicture();
and when I am pasting(Ctrl + v) it on window's paint software its getting displayed.
Issue is while converting Clipboard data to image Using c#
I looked into various link on internet and tried following code which is not working
MemoryStream ms = Clipboard.GetData("DeviceIndependentBitmap") as MemoryStream;
above line returning null
clipboardData.GetDataPresent(System.Windows.Forms.DataFormats.Bitmap)
Above line returning false
Can anyone please suggest how can convert the clipboard data to image.
If all you are looking for is getting the bitmap of the image in the clipboard (or the underlying binary data), look into using GetImage.
Here is a code snippet you can try:
BitmapSource bmpSource = Clipboard.GetImage();
MemoryStream ms = new MemoryStream();
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bmpSource));
encoder.Save(ms);
ms.Seek(0, SeekOrigin.Begin);
In case that also doesn't seem to work, you can try looking into this workaround, it doesn't seem directly related, but it might be just what you need.
Apparently MS Office puts images on the clipboard as a stream of PNG bytes, which is actually a really sensible innovation. This image data simply uses the identifier "PNG".
So try this instead:
if (retrievedData.GetDataPresent("PNG"))
{
MemoryStream png_stream = retrievedData.GetData("PNG") as MemoryStream;
if (png_stream != null)
return new Bitmap(png_stream);
}
This seems like a fairly simple issue, but I can't seem to figure a way to work around it.
In a WPF window I have an image, image_small_pic. In the associated C# file I set the value of that using this code:
Uri src = new Uri(image_source, UriKind.RelativeOrAbsolute);
small_image_bmp = new BitmapImage(src);
image_small_pic.Source = small_image_bmp;
Where small_image_bmp is a public BitmapImage object. But then if then, later on, if I change small_image_bmp to another file and reassign image_small_pic.Source, then the original image is still locked and I can't delete it. Even if I try later it's still locked. Any thoughts how I can free this up?
Check out this article. There's some odd behaviour with WPF images that you're coming across. The solution is to read in the bytes yourself and then create an image based on them, since if you let the framework handle it, the file will remain locked.
Uri src = new Uri(image_source, UriKind.RelativeOrAbsolute);
var small_image_bmp = new BitmapImage();
small_image_bmp.BeginInit();
small_image_bmp.CacheOption = BitmapCacheOption.OnLoad;
small_image_bmp.UriSource = src;
small_image_bmp.EndInit();
image_small_pic.Source = small_image_bmp;
This is not working for some reason. I'm not sure why:
objBitmap = new Bitmap(Resource1.im);
Stream stream;
objBitmap.Save(stream, ImageFormat.Bmp);
this.pictureBox2.Image = Image.FromStream(stream);
objBitmap.Dispose();
Basically, I need to show an image in a PictureBox control and I am not sure how to do that.
pictureBox2.Image = objBitmap;
Well, it ought to go kaboom on the Save() method, the stream was never initialized. Not sure what the point of doing this was. There might be one but it isn't visible from your code. The normal version is:
if (this.pictureBox2.Image != null) this.pictureBox2.Dispose();
this.pictureBox2.Image = Properties.Resources.im;
With some question marks about what Resource1 might be. You get my version going by using Project + Properties, Resource tab and click the arrow on the Add Resource button, Add Existing File.
You can change that to
pictureBox2.Image = Resource1.im;
To answer your question, you need to put a stream (probably a MemoryStream) in the stream variable.
You'll also need to "rewind" the stream before reading it back into a Bitmap. (stream.Position = 0)
I display images in my WPF app using BitmapImage.
However, I would like an easy way to save these (as JPG) to a different location (ideally into a Stream or object that can be passed around).
Is it possible using BitmapImage or do I have to use other means? If so what other means are there for either loading an Image and saving as JPG or converting a BitmapImage into this element to then save off?
Thanks
Something like:
public byte[] GetJPGFromImageControl(BitmapImage imageC)
{
MemoryStream memStream = new MemoryStream();
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(imageC));
encoder.Save(memStream);
return memStream.GetBuffer();
}
(from: WPF Image to byte[])