PictureBox and Dispose - c#

I must delete an image file if it already exists (overwriting it) while a PictureBox is showing the same.
However If I try to delete the file it's blocked by PictureBox.
So I write the following code:
if (File.Exists(file))
{
Image _tmp = (Image)current_pic.Image.Clone();
current_pic.Image.Dispose();
current_pic.Dispose();
File.Delete(path);
current_pic.Image = _tmp;
current_pic.Image.Save(file, ImageFormat.Jpeg);
}
else
current_pic.Image.Save(file, ImageFormat.Jpeg);
and the Image on filesystem is deleted thanks to pic.Dispose() but the Image is not
more showed inside the PictureBox.
Maybe does Dispose() method invalidate PictureBox?

You can read a image into the picture box without locking it as shown below
Image img;
string file = #"d:\a.jpg";
using (Bitmap bmp = new Bitmap(file))
{
img = new Bitmap(bmp);
current_pic.Image = img;
}
if (File.Exists(file))
{
File.Delete(file);
current_pic.Image.Save(file, ImageFormat.Jpeg);
}
else
current_pic.Image.Save(file, ImageFormat.Jpeg);
I have updated the code to even support the save operation.
While the previous code supported the delete even after linking the images. The stream was closed and this while saving resulted in a GDI+ error.
The newly updated code meets all your requirements as follows
Allowing a delete of the file while the images is linked
Save of the Image using the Image property in the Picturebox control

Related

Washed out colors in PictureBox

When I show a specific image in a PictureBox (or Cyotek's ImageBox in my case, doesn't matter), the color gets a little washed out. Most images displays correctly but some few images gets washed out.
Here's what it looks like:
The original image
Opened in Windows Photo Viewer
Opened in my application
I tried loading the image in 3 different ways, but same result:
Image image = GetImage(OPEN);
imgBox.Image = image;
public Image GetImage(string path)
{
Image image = null;
//image = Image.FromFile(#"D:\Visual Studio\pictures\pokemon.jpg"); // washed out colors
try
{
using (FileStream file_stream = new FileStream(path, FileMode.Open, FileAccess.Read)) // washed out colors
{
MemoryStream memory_stream = new MemoryStream();
file_stream.CopyTo(memory_stream);
image = Image.FromStream(memory_stream, false, false);
file_stream.Dispose();
}
}
catch
{
try
{
FIBITMAP picture = FreeImage.LoadEx(path); // washed out colors
Bitmap bitmap = FreeImage.GetBitmap(picture);
image = bitmap;
FreeImage.Unload(picture);
}
catch { }
}
return image;
}
Anyone know why this is? Maybe some specific tag in this image that Windows and PictureBox handles differently?
You should use Image.FromStream() and pass true for the useEmbeddedColorManagement argument to ensure that any metadata for color management is used.

C# save image to file system, error in gdi+

