Unable to overwrite image file... I think...

lidds

Junior Contributor
Joined
Nov 9, 2004
Messages
210
I have written some code to capture a image of the desktop and preview it within a picturebox, this works fine. The problem comes when I try to repeat the process and the following error is produced

"An unhandled exception of type 'System.Runtime.InteropServices.ExternalException' occurred in system.drawing.dll

Additional information: A generic error occurred in GDI+."

I can only presume this is because my picturebox is still keeping the file open. There is not problem in overwritting the file if I close my program and open it again. I have tried pointing the picturebox image to nothing but this does not work.

Visual Basic:
    Private Sub btnCapture_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCapture.Click
        Dim SC As New ScreenShot.ScreenCapture
        Me.picPreview.Image = Nothing

        Dim MyBitMap As Bitmap = SC.CaptureDeskTopRectangle(New Rectangle(MRCSData.Instance.X1, MRCSData.Instance.Y1, _
        MRCSData.Instance.X2, MRCSData.Instance.Y2), Math.Abs(MRCSData.Instance.X1 - MRCSData.Instance.X2), Math.Abs(MRCSData.Instance.Y1 - MRCSData.Instance.Y2))
        MyBitMap.Save("c:\desktopregion.jpg", Imaging.ImageFormat.Jpeg)

        Dim path As String = "c:\desktopregion.jpg"
        Me.picPreview.Image = Image.FromFile(path)

        Dim myBMP As Bitmap = New Bitmap(path)
        Me.pnlPreview.Size = New Size(520, 420)

        If myBMP.Width < Me.pnlPreview.Width Then
            Me.pnlPreview.Width = myBMP.Width
        End If

        If myBMP.Height < Me.pnlPreview.Height Then
            Me.pnlPreview.Height = myBMP.Height
        End If

        Me.pnlPreview.AutoScroll = True
        Me.pnlPreview.AutoScrollMinSize = myBMP.Size
    End Sub

Thanks

Simon
 
PlausiblyDamp said:
You will need to dispose of the image assigned to the picturebox rather than just setting it to nothing.

I added the dispose to my script but it produced the same error. Any ideas, or have I made a mistake??

Visual Basic:
    Private Sub btnCapture_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCapture.Click
        Dim SC As New ScreenShot.ScreenCapture
        Me.picPreview.Image = Nothing
        Me.picPreview.Dispose()

        Dim MyBitMap As Bitmap = SC.CaptureDeskTopRectangle(New Rectangle(MRCSData.Instance.X1, MRCSData.Instance.Y1, _
        MRCSData.Instance.X2, MRCSData.Instance.Y2), Math.Abs(MRCSData.Instance.X1 - MRCSData.Instance.X2), Math.Abs(MRCSData.Instance.Y1 - MRCSData.Instance.Y2))
        MyBitMap.Save("c:\desktopregion.jpg", Imaging.ImageFormat.Jpeg)

        Dim path As String = "c:\desktopregion.jpg"
        Me.picPreview.Image = Image.FromFile(path)

        Dim myBMP As Bitmap = New Bitmap(path)
        Me.pnlPreview.Size = New Size(520, 420)

        If myBMP.Width < Me.pnlPreview.Width Then
            Me.pnlPreview.Width = myBMP.Width
        End If

        If myBMP.Height < Me.pnlPreview.Height Then
            Me.pnlPreview.Height = myBMP.Height
        End If

        Me.pnlPreview.AutoScroll = True
        Me.pnlPreview.AutoScrollMinSize = myBMP.Size
    End Sub

Thanks

Simon
 
If you need to access an image file repeatedly you can not use the constructor overload that accepts a filename or the Image.FromFile function. Whether by design or as the result of a bug, the image file is not freed for access (at least not for write access, not sure about read access) until the image is finalized (not when it is disposed).

An easy workaround for this is to create a FileStream on the image file and pass this FileStream to the Bitmap constructor instead of using Image.FromFile. Immediately after creating the Bitmap object, close the FileStream to free it up to be deleted/read/written again.
 
Thanks you. However would it be possible for you to give me an example of how to do this.

Thanks

Simon
 
Visual Basic:
Dim path As String = "c:\\image.jpg"
Dim fs As New IO.FileStream(path, IO.FileMode.Open)
Dim bmp As New Bitmap(fs)
fs.Close()
PictureBox1.Image = bmp
 
Back
Top