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;
}
Related
I am working on to upload and save a thumbnail copy of that image in a thumbnail folder.
I am using following link:
http://weblogs.asp.net/markmcdonnell/archive/2008/03/09/resize-image-before-uploading-to-server.aspx
but
newBMP.Save(directory + "tn_" + filename);
is causing exception "A generic error occurred in GDI+."
I have tried to give permission on folder, also tried to use a new separate bmp object when saving.
Edit:
protected void ResizeAndSave(PropBannerImage objPropBannerImage)
{
// Create a bitmap of the content of the fileUpload control in memory
Bitmap originalBMP = new Bitmap(fuImage.FileContent);
// Calculate the new image dimensions
int origWidth = originalBMP.Width;
int origHeight = originalBMP.Height;
int sngRatio = origWidth / origHeight;
int thumbWidth = 100;
int thumbHeight = thumbWidth / sngRatio;
int bannerWidth = 100;
int bannerHeight = bannerWidth / sngRatio;
// Create a new bitmap which will hold the previous resized bitmap
Bitmap thumbBMP = new Bitmap(originalBMP, thumbWidth, thumbHeight);
Bitmap bannerBMP = new Bitmap(originalBMP, bannerWidth, bannerHeight);
// Create a graphic based on the new bitmap
Graphics oGraphics = Graphics.FromImage(thumbBMP);
// Set the properties for the new graphic file
oGraphics.SmoothingMode = SmoothingMode.AntiAlias; oGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Draw the new graphic based on the resized bitmap
oGraphics.DrawImage(originalBMP, 0, 0, thumbWidth, thumbHeight);
Bitmap newBitmap = new Bitmap(thumbBMP);
thumbBMP.Dispose();
thumbBMP = null;
// Save the new graphic file to the server
newBitmap.Save("~/image/thumbs/" + "t" + objPropBannerImage.ImageId, ImageFormat.Jpeg);
oGraphics = Graphics.FromImage(bannerBMP);
// Set the properties for the new graphic file
oGraphics.SmoothingMode = SmoothingMode.AntiAlias; oGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Draw the new graphic based on the resized bitmap
oGraphics.DrawImage(originalBMP, 0, 0, bannerWidth, bannerHeight);
// Save the new graphic file to the server
bannerBMP.Save("~/image/" + objPropBannerImage.ImageId + ".jpg");
// Once finished with the bitmap objects, we deallocate them.
originalBMP.Dispose();
bannerBMP.Dispose();
oGraphics.Dispose();
}
When either a Bitmap object or an Image object is constructed from a
file, the file remains locked for the lifetime of the object. As a
result, you cannot change an image and save it back to the same file
where it originated.
http://support.microsoft.com/?id=814675
A generic error occurred in GDI+, JPEG Image to MemoryStream
Image.Save(..) throws a GDI+ exception because the memory stream is closed
http://alperguc.blogspot.in/2008/11/c-generic-error-occurred-in-gdi.html
EDIT:
just writing from memory...
save to an 'intermediary' memory stream, that should work
e.g. try this one - replace
Bitmap newBitmap = new Bitmap(thumbBMP);
thumbBMP.Dispose();
thumbBMP = null;
newBitmap.Save("~/image/thumbs/" + "t" + objPropBannerImage.ImageId, ImageFormat.Jpeg);
with something like:
string outputFileName = "...";
using (MemoryStream memory = new MemoryStream())
{
using (FileStream fs = new FileStream(outputFileName, FileMode.Create, FileAccess.ReadWrite))
{
thumbBMP.Save(memory, ImageFormat.Jpeg);
byte[] bytes = memory.ToArray();
fs.Write(bytes, 0, bytes.Length);
}
}
This error message is displayed if the path you pass to Bitmap.Save() is invalid (folder doesn't exist etc).
// Once finished with the bitmap objects, we deallocate them.
originalBMP.Dispose();
bannerBMP.Dispose();
oGraphics.Dispose();
This is a programming style that you'll regret sooner or later. Sooner is knocking on the door, you forgot one. You are not disposing newBitmap. Which keeps a lock on the file until the garbage collector runs. If it doesn't run then the second time you try to save to the same file you'll get the klaboom. GDI+ exceptions are too miserable to give a good diagnostic so serious head-scratching ensues. Beyond the thousands of googlable posts that mention this mistake.
Always favor using the using statement. Which never forgets to dispose an object, even if the code throws an exception.
using (var newBitmap = new Bitmap(thumbBMP)) {
newBitmap.Save("~/image/thumbs/" + "t" + objPropBannerImage.ImageId, ImageFormat.Jpeg);
}
Albeit that it is very unclear why you even create a new bitmap, saving thumbBMP should already be good enough. Anyhoo, give the rest of your disposable objects the same using love.
In my case the bitmap image file already existed in the system drive, so my app threw the error "A Generic error occured in GDI+".
Verify that the destination folder exists
Verify that there isn't already a file with the same name in the destination folder
Check your folder's permission where the image is saved
Right cLick on folder then go :
Properties > Security > Edit > Add-- select "everyone" and check Allow "Full Control"
I was facing the same issue A generic error occurred in GDI+ on saving while working on MVC app, I was getting this error because I was writing wrong path to save image, I corrected saving path and it worked fine for me.
img1.Save(Server.MapPath("/Upload/test.png", System.Drawing.Imaging.ImageFormat.Png);
--Above code need one change, as you need to put close brackets on Server.MapPath() method after writing its param.
Like this-
img1.Save(Server.MapPath("/Upload/test.png"), System.Drawing.Imaging.ImageFormat.Png);
GDI+ exceptions occured due to below points
Folder access issue
Missing properties of images
If folder issue - please provide access to application
If Missing properties then use below code
Code 1
using (Bitmap bmp = new Bitmap(webStream))
{
using (Bitmap newImage = new Bitmap(bmp))
{
newImage.Save("c:\temp\test.jpg", ImageFormat.Jpeg);
}
}
Code 2
using (Bitmap bmp = new Bitmap(webStream))
{
using (Bitmap newImage = new Bitmap(bmp))
{
newImage.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);
Rectangle lockedRect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData bmpData = newImage.LockBits(lockedRect, ImageLockMode.ReadWrite, bmp.PixelFormat);
bmpData.PixelFormat = bmp.PixelFormat;
newImage.UnlockBits(bmpData);
using (Graphics gr = Graphics.FromImage(newImage))
{
gr.SmoothingMode = SmoothingMode.HighQuality;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
}
foreach (var item in bmp.PropertyItems)
{
newImage.SetPropertyItem(item);
}
newImage.Save("c:\temp\test.jpg", ImageFormat.Jpeg);
}
}
Different between code 1 and code 2
Code - 1 : it will just create image and can open it on normal image viewer
the image can't open in Photoshop
Image size will be double
Code - 2 : to open image in image edition tools use code
by using code 1 it just create images but it not assign image marks.
I always check/test these:
Does the path + filename contain illegal characters for the given filesystem?
Does the file already exist? (Bad)
Does the path already exist? (Good)
If the path is relative: am I expecting it in the right parent directory (mostly bin/Debug ;-) )?
Is the path writable for the program and as which user does it run? (Services can be tricky here!)
Does the full path really, really not contain illegal chars? (some unicode chars are close to invisible)
I never had any problems with Bitmap.Save() apart from this list.
I had a different issue with the same exception.
In short:
Make sure that the Bitmap's object Stream is not being disposed before calling .Save .
Full story:
There was a method that returned a Bitmap object, built from a MemoryStream in the following way:
private Bitmap getImage(byte[] imageBinaryData){
.
.
.
Bitmap image;
using (var stream = new MemoryStream(imageBinaryData))
{
image = new Bitmap(stream);
}
return image;
}
then someone used the returned image to save it as a file
image.Save(path);
The problem was that the original stream was already disposed when trying to save the image, throwing the GDI+ exeption.
A fix to this problem was to return the Bitmap without disposing the stream itself but the returned Bitmap object.
private Bitmap getImage(byte[] imageBinaryData){
.
.
.
Bitmap image;
var stream = new MemoryStream(imageBinaryData))
image = new Bitmap(stream);
return image;
}
then:
using (var image = getImage(binData))
{
image.Save(path);
}
I got it working using FileStream, get help from these
http://alperguc.blogspot.in/2008/11/c-generic-error-occurred-in-gdi.html
http://csharpdotnetfreak.blogspot.com/2010/02/resize-image-upload-ms-sql-database.html
System.Drawing.Image imageToBeResized = System.Drawing.Image.FromStream(fuImage.PostedFile.InputStream);
int imageHeight = imageToBeResized.Height;
int imageWidth = imageToBeResized.Width;
int maxHeight = 240;
int maxWidth = 320;
imageHeight = (imageHeight * maxWidth) / imageWidth;
imageWidth = maxWidth;
if (imageHeight > maxHeight)
{
imageWidth = (imageWidth * maxHeight) / imageHeight;
imageHeight = maxHeight;
}
Bitmap bitmap = new Bitmap(imageToBeResized, imageWidth, imageHeight);
System.IO.MemoryStream stream = new MemoryStream();
bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
stream.Position = 0;
byte[] image = new byte[stream.Length + 1];
stream.Read(image, 0, image.Length);
System.IO.FileStream fs
= new System.IO.FileStream(Server.MapPath("~/image/a.jpg"), System.IO.FileMode.Create
, System.IO.FileAccess.ReadWrite);
fs.Write(image, 0, image.Length);
For me it was a permission problem. Somebody removed write permissions on the folder for the user account under which the application was running.
Create folder path image/thumbs on your hard disk => Problem solved!
I used below logic while saving a .png format. This is to ensure the file is already existing or not.. if exist then saving it by adding 1 in the filename
Bitmap btImage = new Bitmap("D:\\Oldfoldername\\filename.png");
string path="D:\\Newfoldername\\filename.png";
int Count=0;
if (System.IO.File.Exists(path))
{
do
{
path = "D:\\Newfoldername\\filename"+"_"+ ++Count + ".png";
} while (System.IO.File.Exists(path));
}
btImage.Save(path, System.Drawing.Imaging.ImageFormat.Png);
I encountered this error while trying to convert Tiff images to Jpeg. For me the issue stemmed from the tiff dimensions being too large. Anything up to around 62000 pixels was fine, anything above this size produced the error.
for me it was a path issue when saving the image.
int count = Directory.EnumerateFiles(System.Web.HttpContext.Current.Server.MapPath("~/images/savedimages"), "*").Count();
var img = Base64ToImage(imgRaw);
string path = "images/savedimages/upImages" + (count + 1) + ".png";
img.Save(Path.Combine(System.Web.HttpContext.Current.Server.MapPath(path)));
return path;
So I fixed it by adding the following forward slash
String path = "images/savedimages....
should be
String path = "/images/savedimages....
Hope that helps anyone stuck!
from msdn: public void Save (string filename); which is quite surprising to me because we dont just have to pass in the filename, we have to pass the filename along with the path for example: MyDirectory/MyImage.jpeg, here MyImage.jpeg does not actually exist yet, but our file will be saved with this name.
Another important point here is that if you are using Save() in a web application then use Server.MapPath() along with it which basically just returns the physical path for the virtual path which is passed in. Something like: image.Save(Server.MapPath("~/images/im111.jpeg"));
I use this solution
int G = 0;
private void toolStripMenuItem17_Click(object sender, EventArgs e)
{
Directory.CreateDirectory("picture");// هذه العملية للرسم بدون ان يحذف بقية الرسومات
G = G + 1;
FormScreen();
memoryImage1.Save("picture\\picture" + G.ToString() + ".jpg");
pictureBox1.Image = Image.FromFile("picture\\picture" + G.ToString() + ".jpg");
}
The code below solved my problem
pictureBox1.Image=myImage;
Bitmap bmp = new Bitmap(pictureBox1.Image);
bmp.Save("C:\\Users/super/Desktop/robin.jpg");
I have a web app that runs on Azure. The user can upload an image and I save that image for them. Now when I receive the image, I have it as byte[]. I would like to save it as JPG to save space. The source image could be anything such as PNG, BMP or JPG.
Is it possible to do so? This needs to run on Azure and I am using WebApps/MVC5/C#.
Thanks for any help.
Get the memorystream and then use System.Drawing
var stream = new MemoryStream(byteArray)
Image img = new Bitmap(stream);
img.Save(#"c:\s\pic.png", System.Drawing.Imaging.ImageFormat.Png);
The last line there where you save the file, you can select the format.
So the answers by #mjwills and Cody was correct. I still thought to put the two methods I exactly needed:
public static Image BitmapToBytes(byte[] image, ImageFormat pFormat)
{
var imageObject = new Bitmap(new MemoryStream(image));
var stream = new MemoryStream();
imageObject.Save(stream, pFormat);
return new Bitmap(stream);
}
Also:
public static byte[] ImgToByteArray(Image img)
{
using (MemoryStream mStream = new MemoryStream())
{
img.Save(mStream, img.RawFormat);
return mStream.ToArray();
}
}
Cheers everyone.
I am working on to upload and save a thumbnail copy of that image in a thumbnail folder.
I am using following link:
http://weblogs.asp.net/markmcdonnell/archive/2008/03/09/resize-image-before-uploading-to-server.aspx
but
newBMP.Save(directory + "tn_" + filename);
is causing exception "A generic error occurred in GDI+."
I have tried to give permission on folder, also tried to use a new separate bmp object when saving.
Edit:
protected void ResizeAndSave(PropBannerImage objPropBannerImage)
{
// Create a bitmap of the content of the fileUpload control in memory
Bitmap originalBMP = new Bitmap(fuImage.FileContent);
// Calculate the new image dimensions
int origWidth = originalBMP.Width;
int origHeight = originalBMP.Height;
int sngRatio = origWidth / origHeight;
int thumbWidth = 100;
int thumbHeight = thumbWidth / sngRatio;
int bannerWidth = 100;
int bannerHeight = bannerWidth / sngRatio;
// Create a new bitmap which will hold the previous resized bitmap
Bitmap thumbBMP = new Bitmap(originalBMP, thumbWidth, thumbHeight);
Bitmap bannerBMP = new Bitmap(originalBMP, bannerWidth, bannerHeight);
// Create a graphic based on the new bitmap
Graphics oGraphics = Graphics.FromImage(thumbBMP);
// Set the properties for the new graphic file
oGraphics.SmoothingMode = SmoothingMode.AntiAlias; oGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Draw the new graphic based on the resized bitmap
oGraphics.DrawImage(originalBMP, 0, 0, thumbWidth, thumbHeight);
Bitmap newBitmap = new Bitmap(thumbBMP);
thumbBMP.Dispose();
thumbBMP = null;
// Save the new graphic file to the server
newBitmap.Save("~/image/thumbs/" + "t" + objPropBannerImage.ImageId, ImageFormat.Jpeg);
oGraphics = Graphics.FromImage(bannerBMP);
// Set the properties for the new graphic file
oGraphics.SmoothingMode = SmoothingMode.AntiAlias; oGraphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Draw the new graphic based on the resized bitmap
oGraphics.DrawImage(originalBMP, 0, 0, bannerWidth, bannerHeight);
// Save the new graphic file to the server
bannerBMP.Save("~/image/" + objPropBannerImage.ImageId + ".jpg");
// Once finished with the bitmap objects, we deallocate them.
originalBMP.Dispose();
bannerBMP.Dispose();
oGraphics.Dispose();
}
When either a Bitmap object or an Image object is constructed from a
file, the file remains locked for the lifetime of the object. As a
result, you cannot change an image and save it back to the same file
where it originated.
http://support.microsoft.com/?id=814675
A generic error occurred in GDI+, JPEG Image to MemoryStream
Image.Save(..) throws a GDI+ exception because the memory stream is closed
http://alperguc.blogspot.in/2008/11/c-generic-error-occurred-in-gdi.html
EDIT:
just writing from memory...
save to an 'intermediary' memory stream, that should work
e.g. try this one - replace
Bitmap newBitmap = new Bitmap(thumbBMP);
thumbBMP.Dispose();
thumbBMP = null;
newBitmap.Save("~/image/thumbs/" + "t" + objPropBannerImage.ImageId, ImageFormat.Jpeg);
with something like:
string outputFileName = "...";
using (MemoryStream memory = new MemoryStream())
{
using (FileStream fs = new FileStream(outputFileName, FileMode.Create, FileAccess.ReadWrite))
{
thumbBMP.Save(memory, ImageFormat.Jpeg);
byte[] bytes = memory.ToArray();
fs.Write(bytes, 0, bytes.Length);
}
}
This error message is displayed if the path you pass to Bitmap.Save() is invalid (folder doesn't exist etc).
// Once finished with the bitmap objects, we deallocate them.
originalBMP.Dispose();
bannerBMP.Dispose();
oGraphics.Dispose();
This is a programming style that you'll regret sooner or later. Sooner is knocking on the door, you forgot one. You are not disposing newBitmap. Which keeps a lock on the file until the garbage collector runs. If it doesn't run then the second time you try to save to the same file you'll get the klaboom. GDI+ exceptions are too miserable to give a good diagnostic so serious head-scratching ensues. Beyond the thousands of googlable posts that mention this mistake.
Always favor using the using statement. Which never forgets to dispose an object, even if the code throws an exception.
using (var newBitmap = new Bitmap(thumbBMP)) {
newBitmap.Save("~/image/thumbs/" + "t" + objPropBannerImage.ImageId, ImageFormat.Jpeg);
}
Albeit that it is very unclear why you even create a new bitmap, saving thumbBMP should already be good enough. Anyhoo, give the rest of your disposable objects the same using love.
In my case the bitmap image file already existed in the system drive, so my app threw the error "A Generic error occured in GDI+".
Verify that the destination folder exists
Verify that there isn't already a file with the same name in the destination folder
Check your folder's permission where the image is saved
Right cLick on folder then go :
Properties > Security > Edit > Add-- select "everyone" and check Allow "Full Control"
I was facing the same issue A generic error occurred in GDI+ on saving while working on MVC app, I was getting this error because I was writing wrong path to save image, I corrected saving path and it worked fine for me.
img1.Save(Server.MapPath("/Upload/test.png", System.Drawing.Imaging.ImageFormat.Png);
--Above code need one change, as you need to put close brackets on Server.MapPath() method after writing its param.
Like this-
img1.Save(Server.MapPath("/Upload/test.png"), System.Drawing.Imaging.ImageFormat.Png);
GDI+ exceptions occured due to below points
Folder access issue
Missing properties of images
If folder issue - please provide access to application
If Missing properties then use below code
Code 1
using (Bitmap bmp = new Bitmap(webStream))
{
using (Bitmap newImage = new Bitmap(bmp))
{
newImage.Save("c:\temp\test.jpg", ImageFormat.Jpeg);
}
}
Code 2
using (Bitmap bmp = new Bitmap(webStream))
{
using (Bitmap newImage = new Bitmap(bmp))
{
newImage.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);
Rectangle lockedRect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData bmpData = newImage.LockBits(lockedRect, ImageLockMode.ReadWrite, bmp.PixelFormat);
bmpData.PixelFormat = bmp.PixelFormat;
newImage.UnlockBits(bmpData);
using (Graphics gr = Graphics.FromImage(newImage))
{
gr.SmoothingMode = SmoothingMode.HighQuality;
gr.InterpolationMode = InterpolationMode.HighQualityBicubic;
gr.PixelOffsetMode = PixelOffsetMode.HighQuality;
}
foreach (var item in bmp.PropertyItems)
{
newImage.SetPropertyItem(item);
}
newImage.Save("c:\temp\test.jpg", ImageFormat.Jpeg);
}
}
Different between code 1 and code 2
Code - 1 : it will just create image and can open it on normal image viewer
the image can't open in Photoshop
Image size will be double
Code - 2 : to open image in image edition tools use code
by using code 1 it just create images but it not assign image marks.
I always check/test these:
Does the path + filename contain illegal characters for the given filesystem?
Does the file already exist? (Bad)
Does the path already exist? (Good)
If the path is relative: am I expecting it in the right parent directory (mostly bin/Debug ;-) )?
Is the path writable for the program and as which user does it run? (Services can be tricky here!)
Does the full path really, really not contain illegal chars? (some unicode chars are close to invisible)
I never had any problems with Bitmap.Save() apart from this list.
I had a different issue with the same exception.
In short:
Make sure that the Bitmap's object Stream is not being disposed before calling .Save .
Full story:
There was a method that returned a Bitmap object, built from a MemoryStream in the following way:
private Bitmap getImage(byte[] imageBinaryData){
.
.
.
Bitmap image;
using (var stream = new MemoryStream(imageBinaryData))
{
image = new Bitmap(stream);
}
return image;
}
then someone used the returned image to save it as a file
image.Save(path);
The problem was that the original stream was already disposed when trying to save the image, throwing the GDI+ exeption.
A fix to this problem was to return the Bitmap without disposing the stream itself but the returned Bitmap object.
private Bitmap getImage(byte[] imageBinaryData){
.
.
.
Bitmap image;
var stream = new MemoryStream(imageBinaryData))
image = new Bitmap(stream);
return image;
}
then:
using (var image = getImage(binData))
{
image.Save(path);
}
I got it working using FileStream, get help from these
http://alperguc.blogspot.in/2008/11/c-generic-error-occurred-in-gdi.html
http://csharpdotnetfreak.blogspot.com/2010/02/resize-image-upload-ms-sql-database.html
System.Drawing.Image imageToBeResized = System.Drawing.Image.FromStream(fuImage.PostedFile.InputStream);
int imageHeight = imageToBeResized.Height;
int imageWidth = imageToBeResized.Width;
int maxHeight = 240;
int maxWidth = 320;
imageHeight = (imageHeight * maxWidth) / imageWidth;
imageWidth = maxWidth;
if (imageHeight > maxHeight)
{
imageWidth = (imageWidth * maxHeight) / imageHeight;
imageHeight = maxHeight;
}
Bitmap bitmap = new Bitmap(imageToBeResized, imageWidth, imageHeight);
System.IO.MemoryStream stream = new MemoryStream();
bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
stream.Position = 0;
byte[] image = new byte[stream.Length + 1];
stream.Read(image, 0, image.Length);
System.IO.FileStream fs
= new System.IO.FileStream(Server.MapPath("~/image/a.jpg"), System.IO.FileMode.Create
, System.IO.FileAccess.ReadWrite);
fs.Write(image, 0, image.Length);
For me it was a permission problem. Somebody removed write permissions on the folder for the user account under which the application was running.
Create folder path image/thumbs on your hard disk => Problem solved!
I used below logic while saving a .png format. This is to ensure the file is already existing or not.. if exist then saving it by adding 1 in the filename
Bitmap btImage = new Bitmap("D:\\Oldfoldername\\filename.png");
string path="D:\\Newfoldername\\filename.png";
int Count=0;
if (System.IO.File.Exists(path))
{
do
{
path = "D:\\Newfoldername\\filename"+"_"+ ++Count + ".png";
} while (System.IO.File.Exists(path));
}
btImage.Save(path, System.Drawing.Imaging.ImageFormat.Png);
I encountered this error while trying to convert Tiff images to Jpeg. For me the issue stemmed from the tiff dimensions being too large. Anything up to around 62000 pixels was fine, anything above this size produced the error.
for me it was a path issue when saving the image.
int count = Directory.EnumerateFiles(System.Web.HttpContext.Current.Server.MapPath("~/images/savedimages"), "*").Count();
var img = Base64ToImage(imgRaw);
string path = "images/savedimages/upImages" + (count + 1) + ".png";
img.Save(Path.Combine(System.Web.HttpContext.Current.Server.MapPath(path)));
return path;
So I fixed it by adding the following forward slash
String path = "images/savedimages....
should be
String path = "/images/savedimages....
Hope that helps anyone stuck!
from msdn: public void Save (string filename); which is quite surprising to me because we dont just have to pass in the filename, we have to pass the filename along with the path for example: MyDirectory/MyImage.jpeg, here MyImage.jpeg does not actually exist yet, but our file will be saved with this name.
Another important point here is that if you are using Save() in a web application then use Server.MapPath() along with it which basically just returns the physical path for the virtual path which is passed in. Something like: image.Save(Server.MapPath("~/images/im111.jpeg"));
I use this solution
int G = 0;
private void toolStripMenuItem17_Click(object sender, EventArgs e)
{
Directory.CreateDirectory("picture");// هذه العملية للرسم بدون ان يحذف بقية الرسومات
G = G + 1;
FormScreen();
memoryImage1.Save("picture\\picture" + G.ToString() + ".jpg");
pictureBox1.Image = Image.FromFile("picture\\picture" + G.ToString() + ".jpg");
}
The code below solved my problem
pictureBox1.Image=myImage;
Bitmap bmp = new Bitmap(pictureBox1.Image);
bmp.Save("C:\\Users/super/Desktop/robin.jpg");
I am having a bit of a hard time converting MemoryStream into BitmapImage. There are a lot of questions on SO regarding similar situations, but after trying everything on them, I've been unable to fix this, so I turn to you. Note that I'm working with Magick.NET (ImageMagick.NET) and Tessnet2 -- that is what some of that code is.
I use Bitmap class to do most of the work in Magick.NET and Tessnet2. BitmapImage is used for displaying purposes.
First, I load up the PDF and extract a cropped bitmap from its first page:
public Task PdfToBmp(string path)
{
return Task.Run(() =>
{
using (var image = new MagickImage())
{
MagickNET.SetGhostscriptDirectory("./");
var settings = new MagickReadSettings
{
Density = new MagickGeometry(300, 300),
FrameCount = 1
};
image.Read(path, settings);
image.Crop(new MagickGeometry(1850, 200, 600, 140));
// ImageStream is a MemoryStream property.
ImageStream = new MemoryStream();
image.Write(ImageStream, MagickFormat.Bmp);
ImageStream.Position = 0;
}
});
}
That is when I save the bitmap into the MemoryStream. Once I have MemoryStream loaded up, I move onto working with it. I instantiate a Bitmap, so that I may use it for Tessnet2 related work and then try to instantiate a BitmapImage.
public Task DoOcr()
{
if (ImageStream == null)
{
return null;
}
TargetImage = new Bitmap(ImageStream);
ImageStream.Position = 0;
// ----------------------- Problem Area ----------------------- //
DisplayImage = new BitmapImage();
DisplayImage.BeginInit();
DisplayImage.StreamSource = ImageStream;
DisplayImage.CacheOption = BitmapCacheOption.OnLoad;
DisplayImage.EndInit();
//ImageStream.Close();
// ------------------------------------------------------------ //
return Task.Run(() =>
{
var ocr = new Tesseract();
ocr.Init("tessdata", "eng", false);
var results = ocr.DoOCR(TargetImage, Rectangle.Empty);
Dispatcher.Invoke(() =>
{
Results = new ObservableCollection<Word>(results);
});
});
}
This is where I'm having a problem. Without that DisplayImage block, the program runs fine and I just don't get the displayed image. I'm even able to save the Bitmap (TargetImage) to a file with no problems. However, with the DisplayImage block, I get System.NullReferenceException:
System.NullReferenceException occurred
_HResult=-2147467261
_message=Object reference not set to an instance of an object.
HResult=-2147467261
IsTransient=false
Message=Object reference not set to an instance of an object.
Source=System
StackTrace:
at System.Uri.CreateThisFromUri(Uri otherUri)
InnerException:
I'm unable to pinpoint where it occurs exactly, because the ImageStream object looks "fine" upon inspection. It contains data and is at position 0. If I try to close it, or do anything with it, after assigning it as the StreamSource to DisplayImage, I get a null exception on the line that attempts to perform such action. I even tried creating two different streams, to see if that's the problem; however, I was getting the exact same behavior. Debugging this is kind of a pain, considering it doesn't point to any one specific line. There's obviously an issue between this MemoryStream and BitmapImage. Could it be possible that there's some sort of format/conversion problem between the two, but not between MemoryStream and Bitmap in this particular situation?
I tried the file route, where I save MagickImage to a file and load it up into BitmapImage through Uri and it worked flawlessly; however, I would like to be able to perform this in-memory. By the way, setting position to 0 on the MemoryStream did not seem to affect either Bitmap (loads properly) or BitmapImage (same exception).
The temporary fix I currently use is to make DisplayImage a BitmapSource, rather than BitmapImage:
DisplayImage = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
TargetImage.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty,
BitmapSizeOptions.FromWidthAndHeight(TargetImage.Width, TargetImage.Height));
The Magick.NET's Write() method has some bugs, so we have to use ToBitmap().
image.ToBitmap().Save(ImageStream, System.Drawing.Imaging.ImageFormat.Bmp);
I Tried many solutions to remove Generic error Occured in GDI + but nothing is working for me , I am posting Codes that i had used.This error occured in server machine
Images bytes are stored successfully in Database but doesnt retrieve on PictureBox.
1st Method :
ODetail.InsuranceCardImages Contains Bytes of Images From Database.
pcinsurance is my PictureBox
System.Byte[] imagefront = (byte[])oDetail.InsuranceCardImage;
//this.pcInsurance.Image = Utility.byteArrayToImage(oDetail.InsuranceCardImage);
MemoryStream ms = new MemoryStream(imagefront);
try
{
//Process currentProcess1 = Process.GetCurrentProcess();
Image returnImage = Image.FromStream(ms);
pcInsurance.Image= returnImage;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
try
{
ms.Flush();
ms.SetLength(0);
ms.Close();
ms.Dispose();
ms = null;
//GC.Collect();
}
catch
{
}
}
2nd Method :
where pcinsurance is my PictureBox
byte[] byteArray = oDetail.InsuranceCardImage;
var imageStream = new MemoryStream(byteArray);
var image = (Bitmap)Bitmap.FromStream(imageStream);
pcInsurance.Image = image;
Still cant fix this issue ,
Kindly provide your solutions so that i will carry on my work
Thank You.
Why do you use ms.Close();,ms.Dispose(); and ms = null;?
You dispose this stream twice and afterwards set it to null.
Finally is performed always so MemoryStream is always disposed.
I suspect that all resources are released before they're used by GDI. I experienced similar problem some time ago.
According to MSDN:
http://msdn.microsoft.com/en-us/library/93z9ee4x.aspx
You must keep the stream open for the lifetime of the Image.
The solution was a creation a Bitmap object:
Bitmap bmp = new Bitmap(ms);
this.pcInsurance.Image = bmp;
In fact I used using statement to simplify code, closing stream before final braces. Works exactly the same but is shorter and in my opinion more readable.
Bitmap and picturebox.Imageobjects must be disposed before setting another picture.
Hope this helps.