[RESOLVED] GdipLoadImageFromFile & access denied!-VBForums
Results 1 to 11 of 11

Thread: [RESOLVED] GdipLoadImageFromFile & access denied!

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2014
    Posts
    291

    Resolved [RESOLVED] GdipLoadImageFromFile & access denied!

    I have a problem.

    I have a class that load a picture using GdipLoadImageFromFile.
    then Im doing this and that, graphic work.
    when its time to save, I get access denied. I can't kill/rename/rewrite the picture at all.

    - no solution if I try run as administrator
    - no solution if I try to save different name, and then after cleanup(set = nothing) try to access the file.

    I need to exit my program to access the picture again. something is locking it.

    Anyone know why or a way to go around it?

  2. #2
    PowerPoster
    Join Date
    Feb 2006
    Posts
    17,529

    Re: GdipLoadImageFromFile & access denied!

    Can you create a stripped down example? It sounds like a handle/object leak.

  3. #3

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2014
    Posts
    291

    Re: GdipLoadImageFromFile & access denied!

    Code:
    Private Function LoadImage(ByVal FileName$, ByVal Index&) As Long
        Dim Img As Long
        Dim iPixelFormat As Long
        Dim ArrayWidth As Long
        Dim colorDepth As Long
        Dim DIBHeader As BITMAPINFOHEADER
        Dim layerRect As RECT
        Dim hBrush As Long
        Dim copyBitmapData As BitmapData
        Dim tmpRect As RECTL
        Dim iGraphics As Long
        Dim DIBits As Long
        Dim Widths As Single
        Dim Heights As Single
        Dim Width As Single
        Dim Height As Single
        Const PixelFormat32bppPARGB = &HE200B
    
        With Image(Index)
        
        GdipLoadImageFromFile StrPtr(FileName$), Img
        If Img Then
            GdipGetImageDimension Img, Widths, Heights
            GdipGetImagePixelFormat Img, iPixelFormat
            Width = Widths
            Height = Heights
            .Width = Width
            .Height = Height
            If (iPixelFormat And &H40000) Or (iPixelFormat And &H80000) Then colorDepth = 32 Else colorDepth = 24
            With DIBHeader
                .biSize = Len(DIBHeader)
                .biPlanes = 1
                .biBitCount = colorDepth
                .biWidth = Width
                .biHeight = -Height
                If colorDepth = 32 Then ArrayWidth = 4 * Width Else ArrayWidth = (Width * 3 + 3) And &HFFFFFFFC
                .biSizeImage = ArrayWidth * Height
            End With
            .hDC = CreateCompatibleDC(0)
            .DIB = CreateDIBSection(.hDC, DIBHeader, 0, DIBits, 0, 0)
            If .DIB Then
                .orgDIB = SelectObject(.hDC, .DIB)
                SetRect layerRect, 0, 0, Width, Height
                hBrush = CreateSolidBrush(0)
                FillRect .hDC, layerRect, hBrush
                DeleteObject hBrush
            End If
            If colorDepth = 32 Then
                If iPixelFormat <> PixelFormat32bppPARGB Then GdipCloneBitmapAreaI 0, 0, Width, Height, PixelFormat32bppPARGB, Img, Img
                With copyBitmapData
                    .Width = -Width
                    .Height = Height
                    .PixelFormat = PixelFormat32bppPARGB
                    .Stride = ArrayWidth
                    .scan0 = DIBits
                End With
                
                With tmpRect: .Width = Width: .Height = Height: End With
                GdipBitmapLockBits Img, tmpRect, &H4 Or &H2 Or &H1, PixelFormat32bppPARGB, copyBitmapData
                GdipBitmapUnlockBits Img, copyBitmapData
                .Alpha = 33488896
            Else
                GdipCreateFromHDC .hDC, iGraphics
                GdipDrawImageRect iGraphics, Img, 0, 0, Widths, Heights
                GdipDeleteGraphics iGraphics
                .Alpha = 16711680
            End If
        End If
        GdipDisposeImage Img
        End With
    End Function
    the is the loading function, the image(index) is a collection to store the .hdc/.dib/.orgDib so that I can later delete it.
    when Termination, I run
    Code:
    SelectObject .hDC, .orgDIB
    DeleteObject .DIB
    DeleteDC .hDC
    for each picture I have loaded into it.

  4. #4
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    16,537

    Re: GdipLoadImageFromFile & access denied!

    GDI+ locks the file when that function is used. This is documented on MSDN.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VB and DPI Tutorial} {XP/Vista Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  5. #5

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2014
    Posts
    291

    Re: GdipLoadImageFromFile & access denied!

    but how can it be locked when I destroy the class?
    at the end of the program, at unload, I remove everything, and still the picture is locked.
    I mean, we have programs out there that can load and save pictures. why can't vb6/gdi+ do that?

  6. #6
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    16,537

    Re: GdipLoadImageFromFile & access denied!

    Quote Originally Posted by baka
    why can't vb6/gdi+ do that?
    It can, if GDI+ is used correctly... The following line and any like it are likely the reason
    Code:
    GdipCloneBitmapAreaI 0, 0, Width, Height, PixelFormat32bppPARGB, Img, Img
    Img was the result of GdipLoadImageFromFile and the above line overwrites Img with a different GDI+ handle. The original handle isn't destroyed. At the end of your routine, you GdipDisposeImage Img, but it's too late, it's destroying the cloned Img. The one loaded from GdipLoadImageFromFile is still alive and has the file locked until the process (VB) is unloaded. In any case, you created two GDI+ images and destroyed only one of them -- not the one that is locking the file.

    You should be able to see this. Debug.Print Img before you call that clone then again afterwards, Img should've changed.

    Edited: What you've basically done is something like this, using GDI APIs.
    Code:
       bmp = CreateDIBSection(....)  ' bmp is one image
    ...
       bmp = CopyImage(bmp, ...) ' now bmp is another image, the original no longer referenced
    ...
       DeleteObject bmp  ' deletes 2nd bmp, first one is alive (leaked until process ends)
    Last edited by LaVolpe; Oct 11th, 2017 at 08:14 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VB and DPI Tutorial} {XP/Vista Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  7. #7

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2014
    Posts
    291

    Re: GdipLoadImageFromFile & access denied!

    Ah, didn't see that one. I just copied the source from somewhere without thinking twice.

    Changed the code so that I dispose the img if GdipCloneBitmapAreaI is used.
    It works now! Thanks a bunch!
    But before I read your post I came up with a "solution" that in the end its not that bad.
    At startup I rename the picture to ".old", like a backup. then I use that when I read the picture.
    When Im done I save it with the "original" name.

    But I will of course change the function anyway, not good that I have a memory leak!

  8. #8
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    16,537

    Re: [RESOLVED] GdipLoadImageFromFile & access denied!

    Unfortunately, your workaround was a solution to an unfixed problem. In one sense, be glad the problem came up. If it didn't you could have been leaking GDI+ assets like crazy.

    OPC (other people's code) can come back and bite you and it usually does at some point. Got you, got me, got nearly all coders at one time or another. After being burned a couple times, we learn to double or triple check it.

    P.S. If the author of the code you used made such a careless mistake, I'd seriously spend time and review any other code you borrowed from that source! Some mistakes just make one think the coder was simply throwing variables at a function & hoping for the best, not understanding how the function used those variables. Hmmm
    Last edited by LaVolpe; Oct 11th, 2017 at 08:51 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VB and DPI Tutorial} {XP/Vista Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  9. #9

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2014
    Posts
    291

    Re: [RESOLVED] GdipLoadImageFromFile & access denied!

    not 100% sure where I found it, I think I merged two different codes as I wanted to have the image in a DC to use with GdiAlphaBlend instead of GdipDrawImageRectRectI.
    yeah, I think I leaked a lot. I use the same load function in another project where I load tons of pictures!
    now I can fix that! it feels good to clean up the code!

  10. #10
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    16,537

    Re: [RESOLVED] GdipLoadImageFromFile & access denied!

    In my signature block below, you can find a link regarding "memory leaks" related to GDI & some GDI+ (since it also uses GDI). It was originally written nearly a decade ago, but still applies today. And I still use task manager on a regular basis to test for leaks. Not a bad read really. Informative at the very least.

    Cute. Went back and re-read part of that tutorial and here is a quote that seems to apply to your thread...
    Research the API on www.MSDN.com if you are unfamiliar with it. Never assume code you copied from some other source is correct. Some APIs will create objects that you are responsible for destroying and you may not even be aware of it and the author of the code you copied may not be aware of it either.
    Last edited by LaVolpe; Oct 11th, 2017 at 09:36 PM.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VB and DPI Tutorial} {XP/Vista Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  11. #11

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2014
    Posts
    291

    Re: [RESOLVED] GdipLoadImageFromFile & access denied!

    interesting read.

    analyzing my "gdi" program, Im doing:

    - Form_Unload: Cancel = True, to unload classes, stop subclassing. - check -
    - Create$$$ API's gets Deleted. - check -
    - Im lazy to check return values. This can cause problems if run low on memory! - can cause problems -
    - Using as little possible vb6 own controls. using 1 picturebox, autoredraw false and from there only API. - check -
    - Fixed 1 leak (using your tip to check GDI Objects) - found leak! -
    the leak is that 1 picture didn't unload. the cleanup function looped from 2 to end. (because of how the code worked first, saved index 1 until termination, but after I changed the code to not do so, I forgot to change it to 1)
    when I run the next map, index#1 gets replaced with a new picture, and the old picture is there somewhere in limbo.
    reloading the map with this "leak" caused the program to eat memory! fixed it!

    this is a good reminder and also a great way to analyze the program to check for leaks.
    nobody wants leaks! thanks a lot LaVolpe!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Featured


Click Here to Expand Forum to Full Width

Survey posted by VBForums.