I have a C# WPF application which cuts a image to the size I need it. The WPF window is used to put in a user ID to save the image into a database. When I test my application it works sometimes and sometimes i get a error in gdi+ on the line I save the image to the file system.
Here is my code:
public static void CutImage(Image image)
{
//create new image
Bitmap source = new Bitmap(image);
//cut image
Bitmap cuttedImage = source.Clone(new System.Drawing.Rectangle(250, 0, 5550, 4000), source.PixelFormat);
//copy bitmap to avoid "general error in gdi+"
Bitmap copyImage = new Bitmap(cuttedImage.Width, cuttedImage.Height, PixelFormat.Format24bppRgb);
Graphics g = Graphics.FromImage(copyImage);
g.DrawImageUnscaled(cuttedImage, 0, 0);
//dispose graphics object
g.Dispose();
//dispose image
cuttedImage.Dispose();
//save image to filesystem
copyImage.Save(#"path\tmp.jpg", ImageFormat.Jpeg);
}
//get image
Image i = Image.FromFile(path\image.jpg);
//cut image
CutImage(i);
I searched for a solution and somebody said I have to create a copy of the image I got from Image.FromFile(). But the error still happens sometimes. I tried it a few times and it seems to be random when it happens. The error is always on the Image.Save() line.
Does somebody know how to solve this problem or is there a alternative to Image.Save()?
Thanks for your help!
You're creating so many bitmaps and you're not disposing them. Every single IDisposable must be explicitly disposed when you're finished with them.
Try this and see if the error goes away:
public static void CutImage(Image image)
{
using (Bitmap source = new Bitmap(image))
{
using (Bitmap cuttedImage = source.Clone(new System.Drawing.Rectangle(250, 0, 5550, 4000), source.PixelFormat))
{
using (Bitmap copyImage = new Bitmap(cuttedImage.Width, cuttedImage.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb))
{
using (Graphics g = Graphics.FromImage(copyImage))
{
g.DrawImageUnscaled(cuttedImage, 0, 0);
copyImage.Save(#"path\tmp.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
}
}
}

Save rotate image onto server

I want to save rotate image onto the server
I found some solution but its not working..
UPDATE
Image path is in xml..
here is the code:
public Boolean saveRotateImg(string path)
{
string new_path="/Job_Files/"+Job_ID+"/"+GroupName+"/Images/"+path;
using (Image image = Image.FromFile(new_path))
{
//rotate the picture by 90 degrees and re-save the picture as a Jpeg
image.RotateFlip(RotateFlipType.Rotate90FlipNone);
System.IO.File.Delete(path);
image.Save(output, System.Drawing.Imaging.ImageFormat.Jpeg);
image.Dispose();
}
}
Can anyone suggest how to do that or any other way for that..
Based on the comments above it should be something like this:
public Boolean saveRotateImg(string path)
{
string new_path="/Job_Files/"+Job_ID+"/"+GroupName+"/Images/"+path;
// Load the image from the original path
using (Image image = Image.FromFile(path))
{
//rotate the picture by 90 degrees and re-save the picture as a Jpeg
image.RotateFlip(RotateFlipType.Rotate90FlipNone);
// Save the image to the new_path
image.Save(new_path, System.Drawing.Imaging.ImageFormat.Jpeg);
}
System.IO.File.Delete(path);
}
Though you will have to make sure that the variables path and new_path contain the full path + filename of the image.
EDIT: I've removed the image.Dispose() as the using will take care of this. Also I've replaced the System.IO.File.Delete(path) call to the end of the routine, not sure if this is required, but in this case it will never interfere with the usage of the image.

Steam Game Icon

I am making a file explorer and for the thumbnail view it requires the icon of a file. I have gotten an icon for all of the files except for steam games. I have looked around and cannot find a way to get the icon like Windows does.
Edit:
This is what i currently use to get my file icons:
public static Bitmap GetBigImage(string path, Size size)
{
Bitmap bmp;
string ext = System.IO.Path.GetExtension(path);
if (ext == ".exe")
{
Icon ico = Icon.ExtractAssociatedIcon(path);
bmp = ico.ToBitmap();
ico.Dispose();
}
else
{
if (imageType.Contains(ext.Replace(".", "")))
{
Image img = Image.FromFile(path);
bmp = new Bitmap(img, new Size(size.Width - 20, 80));
img.Dispose();
}
else
{
Icon ico = Win32.GetLargeIconForExtension(ext);
bmp = ico.ToBitmap();
ico.Dispose();
}
}
return bmp;
}
This is the path I am trying to get steam://rungameid/209170
In GetBigImage, if I see if the path contains steam:// (in either of the if statements) the method still returns no icon.
There is a Database of Steam Games here. Each entry leads to a page that includes a link to the game's icon.
Your ID leads to this page where this link points to the icon.
Note that there usually is a real icon under the field 'clienticon' and also a plain jpg strangely named 'icon'!
For an explorer type app I recommend caching those icon.
Hope this helps.
Have you tried,
Icon.ExtractAssociatedIcon
From the System.Drawing namespace?
http://msdn.microsoft.com/en-us/library/system.drawing.icon.extractassociatedicon(v=vs.110).aspx

Saving a Graphics content to a file

I have some code where I draw a function graph into a PictureBox graphics. The code is implemented in the Paint event. At some point I want to save a bitmap of the content of the graphics in a file.
I already read the answers to this question, and didn't found what I was looking for.
What I need is both to draw in the PictureBox (or any other control that you suggest) so that I don't loose the drawing when the control is hidden or something (so I think I cannot CreateGraphics()) and be able to save that drawing in a button's click event.
I'm willing to put the drawing logic out of the Paint event if necesary.
Thanks in advance.
I went ahead and answered the question based on my assumption,
I created a new Winforms application
I added a panel and a button
I created a Bitmap named buffer, and in the Form1 constructor, initialized it to the size of the panel. Instead of drawing directly to the panel, I draw to the Bitmap, then set the panels background image buffer; This will add persistance to your graphics. If you truly wish to write to a file, I can show you that. Just ask.
To write to file you will need this namespace reference :
using System.IO;
I added the ImageToDisc function you were asking for.
Here is the Code :
Bitmap buffer;
public Form1()
{
InitializeComponent();
panel1.BorderStyle = BorderStyle.FixedSingle;
buffer = new Bitmap(panel1.Width,panel1.Height);
}
private void button1_Click(object sender, EventArgs e)
{
using (Graphics g = Graphics.FromImage(buffer))
{
g.DrawRectangle(Pens.Red, 100, 100,100,100);
}
panel1.BackgroundImage = buffer;
//writes the buffer Bitmap to a binary file, only neccessary if you want to save to disc
ImageToDisc();
//just to prove that it did write it to file and can be loaded I set the mainforms background image to the file
this.BackgroundImage=FileToImage();
}
//Converts the image to a byte[] and writes it to disc
public void ImageToDisc()
{
ImageConverter converter = new ImageConverter();
File.WriteAllBytes(#"c:\test.dat", (byte[])converter.ConvertTo(buffer, typeof(byte[])));
}
//Converts the image from disc to an image
public Bitmap FileToImage()
{
ImageConverter converter = new ImageConverter();
return (Bitmap)converter.ConvertFrom(File.ReadAllBytes(#"c:\test.dat"));
}

Categories

Resources