The problem seems to be already known with the handling of Image(s). I want to read a Image without locking it. Through various other questions (ex. question), I have found various workarounds. Something that works for many is to save the image using a bitmap ex:
if (new FileInfo(openImageDialog.FileName).Exists) {
Image tmp = Image.FromFile(openImageDialog.FileName);
pictureBoxImage.Image = new Bitmap(tmp);
tmp?.Dispose();
}
My problem with this is that I want to display a png with transparency, which is clearly lost with a bitmap.
Can someone come to my rescue?
Create your file stream explicitly and use Image.FromStream instead, allowing you to specify FileShare-mode:
using var fs = File.Open(openImageDialog.FileName, FileMode.Open, FileAccess.Read, FileShare.Read);
Image tmp = Image.FromStream(fs);
You could allow FileShare.ReadWrite, but that might not be a good idea since things will likely break if someone is concurrently writing to the same file.
I'm not sure what problem you are describing with regards to transparency. .Net Bitmaps support transparency just fine, .bmp files do not, but you can save and load png files using the Bitmap or Image classes. I'm also unsure what transparency has to do with file locking.
Related
So I have some code that takes a capture of the screen and saves it to a jpeg file. This works fine, however I want to instead save the jpeg encoded capture to a new ZipArchive without writing the Bitmap to the file system first.
Here is what I have so far:
FileInfo zipArchive = new FileInfo(fileToZip.FullName + ".zip");
using (ZipArchive zipFile = ZipFile.Open(zipArchive.FullName, ZipArchiveMode.Create)))
{
ZipArchiveEntry zae = zipFile.CreateEntry(fileToZip.FullName, CompressionLevel.Optimal);
using (Stream zipStream = zae.Open())
bmp.Save(zipStream, ImageFormat.Jpeg);
}
The problem is that on the bmp.Save() line a System.NotSupportedException is thrown
This stream from ZipArchiveEntry does not support seeking.
I've seen a lot of examples that write directly to the Stream returned from zae.Open() so I am not sure why this doesn't work because I figured that all bmp.Save() would need to do is write, not seek. I don't know if this would work but I don't want to have to save the Bitmap to a MemoryStream and the copy that stream to the Stream returned from zae.Open() because it feels like unnecessary extra work. Am I missing something obvious?
Many file formats have pointers to other parts of the file, or length values, which may not be known beforehand. The simplest way is to just write zeros first, then the data and then seek to change the value. If this way is used, there is no way to get by this, so you will need to first write the data into a MemoryStream and then write the resulting data into the ZipStream, as you mentioned.
This doesn't really add that much code and is a simple fix for the problem.
I want to know how many frames a TIFF picture contains. However, to minimize the execution time, I would like to know this information without actually loading the full file. How can I achieve this?
For your information, I am using the following code right now:
FileStream mystream = new FileStream("mypicture.tif", FileMode.Open);
_Image _currentImg = Image.FromStream(mystream );
mystream.Close();
FrameDimension myframeDimensions = new
FrameDimension(_currentImg.FrameDimensionsList[0]);
Int32 numberOfFrames = _currentImg.GetFrameCount(myframeDimensions );
I have a imagestream in c# and i want to save them on the hard drive using the c# code. when i trying to do that i found Out of Memory whennever i have much enough Memory.
so i am sure that my code leak the resources so can someone show me how i can do that
HttpPostedFileBase file
file.SaveAs(location);
Image image = Image.FromFile(location,false);
image.Save(location, System.Drawing.Imaging.ImageFormat.Png);
image.fromFile line [3] caused Exception that out of Memory. can someone show me how i can do this in c#.
The file come from PNG using Ajax Request are come as octet type as Mime type so how i can do that.
Assuming you want to convert the image to PNG (otherwise there's no need to save the image once, reload it and re-save it again), it might be a good idea to avoid loading the image twice. See if something like this helps:
Image.FromStream(file.InputStream, false).Save(location, System.Drawing.Imaging.ImageFormat.Png);
file.SaveAs(location);
already saved the image at the given location or threw an exception, so the following lines are unnecessary.
Bitmap bmp = new Bitmap(file.InputStream);
bmp.Save(filename, ImageFormat.Png);
I'm doing a join of multiple multi-image tiff files to a single multi-image tiff file and have a problem with deleting the source tiff files, because the Image class continues to hold the handle on them.
I'm reading a tiff image through Image.FromFile:
Bitmap resultTiff = (Bitmap) Image.FromFile(strImageFile);
After which I read all other tiff images the same way and append them to the resulting tiff image.
When I finish I use this code to release references and to save resulting file:
ep.Param[0] = new EncoderParameter(enc, (long) EncoderValue.Flush);
resultTiff.SaveAdd(ep);
resultTiff.Dispose();
Now the problem is that the handle on the files still exists (and therefore files can't be deleted) unless I call the GC.Collect() after the resultTiff.Dispose() call.
You can imagine that I don't feel very comfortable by calling GC, so is there any other way of achieving this?
The best way to solve the issue with Image.FromFile wherein it leaves file handles open is to use Image.FromStream instead.
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
using (Image original = Image.FromStream(fs))
{
...
Using an explicit Dispose(), a using() statement or setting the value to null doesn't solve the issue until a garbage collection happens. Forcing a garbage collection to happen is generally a bad idea.
Or try:
Using(Bitmap resultTiff = (Bitmap) Image.FromFile(strImageFile))
{
ep.Param[0] = new EncoderParameter(enc, (long) EncoderValue.Flush);
resultTiff.SaveAdd(ep);
}
You can try:
resultTiff = null;
I was loading a Bitmap Image from a File. When I tried to save the Image to another file I got the following error "A generic error occurred in GDI+". I believe this is because the file is locked by the image object.
Ok so tried calling the Image.Clone function. This still locks the file.
hmm. Next I try loading a Bitmap Image from a FileStream and load the image into memory so GDI+ doesn't lock the file. This works great except I need to generate thumbnails using Image.GetThumbnailImage method it throws an out of memory exception. Apparently I need to keep the stream open to stop this exception but if I keep the stream open then the file remains locked.
So no good with that method. In the end I created a copy of the file. So now I have 2 versions of the file. 1 I can lock and manipulate in my c# program. This other original file remains unlocked to which I can save modifications to. This has the bonus of allowing me to revert changes even after saving them because I'm manipulating the copy of the file which cant change.
Surely there is a better way of achieving this without having to have 2 versions of the image file. Any ideas?
Well if you're looking for other ways to do what you're asking, I reckon it should work to create a MemoryStream, and read out the FileStream to it, and load the Image from that stream...
var stream = new FileStream("original-image", FileMode.Open);
var bufr = new byte[stream.Length];
stream.Read(bufr, 0, (int)stream.Length);
stream.Dispose();
var memstream = new MemoryStream(bufr);
var image = Image.FromStream(memstream);
Or something prettier to that extent.
Whether or not that's the way you should go about solving that problem, I don't know. :)
I've had a similar problem and wound up fixing it like this.
I have since found an alternative method to clone the image without locking the file. Bob Powell has it all plus more GDI resources.
//open the file
Image i = Image.FromFile(path);
//create temporary
Image t=new Bitmap(i.Width,i.Height);
//get graphics
Graphics g=Graphics.FromImage(t);
//copy original
g.DrawImage(i,0,0);
//close original
i.Dispose();
//Can now save
t.Save(path)
I had a similar problem. But I knew, that I will save the image as a bitmap-file. So I did this:
public void SaveHeightmap(string path)
{
if (File.Exists(path))
{
Bitmap bitmap = new Bitmap(image); //create bitmap from image
image.Dispose(); //delete image, so the file
bitmap.Save(path); //save bitmap
image = (Image) bitmap; //recreate image from bitmap
}
else
//...
}
Sure, thats not the best way, but its working :-)