Loading WPF Image control from byte array - c#

Hey, I am trying to load an Image control from a byte array, I've tried multiple solutions found online (particularly this site) but nothing seems to work.
My main goal was to obtain an ImageSource from the byte array and return it from a converter.
I've tried:
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = new MemoryStream(lBytes);
bi.EndInit();
But this fails with:
NotSupportedException
No imaging component suitable to complete this operation was found.
Also tried first loading a Bitmap and from there try to get the ImageSource.
using (MemoryStream lMem = new MemoryStream(lBytes))
{
TypeConverter tc = TypeDescriptor.GetConverter(typeof(System.Drawing.Bitmap));
System.Drawing.Bitmap b = (System.Drawing.Bitmap)tc.ConvertFrom(lBytes);
lResult = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
b.GetHbitmap(),
IntPtr.Zero,
System.Windows.Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
b.Dispose();
}
But this fails on the ConvertFrom with "Parameter is not valid."
All of this when loading a valid PNG file in my filesystem.
I am running out of ideas, any clue?
Thanks.
Edit:
Alright, the problem was my way of loading the file...
I was using
using (FileStream lFileStream = new FileStream(pFilePath, FileMode.Open))
{
using (StreamReader lReader = new StreamReader(lFileStream))
{
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
string lString = lReader.ReadToEnd();
bf.Serialize(ms, lString);
ms.Seek(0, 0);
lImage = ms.ToArray();
}
lResult = new Graphic(lImage);
}
}
But then read that I could use:
lImage = File.ReadAllBytes(pFilePath);
And that's it.
Thank you.

First solution works correctly but I think your problem is about how to read array byte not how to convert the array to bitmap.
I've used that solution many times. The difference between my solution and your solution is how to read the file and convert it to an array.
I simply use:
System.IO.File.ReadAllBytes(filepath)

Related

Conversion from byte[] to image using image.FromStream method

