this is how my code look now:
System.Drawing.Image objImage = System.Drawing.Image.FromFile(Server.MapPath("aaa.jpg"));
int height = objImage.Height;
int width = objImage.Width;
System.Drawing.Bitmap bitmapimage = new System.Drawing.Bitmap(objImage, width, height);
System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmapimage);
System.Drawing.Image bitmap2 = (System.Drawing.Image)Bitmap.FromFile(Server.MapPath("sem.png"));
g.DrawImage(bitmap2, (objImage.Width - bitmap2.Width) / 2, (objImage.Height - bitmap2.Height) / 2);
MemoryStream stream = new MemoryStream();
bitmapimage.Save(stream, ImageFormat.Jpeg);
String saveImagePath = Server.MapPath("ImagesMerge/") + "aaa.jpg";
bitmapimage.Save(saveImagePath);
imgBig.ImageUrl = saveImagePath;
The problem I have now is that the image is not displayed in browser, I don't understand why .
like jmaglasang said, I would suggest to you to use an ashx file and if you don't need to keep the image, just send the image stream directly to the http without saving it on the disk
so you only need to do something like
<img src="Handler.ashx?action=merge&image1=blah.jpg&image2=bloh.jpg">
look at this code for an example of how to send an image made in memory that does not exist on the drive
Bitmap is a subclass of Image, so there no need to convert Bitmap to Image. It already is...
Probably because saveImagePath will be a local path (such as c:\somepath\aaa.jpg) that is not reachable from the browser. You probably want to set the ImageUrl = "ImagesMerge/aaa.jpg" instead.
You can also try:
imgBig.ImageUrl = ResolveUrl(saveImagePath);
EDIT:
If saveImagePath is under the WebApplication Directory, doing some modifications on the directory structure i.e. modifying files, deleting and creating can cause the application pool to recycle, and once it reaches the maximum recycle count the application pool will be stopped causing "Server unavailable" error.
I would suggests to add/save/modify images on a separate directory (not under the Apps Directory) then create a Handler(ASHX) that will read the images, just an advice though.
MapPath will give you a physycal address, not a virtual address which is what the browser needs to get to the image.
You might be forgetting to set the Response.Headers. Check out the following example that shows how to create bar chart images and then display it on the screen:
http://www.highoncoding.com/Articles/399_Creating_Bar_Chart_Using__NET_Graphics_API.aspx
Related
Having a code that works for ages when loading and storing images, I discovered that I have one single image that breaks this code:
const string i1Path = #"c:\my\i1.jpg";
const string i2Path = #"c:\my\i2.jpg";
var i = Image.FromFile(i1Path);
i.Save(i2Path, ImageFormat.Jpeg);
The exception is:
System.Runtime.InteropServices.ExternalException occurred
A generic error occurred in GDI+.
at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
at System.Drawing.Image.Save(String filename, ImageFormat format)
at ...
As far as I can see, there is nothing special about the image. It is approx 250 pixels in size and can be opened in e.g. Windows Image Viewer or Paint.NET:
(Since the image above, after being uploaded to Stack Overflow does not produce the error anymore, I've put the original image here)
What I discovered is that upon calling the Save method, the destination image file is being created with zero bytes.
I am really clueless on what causes the error.
My questions:
Can you think of any special thing that would hinder .NET from saving the image?
Is there any way (beside panicing) to narrow down these kind of errors?
While I still did not find out the reason what exactly caused the error when saving the image, I found a workaround to apply:
const string i1Path = #"c:\my\i1.jpg";
const string i2Path = #"c:\my\i2.jpg";
var i = Image.FromFile(i1Path);
var i2 = new Bitmap(i);
i2.Save(i2Path, ImageFormat.Jpeg);
I.e. by copying the image internally into a Bitmap instance and saving this image instead of the original image, the error disappeared.
I'm assuming that by copying it, the erroneous parts the caused the original Save call to fail are being removed an/or normalized, thus enabling the save operation to succeed.
Interestingly, the so stored image has a smaller file on disk (16 kB) than its original source (26 kB).
First of all make sure, that the desired folder has Read/Write permissions. Changing the permissions solved this problem for me.
Solution is here, you must dispose image object to release the memory on the server.
Try use using statement. Make sure destination directory on server exists too.
The reason may be that the image is loaded lazily and the loading process is not yet finished when you try to save it.
Following what's said in this blog post (assuming you're German by the picture you linked in your question) provides a possible solution. Also this SO question's accepted answer indicates this is due to the fact the image file you're trying to save to is locked.
EDIT
For Ulysses Alves, from the linked blog entry: If you load an image using Image.FromFile() it remains locked until it is disposed of. This prevents calls to Save().
pictureBox1.Image = Image.FromFile("C:\\test\\test1.jpg");
pictureBox1.Image.Save("C:\\test\\test2.jpg");
The above code throws an error.
To make it work, you need to copy the image. The following code works:
pictureBox1.Image = Image.FromFile("C:\\test\\test1.jpg");
Image copy = pictureBox1.Image;
copy.Save("C:\\test\\test2.jpg")
I found this question because I also faced the similar error and the file was actually created with zero length (if you don't see any file, first check the permissions to write into folder as other answers suggest). Although my code was slightly different (I use stream to read the image from memory, not from file), I think my answer may be helpful to anyone facing similar problem.
It may looks counter-intuitive, but you can't really dispose memory stream until you finish with image.
NOT WORKING:
Image patternImage;
using (var ms = new MemoryStream(patternBytes)) {
patternImage = new Bitmap(ms);
}
patternImage.Save(patternFile, ImageFormat.Jpeg);
Just don't dispose the stream until you done with image.
WORKS:
using (var ms = new MemoryStream(patternBytes)) {
patternImage = new Bitmap(ms);
patternImage.Save(patternFile, ImageFormat.Jpeg);
}
What is misleading:
Error message doesn't really tell you anything
You can see the image properties, like width and height, but can't
save it
my solution was to make, write temp content (File.WriteAllText) just before saving the file
Here is the code:
var i = Image.FromFile(i1Path);
File.WriteAllText(i2Path, "empty"); // <---- magic goes here
i.Save(i2Path, ImageFormat.Jpeg);
Please try and let me know
In my case I have accidentally deleted the directory where image was getting stored.
Key Information:
// Using System.Drawing.Imaging:
new Bitmap(image).Save(memoryStream, ImageFormat.Jpeg);
You MUST Cast the Image to a Bitmap to Save it.
Using:
// Using System.Drawing.Imaging:
image.Save(memoryStream, ImageFormat.Jpeg);
WILL throw the Error:
Generic GDI+ error when saving an image
Just use the visual studio as administrator or run the application created by the code as administrator it should work smoothly.
It is user access rights issue.
I faced the same and resolved it by running visual studio as administrator.
In my case, I set validateImageData to false:
Image.FromStream(stream, validateImageData: false);
solution:
Image.FromStream(stream, validateImageData: true);
Open in the program
const string i1Path = #"c:\my\i1.jpg";
const string i2Path = #"c:\my\i2.jpg";
var i = Image.FromFile(i1Path);
i.Save(i2Path, ImageFormat.Jpeg);
i.Dispose();
Having a code that works for ages when loading and storing images, I discovered that I have one single image that breaks this code:
const string i1Path = #"c:\my\i1.jpg";
const string i2Path = #"c:\my\i2.jpg";
var i = Image.FromFile(i1Path);
i.Save(i2Path, ImageFormat.Jpeg);
The exception is:
System.Runtime.InteropServices.ExternalException occurred
A generic error occurred in GDI+.
at System.Drawing.Image.Save(String filename, ImageCodecInfo encoder, EncoderParameters encoderParams)
at System.Drawing.Image.Save(String filename, ImageFormat format)
at ...
As far as I can see, there is nothing special about the image. It is approx 250 pixels in size and can be opened in e.g. Windows Image Viewer or Paint.NET:
(Since the image above, after being uploaded to Stack Overflow does not produce the error anymore, I've put the original image here)
What I discovered is that upon calling the Save method, the destination image file is being created with zero bytes.
I am really clueless on what causes the error.
My questions:
Can you think of any special thing that would hinder .NET from saving the image?
Is there any way (beside panicing) to narrow down these kind of errors?
While I still did not find out the reason what exactly caused the error when saving the image, I found a workaround to apply:
const string i1Path = #"c:\my\i1.jpg";
const string i2Path = #"c:\my\i2.jpg";
var i = Image.FromFile(i1Path);
var i2 = new Bitmap(i);
i2.Save(i2Path, ImageFormat.Jpeg);
I.e. by copying the image internally into a Bitmap instance and saving this image instead of the original image, the error disappeared.
I'm assuming that by copying it, the erroneous parts the caused the original Save call to fail are being removed an/or normalized, thus enabling the save operation to succeed.
Interestingly, the so stored image has a smaller file on disk (16 kB) than its original source (26 kB).
First of all make sure, that the desired folder has Read/Write permissions. Changing the permissions solved this problem for me.
Solution is here, you must dispose image object to release the memory on the server.
Try use using statement. Make sure destination directory on server exists too.
The reason may be that the image is loaded lazily and the loading process is not yet finished when you try to save it.
Following what's said in this blog post (assuming you're German by the picture you linked in your question) provides a possible solution. Also this SO question's accepted answer indicates this is due to the fact the image file you're trying to save to is locked.
EDIT
For Ulysses Alves, from the linked blog entry: If you load an image using Image.FromFile() it remains locked until it is disposed of. This prevents calls to Save().
pictureBox1.Image = Image.FromFile("C:\\test\\test1.jpg");
pictureBox1.Image.Save("C:\\test\\test2.jpg");
The above code throws an error.
To make it work, you need to copy the image. The following code works:
pictureBox1.Image = Image.FromFile("C:\\test\\test1.jpg");
Image copy = pictureBox1.Image;
copy.Save("C:\\test\\test2.jpg")
I found this question because I also faced the similar error and the file was actually created with zero length (if you don't see any file, first check the permissions to write into folder as other answers suggest). Although my code was slightly different (I use stream to read the image from memory, not from file), I think my answer may be helpful to anyone facing similar problem.
It may looks counter-intuitive, but you can't really dispose memory stream until you finish with image.
NOT WORKING:
Image patternImage;
using (var ms = new MemoryStream(patternBytes)) {
patternImage = new Bitmap(ms);
}
patternImage.Save(patternFile, ImageFormat.Jpeg);
Just don't dispose the stream until you done with image.
WORKS:
using (var ms = new MemoryStream(patternBytes)) {
patternImage = new Bitmap(ms);
patternImage.Save(patternFile, ImageFormat.Jpeg);
}
What is misleading:
Error message doesn't really tell you anything
You can see the image properties, like width and height, but can't
save it
my solution was to make, write temp content (File.WriteAllText) just before saving the file
Here is the code:
var i = Image.FromFile(i1Path);
File.WriteAllText(i2Path, "empty"); // <---- magic goes here
i.Save(i2Path, ImageFormat.Jpeg);
Please try and let me know
In my case I have accidentally deleted the directory where image was getting stored.
Key Information:
// Using System.Drawing.Imaging:
new Bitmap(image).Save(memoryStream, ImageFormat.Jpeg);
You MUST Cast the Image to a Bitmap to Save it.
Using:
// Using System.Drawing.Imaging:
image.Save(memoryStream, ImageFormat.Jpeg);
WILL throw the Error:
Generic GDI+ error when saving an image
Just use the visual studio as administrator or run the application created by the code as administrator it should work smoothly.
It is user access rights issue.
I faced the same and resolved it by running visual studio as administrator.
In my case, I set validateImageData to false:
Image.FromStream(stream, validateImageData: false);
solution:
Image.FromStream(stream, validateImageData: true);
Open in the program
const string i1Path = #"c:\my\i1.jpg";
const string i2Path = #"c:\my\i2.jpg";
var i = Image.FromFile(i1Path);
i.Save(i2Path, ImageFormat.Jpeg);
i.Dispose();
I use the following code block with some more code inside the using block:
using (System.Drawing.Bitmap tempImg =
(System.Drawing.Bitmap)tempObj.GetData(System.Windows.Forms.DataFormats.Bitmap))
{
// ...
tempImg.Save("..\\..\\testdata\\tempImg.bmp", ImageFormat.Bmp);
// ...
}
But I still get the error:
A Generic Error occured at GDI+
only after I make some action which is not related to the code inside the using block. In other times this works well.
Also the tempImg.bmp is a temporary file, so I delete the tempImg.bmp within the using block itself.
Since the tempImg is inside the using and this it's disposed, I think the locking problem should be solved.
Can someone please let me know what is the mistake in this code?
Edit:
System.Drawing.Image to System.Drawing.Bitmap as the type of tempImg.
Edit:
I have identified I get this error only after SaveFileDialog is created and user clicks on 'Save'.
Finally I could find what was wrong in my code and would like to mention it here as I think it may be useful to someone....
As I have given a relative path in tempImg.Save, and after the user clicks 'Save' in SaveFileDialog, the actual path for tempImg.Save become :
Path specified by SaveFileDialog + the relative path
automatically.
Thus if the path does not exist, this error occurs.
Thanks every one for the answers.
I also had once this problem- it happens because the bitmap locks and you can't save it( if you want I can find the exact explanation) so anyway a fix around is this:
Create a new bitmap the size of the original bitmap you have- copy the original bitmap to the new created bitmap and then dispose the original bitmap and save the new one.
Bitmap bm3 = new Bitmap(bm2);
And then save.
This is usually an indicator that something else, potentially some other thread in your own application, already has the target file that you're trying to save locked at the file system level. If you look at the inner exception I believe it should mention this. If it's not directly in the InnerException Another way to confirm this (or discover what it might really be instead) is to turn on first chance exceptions in the debugger and watch for what exception is being thrown "underneath" Save and then being turned into this generic exception.
Tried all the solutions given here, but in vain. Found the solution eventually.
Dispose any Graphics applied on image: g.dispose();
Make sure save path exists: System.IO.Directory.Exists(dir);
Is this an ASP.NET application?
A Generic Error occured at GDI+ in asp.net mostly because of missing target folder / access permissions.
Also your code could be simplified to :
using (Image image= dataObject.GetImage())
{
if (image != null)
{
image.Save("test.bmp");
}
}
In my case it was an ASP.NET application in which I replaced a single DLL, and I had to simply re-start the application pool after deployment. Then it worked fine.
This is code sample from Microsoft Forums.
// new image with transparent Alpha layer
using (var bitmap = new Bitmap(330, 18, PixelFormat.Format32bppArgb))
{
using (var graphics = Graphics.FromImage(bitmap))
{
// add some anti-aliasing
graphics.SmoothingMode = SmoothingMode.AntiAlias;
using (var font = new Font("Arial", 14.0f, GraphicsUnit.Pixel))
{
using (var brush = new SolidBrush(Color.White))
{
// draw it
graphics.DrawString(user.Email, font, brush, 0, 0);
}
}
}
// setup the response
Response.Clear();
Response.ContentType = "image/png";
Response.BufferOutput = true;
// write it to the output stream
bitmap.Save(Response.OutputStream, ImageFormat.Png);
Response.Flush();
}
I am trying to save image from resource and it gives me too GDI error when I directly use the method Bitmap.Save(filepath).
I think We can use the same below code for any other bitmap image by cloning it.
Private void SaveResourceImage() {
object resBmpObject = Resource.Image1.Clone();//Bitmap Image from resource file
//object resBmpObject = anyBmpImage.clone(); //for image other than resource image
Bitmap resBmpImage = (Bitmap)resBmpObject;
resBmpImage.Save(destFilePath, System.Drawing.Imaging.ImageFormat.Png);
resBmpImage.dispose();
}
Dispose your bitMap object after save image:
bitMap.Dispose()
oimg.Dispose()
bitMap = Nothing
oimg = Nothing
In my case, i was saving the bitmap file on the same location as the source,
So that's the problem.
I save the bitmap to the new location and all fine now.
I was facing the same issue, by changing image type ".bmp" to ".png" its work form me
i have some images..if these images are selected then it should generate another image which is the combination of all the selected images..
can anyone suggest as how to start with?
thanks
Use someting like that:
public void MergeImages(string FirstFileName, string SecondFileName)
{
Image firstImg = Image.FromFile(#"C:\temp\pic1.jpg");
Image secondImg = Image.FromFile(#"C:\temp\pic2.jpg");
Bitmap im1 = new Bitmap(firstImg);
Bitmap im2 = new Bitmap(secondImg);
Bitmap result = new Bitmap(im1.Width + im2.Width, (im1.Height > im2.Height) ? im1.Height : im2.Height);
Graphics gr = Graphics.FromImage(result);
gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
gr.DrawImage(firstImg, 0, 0);
gr.DrawImage(secondImg, im1.Width + 1, 0);
gr.Save();
result.Save(#"C:\test.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
}
this code merges two images in one, systeming them into line.
i used ImageMagick to do these kind of things (http://www.imagemagick.org/Usage/layers/)
It is however a little bit different then using gdi to create images, but it is a very fast (and when you get used to the imagemagick syntax) and powerful way to edit images.
Normally you use gdi to edit images in memory; imagemagick uses a commandline utility to create images.
So for example you want to layer two images on top, you start a new process in your code in which you fire up a imagemagick proces with the right parameters and then the image is created ON DISK.
Then you can server the created image with a response.writebinary.
How can I clone FileStream type?
The problem is that I using MagickNet.Image(inputStream) to get the image distentions before saving it, but it seems to closing the inputStream.
So, I can send a clone of inputStream to the function, so the function cannot edit the real inputStream object?
This is my function:
public Picture GetPictureDimension(Stream inputStream, Picture picture)
{
var img = new MagickNet.Image(inputStream);
picture.Width = img.Columns;
picture.Height = img.Rows;
return picture;
}
You could just re-open the file? But to keep a single Stream without it getting closed, you could try NonClosingStreamWrapper in MiscUtil. Just be sure to reset the Position if appropriate.
You didn't post full code, but I imagine that MagickNet.Image(inputStream) gets the full image and you only use the Size from that, and later you load the Image a second time.
So a more practical solution would be to get and hold the Image in memory just once. That gives you access to the Size.
Edit:
You don't seem to realize it but you are asking how to load the Image twice (w/o reopening the stream). I do think it is more efficient to load it just once.
Picture is a XNA class, right? I don't know to much about that but you could try something like:
public Picture GetPictureDimension(Stream inputStream, ref Picture picture)
{
var img = new MagickNet.Image(inputStream);
picture = new Picture(img); // just guessing here
//picture.Width = img.Columns;
//picture.Height = img.Rows;
return picture;
}