Page 2 of 3 FirstFirst 123 LastLast
Results 41 to 80 of 110

Thread: [VB6] GDI+ Usage & Samples

  1. #41
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: [VB6] GDI+ Usage & Samples

    I don't know how you created the clipboard bitmap.
    By press <Prt Sr> key. You give a try then you see what I means. Your 32bpp code also has the same issue.

  2. #42

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] GDI+ Usage & Samples

    I see what you are talking about now. Honestly, there are only a few things that can be done
    1. Process ALL 32bpp bitmaps as 24bpp
    2. Build a better algo that can guess better whether alpha is in use or not
    3. Live with it
    4. Pass optional parameters to prevent the pvProcessAlphaBitmap routine from running

    The problem is as I described. The print-screen created a 32bpp DIB that wrote values in the alpha channel. Even though the image is obviously not an alpha bitmap and is meant to be a 24bpp bitmap, the alpha channel contains non-zero values. The alpha bitmap processing algo sees this and must assume the bitmap uses the alpha channel.

    When running this for multiple screenshots, I consistently got over 2500 pixels with the alpha channel filled in with values that range from 2 to 253. The unfortunate fact is that the bitmap does populate the alpha channel and therefore, by definition, is an alpha bitmap. Now in real life, we know this is not true, but there is no way for the routines to know that.
    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} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  3. #43
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: [VB6] GDI+ Usage & Samples

    Quote Originally Posted by LaVolpe View Post
    I see what you are talking about now. Honestly, there are only a few things that can be done
    1. Process ALL 32bpp bitmaps as 24bpp
    2. Build a better algo that can guess better whether alpha is in use or not
    3. Live with it
    4. Pass optional parameters to prevent the pvProcessAlphaBitmap routine from running

    The problem is as I described. The print-screen created a 32bpp DIB that wrote values in the alpha channel. Even though the image is obviously not an alpha bitmap and is meant to be a 24bpp bitmap, the alpha channel contains non-zero values. The alpha bitmap processing algo sees this and must assume the bitmap uses the alpha channel.

    When running this for multiple screenshots, I consistently got over 2500 pixels with the alpha channel filled in with values that range from 2 to 253. The unfortunate fact is that the bitmap does populate the alpha channel and therefore, by definition, is an alpha bitmap. Now in real life, we know this is not true, but there is no way for the routines to know that.
    Because <Print Screen> will capture whole screen,including Windows Captionbar,Start Menu,Task bar and System tray whose are alpha unfortunately.

    I have made a funny test:
    Code:
    For B = X - 3& To X - 1&
         If inArray(B) > inArray(X) Then
          ' pARGB can never have a R,G,B value > alpha value so this must be ARGB
           lColorFormat = PixelFormat32bppARGB ' ARGB format; done checking
           X = X + scanWidth   ' exit X loop
           Y = Height          ' exit Y loop
           alphaNum = alphaNum + 1
           Debug.Print inArray(B), inArray(X)
          'Exit For
    End If
    Next
    1.Windows <Start Menu> bar,Alpha number is 3
    2.Windows <Task bar>,Alpha number is 2
    3.Windows <System Tray>,Alpha number is 1
    4.Windows <Desktop>, Alpha number is 2
    5.Windows Caption bar,Alpha number is 0 (exclude the min/max/close button)
    6.Windows Caption bar,Alpha number is 1 (including the min/max/close button)

  4. #44

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] GDI+ Usage & Samples

    Makes sense, but doesn't help. I think the only way to "fix" this is to not process alpha bitmaps automatically, rather provide a parameter for 32bpp images that either skips or enters the pvProcessAlphaBitmap.

    Thinking out loud, this may be a better option. The routine that processes stdPicture objects takes a shortcut, for stdPicture bitmaps, it simply passes the .Handle off to the routine that processes DIB handles. The odds of someone trying to load a real 32bpp alpha bitmap into a stdPicture would be rare I would think. Therefore the routine could be modified to not take that shortcut and process them a bit differently as either paletted or 24bpp bitmaps, ignoring any alpha channels. A thought.

    Continuing with that thought... If someone does load a true alphablended bitmap into a stdPicture object (possible), to process it as alphablended, they would call the routine that loads DIBhandles instead, passing the .Handle property. This new process/option takes some of the automated picture type recognition out for stdPictures (bitmaps only), but provides the coder with both options.
    Last edited by LaVolpe; Jun 5th, 2010 at 12:52 AM.
    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} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  5. #45
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: [VB6] GDI+ Usage & Samples

    Quote Originally Posted by LaVolpe View Post
    Makes sense, but doesn't help. I think the only way to "fix" this is to not process alpha bitmaps automatically, rather provide a parameter for 32bpp images that either skips or enters the pvProcessAlphaBitmap.
    Thinking out loud, this may be a better option. The routine that processes stdPicture objects takes a shortcut, for stdPicture bitmaps, it simply passes the .Handle off to the routine that processes DIB handles. The odds of someone trying to load a real 32bpp alpha bitmap into a stdPicture would be rare I would think. Therefore the routine could be modified to not take that shortcut and process them a bit differently as either paletted or 24bpp bitmaps, ignoring any alpha channels. A thought.
    Continuing with that thought... If someone does load a true alphablended bitmap into a stdPicture object (possible), to process it as alphablended, they would call the routine that loads DIBhandles instead, passing the .Handle property. This new process/option takes some of the automated picture type recognition out for stdPictures (bitmaps only), but provides the coder with both options.
    Put an extra Optional ByVal IgnoreAlpha As Boolean to force LoadPicture_stdPicture to ignore Alpha channel when copy picture from clipboard or screen-capture. I guess you will come out a better solution again.
    Public Function LoadPicture_DIBhandle(DibHandle As Long, TokenClass As cGDIpToken, Optional ByVal ClearAttributes As Boolean = True, Optional ByVal IgnoreAlpha As Boolean = False) As Boolean
    Public Function LoadPicture_stdPicture(Picture As StdPicture, TokenClass As cGDIpToken, Optional ClearAttributes As Boolean = True, Optional IgnoreAlpha As Boolean) As Boolean
    Private Function pvProcessAlphaBitmap(inArray() As Byte, Width As Long, Height As Long, resetFlag As pvCleanUpEnum, Optional IgnoreAlpha As Boolean = False) As Boolean
    Last edited by Jonney; Jun 5th, 2010 at 01:42 AM.

  6. #46

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] GDI+ Usage & Samples

    In other classes/projects I've written, I have a more generic LoadPicture routine that accepts a variant. That routine tests the variant to see if its an array, long handle, stdPic, ClipBoard, Data (drag/drop) object, filename, or IStream/IUnknown object.

    But that is just a tip. I do not plan on making this thread's project commercial quality. It was an attempt to get some people thinking GDI+ that were intimidated by it and I think it can do that.

    There are many advanced functions that I have not included in this project and you are aware of a few of them. I don't mind giving you hints/tips to improve this project, but I don't plan on supersizing this one.
    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} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  7. #47
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: [VB6] GDI+ Usage & Samples

    Quote Originally Posted by Jonney View Post
    Because <Print Screen> will capture whole screen,including Windows Captionbar,Start Menu,Task bar and System tray whose are alpha unfortunately.

    I have made a funny test:


    1.Windows <Start Menu> bar,Alpha number is 3
    2.Windows <Task bar>,Alpha number is 2
    3.Windows <System Tray>,Alpha number is 1
    4.Windows <Desktop>, Alpha number is 2
    5.Windows Caption bar,Alpha number is 0 (exclude the min/max/close button)
    6.Windows Caption bar,Alpha number is 1 (including the min/max/close button)
    One thought:
    According to above trail,Why GDI+ display non-Alpha area with <BLACK> color except of <Start Menu> and <Task bar> and <Desktop> and Windows Caption bar?
    Attached Images Attached Images  

  8. #48

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] GDI+ Usage & Samples

    I couldn't tell you. Except that the alpha values are probably non-zero and low values like 3, 5, etc. Alpha of zero means 100&#37; transparency. So since low alpha values, they show up nearly transparent. When alpha value are used I think any 32bpp-aware graphics engine is going to assume they are indeed alpha. And if any alpha values are used, must assume all alpha channel values are used as alpha, nothing else.
    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} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  9. #49
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: [VB6] GDI+ Usage & Samples

    Quote Originally Posted by LaVolpe View Post
    And if any alpha values are used, must assume all alpha channel values are used as alpha, nothing else.
    Can we manually process?

  10. #50

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] GDI+ Usage & Samples

    Sure, you can use GetDIBits to return a byte array in 24bpp format. That will truncate the alpha channels.
    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} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  11. #51
    Member
    Join Date
    Feb 2011
    Posts
    54

    Re: [VB6] GDI+ Usage & Samples

    How to resize the picturebox and maintain the aspect ratio of the picture when resizing the form?

  12. #52

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] GDI+ Usage & Samples

    Resizing a picturebox? Use Picture1.Move x, y, w, h
    Maintain aspect ratio? Lots of examples in this forum & on the net.
    I've also included 2 functions in that project that you can use: GetScaledImageSizes & GetScaledCanvasSize
    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} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  13. #53
    Member
    Join Date
    Feb 2011
    Posts
    54

    Re: [VB6] GDI+ Usage & Samples

    Please, can you add sample code for GetScaledImageSizes & GetScaledCanvasSize.

    Thanks.

  14. #54

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] GDI+ Usage & Samples

    In the sample project, the form's RenderTheImage sub has an example. Otherwise, you might want to post what you are trying and exactly which you want to do:
    1) size the image to the container's dimensions, keeping aspect ratio
    2) size the container to the image's dimensions, keeping aspect ratio
    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} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  15. #55
    Member
    Join Date
    Feb 2011
    Posts
    54

    Re: [VB6] GDI+ Usage & Samples

    I want to do number 1, resize the image when the container is resizing, for example when I resize the form (dragging the edges of the windows) the container resizes, I want also the image inside the container resize to its dimensions.

  16. #56

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] GDI+ Usage & Samples

    Real short simple example. Note that you'll see flicker. If you want to prevent flicker, you'll want a backbuffer to render to then render the backbuffer to the form. Tons of examples about.
    Code:
    Option Explicit
    
    Dim cImage As cGDIpImage
    Dim cToken As cGDIpToken
    
    Private Sub Form_Load()
        Me.ScaleMode = vbPixels ' cGDIpImage class expects pixel values, not twips
        Set cToken = New cGDIpToken
        If cToken.Token = 0 Then
            MsgBox "GDI+ failed to load", vbExclamation + vbOKOnly
            Unload Me
            Exit Sub
        End If
        
        Set cImage = New cGDIpImage
        ' load your image into cImage now...
    
    End Sub
    
    Private Sub Form_UnLoad(Cancel As Integer)
       Set cImage = Nothing
       Set cToken = Nothing
    End Sub
    
    Private Sub Form_Resize()
        Dim newCx As Long, newCy As Long
        Dim cRenderer As New cGDIpRenderer
        cImage.GetScaledImageSizes Me.ScaleWidth, Me.ScaleHeight, newCx, newCy
        Me.Cls
        cRenderer.RenderImageClassToDC cImage, Me.hDC, (Me.ScaleWidth - newCx) \ 2, (Me.ScaleHeight - newCy) \ 2, newCx, newCy
        ' ^^ drawing from center of form. If not desired, simply change to 0,0 or whatever coords you want
        Set cRenderer = Nothing
    End Sub
    You may be interested in my Alpha Image Control, linked in my signature below. It takes the idea of this project and combines it into a usercontrol that can produce very professional results, flicker-free...
    If using my Alpha Image Control, you can load an image into the control during form design.
    Then the code would be as simple as...
    Code:
    Private Sub Form_Load()
        AlphaImgCtl1.Aspect = lvicScaled
        ' if wanting to draw the image from top/left of the control vs. centered within, then unrem following line
        'AlphaImgCtl1.AlignCenter = False
        
        '^^ both above properties can be set during design time & not required to be set here in Form_Load
    End Sub
    
    Private Sub Form_Resize()
        AlphaImgCtl1.Move 0, 0, Me.ScaleWidth, Me.ScaleHeight
    End Sub
    Last edited by LaVolpe; Jul 29th, 2011 at 10:12 AM.
    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} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  17. #57
    Member
    Join Date
    Feb 2011
    Posts
    54

    Re: [VB6] GDI+ Usage & Samples

    thanks on the code, it was very helpful, on Alpha Image Control how to put a checkered board on the background just like on the sample on the first page

  18. #58

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] GDI+ Usage & Samples

    Quote Originally Posted by rojaldearintok View Post
    thanks on the code, it was very helpful, on Alpha Image Control how to put a checkered board on the background just like on the sample on the first page
    Two immediate options come to play

    1) Simply create a checkerboard PNG or jpg/bmp in Paint or something else. Load that image into the control at design time or runtime

    2) Runtime: Create your own checkerboard pattern to a hidden picturebox (AutoRedraw=True & sized appropriately) or offscreen memory DC/bitmap. Then send the image to LoadPictureGDIplus(), passing the Picturebox.Image property or memory bitmap handle, depending which method you used.
    Last edited by LaVolpe; Jul 31st, 2011 at 03:44 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} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  19. #59
    Member
    Join Date
    Feb 2011
    Posts
    54

    Re: [VB6] GDI+ Usage & Samples

    thank you very much.

  20. #60
    New Member
    Join Date
    Oct 2011
    Posts
    1

    Re: [VB6] GDI+ Usage & Samples

    Hi
    Today just came across a wired bug. The Class fails to load a 8bit 256color JPEG as soon it is compiled. In the IDE it works fine.
    After some debugging, I found that the variable Depth in pvCreateSourcelessImage is reseted to 0 by the following Line when running as .exe and not in die IDE:
    Code:
    CopyMemory BHI.bmiColors(0), pal(8), .biClrImportant
    This makes then GdipBitmapLockBits fail.
    The work around is to make a copy of the variable Depth and to use this in GdipBitmapLockBits.

    Below the modified function:

    Code:
    Private Function pvCreateSourcelessImage(hImage As Long, Width As Long, Height As Long, flipFlag As Long) As Long
    
        ' function creates a stand-alone GDI+ image from a linked image
        ' The routine here follows the instructions given at this MS KB article link
        '       http://support.microsoft.com/kb/814675
        Dim tSize As RECTF, tSizeI As RECTI, BHI As BITMAPINFO
        Dim tBMPsrc As BitmapData, tBMPdst As BitmapData
        Dim cRender As cGDIpRenderer, pal() As Byte
        Dim oldImage As Long, newImage As Long, hObj As Long
        Dim dDC As Long, tDC As Long, Depth As Long, hGraphics As Long, dibPtr As Long
        Dim DepthSave As Long
        
        If Width = 0& Or Height = 0& Then               ' get size of image
            Call GdipGetImageBounds(hImage, tSize, UnitPixel)
            Width = tSize.nWidth: Height = tSize.nHeight
        End If
        Call GdipGetImagePixelFormat(hImage, Depth)
        DepthSave = Depth 'Save as CopyMemory BHI.bmiColors(0), pal(8), .biClrImportant resets Depth to 0
        Select Case Depth
            Case PixelFormat1bppIndexed, PixelFormat4bppIndexed, PixelFormat8bppIndexed
                With BHI.bmiHeader
                    If Depth = PixelFormat1bppIndexed Then
                        .biBitCount = 1
                    ElseIf Depth = PixelFormat4bppIndexed Then
                        .biBitCount = 4
                    Else
                        .biBitCount = 8
                    End If
                    Call GdipGetImagePaletteSize(hImage, .biClrImportant)
                    ReDim pal(0 To .biClrImportant + 7&)
                    GdipGetImagePalette hImage, pal(0), .biClrImportant
                    CopyMemory BHI.bmiColors(0), pal(8), .biClrImportant ' Does reset Depths to 0 when running compiled
                    .biClrImportant = .biClrImportant \ 4&
                    .biClrUsed = 2 ^ .biBitCount
                    Erase pal()
                End With
            Case PixelFormat24bppRGB, PixelFormat16bppGrayScale, PixelFormat16bppRGB555, PixelFormat16bppRGB565, PixelFormat48bppRGB
                BHI.bmiHeader.biBitCount = 24
                    
            Case Else
                Set cRender = New cGDIpRenderer
                cRender.AttachTokenClass m_Token
                oldImage = m_Image(m_SourceIndex)                   ' using the cGDIpRenderer class
                m_Image(m_SourceIndex) = hImage                     ' which requires this class to reflect correct image handle
                hGraphics = cRender.CreateGraphicsFromImageClass(Me) ' create a generic graphics object
                If hGraphics Then                                   ' then create new GDI+ bitmap
                    If GdipCreateBitmapFromGraphics(Width, Height, hGraphics, newImage) = 0& Then
                        cRender.DestroyHGraphics hGraphics
                        Call GdipGetImageBounds(hImage, tSize, UnitPixel)
                        m_Image(m_SourceIndex) = newImage           ' create graphics object around new bitmap
                        hGraphics = cRender.CreateGraphicsFromImageClass(Me)
                        If hGraphics Then                           ' draw the passed bitmap onto the new bitmap & clean up
                            Call cRender.RenderToHGraphics(hImage, hGraphics, 0&, 0&, Width, Height, tSize.nLeft, tSize.nTop, tSize.nWidth, tSize.nHeight)
                            cRender.DestroyHGraphics hGraphics
                            If flipFlag Then GdipImageRotateFlip newImage, flipFlag
                            pvCreateSourcelessImage = newImage
                        End If
                    Else
                        cRender.DestroyHGraphics hGraphics
                    End If
                End If
                m_Image(m_SourceIndex) = oldImage
        End Select
        
        If BHI.bmiHeader.biBitCount Then                            ' handle paletted & 24bit bitmaps here
            tSizeI.nHeight = Height: tSizeI.nWidth = Width
            With BHI.bmiHeader
                .biHeight = Height
                .biPlanes = 1
                .biSize = 40
                .biWidth = Width
                If .biBitCount = 24 Then
                    If GdipBitmapLockBits(hImage, tSizeI, ImageLockModeRead, PixelFormat24bppRGB, tBMPsrc) Then .biBitCount = 0& 'flag meaning failure
                Else
                    If GdipBitmapLockBits(hImage, tSizeI, ImageLockModeRead, DepthSave, tBMPsrc) Then .biBitCount = 0& 'Use DepthSave as Depth is 0 here when running compiled.
                End If
            End With
            If BHI.bmiHeader.biBitCount Then
                dDC = GetDC(GetDesktopWindow())
                hObj = CreateDIBSection(dDC, BHI, 0&, dibPtr, 0&, 0&)
                ReleaseDC GetDesktopWindow(), dDC
                If hObj Then
                    CopyMemory ByVal dibPtr, ByVal tBMPsrc.Scan0Ptr, tBMPsrc.Stride * Height
                    GdipBitmapUnlockBits newImage, tBMPsrc
                    GdipCreateBitmapFromHBITMAP hObj, 0&, newImage
                    DeleteObject hObj
                    GdipImageRotateFlip newImage, (flipFlag Xor 6&)
                    pvCreateSourcelessImage = newImage
                End If
            End If
        End If
        GdipDisposeImage hImage
        
    End Function
    I'm not sure what is causing this behavior. Attached the Image that triggers this bug.

    Kind regards
    Beat
    Attached Files Attached Files

  21. #61

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] GDI+ Usage & Samples

    Good catch. I don't use that function any longer as I've written a more efficient and much faster routine to create such sourceless GDI+ bitmaps. I won't be updating this project with that routine which can be found in my AlphaImage Control project linked in my signature below.

    The problem appears to be writing memory beyond intended bounds. That offending line should be changed to:
    CopyMemory BHI.bmiColors(0), pal(8), .biClrImportant - 8

    What was happening is that by copying 8 more bytes of data to the .bmiColors memory location than that location could hold, corruption of the following 8 bytes of memory on the stack occurs. This could be where the Depth variable resided? Anyway, I think you'll find the above patch suitable.
    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} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  22. #62
    Frenzied Member
    Join Date
    Oct 2008
    Posts
    1,181

    Re: [VB6] GDI+ Usage & Samples

    Quote Originally Posted by LaVolpe View Post
    This project is a teaser to get one's feet wet. For a fully functional usercontrol that is based almost entirely on GDI+, see my alpha image control project.

    If you have questions on how to do something with GDI+ that the attached project does not do, please post your question in the Graphics portion of the forum. I do not want, nor intend that this posting become a proxy "GDI+ Forum"

    If you have questions about this project then by all means ask away. There may be a few logic errors in the project; as we find those I'll continue to update. Jump to bottom to determine when last updated.

    GDI+ is a very handy tool and many coders stay away from it because it appears difficult, at first. So, the classes in this project are aimed at easing you along a bit. GDI+ has 100's of functions and the project herein only touches a small percentage of them. But should be enough for you to get your feet wet without being overwhelmed.

    A great site for descriptions of the GDI+ API functions.

    I do plan on updating this project from time to time. Things I have knowledge on and have not yet added to the project include GDI+ paths, strings, and regions. The project does include a very complete image processing class, a rendering class, and a pens/brushes class to get you started.

    If you want the absolute minimal code to read and display an image at actual size, see post #8 below

    Attachment 75528

    Some advantages of using GDI+
    :: Load/Save PNGs and TIFFs, even multi-page TIFFs
    :: Load and display animated GIFs
    :: Alphablending - images, lines, shapes, everything. GDI+ does not use standard RGB colors. All colors are ARGB which includes level of alphablending.
    :: Built-in niffty options like rotation, mirroring, on-the-fly pixel transformations and more
    :: No manual premultiplication of alpha values
    Some disadvantages of GDI+
    :: Crashes easy if not used properly. Objects created around other objects (i.e., images) are not actually stand-alone. GDI+ requires the source data to remain present until the GDI+ object is destroyed.
    -- Here is the MS KB Article link: http://support.microsoft.com/kb/814675
    -- The workaround is to create a DIBSection, then create a GDI+ bitmap from it and destroy the DIBSection
    -- But that workaround won't allow access to other images in a multi-image formats (GIFs, TIFFs) and 32bpp become pARGB.
    :: In IDE, can crash easily too -- like subclassing, you cannot just hit End or terminate your app from the debug window while GDI+ is running.
    :: As mentioned above, a little complicated for new users
    :: Does not support all older GDI functions. For example, you can't create an XOR pen with GDI+
    :: Requires extra steps to setup for drawing; but like anything new to you, just takes a little getting used to

    ___________________________________________________________________________
    Last Edited: Jan 21, 2010 8:50 PM GMT/Zulu
    :: Modified primarily for TIFF saving
    -- Can now save multiple images with/without attributes applied
    -- TIFF images can be saved in 1,4,8,24,32 bit depths - dependent upon source image depth
    :: Added another optional rendering quality setting when drawing: PixelOffsetMode
    :: Removed requirement of cGDIpRenderer to be passed token class during its function calls.
    -- Now entire class can be passed it one time via its AttachTokenClass method
    :: Single page TIFFs no longer cache their original source data; more memory savings
    Jan 19, 2010 2:20 AM GMT/Zulu
    :: Revamped quite a bit
    -- To reduce memory usage, PNG, BMP, & JPG no longer cache original data
    -- CloneImage routine still had some shortcomings when trying to clone without applying image attributes; fixed
    -- Fixed logic error reported by Jonney when cloning rotated images
    :: Added additional image types: imageIconPNG & imageCursorPNG to distinguish between PNGs loaded from ico/cur resources
    Jan 14, 2010 19:10 PM GMT/Zulu
    :: Found 2 memory leaks, one each in 2 different functions; fixed
    :: Changed logic when loading new images
    -- If new image then all attributes are reset automatically (were not before). Optional load flag prevents this.
    -- If multi-image format displays another image within same source; attributes remain (no change from previous logic)
    :: CreateCloneWithAttributes renamed to CreateClone. WithAttributes now an optional parameter
    :: ImageType property distinguishes between icons and cursors now
    :: Reorganized and cleaned up some routines
    :: Demo reworked a tad
    -- You can now apply multiple attributes to the same image and see results
    -- Included sample of saving a multi-page TIFF
    Jan 12, 2010 01:10 AM GMT/Zulu
    :: Added a little more functionality to the cGDIpImage class
    -- GetPixel, SetPixel, ExtraTransparentColor (similar functionality of TransparentBLT)
    :: Mirroring was off, had my constants swapped around, fixed
    :: When SaveAsOriginalFormat was applied for 32bpp alphablended bitmaps, was saved as 24bpp vs 32pp, fixed
    :: Updated demo a bit
    -- included SaveAsOriginalFormat, TransparentBLT examples
    -- included option to view any image in a multiple image format
    -- included option to view image info: size, depth, type
    Jan 11, 2010 01:30 AM GMT/Zulu
    :: Jonney helped identify a logic error when deciding whether 32bpp images use the Alpha channel and how it is used. Thanx Jonney
    ...
    AWESOME!

    Too bad you don't in your online documentation explain how to use HGraphics. Render Class can create HGraphics from Image Class and a number of other sources. And while the Render Class can directly Render the Image Class to a DC for viewing, what it can't do is render an HGraphics to DC. Sure it can convert a DC to HGraphics, but not the other way. So after getting an HGraphics and using that for the Draw Rectangle command, I have NO WAY TO DISPLAY THE DRAWN RECTANGLE! Please help. Thanks in advance.

  23. #63
    New Member
    Join Date
    Feb 2013
    Posts
    1

    Re: [VB6] GDI+ Usage & Samples

    Sorry for my English, I translate with google!
    Good evening everyone, I'm new to this forum and do not know English well.
    I wanted to complete my little project for my collection of coins and I would, at this point, transfer images with a transparent background on word 2010.
    I would have my picture (picture3.hdc) in transparency would save it in png transparent and then transfer it into word (only know the way through file:
    Code:
    Set Img = wApp.Selection.InlineShapes.AddPicture (FileName: = IMAGEFILE, LinkToFile: = false, SaveWithDocument: = True)
    where Filename = image.png).
    How do I save a picture3.hdc file.png?
    I could give a hand please?
    I tried but I can not save the picture, I am only the background color!!
    To explain better, I hope, I have a picturebox with an image with a white background and I would like to send a word in transparency ('cause word on the sheet there' a background image and you should see below, I have transformed my picturebox in a transparent picturebox.hdc (with mask), and now I would like to save it in png with transparent background.
    Can you help me with the command line that I include in my project?
    thank you very much
    Last edited by egits75; Feb 20th, 2013 at 11:49 AM.

  24. #64
    New Member
    Join Date
    Mar 2013
    Posts
    3

    Cool Re: [VB6] GDI+ Usage & Samples

    Hello; I am not so clever person. So I need your help: I want to display PNG data from a vCard in a picturebox. I already decoded the base64 data into an byte array. I would prefer to convert the data into a StdPicture to load it easily into the picturebox or imagebox.
    Please can you provide me the minimal code for this? I need a function like this:

    Private Function GetPictureFromPNGArray(PNG() as Byte) as StdPicture

  25. #65
    New Member
    Join Date
    Jan 2015
    Posts
    4

    Question Re: [VB6] GDI+ Usage & Samples

    Ciao LaVolpe,
    first of all, thanks for this well done work, you saved me tons of hours about writing code to manage GDI+ from VB6!!

    Your classes works very well for my pourposes. However I need something it seems to be not present at all in this classes: create a Bitmap/Image in memory.

    At the moment, sources for creating cGDIpImage objec are: File, Stream, StdPicture and Dib handle. But there is no way to create a in-memory-bitmap like in C# i can do with the code:

    Code:
    Bitmap bitmap = new Bitmap(100, 100);
    Suppose I've a .png with a round button shape inside (100x100px), and a .png with the floppy image(48x48px). Both .png are 32bbp and have transparence and AlphaChannel for a drop shadow effect. I need to obtain a single image, with the result of a paste operation between the two .pngs. This I can do with your class in this way:

    1) load the two .pngs in two cGDIpImage objects via .LoadPicture_FileName() method
    2) create a cGDIpRenderer object via .CreateGraphicsFromImageClass() method from first cGDIpImage object (the button image)
    3) use the .RenderImageClassToHGraphics() method to paste then floppy object over the button object
    4) save to new .png or use it with a PictureBox standard control

    This works fine. But: if I need to get a 300x300px image as result of the merge operation, with button and floppy centered, I need a new image (not existing as .png file!!) of 300x300px, wich I use as starting point for cGDIpRenderer object, where I can paste over the button and floppy objects. Well, this new image of 300x300px should be created as new memory bitmap, then saved to .png file using .SaveAsPNG() method, preserving transparence and AlphaChannel.

    I've been able to create a in-memory bitmap using this code:

    Code:
    Public Function Create(Width As Integer, Height As Integer)
    
      Dim pbmi As BITMAPINFO
    
      'Memorizza dimensioni
      m_Width = Width
      m_Height = Height
    
      'Prepara informazioni per la generazione del bitmap
      With pbmi.bmiHeader
        .biBitCount = 32
        .biCompression = BI_RGB
        .biPlanes = 1
        .biSize = Len(pbmi.bmiHeader)
        .biWidth = m_Width
        .biHeight = m_Height
        .biSizeImage = m_Height * m_Width * 4&
      End With
    
      'Crea in memoria un DC compatibile con lo schermo
      m_hDC = CreateCompatibleDC(0)
    
      'Crea un BMP compatibile con il DC creato
      m_hBMP = CreateDIBSection(m_hDC, pbmi, DIB_RGB_COLORS, m_hDIBS, ByVal 0&, ByVal 0&)
    
      'Azzera contenuto
      FillMemory ByVal m_hDIBS, (m_Width * m_Height * 4&), 0
    
    End Function
    
    Public Sub Dispose()
    
      'Scarica oggetti
      If (m_hBMP <> 0) Then DeleteObject m_hBMP
      If (m_hDC <> 0) Then DeleteDC m_hDC
    
    End Sub
    and after creating the in-memory 300x300 surface bitmap I can use the

    Code:
    .LoadPicture_DIBhandle(m_hBMP , mclsToken)
    method to create theh cGDIpImage object I can work with, starting from a bitmap created in memory and not loaded from file.

    The problem is that this in-memory bitmap has the background setted to black (I mean due to the fact all BMP bytes are filled to 0). So, when I display the result in a PictureBox or save to a .png file, the background around the button is not transparent, but black. If I FillMemory with &H255 the background becomes white, of course.

    At the moment my workaround is to load a file .png that is completely transparent in a "surface" cGDIpImage object, stretch it to the size I need, load others .png files, .RenderImageClassToHGraphics() to paste loaded .png over the "surface" object, then finally save it back to .png file (preserving transparence and AlphaChannel) or paste into Picturebox (with alphablend to the PictureBox background color).

    It would be perfect if you can suggest me the code to obtain an ARBG, completely transparent, cGDIpImage object created directly in memory, giving only then Width and Height parameters.

    Thanks a lot!

  26. #66

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] GDI+ Usage & Samples

    With GDIP you can create a 32bit blank image with this line of code:
    GdipCreateBitmapFromScan0 Width, Height, 0&, PixelFormat32bppPARGB, ByVal 0&, hImage

    In the cGDIpImage class, you may want to create a new function where you pass the width,height and assign the hImage of the GdipCreateBitmapFromScan0 to the m_Image(0) variable in that class. Once you have a class you can render from GDIP to GDIP via the RenderImageClassToHGraphics after first calling CreateGraphicsFromImageClass and passing the destination class.

    So logic could be:
    1) modify then cGDIpImage class to add new function to create a blank 32bit bitmap as suggested above. Set that class' m_ImageType to imageBitmap and other properties as appropriate, i.e, m_Size, m_OrigColorType
    2) call cGDIpRenderer.CreateGraphicsFromImageClass to get a graphics handle for that blank bitmap
    3) call cGDIpRenderer.RenderImageClassToHGraphics, passing the source image class and the hGraphics handle
    4) call cGDIpRenderer.DestroyHGraphics when done drawing

    These classes were designed to get one started with GDI+, just intended as an outline to be learned from & eventually moved on to one's own classes & implementation.
    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} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  27. #67
    New Member
    Join Date
    Jan 2015
    Posts
    4

    Resolved Re: [VB6] GDI+ Usage & Samples

    Quote Originally Posted by LaVolpe View Post
    With GDIP you can create a 32bit blank image with this line of code:
    GdipCreateBitmapFromScan0 Width, Height, 0&, PixelFormat32bppPARGB, ByVal 0&, hImage

    In the cGDIpImage class, you may want to create a new function where you pass the width,height and assign the hImage of the GdipCreateBitmapFromScan0 to the m_Image(0) variable in that class. Once you have a class you can render from GDIP to GDIP via the RenderImageClassToHGraphics after first calling CreateGraphicsFromImageClass and passing the destination class.

    So logic could be:
    1) modify then cGDIpImage class to add new function to create a blank 32bit bitmap as suggested above. Set that class' m_ImageType to imageBitmap and other properties as appropriate, i.e, m_Size, m_OrigColorType
    2) call cGDIpRenderer.CreateGraphicsFromImageClass to get a graphics handle for that blank bitmap
    3) call cGDIpRenderer.RenderImageClassToHGraphics, passing the source image class and the hGraphics handle
    4) call cGDIpRenderer.DestroyHGraphics when done drawing

    These classes were designed to get one started with GDI+, just intended as an outline to be learned from & eventually moved on to one's own classes & implementation.
    Great!!! You are the man LaVolpe!!!

    So, new function to create in-memory bitmap could be:

    Code:
    Public Function LoadPicture_Memory(Width As Long, Height As Long, ImageFormat As ImageColorFormatConstants, TokenClass As cGDIpToken) As Boolean
    
        If TokenClass Is Nothing Then Exit Function
        If TokenClass.Token = 0& Then Exit Function
        If Width = 0 Then Exit Function
        If Height = 0 Then Exit Function
        
        Dim lResult As Long
        Dim hImage  As Long
    
        If m_Token Is Nothing Then
            Set m_Token = TokenClass
            TokenClass.AddUser Me
        End If
        
        'Tenta creazione del Bitmap in memoria
        GdipCreateBitmapFromScan0 Width, Height, 0&, ImageFormat, ByVal 0&, hImage
        If hImage <> 0 Then
          m_Image(0) = hImage
          m_ImageType = imageBitmap
          m_Size.nWidth = Width
          m_Size.nHeight = Height
          m_Attr = 0
          m_Alpha = 0
          m_TransColor = 0
          m_Angle = 0
          m_Lightness = 0
          m_GrayScale = attrGrayNone
          m_Mirror = attrMirrorNone
          m_OrigColorType = ImageFormat
        End If
    
        LoadPicture_Memory = (hImage <> 0)
    
    End Function
    Then, calling
    Code:
    .LoadPicture_Memory(300, 300, PixelFormat32bppARGB, mclsToken)
    will do the trick!

    Image created by GdipCreateBitmapFromScan0 (handle in m_Image(0)) will be automatically disposed by
    Code:
    GdipDisposeImage m_Image(0)
    in pvCleanUp function.

    So, what's the difference to use PixelFormat32bppPARGB and PixelFormat32bppARGB values as PixelFormat for the new in-memory bitmap?? The resulting .png file seems to be the same..

    Thanks once more for this huge work you've made and released as free usable code!

  28. #68

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] GDI+ Usage & Samples

    So, what's the difference to use PixelFormat32bppPARGB and PixelFormat32bppARGB values as PixelFormat for the new in-memory bitmap?? The resulting .png file seems to be the same..
    Very slight pixel modification due to rounding during premultiplication. However, theoretically faster internal GDI+ usage, especially if intending to render to an old-fashioned GDI device context

    Enjoy.

    Edited: One flaw with your new function. ImageFormat should be restricted to 24 bit or higher. Honestly can't recall whether GDI+ allows creating of blank 16bit or not? However, anything less than 16bit requires a palette and your code doesn't currently support that. If GDI+ doesn't support creation (via Scan0 method) of specific bit depths, it uses the next higher depth it does support, or defaults to 32bit as a last resort
    Last edited by LaVolpe; Jan 14th, 2015 at 11:11 AM.
    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} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  29. #69
    New Member
    Join Date
    Jan 2015
    Posts
    4

    Re: [VB6] GDI+ Usage & Samples

    Quote Originally Posted by LaVolpe View Post
    Very slight pixel modification due to rounding during premultiplication. However, theoretically faster internal GDI+ usage, especially if intending to render to an old-fashioned GDI device context

    Enjoy.

    Edited: One flaw with your new function. ImageFormat should be restricted to 24 bit or higher. Honestly can't recall whether GDI+ allows creating of blank 16bit or not? However, anything less than 16bit requires a palette and your code doesn't currently support that. If GDI+ doesn't support creation (via Scan0 method) of specific bit depths, it uses the next higher depth it does support, or defaults to 32bit as a last resort
    Ok, I mean.

    Last (stupid) question, regarding plain BMP (24 bit) and VB6 StdPicture object.

    If I use the code
    Code:
    Dim thePic as StdPicture
    set thePic = LoadPicture("background.bmp")
    I get the bitmap inside StdPicture object; then I can pass it to control's .Picture property to show it. Fine.

    But if bmp is a set of contiguos icons of 32x32 size, and I'd like to create an array of n 32x32 StdPicture objects, each one with his own n-icon graphics from original bmp, how can I do this without any .hDC available??

    I'm trying to use the .Render method of the StdPicture object, but it requires .hDC. More, if I create a new instance of StdPictures, Width, Height, Handle all equals 0.

    I tried to create in-memory bitmap 32x32 and convert it to StdPicture via OleCreatePictureIndirect() and I get correct properties values, but Render method fails.

    Have you some suggestions??

    Thanks a lot!

  30. #70

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] GDI+ Usage & Samples

    I'm surprised that .Render method of stdPicture would fail on a valid stdPicture object?

    As far as an array of stdPicture objects, that can be done a few ways. Using a VB control called PictureClip I believe? You could also do this with these classes or using a hidden picturebox (autoredraw=true & sized to 32x32).

    The logic for these classes, looks like this:
    1) Use your new function to create a memory 32x32 (24 bit) bitmap
    2) Load the bitmap that has the strip of 32x32 images into a separate image class
    3) Using cGDIpRenderer, draw the current 32x32 block, offsetting x,y as needed, to the blank image
    4) in that image class, Save the 32x32 image to a bitmap array that you can send to OleCreatePictureIndirect
    5) now blank out that memory bitmap using cGDIpRenderer.EraseHGraphics
    6) repeat steps 3-5 for each 32x32 block
    7) destroy the created Graphics object & unload your classes

    The logic for VB's picbox is very similar
    1) PicboxBuffer: autoredraw=true, sized to 32x32 inside width (or 32x32 without borders)
    2) Set PicboxBuffer.Picture = Nothing
    3) BitBlt or stdPicture.Render a 32x32 block, offsetting x,y as needed, to PicboxBuffer.hDC
    4) Set PicboxBuffer.Picture = PicboxBuffer.Image
    5) cache PicboxBuffer.Picture to a new stdPicture object
    6) repeat steps 2-5 for each 32x32 block
    7) Clean up: Set PicboxBuffer.Picture = Nothing: PicboxBuffer.AutoRedraw = False, etc

    The above is air-code. Hopefully I didn't miss an obvious (or subtle) step anywhere. Sounds like you are a good coder & can fill in any blanks I may have missed.

    Edited: I just glanced over a comment you made and shouldn't have. You don't want to use an .hDC? Sounds like this is a class-based issue then? Just FYI: You always have an hDC to render to, just need to create one via GDI API calls. Of course that usually means you have to create a bitmap (GDI calls) & move it in & out of the hDC as needed. Using the 1st idea above avoids those extra steps since the classes have the necessary code to get what you want.
    Last edited by LaVolpe; Jan 14th, 2015 at 03:08 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} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  31. #71
    New Member
    Join Date
    Mar 2013
    Posts
    3

    Re: [VB6] GDI+ Usage & Samples

    Quote Originally Posted by rebo View Post
    Hello; I am not so clever person. So I need your help: I want to display PNG data from a vCard in a picturebox. I already decoded the base64 data into an byte array. I would prefer to convert the data into a StdPicture to load it easily into the picturebox or imagebox.
    Please can you provide me the minimal code for this? I need a function like this:

    Private Function GetPictureFromPNGArray(PNG() as Byte) as StdPicture
    It seems you ignore me here.

  32. #72

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] GDI+ Usage & Samples

    Quote Originally Posted by rebo View Post
    It seems you ignore me here.
    Don't be mad. I took over a year off from this forum. When I came back I was ignoring all posts that were 1+ years old

    You have two issues:
    1) VB6 does not support PNG as a stdPicture. The PNG will have to be converted to a bitmap/jpg for use in the stdPicture object
    2) The classes in this project do not directly support saving any images to a stdPicture object

    So, workarounds.
    1) Consider using my AlphaImage control. It accepts base64 and can also save to various formats, including saving to a stdPicture object. However, that control was an attempt to replace VB's image control. So all you have to do is simply add it to a form and use it as is.
    2) There are several examples of sending a byte array to the OleCreatePictureIndirect API. If you search for that API in the VB forum, you will find examples. So, what you can do is send the PNG array to the cGDIpImage class' LoadPicture_Stream function to create an image. Then call the SaveAsBMP or SaveAsJPG method and pass the array returned from those functions to the OleCreatePictureIndirect API to create a stdPicture
    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} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  33. #73
    New Member
    Join Date
    Mar 2013
    Posts
    3

    Re: [VB6] GDI+ Usage & Samples

    Thank you very much!

  34. #74
    New Member
    Join Date
    Jan 2015
    Posts
    4

    Re: [VB6] GDI+ Usage & Samples

    Thanks for your reply!

    Quote Originally Posted by LaVolpe View Post
    I'm surprised that .Render method of stdPicture would fail on a valid stdPicture object?
    You can try by yourself.. creating a new StdPicture you won't get a valid bitmap behind the object.. you have to get a reference from an existing .Picture from PictureBox or use LoadImage() function.. really strange!

    Quote Originally Posted by LaVolpe View Post
    As far as an array of stdPicture objects, that can be done a few ways. Using a VB control called PictureClip I believe? You could also do this with these classes or using a hidden picturebox (autoredraw=true & sized to 32x32).
    Oh, that was only an example.. I don't really need a PictureClip control, or, at least, I don't need only that kind of solution.. For example, I'm implementing some code for 9patch images: starting from 256x256 .png button I've to create some other buttons in different sizes (100x80, 180x120, 90x45..) and each one, once created with your classes and pasted over a graphic background (a photo for example), I need to keep it in memory, in the form of StdPicture object, so is very easy to assign it to the corresponding PictureBox control on the form.

    Quote Originally Posted by LaVolpe View Post
    The logic for these classes, looks like this:
    1) Use your new function to create a memory 32x32 (24 bit) bitmap
    2) Load the bitmap that has the strip of 32x32 images into a separate image class
    3) Using cGDIpRenderer, draw the current 32x32 block, offsetting x,y as needed, to the blank image
    4) in that image class, Save the 32x32 image to a bitmap array that you can send to OleCreatePictureIndirect
    5) now blank out that memory bitmap using cGDIpRenderer.EraseHGraphics
    6) repeat steps 3-5 for each 32x32 block
    7) destroy the created Graphics object & unload your classes

    The logic for VB's picbox is very similar
    1) PicboxBuffer: autoredraw=true, sized to 32x32 inside width (or 32x32 without borders)
    2) Set PicboxBuffer.Picture = Nothing
    3) BitBlt or stdPicture.Render a 32x32 block, offsetting x,y as needed, to PicboxBuffer.hDC
    4) Set PicboxBuffer.Picture = PicboxBuffer.Image
    5) cache PicboxBuffer.Picture to a new stdPicture object
    6) repeat steps 2-5 for each 32x32 block
    7) Clean up: Set PicboxBuffer.Picture = Nothing: PicboxBuffer.AutoRedraw = False, etc

    The above is air-code. Hopefully I didn't miss an obvious (or subtle) step anywhere. Sounds like you are a good coder & can fill in any blanks I may have missed.

    Edited: I just glanced over a comment you made and shouldn't have. You don't want to use an .hDC? Sounds like this is a class-based issue then? Just FYI: You always have an hDC to render to, just need to create one via GDI API calls. Of course that usually means you have to create a bitmap (GDI calls) & move it in & out of the hDC as needed. Using the 1st idea above avoids those extra steps since the classes have the necessary code to get what you want.
    However the code to create 9-path images and all the other graphics will be the best to be keept in common classes/modules, without the need of a form and a hidden PictureBox control. That's the reason why I said "no .dHC", I don't (want to) have a PictureBox to use for graphics pourposes, and if I can load sources images from files, I need a "destination surface" in memory, and I've to create it from scratch.. Your classes can manage this (now with GdipCreateBitmapFromScan0) but I don't want to bother GDI+ to create a plain 24bit bitmap for raster operation, so I developed the following code to create an in-memory bitmap using the standard GDI APIs, and convert it back to StdPicture object I cas store in a Collection for faster later use.

    Code:
    Option Explicit
    
    Private Declare Function OleCreatePictureIndirect Lib "olepro32.dll" (lpPictDesc As PICTDESC, RefIID As GUID, ByVal fPictureOwnsHandle As Long, IPic As Any) As Long
    Private Declare Function CreateCompatibleDC Lib "gdi32.dll" (ByVal hDC As Long) As Long
    Private Declare Function DeleteDC Lib "gdi32.dll" (ByVal hDC As Long) As Long
    Private Declare Function DeleteObject Lib "gdi32.dll" (ByVal hObject As Long) As Long
    Private Declare Function GetObjectType Lib "gdi32.dll" (ByVal hGDIObj As Long) As Long
    Private Declare Function GetObject Lib "gdi32.dll" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
    Private Declare Function SelectObject Lib "gdi32.dll" (ByVal hDC As Long, ByVal hObject As Long) As Long
    Private Declare Function CreateDIBSection Lib "gdi32.dll" (ByVal hDC As Long, pBitmapInfo As BitmapInfo, ByVal un As Long, ByRef lplpDIBS As Long, ByVal handle As Long, ByVal dw As Long) As Long
    Private Declare Function FillMemory Lib "kernel32.dll" Alias "RtlFillMemory" (ByRef Destination As Any, ByVal Length As Long, ByVal Fill As Byte) As Long
    Private Declare Function FillRect Lib "user32.dll" (ByVal hDC As Long, lpRC As RECT, ByVal hBR As Long) As Long
    Private Declare Function CreateSolidBrush Lib "gdi32.dll" (ByVal crColor As Long) As Long
    
    Private Const OBJ_BITMAP As Long = &H7
    Private Const PICTYPE_BITMAP As Long = &H1
    
    Private Const BI_RGB = 0
    Private Const DIB_RGB_COLORS = 0
    
    Private Type GUID
      Data1 As Long
      Data2 As Integer
      Data3 As Integer
      Data4(7) As Byte
    End Type
    
    Private Type PICTDESC
      cbSize As Long
      picType As Long
      hImage As Long
      xExt As Long
      yExt As Long
    End Type
    
    Private Type BitmapInfoHeader '40 bytes
      biSize As Long
      biWidth As Long
      biHeight As Long
      biPlanes As Integer
      biBitCount As Integer
      biCompression As Long
      biSizeImage As Long
      biXPelsPerMeter As Long
      biYPelsPerMeter As Long
      biClrUsed As Long
      biClrImportant As Long
    End Type
    
    Private Type RGBQUAD
      rgbBlue As Byte
      rgbGreen As Byte
      rgbRed As Byte
      rgbReserved As Byte
    End Type
    
    Private Type BitmapInfo
      bmiHeader As BitmapInfoHeader
      bmiColors As RGBQUAD
    End Type
    
    Private Type RECT
      nLeft   As Long
      nTop    As Long
      nWidth  As Long
      nHeight As Long
    End Type
    
    Private Type BITMAP
      bmType As Long
      bmWidth As Long
      bmHeight As Long
      bmWidthBytes As Long
      bmPlanes As Integer
      bmBitsPixel As Integer
      bmBits As Long
    End Type
    
    Public Function CreateStdPicture(Width As Long, Height As Long, Optional BackgroundColor As OLE_COLOR = vbBlack) As IPicture
    
      Dim pbmi      As BitmapInfo
      
      Dim hDC       As Long
      Dim hBMP      As Long
      Dim hDIBS     As Long
      Dim hOldBMP   As Long
      Dim hBrush    As Long
      Dim tRECT     As RECT
      
      Dim lResult   As Long
    
      'Prepara informazioni per la generazione del bitmap
      With pbmi.bmiHeader
        .biSize = Len(pbmi.bmiHeader)
        .biBitCount = 24
        .biCompression = BI_RGB
        .biPlanes = 1
        .biWidth = Width
        .biHeight = Height
        .biSizeImage = ((((Width * .biBitCount) + &H1F) And Not &H1F) \ &H8) * Height
      End With
    
      'Crea in memoria un DC compatibile con lo schermo
      hDC = CreateCompatibleDC(0)
    
      'Crea un BMP compatibile con il DC creato
      hBMP = CreateDIBSection(hDC, pbmi, DIB_RGB_COLORS, hDIBS, ByVal 0&, ByVal 0&)
      
      'Azzera contenuto
      FillMemory ByVal hDIBS, pbmi.bmiHeader.biSizeImage, 0
      
      'Se colore diverso da nero, effettua un fill dell'area del BMP
      If (BackgroundColor <> vbBlack) Then
      
        'Seleziona il BMP nel DC
        hOldBMP = SelectObject(hDC, hBMP)
        
        'Colora il bitmap con il colore di sfondo
        With tRECT
          .nTop = 0
          .nLeft = 0
          .nWidth = Width
          .nHeight = Height
        End With
        
        'Crea un brush solido
        hBrush = CreateSolidBrush(BackgroundColor)
        
        'Riempie il bitmap con il brush creato
        lResult = FillRect(hDC, tRECT, hBrush)
        
        'Elimina il brush
        lResult = DeleteObject(hBrush)
        
        'Rilascia il BMP
        SelectObject hDC, hOldBMP
      
      End If
      
      'Distrugge il DC generato, mentre il BMP rimane valido e verrà automaticamente distrutto al momento della distruzione dell'oggetto
      'OLE generato tramite la GDIToPicture(), grazie all'automazione offerta dall'interfaccia IDispatch
      lResult = DeleteDC(hDC)
      
      'Converte in IPicture e ritorna l'oggetto
      Set CreateStdPicture = GDIToPicture(hBMP)
    
    End Function
    
    Public Function GDIToPicture(ByVal hGDIObj As Long) As IPicture
      
      Dim PicDesc   As PICTDESC
      Dim IPict     As IPicture
      
      Dim lObjType  As Long
      Dim lResult   As Long
      
      'Recupera tipologia di oggetto presente nell'handle passato
      lObjType = GetObjectType(hGDIObj)
      
      Select Case lObjType
          
          Case OBJ_BITMAP
            PicDesc.cbSize = 16
            PicDesc.picType = PICTYPE_BITMAP
            
          Case Else
            'Oggetto non riconosciuto
            Exit Function
            
      End Select
      
      'Imposta l'handle del DC
      PicDesc.hImage = hGDIObj
      
      'Tenta la conversione da BMP a StdPicture
      lResult = OleCreatePictureIndirect(PicDesc, IPictureGUID(), 1, IPict)
      If (lResult = 0) Then Set GDIToPicture = IPict
      
      'Scarica riferimento all'oggetto IPucture locale
      Set IPict = Nothing
        
    End Function
    
    Private Function IPictureGUID() As GUID
      
      'IPicture GUID {7BF80980-BF32-101A-8BBB-00AA00300CAB}
      With IPictureGUID
        .Data1 = &H7BF80980
        .Data2 = &HBF32
        .Data3 = &H101A
        .Data4(0) = &H8B
        .Data4(1) = &HBB
        .Data4(2) = &H0
        .Data4(3) = &HAA
        .Data4(4) = &H0
        .Data4(5) = &H30
        .Data4(6) = &HC
        .Data4(7) = &HAB
      End With
      
    End Function
    
    Public Sub RenderStdPicture(SourcePic As IPicture, DestPic As IPicture, Optional X As Long = -1, Optional Y As Long = -1, Optional Width As Long = -1, Optional Height As Long = -1, Optional xSrc As Long = -1, Optional ySrc As Long = -1, Optional WidthSrc As Long = -1, Optional HeightSrc As Long = -1)
      
      Dim hDC       As Long
      Dim hBMP      As Long
      Dim hOldBMP   As Long
      
      Dim tBITMAP   As BITMAP
      Dim lResult   As Long
       
      'Effettua render delle due StdPicuture
      
      'Verifica i valori x,y,width,height. I parametri devono essere espressi tutti in Pixel
      If (X = -1) Then X = 0
      If (Y = -1) Then Y = 0
      If (Width = -1) Then Width = HimetricToPixelX(SourcePic.Width)
      If (Height = -1) Then Height = HimetricToPixelY(SourcePic.Height)
      If (xSrc = -1) Then xSrc = 0
      If (ySrc = -1) Then ySrc = 0
      If (WidthSrc = -1) Then WidthSrc = HimetricToPixelX(SourcePic.Width)
      If (HeightSrc = -1) Then HeightSrc = HimetricToPixelY(SourcePic.Height)
    
      'Crea un DC per la StdPicture di destinazione
      hDC = CreateCompatibleDC(0)
    
      'Seleziona il BMP nel DC
      hOldBMP = SelectObject(hDC, DestPic.handle)
      
      'Effettua il render
      SourcePic.Render hDC, X, Y, Width, Height, PixelToHimetricX(xSrc), SourcePic.Height - PixelToHimetricY(ySrc), PixelToHimetricX(WidthSrc), -PixelToHimetricY(HeightSrc), 0&
        
      'Rilascia il BMP
      SelectObject hDC, hOldBMP
        
      'Distrugge il DC generato
      lResult = DeleteDC(hDC)
      
    End Sub
    
    Private Function HimetricToPixelY(Value As Long) As Long
    
      HimetricToPixelY = (CDbl(Value) / 1000) * 567 / Screen.TwipsPerPixelY
    
    End Function
    
    Private Function PixelToHimetricY(Value As Long) As Long
    
      PixelToHimetricY = (CDbl(Value) * 1000) / 567 * Screen.TwipsPerPixelY
    
    End Function
    
    Private Function HimetricToPixelX(Value As Long) As Long
    
      HimetricToPixelX = (CDbl(Value) / 1000) * 567 / Screen.TwipsPerPixelX
    
    End Function
    
    Private Function PixelToHimetricX(Value As Long) As Long
    
      PixelToHimetricX = (CDbl(Value) * 1000) / 567 * Screen.TwipsPerPixelX
    
    End Function
    What do you think about this way to deal with graphics resources?!?

  35. #75
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    Re: [VB6] GDI+ Usage & Samples

    In case you want to handle your graphics without any Controls - and store them in a
    VB-Collection as StdPictures as a kind of global ImageCache...

    I've managed that already in a combination of GDI+ based PNG-Loading - and then storing
    the resulting DIBs (as 32Bit ones, including the AlphaChannel) in normal StdPictures.

    That is managed in a small wrapper-class (cPngCacheGDIP), which when declared globally
    (and then filled with PNG-resources at App-Startup) - would then be reachable throughout
    your Application, to render its preloaded Alpha-Image-StdPictures "per Key".

    The appropriate codebank-example is here:
    http://www.vbforums.com/showthread.p...ely-per-WIA%29

    Not sure if that is more like, what you are after?

    Here's a variation of the above, which is using the base-mechanism (the cPngCacheGDIP),
    in lightweight UserControl-encapsulations - but that's not as "pure VBClass-driven" anymore,
    as the example in the above link.
    http://www.vbforums.com/showthread.p...mage-Sprite%29


    Olaf

  36. #76

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] GDI+ Usage & Samples

    Quote Originally Posted by minimega
    What do you think about this way to deal with graphics resources?!?
    There are various ways to deal with graphics. In my alpha image control, I don't use stdPictures at all, but since VB uses them, that control has a SaveAs option to create them if the user needs them.

    I must stress that these classes were not designed to be a graphics factory for any serious projects. There were designed to get people comfortable with using GDI+, more or less: "Graphics 101 with GDI+", borrowing college terminology as a play on words.
    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} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  37. #77
    Addicted Member
    Join Date
    Feb 2015
    Posts
    154

    Re: [VB6] GDI+ Usage & Samples

    Hey LaVolpe, just a note of appreciation - these classes are awesome for my purposes and are very much appreciated as they saved me tons of time. I've been using Freeimage in this particular application for several years now but I've decided to streamline the code and that my program doesn't really need to support 23+ image formats. And using GDI+ internally dumps the dependence on the Freeimage dll as well. Anyway, thanks again for the fine work!

  38. #78
    Hyperactive Member Daniel Duta's Avatar
    Join Date
    Feb 2011
    Location
    Bucharest, Romania
    Posts
    396

    Re: [VB6] GDI+ Usage & Samples

    Quote Originally Posted by rebo View Post
    Thank you very much!
    I can't believe it. This guy was waiting for a response almost 2 years... No doubt it is a record of this forum
    My respect, Rebo.

  39. #79
    Hyperactive Member
    Join Date
    Jun 2011
    Posts
    461

    Re: [VB6] GDI+ Usage & Samples

    Can someone give me minimal code which will load and display an ICO file into a PictureBox? Thanks in advance!
    Last edited by MikiSoft; Aug 12th, 2015 at 04:09 PM.

  40. #80

    Thread Starter
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [VB6] GDI+ Usage & Samples

    Minimal code: Picture1.Picture = LoadPicture(path/filename)

    Maybe you can more specific. To handle icons that O/S supports but VB doesn't
    Code:
    hIcon = LoadImage(0&, path/filename, IMAGE_ICON, desiredWidth, desiredHeight, LR_LOADFROMFILE)
    If hIcon Then
        DrawIconEx Picture1.hDC, 0, 0, hIcon, targetWidth, targetHeight, 0, 0, DI_NORMAL)
        DestroyIcon hIcon
    End If
    LoadImage: https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx
    DrawIconEx: https://msdn.microsoft.com/en-us/lib...=vs.85%29.aspx
    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} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

Page 2 of 3 FirstFirst 123 LastLast

Posting Permissions

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



Click Here to Expand Forum to Full Width