while deleting image from path getting error in vb.net - c#

I am working on windowes form application..in show button event i wrote code like this:
Me.PictureBox1.Load("C:/Signature.tif")
PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage
Me.PictureBox1.BorderStyle = BorderStyle.Fixed3D
then save button click i wrote code like this:
Dim exittime As String = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")
Dim ms As New MemoryStream
Dim byt() As Byte
PictureBox1.Image.Save(ms, PictureBox1.Image.RawFormat)
byt = ms.GetBuffer
Dim sqlstr As String = "Update Visitorlogo_tbl set signimage=#pic,exittime='" & exittime & "',status=2 where PassNo='" & txtvisitorid.Text & "'"
Dim cmd1 As New SqlCommand(sqlstr, con.connect)
cmd1.Parameters.Add("#pic", SqlDbType.Image)
cmd1.Parameters("#pic").Value = byt
cmd1.ExecuteNonQuery()
con.disconnect()
PictureBox1.Image = Nothing
If System.IO.File.Exists("C:/Signature.tif") Then
System.IO.File.Delete("C:/Signature.tif")
End If
while saving image image got saving,,but after that i want to delete image from that path.. while coming to this line : System.IO.File.Delete("C:/Signature.tif") am getting error: The process cannot access the file 'C:\Signature.tif' because it is being used by another process

Possible the problem is here.
Me.PictureBox1.Load("C:/Signature.tif")
try this
Me.PictureBox1.Image = new Bitmap("C:\Signature.tif");
UPDATED:
PictureBox1.Load() method will load the file from given location and stores the file path in PictureBox.ImageLocation property. with this method, application will open that image and lock so, other user cannot modify or read it.
PictureBox1.Image = new Bitmap("filePath"); will create the another image object from given file path and it will not lock down the original one. This method will not load the original image from given file location. So, the PictureBox1.ImageLocation property will not be set here. How you can access that image and modify it.

The PictureBox will keep the file open. Therefore you can use the fix suggested by #Shell to release the file after reading the contents. This behavior is by design of the PictureBox.
http://support.microsoft.com/kb/309482
Here is a workaround adapted from the knowledge base article
Using fs as New System.IO.FileStream("C:\Signature.tif", IO.FileMode.Open, IO.FileAccess.Read)
PictureBox1.Image = System.Drawing.Image.FromStream(fs)
End Using

As the error message suggests the image is open by another process. Have you got the image open in a graphics program for example?
Do you have another instance of your application running in the background that has locked the image for reading?
If so close the other programs.

Related

Cannot save array of png images: "generic error in GDI+" [duplicate]

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();

Identify Last Captured Image in a Folder Using .Net

I have a PictureBox in .Net that displays images from a folder "Photos" using the following code on a click event:
PictureBox1.Image = Nothing 'Clearing PictureBox1
Dim bmPhotos as new Bitmap("C:\Photos\ImageName.gif")
PictureBox1.Image = bmPhotos
I want to replace "ImageName" in the file path with the name of the last captured image programatically. Is there a way to find out the name of the image that was added last to the "Photos" folder?
Thank you.
If the last created file is what you need, you can find it this way:
Dim file = System.IO.Directory.GetFiles("path") _
.OrderByDescending(Function(f) New System.IO.FileInfo(f).CreationTime) _
.FirstOrDefault()
You can also use GetFiles("path", "*.gif") to limit the result between gif files.
Also you can add some criteria after GetFiles, to limit the file types to be between specific file types, for example:
.Where(Function(f) New String() {".gif", ".png"}.Contains(System.IO.Path.GetExtension(f)))
Then you can show the image this way:
Me.PictureBox1.ImageLocation = file
Or
Me.PictureBox1.Load(file)

The dispose of an OpenFileDialog in C#?

