Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delete an image being used by another process

Tags:

c#

svg

I am writing a winform application in C# to open an image and overlay another image on top of it.

The bottom image is a .jpg and the top one is a .bmp converted from .svg. The .jpg and the .svg are the only ones I want to keep in the folder. The .bmp works as a temp.

I was using the following code to overlay the images. But I am having trouble to delete the temp .bmp as it is used by another process. I think it is this combine code still have access to the last .bmp file.

Could anyone help me on this? Thanks.

    private void buttonSearch_Click(object sender, EventArgs e)
    {
        FailInfo.Text = "";

        deletebmp(strFolderPath); 

        ...

        // Check if the specified front image exists. Yes, show the file name and convert SVG to BMP. No, show the error msg.
        if (File.Exists(strFilePathF))
        {
            labelFront.Text = strFileNameF;
            var svgConvert = SvgDocument.Open(svgFilePathF);
            svgConvert.Draw().Save(bmpFilePathF);
            pictureBoxFront.Image = Image.FromFile(strFilePathF);
        }
        else
        {
            labelFront.Text = "Couldn't find the file!";
            pictureBoxFront.Image = null;
        }

        // Check if the specified back image exists. Yes, show the file name and convert SVG to BMP. No, show the error msg.   
        if (File.Exists(strFilePathBF))
        {
            labelBack.Text = strFileNameBF;
            strFilePathB = strFilePathBF;
            pictureBoxBack.Image = Image.FromFile(strFilePathB);
            labelResult.Text = "FAIL";
            labelResult.BackColor = Color.FromArgb(255, 0, 0);
            var svgConvert = SvgDocument.Open(svgFilePathBF);
            bmpFilePathB = strFolderPath + strFileNameBF + ".bmp";
            svgConvert.Draw().Save(bmpFilePathB);
            svgFilePathB = svgFilePathBF;
            inspectionres(svgFilePathB);
            labelreason.Visible = true;
        }
        else if (File.Exists(strFilePathBP))
        {
            labelBack.Text = strFileNameBP;
            strFilePathB = strFilePathBP;
            pictureBoxBack.Image = Image.FromFile(strFilePathB);
            labelResult.Text = "PASS";
            labelResult.BackColor = Color.FromArgb(0, 255, 0);
            var svgConvert = SvgDocument.Open(svgFilePathBP);
            bmpFilePathB = strFolderPath + strFileNameBP + ".bmp";
            svgConvert.Draw().Save(bmpFilePathB);
            svgFilePathB = svgFilePathBP;
            inspectionres(svgFilePathB);
            labelreason.Visible = false;
        }
        else
        {
            labelBack.Text = "Couldn't find the file!";
            pictureBoxBack.Image = null;
            labelResult.Text = "ERROR";
            labelResult.BackColor = Color.FromArgb(0, 255, 255);
            labelreason.Visible = false;
        }
    }

    //
    // Overlay the SVG file on top of the JPEG file
    //
    private Bitmap Combine(string jpegFile, string bmpFile)
    {        
        Image image1 = Image.FromFile(jpegFile);
        Image image2 = Image.FromFile(bmpFile);
        Bitmap temp = new Bitmap(image1.Width, image1.Height);

        using (Graphics g = Graphics.FromImage(temp))
        {
            g.DrawImageUnscaled(image1, 0, 0);
            g.DrawImageUnscaled(image2, 0, 0);
        }

        return temp;
    }

    //
    // Show the overlaid graphic in the picturebox
    //
    private void checkBoxOverlay_CheckedChanged(object sender, EventArgs e)
    {
        try
        {
            if (FindFront)
                if (checkBoxOverlay.Checked)
                    pictureBoxFront.Image = Combine(strFilePathF, bmpFilePathF);
                else
                    pictureBoxFront.Image = Image.FromFile(strFilePathF);
            else
                pictureBoxFront.Image = null;

            if (FindBack)
                if (checkBoxOverlay.Checked)
                    pictureBoxBack.Image = Combine(strFilePathB, bmpFilePathB);
                else
                    pictureBoxBack.Image = Image.FromFile(strFilePathB);
            else
                pictureBoxBack.Image = null;
        }
        catch (Exception ex)
        {
            MessageBox.Show("Error loading image" + ex.Message);
        }
    }

    //
    // Option of changing the image folder
    //
    private void buttonPath_Click(object sender, EventArgs e)
    {
        FolderBrowserDialog FolderBrowserDialog1 = new FolderBrowserDialog();
        if (FolderBrowserDialog1.ShowDialog() == DialogResult.OK)
        {
            strFolderPath = FolderBrowserDialog1.SelectedPath + "\\";
        }
    }

    //
    // Pull the inspection result info from the SVG file
    //
    private void inspectionres(string filename)
    {
        XDocument document = XDocument.Load(filename);
        XElement svg_Element = document.Root;
        string sb = null;

        var faillist = (from svg_path in svg_Element.Descendants("{http://www.w3.org/2000/svg}text") select svg_path).ToList();

        foreach (var item in faillist)
        {
            sb += item.ToString();
        }
    }

    //
    // Delete all the .bmp files generated from .svg files
    //
    private void deletebmp(string path)
    {
        // Unload the images from the picturebox if applicable
        pictureBoxFront.Image = null;
        pictureBoxBack.Image = null;

        string[] files = Directory.GetFiles(path, "*.bmp");
        for (int i = 0; i < files.Length; i ++ )
            File.Delete(files[i]);
    }
}
like image 225
Stephen127 Avatar asked Mar 16 '23 06:03

Stephen127


2 Answers

Image implements IDisposable, so simply setting the pictureBox.Image property to null will not release resources (in your case, the file). Your Combine method also leaves the images open. You have to call Dispose before attempting to delete the file:

Image image1 = Image.FromFile(path1);
File.Delete(path1);  // error - file is locked 

Image image2 = Image.FromFile(path2);
image2.Dispose();
File.Delete(path2);  // works

An alternative approach (and I assume you're using WinForms here, in WPF it's a little different) would be to load the bitmap from the file manually (using FromStream). Then, you can close the stream immediately and delete the file:

Image image;
using (Stream stream = File.OpenRead(path))
{
    image = System.Drawing.Image.FromStream(stream);
}
pictureBox.Image = image;
File.Delete("e:\\temp\\copy1.png");  //works
like image 71
vesan Avatar answered Mar 25 '23 06:03

vesan


Vesan's answer didn't helped me so I found an different solution. So I can safe/open an image and if I want instantly delete the image.

i used it for my dataGridView_SelectionChanged:

private void dataGridViewAnzeige_SelectionChanged(object sender, EventArgs e)
{
    var imageAsByteArray = File.ReadAllBytes(path);
    pictureBox1.Image = byteArrayToImage(imageAsByteArray);
}

public Image byteArrayToImage(byte[] byteArrayIn)
{
    MemoryStream ms = new MemoryStream(byteArrayIn);
    Image returnImage = Image.FromStream(ms);
    return returnImage;
}
like image 26
Deniz Avatar answered Mar 25 '23 05:03

Deniz