I will appreciate any help. This is a very famous issue, but whatever I read and tried to apply to my specific case, it did not help.
I have a simple function, which takes an image as a base64 string and saves it as a png image. The destination folder is constant. The filename is taken from the imageUrl parameter and is made unique before saving.
public static void SaveWorkOrderImage(string imageData, string imageUrl)
{
try
{
//convert png image saved in a base64 string to Image object
imageData = imageData.Replace("data:image/png;base64,", "");
byte[] bytes = Convert.FromBase64String(imageData);
//...
//some code here which generates the destination path for the new image
//...
using (MemoryStream ms = new MemoryStream(bytes))
{
using (System.Drawing.Image newData = System.Drawing.Image.FromStream(ms))
{
using (Bitmap bmpData = new Bitmap(newData))
{
bmpData.Save(destPath, ImageFormat.Png);
}
}
}
}
catch (Exception ex)
{
//processing and logging exception
}
}
This code runs just fine as MVC application in IIS. But suddenly in about a week of perfect working it starts throwing the following exception for every image that is saved:
Exception Type: System.Runtime.InteropServices.ExternalException
Exception: A generic error occurred in GDI+.
Stack Trace:
at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
at System.Drawing.Image.Save(String filename, ImageFormat format)
If I restart the App Pool, then it again works normally for several days. Usually about a week. Then everything repeats again. It looks like some resources are not being disposed, or there is an overflow of some buffer. But, as you can see, there is a "using" statement for each disposable object.
I also tried to convert it first to a Bitmap (I found such an advise in the similar question). It looked like this before:
using (MemoryStream ms = new MemoryStream(bytes))
{
using (System.Drawing.Image newData = System.Drawing.Image.FromStream(ms))
{
newData.Save(destPath, ImageFormat.Png);
}
}
It did not help however.
I'm doing one application,
i add a picturebox to add image to some products, i have one question, i would like edit the images already added to one product, how can i do that?
This is my actually code.
private void pbImagenEquipo_DoubleClick(object sender, EventArgs e)
{
ofdImagenes.Filter = "Imagenes JPG (*.jpg)|*.jpg; *.jpeg;|Imagenes PNG (*.png)|*.png";
DialogResult resp = ofdImagenes.ShowDialog();
if (resp == DialogResult.OK)
{
Bitmap b = new Bitmap(ofdImagenes.FileName);
string [] archivo = ofdImagenes.FileName.Split('.');
nombre = "Equipo_" + lbID+ "." + archivo[archivo.Length-1];
b.Save(Path.Combine(Application.StartupPath, "Imagenes", nombre));
pbImagenEquipo.Image = b;
}
}
But when i try to replace the image i got this error:
An unhandled exception of type 'System.Runtime.InteropServices.ExternalException' occurred in System.Drawing.dll
Additional information: Error generoc in e GDI+.
This is a common issue.
The documentation says:
Saving the image to the same file it was constructed from is not
allowed and throws an exception.
There are two options. One is to delete the file before writing it.
The other is to use a Stream to write it. I prefer the latter..:
string fn = "d:\\xyz.jpg";
// read image file
Image oldImg = Image.FromFile(fn);
// do something (optional ;-)
((Bitmap)oldImg).SetResolution(123, 234);
// save to a memorystream
MemoryStream ms = new MemoryStream();
oldImg.Save(ms, ImageFormat.Jpeg);
// dispose old image
oldImg.Dispose();
// save new image to same filename
Image newImage = Image.FromStream(ms);
newImage.Save(fn);
Note that saving jpeg files often achieves better quality if you take control of encoding options. Use this overload for this..
Also note that since we need to dispose of the image you need to make sure that it is not used anywhere, like in a PictureBox.Image! If it is, set it to null there before disposing : pictureBox1.Image = null; !
For a solution deleting the old file see here
I am trying to save image date to physical file
Below is image data which I got from a jpeg image (via some browser response):
data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/.....blah blah .....//2Q==
Below is the code I am using to save image data string to Image
Image image = LoadImage(dataURL);
image.Save(saveLocation);
image.Dispose();
public Image LoadImage(string imageString)
{
imageString = imageString.Substring(imageString.IndexOf(',') + 1);
byte[] bytes = Convert.FromBase64String(imageString);
Image image;
using (MemoryStream ms = new MemoryStream(bytes))
{
image = Image.FromStream(ms);
}
return image;
}
Getting the following exception at image.Save(saveLocation); line
A generic error occurred in GDI+.
I have no issues when the image source with png images with the same code but with jpeg images no matter what the size of jpeg is I am getting that exception every time.
I am able to save the png images with same code at same location.
Edit: Please note that I am getting just data image string from browser (which I am capturing via clipboard of browser) i.e I am not getting bytes from client.
Is there any limit for the bytes which can be converted to image stream and then save back to physical file?
Is there any other approach to do the same?
There doesn't seem to be any reason to go through Image at all here.
Assuming the posted data is valid, just write the content to a file directly:
SaveImage(dataURL, saveLocation);
public bool SaveImage(string imageString, string location)
{
try {
imageString = imageString.Substring(imageString.IndexOf(',') + 1);
byte[] bytes = Convert.FromBase64String(imageString);
using (FileStream fs = new FileStream(location, FileMode.Create))
{
fs.Write(bytes, 0, bytes.Count);
}
}
catch(Exception)
{
return false;
}
return true;
}
When trying to save an uploaded file, I get this error and are having some difficulties solving it:
ExternalException: A generic error occurred in GDI+.
It's a very specific exception message!
This is my code.
// Gets the original image.
byte[] original = new byte[file.InputStream.Length];
file.InputStream.Position = 0;
file.InputStream.Read(original, 0, (int)file.InputStream.Length);
// Redimensions the original image and saves it for each of the desired pictures classes.
foreach (ClassDetails c in picturesClasses)
{
byte[] resized = Images.Resize(original, new Size(c.Width, c.Height), c.ResizeToExactProportions);
MemoryStream stream = new MemoryStream(resized);
Image resizedImage = Image.FromStream(stream);
uniqueFilename = string.Format("{0}{1}{2}", Path.GetFileNameWithoutExtension(file.FileName), Guid.NewGuid().ToString(), ".png");
// The exception happens HERE **************************************************
resizedImage.Save(Path.Combine(c.Path, uniqueFilename), ImageFormat.Png);
}
Please, any idea of what could be wrong? Thanks.
Mmm... I love it when problems are solved fast!
The path I had was a relative one. I had to use the Server.MapPath method. See below:
resizedImage.Save(HttpContext.Current.Server.MapPath(Path.Combine(c.Path, uniqueFilename)), ImageFormat.Png);
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;
}