I have searched throughout entire Stack Overflow, but I couldn't find an answer to the following:
When I'm using my OpenFileDialog, the files I open get blocked for use out of my program until I close my program. So if I open an image, I am not allowed to replace that image in my Windows Explorer anymore.
I think this is a problem with disposing my OpenFileDialog, but I'm not sure how to solve it...
My code:
using (OpenFileDialog ofd = new OpenFileDialog())
{
ofd.Title = "Open Image";
ofd.Filter = "PNG Image(*.png|*.png" +
"|GIF Image(*.gif|*.gif" +
"|Bitmap Image(*.bmp|*.bmp" +
"|JPEG Compressed Image (*.jpg|*.jpg";
if (ofd.ShowDialog() == DialogResult.OK)
{
pictureBox1.Image = new Bitmap(ofd.FileName);
}
}
I thought that the using block would solve this problem, but nope... It still gets used by the program. I want to load the image in the picturebox and then I want the image to be available again (so I can rename it, replace it, etc...).
This is not related to the OpenFileDialog. It couldn't possibly be, because the dialog doesn't actually open the file. It just allows the user to select a file to open, and then returns that path to you so that you can write code that opens the file. Besides, you're correctly disposing of the OpenFileDialog through your use of the using statement.
The problem here comes from your actually opening the file—ofd.FileName—as a Bitmap. When you use the Bitmap constructor overload that accepts a path string, the file on disk that contains the image remains locked until the Bitmap object is disposed. So says the documentation:
The file remains locked until the Bitmap is disposed.
Because you're assigning the bitmap to pictureBox1.Image, the Bitmap object will not be disposed until pictureBox1 is disposed. And therefore your image file on disk will remain locked.
If you want to unlock the file, you will either need to make a copy of the bitmap and dispose the original, or clear out the PictureBox and dispose its previous image when you are finished with it.
As I understand your question, it sounds like you want to be able to make changes to the image file on disk while continuing to display the image in the picture box. If that's the case, you will need to make a copy. Do that using the constructor overload that takes an Image, like this:
if (ofd.ShowDialog() == DialogResult.OK)
{
// Load the image the user selected
using (Image img = Image.FromFile(ofd.FileName))
{
// Create a copy of it
Bitmap bmpCopy = new Bitmap(img);
// Clear out the bitmap currently in the picture box,
// if there is one.
if (pictureBox1.Image != null)
{
pictureBox1.Image.Dispose();
}
// Assign the copy of the bitmap to the picture box.
pictureBox1.Image = bmpCopy;
}
}
As written by Chris, try something like:
pictureBox1.Image = Image.FromStream(new MemoryStream(File.ReadAllBytes(old.FileName)));
It reads all the file with File.ReadAllBytes, put it in a MemoryStream and pass the MemoryStream to the Image static initializer.
Equivalent to:
byte[] bytes = File.ReadAllBytes(old.FileName);
MemoryStream ms = new MemoryStream(bytes);
pictureBox1.Image = Image.FromStream(ms);
You mustn't dispose the MemoryStream! If/when the Image will be disposed, the finalizer of MemoryStream will kick in (if you don't have other references to ms) and the MemoryStream will be disposed (note that this isn't something that will happen immediately... It's something that will happen when the GC will run)
The technique I've found to be best is to read the file into a byte array with File.ReadAllBytes() (that opens and closes the file), and then use ImageConverter to convert the byte array into an Image. See here for example: https://stackoverflow.com/a/16576471/253938
Edit:
Quote from that previous post of mine: "Some of the other techniques I've tried have been non-optimal because they changed the bit depth of the pixels (24-bit vs. 32-bit) or ignored the image's resolution (dpi)."

Save Icon File To Hard Drive

I know that this must be incredibly easy - It's unbelievable how long I have searched for an answer to this question based on how simple it is in VB6. I simply want to extract an Icon from an EXE File using Icon.ExtractAssociatedIcon, and then save this icon file to my hard drive.
So, here is what I have, and I will also show you what I have tried so you don't think I'm being lazy.
OpenFileDialog ofd = new OpenFileDialog();
ofd.ShowDialog();
string s = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + #"\IconData.ico";
Icon ico = Icon.ExtractAssociatedIcon(ofd.FileName);
Bitmap bmp = ico.ToBitmap();
bmp.Save(s, System.Drawing.Imaging.ImageFormat.Icon);
The above code just makes a file called "IconData.ico" on my desktop which is 0 bytes in length. Again, I am sure this must be incredibly easy to do, but for the life of my I can't figure it out.
Thank you!
You will get better results if you save the icon without first converting to a bitmap. This is because an "Icon" can contain multiple sizes whereas a bitmap is a single size chosen during the conversion.
The Icon class does not have a save to file method, but it does have a save to FileStream method, so you can save it like this:
string s = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + #"\IconData.ico";
using (FileStream fs = new FileStream(s, FileMode.Create))
ico.Save(fs);

convert bitmap to image c# [duplicate]

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

Categories