I try converting image data from the database which is already in byte[] back to the image and I'm getting "invalid parameter error" using Image.FileStream.
Please, can anyone help me out with this?
I've tried working around the code using various methods and the last one is below in my code.
byte[] data = validaccount.FingerPrint;
try
{
using (MemoryStream strm = new MemoryStream())
{
strm.Write(data, 0, data.Length);
strm.Position = 0;
System.Drawing.Image img = System.Drawing.Image.FromStream(strm);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
MemoryStream ms = new MemoryStream();
img.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
ms.Seek(0, SeekOrigin.Begin);
bi.StreamSource = ms;
bi.EndInit();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
The code is supposed to convert the byte[] into an image.
According to the docs, Image.FromStream(stream) will throw an argument exception if "The stream does not have a valid image format". Have you verified the data is actually correct? If so, what type of image is it?
You're misusing your streams. You only need 1 memory stream and it has a constructor that takes a byte array (no need to write the bytes yourself). Be sure to wrap it in a using block (like you did for your first stream).
You may not want to use BitmapImage - that's for xaml/wpf apps. You probably want System.Drawing.Bitmap which inherits/extends System.Drawing.Image. Additionally, Bitmap has a constructor which takes a stream - no need to use FromStream.
Finally, Image (and hence Bitmap since Bitmap inherits Image) implements IDisposable, so you should also wrap it in a using block.
P.S. This is a duplicate question.
Though its not memory stream, this method has worked for me and if you browse SO for your question, some times MS does not work.
using System.Drawing;
var converterdImage = (Bitmap)((new ImageConverter()).ConvertFrom(byteArray));
Byte Array to Image Conversion

Why can't I create an image from image array

I'm getting an error very similar to A generic error occurred in GDI+, JPEG Image to MemoryStream
However, I don't believe I'm shutting down the stream and as such, the answers don't apply
Please consider
var img = (Tests.Properties.Resources.image).ToByteArray(); //img is a png;
using (var ms = new MemoryStream(img))
{
var pic = Image.FromStream(ms);
pic.Save(this._absolutePath, this._format); //kaboomn
}
The issue is the final line of code goes kaboom!
"A generic error occurred in GDI+."
This is the extension method
public static byte[] ToByteArray(this Bitmap image)
{
using (var ms = new MemoryStream())
{
image.Save(ms, image.RawFormat);
return ms.ToArray();
}
}
So, although I'm using 2 streams, the first time returns the bytes and as such, I'm not using the same stream, I'm simply working with the bytes.
replace
using (var ms = new MemoryStream(img))
{
var pic = Image.FromStream(ms);
pic.Save(this._absolutePath, this._format);
}
to
var pic = Image.FromStream(new MemoryStream(img)));
pic.Save(this._absolutePath, this._format);
Check this Bitmap and Image constructor dependencies

How to change a Android.graphics.bitmap into a byte array in c#

I have an android.graphics.bitmap and an android.net.Uri both of these I can use anyway I want. But I don't know how to take the bitmap and turn it into a byte[] I have tried using a Parcel but I can't initialize it, and when I use it in the writetoparcel method for both the bitmap and uri it throws an error.
I tried the bitmaps ToArray method and that does nothing but create an empty array.
I also tried to use the compress method but I cannot initialize a stream. The text editor throws an error about creating a new Stream inside an abstract class.
Is there some reference that I am missing that allows me to do this.
This is what I ended up using to get it into a byte array and resize.
Bitmap thumb;
Android.Net.Uri val;
this.thumb = MediaStore.Images.Media.GetBitmap(this.ContentResolver, this.val);
Bitmap scaledThumb = Bitmap.CreateScaledBitmap(this.thumb, 1600, 1200, true);
MemoryStream stream = new MemoryStream();
scaledThumb.Compress(Bitmap.CompressFormat.Jpeg, 50, stream);
this.byteArr = stream.ToArray();
This is how you do it.
byte[] bitmapData;
using (var stream = new MemoryStream())
{
bitmap.Compress(Bitmap.CompressFormat.Png, 0, stream);
bitmapData = stream.ToArray();
}
My guess is you would want to use:
Android.Graphics.Bitmap.CopyPixelsToBuffer (Java.Nio.Buffer)
or:
Android.Graphics.Bitmap.GetPixels (int[], int, int, int, int, int, int)

Load a byte[] into an Image at Runtime

I have a byte[] that is represented by an Image. I am downloading this Image via a WebClient. When the WebClient has downloaded the picture and I reference it using its URL, I get a byte[]. My question is, how do I load a byte[] into an Image element in WPF? Thank you.
Note: This is complementary to the question I asked here: Generate Image at Runtime. I cannot seem to get that approach to work, so I am trying a different approach.
Create a BitmapImage from the MemoryStream as below:
MemoryStream byteStream = new MemoryStream(bytes);
BitmapImage image = new BitmapImage();
image.BeginInit();
image.StreamSource = byteStream;
image.EndInit();
And in XAML you can create an Image control and set the above image as the Source property.
You can use a BitmapImage, and sets its StreamSource to a stream containing the binary data. If you want to make a stream from a byte[], use a MemoryStream:
MemoryStream stream = new MemoryStream(bytes);
In .Net framework 4.0
using System.Drawing;
using System.Web;
private Image GetImageFile(HttpPostedFileBase postedFile)
{
if (postedFile == null) return null;
return Image.FromStream(postedFile.InputStream);
}
One way that I figured out how to do it so that it was both fast and thread safe was the following:
var imgBytes = value as byte[];
if (imgBytes == null)
return null;
using (var stream = new MemoryStream(imgBytes))
return BitmapFrame.Create(stream,BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
I threw that into a converter for my WPF application after running the images as Varbinary from the DB.

Image.Save(..) throws a GDI+ exception because the memory stream is closed

i've got some binary data which i want to save as an image. When i try to save the image, it throws an exception if the memory stream used to create the image, was closed before the save. The reason i do this is because i'm dynamically creating images and as such .. i need to use a memory stream.
this is the code:
[TestMethod]
public void TestMethod1()
{
// Grab the binary data.
byte[] data = File.ReadAllBytes("Chick.jpg");
// Read in the data but do not close, before using the stream.
Stream originalBinaryDataStream = new MemoryStream(data);
Bitmap image = new Bitmap(originalBinaryDataStream);
image.Save(#"c:\test.jpg");
originalBinaryDataStream.Dispose();
// Now lets use a nice dispose, etc...
Bitmap2 image2;
using (Stream originalBinaryDataStream2 = new MemoryStream(data))
{
image2 = new Bitmap(originalBinaryDataStream2);
}
image2.Save(#"C:\temp\pewpew.jpg"); // This throws the GDI+ exception.
}
Does anyone have any suggestions to how i could save an image with the stream closed? I cannot rely on the developers to remember to close the stream after the image is saved. In fact, the developer would have NO IDEA that the image was generated using a memory stream (because it happens in some other code, elsewhere).
I'm really confused :(
As it's a MemoryStream, you really don't need to close the stream - nothing bad will happen if you don't, although obviously it's good practice to dispose anything that's disposable anyway. (See this question for more on this.)
However, you should be disposing the Bitmap - and that will close the stream for you. Basically once you give the Bitmap constructor a stream, it "owns" the stream and you shouldn't close it. As the docs for that constructor say:
You must keep the stream open for the
lifetime of the Bitmap.
I can't find any docs promising to close the stream when you dispose the bitmap, but you should be able to verify that fairly easily.
A generic error occurred in GDI+.
May also result from incorrect save path!
Took me half a day to notice that.
So make sure that you have double checked the path to save the image as well.
Perhaps it is worth mentioning that if the C:\Temp directory does not exist, it will also throw this exception even if your stream is still existent.
Copy the Bitmap. You have to keep the stream open for the lifetime of the bitmap.
When drawing an image: System.Runtime.InteropServices.ExternalException: A generic error occurred in GDI
public static Image ToImage(this byte[] bytes)
{
using (var stream = new MemoryStream(bytes))
using (var image = Image.FromStream(stream, false, true))
{
return new Bitmap(image);
}
}
[Test]
public void ShouldCreateImageThatCanBeSavedWithoutOpenStream()
{
var imageBytes = File.ReadAllBytes("bitmap.bmp");
var image = imageBytes.ToImage();
image.Save("output.bmp");
}
I had the same problem but actually the cause was that the application didn't have permission to save files on C. When I changed to "D:\.." the picture has been saved.
You can try to create another copy of bitmap:
using (var memoryStream = new MemoryStream())
{
// write to memory stream here
memoryStream.Position = 0;
using (var bitmap = new Bitmap(memoryStream))
{
var bitmap2 = new Bitmap(bitmap);
return bitmap2;
}
}
This error occurred to me when I was trying from Citrix. The image folder was set to C:\ in the server, for which I do not have privilege. Once the image folder was moved to a shared drive, the error was gone.
A generic error occurred in GDI+. It can occur because of image storing paths issues,I got this error because my storing path is too long, I fixed this by first storing the image in a shortest path and move it to the correct location with long path handling techniques.
I was getting this error, because the automated test I was executing, was trying to store snapshots into a folder that didn't exist. After I created the folder, the error resolved
One strange solution which made my code to work.
Open the image in paint and save it as a new file with same format(.jpg). Now try with this new file and it works. It clearly explains you that the file might be corrupted in someway.
This can help only if your code has every other bugs fixed
It has also appeared with me when I was trying to save an image into path
C:\Program Files (x86)\some_directory
and the .exe wasn't executed to run as administrator, I hope this may help someone who has same issue too.
For me the code below crashed with A generic error occurred in GDI+on the line which Saves to a MemoryStream. The code was running on a web server and I resolved it by stopping and starting the Application Pool that was running the site.
Must have been some internal error in GDI+
private static string GetThumbnailImageAsBase64String(string path)
{
if (path == null || !File.Exists(path))
{
var log = ContainerResolver.Container.GetInstance<ILog>();
log.Info($"No file was found at path: {path}");
return null;
}
var width = LibraryItemFileSettings.Instance.ThumbnailImageWidth;
using (var image = Image.FromFile(path))
{
using (var thumbnail = image.GetThumbnailImage(width, width * image.Height / image.Width, null, IntPtr.Zero))
{
using (var memoryStream = new MemoryStream())
{
thumbnail.Save(memoryStream, ImageFormat.Png); // <= crash here
var bytes = new byte[memoryStream.Length];
memoryStream.Position = 0;
memoryStream.Read(bytes, 0, bytes.Length);
return Convert.ToBase64String(bytes, 0, bytes.Length);
}
}
}
}
I came across this error when I was trying a simple image editing in a WPF app.
Setting an Image element's Source to the bitmap prevents file saving.
Even setting Source=null doesn't seem to release the file.
Now I just never use the image as the Source of Image element, so I can overwrite after editing!
EDIT
After hearing about the CacheOption property(Thanks to #Nyerguds) I found the solution:
So instead of using the Bitmap constructor I must set the Uri after setting CacheOption BitmapCacheOption.OnLoad.(Image1 below is the Wpf Image element)
Instead of
Image1.Source = new BitmapImage(new Uri(filepath));
Use:
var image = new BitmapImage();
image.BeginInit();
image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
image.CacheOption = BitmapCacheOption.OnLoad;
image.UriSource = new Uri(filepath);
image.EndInit();
Image1.Source = image;
See this: WPF Image Caching
Try this code:
static void Main(string[] args)
{
byte[] data = null;
string fullPath = #"c:\testimage.jpg";
using (MemoryStream ms = new MemoryStream())
using (Bitmap tmp = (Bitmap)Bitmap.FromFile(fullPath))
using (Bitmap bm = new Bitmap(tmp))
{
bm.SetResolution(96, 96);
using (EncoderParameters eps = new EncoderParameters(1))
{
eps.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
bm.Save(ms, GetEncoderInfo("image/jpeg"), eps);
}
data = ms.ToArray();
}
File.WriteAllBytes(fullPath, data);
}
private static ImageCodecInfo GetEncoderInfo(string mimeType)
{
ImageCodecInfo[] encoders = ImageCodecInfo.GetImageEncoders();
for (int j = 0; j < encoders.Length; ++j)
{
if (String.Equals(encoders[j].MimeType, mimeType, StringComparison.InvariantCultureIgnoreCase))
return encoders[j];
}
return null;
}
I used imageprocessor to resize images and one day I got "A generic error occurred in GDI+" exception.
After looked up a while I tried to recycle the application pool and bingo it works. So I note it here, hope it help ;)
Cheers
I was getting this error today on a server when the same code worked fine locally and on our DEV server but not on PRODUCTION. Rebooting the server resolved it.
public static byte[] SetImageToByte(Image img)
{
ImageConverter converter = new ImageConverter();
return (byte[])converter.ConvertTo(img, typeof(byte[]));
}
public static Bitmap SetByteToImage(byte[] blob)
{
MemoryStream mStream = new MemoryStream();
byte[] pData = blob;
mStream.Write(pData, 0, Convert.ToInt32(pData.Length));
Bitmap bm = new Bitmap(mStream, false);
mStream.Dispose();
return bm;
}

Categories

Resources