Results 1 to 35 of 35

Thread: [RESOLVED] Fastest way to render transparent stdPictures or pngs to grid cells

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Sep 2012
    Posts
    2,083

    Resolved [RESOLVED] Fastest way to render transparent stdPictures or pngs to grid cells

    I need to quickly render a large number of small pictures in my grid cells, and the pictures need to be transparent to the grid backcolor. I'm ready to use the following code to achieve my purpose, I'd like to know if there is a simpler, more efficient way.

    Code:
    Private Sub DrawPicture(lpRect As RECT, Optional lBrushColor As Long = -1)
    
    '****************************************************************************
    ' draw the picture by calling the TransBlt routines                         *
    '****************************************************************************
    
       Dim tmpMaskColor     As Long
    
       ' --Draw picture
       If tmppic.Type = vbPicTypeIcon Then
          tmpMaskColor = TranslateColor(&HC0C0C0)
       Else
          tmpMaskColor = m_nMaskColor
       End If
       
       If Is32BitBMP(tmppic) Then
          TransBlt32 hDC, lpRect.Left, lpRect.Top, PicW, PicH, tmppic, lBrushColor
       Else
          TransBlt hDC, lpRect.Left, lpRect.Top, PicW, PicH, tmppic, tmpMaskColor, lBrushColor
       End If
       
    End Sub
    
    Private Sub TransBlt32(ByVal DstDC As Long, ByVal dstX As Long, ByVal dstY As Long, ByVal DstW As Long, ByVal DstH As Long, ByVal SrcPic As StdPicture, Optional ByVal BrushColor As Long = -1, Optional ByVal isGreyscale As Boolean = False)
    
       '****************************************************************************
       '* Routine : Renders 32 bit Bitmap                                          *
       '* Author  : Dana Seaman                                                    *
       '****************************************************************************
    
       Dim b                As Long, H As Long, f As Long, i As Long, newW As Long
       Dim TmpDC            As Long, TmpBmp As Long, TmpObj As Long
       Dim Sr2DC            As Long, Sr2Bmp As Long, Sr2Obj As Long
       Dim DataDest()       As RGBQUAD, DataSrc() As RGBQUAD
       Dim Info             As BITMAPINFO, BrushRGB As RGBQUAD, gCol As Long
       Dim hOldOb           As Long, PicEffect As enumPicEffect
       Dim SrcDC            As Long, tObj As Long, ttt As Long
       Dim bDisOpacity      As Byte
       Dim OverOpacity      As Byte
       Dim a2               As Long
       Dim a1               As Long
    
       If DstW = 0 Or DstH = 0 Then Exit Sub
       If SrcPic Is Nothing Then Exit Sub
    
       If m_ButtonState = eStateOver Then
          PicEffect = m_PicEffectonOver
       ElseIf m_ButtonState = eStateDown Then
          PicEffect = m_PicEffectonDown
       End If
       
       If Not m_bEnabled Then
          Select Case m_PicDisabledMode
          Case edpBlended
             bDisOpacity = 52
          Case edpGrayed
             bDisOpacity = m_PictureOpacity * 0.75
             isGreyscale = True
          End Select
       End If
          
       If m_ButtonState = eStateOver Then
          OverOpacity = m_PicOpacityOnOver
       End If
       
       SrcDC = CreateCompatibleDC(hDC)
    
       If DstW < 0 Then DstW = UserControl.ScaleX(SrcPic.Width, 8, UserControl.ScaleMode)
       If DstH < 0 Then DstH = UserControl.ScaleY(SrcPic.Height, 8, UserControl.ScaleMode)
    
       tObj = SelectObject(SrcDC, SrcPic)
    
       TmpDC = CreateCompatibleDC(SrcDC)
       Sr2DC = CreateCompatibleDC(SrcDC)
    
       TmpBmp = CreateCompatibleBitmap(DstDC, DstW, DstH)
       Sr2Bmp = CreateCompatibleBitmap(DstDC, DstW, DstH)
       TmpObj = SelectObject(TmpDC, TmpBmp)
       Sr2Obj = SelectObject(Sr2DC, Sr2Bmp)
    
       With Info.bmiHeader
          .biSize = Len(Info.bmiHeader)
          .biWidth = DstW
          .biHeight = DstH
          .biPlanes = 1
          .biBitCount = 32
          .biSizeImage = 4 * ((DstW * .biBitCount + 31) \ 32) * DstH
       End With
       ReDim DataDest(Info.bmiHeader.biSizeImage - 1)
       ReDim DataSrc(UBound(DataDest))
    
       BitBlt TmpDC, 0, 0, DstW, DstH, DstDC, dstX, dstY, vbSrcCopy
       BitBlt Sr2DC, 0, 0, DstW, DstH, SrcDC, 0, 0, vbSrcCopy
       GetDIBits TmpDC, TmpBmp, 0, DstH, DataDest(0), Info, 0
       GetDIBits Sr2DC, Sr2Bmp, 0, DstH, DataSrc(0), Info, 0
    
       If BrushColor <> -1 Then
          BrushRGB.rgbBlue = (BrushColor \ &H10000) Mod &H100
          BrushRGB.rgbGreen = (BrushColor \ &H100) Mod &H100
          BrushRGB.rgbRed = BrushColor And &HFF
       End If
    
       newW = DstW - 1
    
       For H = 0 To DstH - 1
          f = H * DstW
          For b = 0 To newW
             i = f + b
             If m_bEnabled Then
                 If m_ButtonState = eStateOver Then
                    a1 = (CLng(DataSrc(i).rgbAlpha) * OverOpacity) \ 255
                 Else
                    a1 = (CLng(DataSrc(i).rgbAlpha) * m_PictureOpacity) \ 255
                 End If
             Else
                a1 = (CLng(DataSrc(i).rgbAlpha) * bDisOpacity) \ 255
             End If
             a2 = 255 - a1
             With DataDest(i)
                If BrushColor <> -1 Then
                   If a1 = 255 Then
                      DataDest(i) = BrushRGB
                   ElseIf a1 > 0 Then
                      .rgbRed = (a2 * .rgbRed + a1 * BrushRGB.rgbRed) \ 256
                      .rgbGreen = (a2 * .rgbGreen + a1 * BrushRGB.rgbGreen) \ 256
                      .rgbBlue = (a2 * .rgbBlue + a1 * BrushRGB.rgbBlue) \ 256
                   End If
                Else
                   If isGreyscale Then
                      gCol = CLng(DataSrc(i).rgbRed * 0.3) + DataSrc(i).rgbGreen * 0.59 + DataSrc(i).rgbBlue * 0.11
                      If a1 = 255 Then
                         .rgbRed = gCol: .rgbGreen = gCol: .rgbBlue = gCol
                      ElseIf a1 > 0 Then
                         .rgbRed = (a2 * .rgbRed + a1 * gCol) \ 256
                         .rgbGreen = (a2 * .rgbGreen + a1 * gCol) \ 256
                         .rgbBlue = (a2 * .rgbBlue + a1 * gCol) \ 256
                      End If
                   Else
                      If a1 = 255 Then
                         If (PicEffect = epeLighter) Then
                            .rgbRed = aLighten(DataSrc(i).rgbRed)
                            .rgbGreen = aLighten(DataSrc(i).rgbGreen)
                            .rgbBlue = aLighten(DataSrc(i).rgbBlue)
                         ElseIf PicEffect = epeDarker Then
                            .rgbRed = aDarken(DataSrc(i).rgbRed)
                            .rgbGreen = aDarken(DataSrc(i).rgbGreen)
                            .rgbBlue = aDarken(DataSrc(i).rgbBlue)
                         Else
                            DataDest(i) = DataSrc(i)
                         End If
                      ElseIf a1 > 0 Then
                         If (PicEffect = epeLighter) Then
                            .rgbRed = (a2 * .rgbRed + a1 * aLighten(DataSrc(i).rgbRed)) \ 256
                            .rgbGreen = (a2 * .rgbGreen + a1 * aLighten(DataSrc(i).rgbGreen)) \ 256
                            .rgbBlue = (a2 * .rgbBlue + a1 * aLighten(DataSrc(i).rgbBlue)) \ 256
                         ElseIf PicEffect = epeDarker Then
                            .rgbRed = (a2 * .rgbRed + a1 * aDarken(DataSrc(i).rgbRed)) \ 256
                            .rgbGreen = (a2 * .rgbGreen + a1 * aDarken(DataSrc(i).rgbGreen)) \ 256
                            .rgbBlue = (a2 * .rgbBlue + a1 * aDarken(DataSrc(i).rgbBlue)) \ 256
                         Else
                            .rgbRed = (a2 * .rgbRed + a1 * DataSrc(i).rgbRed) \ 256
                            .rgbGreen = (a2 * .rgbGreen + a1 * DataSrc(i).rgbGreen) \ 256
                            .rgbBlue = (a2 * .rgbBlue + a1 * DataSrc(i).rgbBlue) \ 256
                         End If
                      End If
                   End If
                End If
             End With
          Next b
       Next H
    
       ' /--Paint it!
       SetDIBitsToDevice DstDC, dstX, dstY, DstW, DstH, 0, 0, 0, DstH, DataDest(0), Info, 0
    
       Erase DataDest, DataSrc
       DeleteObject SelectObject(TmpDC, TmpObj)
       DeleteObject SelectObject(Sr2DC, Sr2Obj)
       If SrcPic.Type = vbPicTypeIcon Then DeleteObject SelectObject(SrcDC, tObj)
       DeleteDC TmpDC
       DeleteDC Sr2DC
       DeleteObject tObj
       DeleteDC SrcDC
    
    End Sub
    
    Private Sub TransBlt(ByVal DstDC As Long, ByVal dstX As Long, ByVal dstY As Long, ByVal DstW As Long, ByVal DstH As Long, ByVal SrcPic As StdPicture, Optional ByVal TransColor As Long = -1, Optional ByVal BrushColor As Long = -1, Optional ByVal MonoMask As Boolean = False, Optional ByVal isGreyscale As Boolean = False)
    
       '****************************************************************************
       '* Routine : To make transparent and grayscale images
       '* Author  : Gonkuchi
       '
       '* Modified by Dana Seaman
       '****************************************************************************
    
       Dim b                As Long, H As Long, f As Long, i As Long, newW As Long
       Dim TmpDC            As Long, TmpBmp As Long, TmpObj As Long
       Dim Sr2DC            As Long, Sr2Bmp As Long, Sr2Obj As Long
       Dim DataDest()       As RGBTRIPLE, DataSrc() As RGBTRIPLE
       Dim Info             As BITMAPINFO, BrushRGB As RGBTRIPLE, gCol As Long
       Dim hOldOb           As Long, PicEffect As enumPicEffect
       Dim SrcDC            As Long, tObj As Long, ttt As Long
       Dim bDisOpacity      As Byte
       Dim OverOpacity      As Byte
       Dim a2               As Long
       Dim a1               As Long
    
       If DstW = 0 Or DstH = 0 Then Exit Sub
       If SrcPic Is Nothing Then Exit Sub
    
       If m_ButtonState = eStateOver Then
          PicEffect = m_PicEffectonOver
       ElseIf m_ButtonState = eStateDown Then
          PicEffect = m_PicEffectonDown
       End If
       
       If Not m_bEnabled Then
          Select Case m_PicDisabledMode
          Case edpBlended
             bDisOpacity = 52
          Case edpGrayed
             bDisOpacity = m_PictureOpacity * 0.75
             isGreyscale = True
          End Select
       End If
       
       If m_ButtonState = eStateOver Then
          OverOpacity = m_PicOpacityOnOver
       End If
    
       SrcDC = CreateCompatibleDC(hDC)
    
       If DstW < 0 Then DstW = UserControl.ScaleX(SrcPic.Width, 8, UserControl.ScaleMode)
       If DstH < 0 Then DstH = UserControl.ScaleY(SrcPic.Height, 8, UserControl.ScaleMode)
    
       If SrcPic.Type = vbPicTypeBitmap Then 'check if it's an icon or a bitmap
          tObj = SelectObject(SrcDC, SrcPic)
       Else
          Dim hBrush           As Long
          tObj = SelectObject(SrcDC, CreateCompatibleBitmap(DstDC, DstW, DstH))
          hBrush = CreateSolidBrush(TransColor)
          DrawIconEx SrcDC, 0, 0, SrcPic.handle, DstW, DstH, 0, hBrush, DI_NORMAL
          DeleteObject hBrush
       End If
    
       TmpDC = CreateCompatibleDC(SrcDC)
       Sr2DC = CreateCompatibleDC(SrcDC)
       TmpBmp = CreateCompatibleBitmap(DstDC, DstW, DstH)
       Sr2Bmp = CreateCompatibleBitmap(DstDC, DstW, DstH)
       TmpObj = SelectObject(TmpDC, TmpBmp)
       Sr2Obj = SelectObject(Sr2DC, Sr2Bmp)
       ReDim DataDest(DstW * DstH * 3 - 1)
       ReDim DataSrc(UBound(DataDest))
       With Info.bmiHeader
          .biSize = Len(Info.bmiHeader)
          .biWidth = DstW
          .biHeight = DstH
          .biPlanes = 1
          .biBitCount = 24
       End With
    
       BitBlt TmpDC, 0, 0, DstW, DstH, DstDC, dstX, dstY, vbSrcCopy
       BitBlt Sr2DC, 0, 0, DstW, DstH, SrcDC, 0, 0, vbSrcCopy
       GetDIBits TmpDC, TmpBmp, 0, DstH, DataDest(0), Info, 0
       GetDIBits Sr2DC, Sr2Bmp, 0, DstH, DataSrc(0), Info, 0
    
       If BrushColor > 0 Then
          BrushRGB.rgbBlue = (BrushColor \ &H10000) Mod &H100
          BrushRGB.rgbGreen = (BrushColor \ &H100) Mod &H100
          BrushRGB.rgbRed = BrushColor And &HFF
       End If
    
       ' --No Maskcolor to use
       If Not m_bUseMaskColor Then TransColor = -1
    
       newW = DstW - 1
    
       For H = 0 To DstH - 1
          f = H * DstW
          For b = 0 To newW
             i = f + b
             If m_ButtonState = eStateOver Then
                a1 = OverOpacity
             Else
                a1 = IIf(m_bEnabled, m_PictureOpacity, bDisOpacity)
             End If
             a2 = 255 - a1
             If GetNearestColor(hDC, CLng(DataSrc(i).rgbRed) + 256& * DataSrc(i).rgbGreen + 65536 * DataSrc(i).rgbBlue) <> TransColor Then
                With DataDest(i)
                   If BrushColor > -1 Then
                      If MonoMask Then
                         If (CLng(DataSrc(i).rgbRed) + DataSrc(i).rgbGreen + DataSrc(i).rgbBlue) <= 384 Then DataDest(i) = BrushRGB
                      Else
                         If a1 = 255 Then
                            DataDest(i) = BrushRGB
                         ElseIf a1 > 0 Then
                            .rgbRed = (a2 * .rgbRed + a1 * BrushRGB.rgbRed) \ 256
                            .rgbGreen = (a2 * .rgbGreen + a1 * BrushRGB.rgbGreen) \ 256
                            .rgbBlue = (a2 * .rgbBlue + a1 * BrushRGB.rgbBlue) \ 256
                         End If
                      End If
                   Else
                      If isGreyscale Then
                         gCol = CLng(DataSrc(i).rgbRed * 0.3) + DataSrc(i).rgbGreen * 0.59 + DataSrc(i).rgbBlue * 0.11
                         If a1 = 255 Then
                            .rgbRed = gCol: .rgbGreen = gCol: .rgbBlue = gCol
                         ElseIf a1 > 0 Then
                            .rgbRed = (a2 * .rgbRed + a1 * gCol) \ 256
                            .rgbGreen = (a2 * .rgbGreen + a1 * gCol) \ 256
                            .rgbBlue = (a2 * .rgbBlue + a1 * gCol) \ 256
                         End If
                      Else
                         If a1 = 255 Then
                            If PicEffect = epeLighter Then
                               .rgbRed = aLighten(DataSrc(i).rgbRed)
                               .rgbGreen = aLighten(DataSrc(i).rgbGreen)
                               .rgbBlue = aLighten(DataSrc(i).rgbBlue)
                            ElseIf PicEffect = epeDarker Then
                               .rgbRed = aDarken(DataSrc(i).rgbRed)
                               .rgbGreen = aDarken(DataSrc(i).rgbGreen)
                               .rgbBlue = aDarken(DataSrc(i).rgbBlue)
                            Else
                               DataDest(i) = DataSrc(i)
                            End If
                         ElseIf a1 > 0 Then
                            If (PicEffect = epeLighter) Then
                               .rgbRed = (a2 * .rgbRed + a1 * aLighten(DataSrc(i).rgbRed)) \ 256
                               .rgbGreen = (a2 * .rgbGreen + a1 * aLighten(DataSrc(i).rgbGreen)) \ 256
                               .rgbBlue = (a2 * .rgbBlue + a1 * aLighten(DataSrc(i).rgbBlue)) \ 256
                            ElseIf PicEffect = epeDarker Then
                               .rgbRed = (a2 * .rgbRed + a1 * aDarken(DataSrc(i).rgbRed)) \ 256
                               .rgbGreen = (a2 * .rgbGreen + a1 * aDarken(DataSrc(i).rgbGreen)) \ 256
                               .rgbBlue = (a2 * .rgbBlue + a1 * aDarken(DataSrc(i).rgbBlue)) \ 256
                            Else
                               .rgbRed = (a2 * .rgbRed + a1 * DataSrc(i).rgbRed) \ 256
                               .rgbGreen = (a2 * .rgbGreen + a1 * DataSrc(i).rgbGreen) \ 256
                               .rgbBlue = (a2 * .rgbBlue + a1 * DataSrc(i).rgbBlue) \ 256
                            End If
                         End If
                      End If
                   End If
                End With
             End If
          Next b
       Next H
    
       ' /--Paint it!
       SetDIBitsToDevice DstDC, dstX, dstY, DstW, DstH, 0, 0, 0, DstH, DataDest(0), Info, 0
    
       Erase DataDest, DataSrc
       DeleteObject SelectObject(TmpDC, TmpObj)
       DeleteObject SelectObject(Sr2DC, Sr2Obj)
       If SrcPic.Type = vbPicTypeIcon Then DeleteObject SelectObject(SrcDC, tObj)
       DeleteDC TmpDC
       DeleteDC Sr2DC
       DeleteObject tObj
       DeleteDC SrcDC
    
    End Sub
    I know that AlphaBlend (msimg32) and GdiAlphaBlend (gdi32.dll) can do similar work. In addition, I also know that LaVolpe's stdPicEx2 can achieve this functionality, but stdPicEx2 is too large for my grid control, and I'm not familiar with GdiPlus. I wonder if I can use gdi32 or Cairo to simply and quickly render pictures in grid cells.

    Any advice and suggestions would be greatly appreciated.
    Last edited by dreammanor; Jun 10th, 2018 at 09:45 AM.

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

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    Couple things

    I also know that LaVolpe's stdPicEx2 can achieve this functionality, but stdPicEx2 is too large for my grid control, and I'm not familiar with GdiPlus. I wonder if I can use gdi32 or Cairo to simply and quickly render pictures in grid cells.
    So, stdPicEx2 class is too large? But Cairo isn't? Just saying. Dilettante has posted many examples using WIC. I'm not familiar with that library, but since it's deployed on most O/S, it may be an option? From his posts regarding WIC, it appears WIC may use GDI+ in the background; therefore, I'd think it can grayscale and know it can blend.

    You mentioned PNGs. So, I assume you are using some library to load PNGs and convert them to 32bpp bitmaps? If not, could you clarify a bit. Reason I ask is that if you are using GDI+ to load the PNG, you can also use it to blend and grayscale while the PNG is loaded. If using some other library, it may have functions to do what you want.

    AlphaBlend can be useful, but it's scaling quality is as poor as VB. It can't grayscale, but can blend. So if used, the bitmap must first be grayscaled. In any case, AlphaBlend requires the bitmap format to have its pixel RGB values premultiplied against the pixel's alpha value
    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. #3
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    Here's an idea and don't know if it will apply to your case

    Since you are talking about small images, you may be able to improve speed dramatically by building a single bitmap containing multiple images. Think of a grid of images contained by a single bitmap. If the individual small images are dynamic, then this may not be easy. The idea is that you'd have 2 such grid-bitmaps, one grayscaled, one not. Then you'd use alphablend or whatever to transfer the desired cell-image from the grid-image to your hDC.

    If your grid control can contain 1000s of items & therefore, 1000s of images, I'd think you risk "out of memory" errors if those images are cached vs loaded-drawn-released. A grid-like single bitmap may be able to avoid that problem.
    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}

  4. #4

    Thread Starter
    PowerPoster
    Join Date
    Sep 2012
    Posts
    2,083

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    Quote Originally Posted by LaVolpe View Post
    Couple things

    So, stdPicEx2 class is too large? But Cairo isn't? Just saying. Dilettante has posted many examples using WIC. I'm not familiar with that library, but since it's deployed on most O/S, it may be an option? From his posts regarding WIC, it appears WIC may use GDI+ in the background; therefore, I'd think it can grayscale and know it can blend.

    You mentioned PNGs. So, I assume you are using some library to load PNGs and convert them to 32bpp bitmaps? If not, could you clarify a bit. Reason I ask is that if you are using GDI+ to load the PNG, you can also use it to blend and grayscale while the PNG is loaded. If using some other library, it may have functions to do what you want.

    AlphaBlend can be useful, but it's scaling quality is as poor as VB. It can't grayscale, but can blend. So if used, the bitmap must first be grayscaled. In any case, AlphaBlend requires the bitmap format to have its pixel RGB values premultiplied against the pixel's alpha value
    Hi LaVolpe, thanks for your reply. I'm going to migrate my software to Linux (Wine), so I hope there are no other third-party libs in my software except RC5, no Microsoft Common Controls, no Farpoint Spread. This is why I spent a lot of time writing my own grid control to replace the Farpoint Spread I've used for many years. For the same reason, I also don't want to use WIC and msimg32. Cairo is a library that RC5 brings, and it is also a graphics library that I'll use extensively in the future. It's just that I'm not quite familiar with Cairo yet, so I might temporarily use GDI32 to draw transparent stdPictures.

    Currently, my grid control only load stdPictures but will load PNGs in the future. In the future I need to implement the following features of Farpoint Spread:

    Code:
    Function LoadFromBuffer(Buff) As Boolean
    Function LoadFromFile(FileName As String) As Boolean
    Function LoadPicture(FileName As String, PictType As PictureTypeConstants) As StdPicture
    Function LoadPictureBuffer(Buffer, Size, PictType As PictureTypeConstants) As StdPicture
    Function LoadResPicture(hInstance As Long, ResourceName As String, ResourceType As String, PictType As PictureTypeConstants) As StdPicture
    Function LoadTabFile(FileName As String) As Boolean
    Function LoadTextFile(FileName As String, CellDelim As String, ColDelim As String, RowDelim As String, Flags As LoadTextFileConstants, LogFile As String) As Boolean
    
    Function SavePicture(Picture As StdPicture, FileName As String, PictType As PictureTypeConstants) As Boolean
    Function SavePictureBuffer(Picture As StdPicture, PictType As PictureTypeConstants, Buffer, Size) As Boolean
    Function SaveTabFile(FileName As String) As Boolean
    Function SaveTabFileU(FileName As String) As Boolean
    Function SaveToBuffer()
    Function SaveToFile(FileName As String, DataOnly As Boolean) As Boolean

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

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    I'm thinking that you should be talking with Olaf about RC5 vs. temporarily using APIs that you'll likely convert to RC5 calls anyway.

    Do note that many windows DLLs call other windows DLLs

    Edited & just FYI

    Most of your picture loading functions can be done by reading data (file, byte array) into a stream and creating a stdPicture from that stream: OleCreatePictureIndirect or OleLoadPicture. The resource-related load functions can get res data in an array from VB via resource-related APIs when compiled. Maybe Olaf's RC5 has routines for creating stdPicture from file, array?

    Your picture saving routines will need effort. COM (via StdPicture) doesn't support all formats and is lacking on some. But Olaf's RC5 may have routines for that?
    Last edited by LaVolpe; Jun 10th, 2018 at 10:53 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}

  6. #6

    Thread Starter
    PowerPoster
    Join Date
    Sep 2012
    Posts
    2,083

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    Quote Originally Posted by LaVolpe View Post
    Here's an idea and don't know if it will apply to your case

    Since you are talking about small images, you may be able to improve speed dramatically by building a single bitmap containing multiple images. Think of a grid of images contained by a single bitmap. If the individual small images are dynamic, then this may not be easy. The idea is that you'd have 2 such grid-bitmaps, one grayscaled, one not. Then you'd use alphablend or whatever to transfer the desired cell-image from the grid-image to your hDC.

    If your grid control can contain 1000s of items & therefore, 1000s of images, I'd think you risk "out of memory" errors if those images are cached vs loaded-drawn-released. A grid-like single bitmap may be able to avoid that problem.

    I'll try your method. Thank you very much, LaVolpe.

    At the moment, my idea is this: For images with the same color as the background of the grid cells, I'll use the StdPicture.Render method directly. For images that are different from the backcolor of the grid cells, I'll use GdiAlphaBend to blend the pictures with the backcolor of the grid cells and cache them and then render them to the grid cells.

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

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    Quote Originally Posted by dreammanor View Post
    I'll try your method. Thank you very much, LaVolpe.
    A concern would be the amount of images you may be caching. This won't be easy to implement. Why?

    Well, bitmaps can't be infinite in size. So if a very large number of images are added to the grid-image, that grid-image can't just magically keep growing. There will be a speed bump when needing to resize the grid-image, but it can be oversized initially to reduce continuous resizing. What happens when an image from that grid-image is no longer needed? One idea is to keep track of "empty/unused cells" within the grid-image and append new images to those cells.

    If using something like above, I wouldn't suggest caching the grid-image items using some static backcolor -- keep them 32bpp with alpha channel. That way, should user change background of your grid control, you don't need to rebuild the grid-image. Additionally, theoretically, your grid-image could be used for multiple grid controls, different backcolors. Just a thought.
    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}

  8. #8

    Thread Starter
    PowerPoster
    Join Date
    Sep 2012
    Posts
    2,083

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    Quote Originally Posted by LaVolpe View Post
    I'm thinking that you should be talking with Olaf about RC5 vs. temporarily using APIs that you'll likely convert to RC5 calls anyway.

    Do note that many windows DLLs call other windows DLLs

    Edited & just FYI

    Most of your picture loading functions can be done by reading data (file, byte array) into a stream and creating a stdPicture from that stream: OleCreatePictureIndirect or OleLoadPicture. The resource-related load functions can get res data in an array from VB via resource-related APIs when compiled. Maybe Olaf's RC5 has routines for creating stdPicture from file, array?

    Your picture saving routines will need effort. COM (via StdPicture) doesn't support all formats and is lacking on some. But Olaf's RC5 may have routines for that?
    LaVolpe, your information is very useful to me.

    Yes, Olaf wrote many examples for Cairo. I've collected almost all of his examples, but I need time to learn and digest them. My current project is quite urgent, so I'll use the GDI32 that I'm familiar with to complete the project. After I'm free, I'll study Cairo in depth.

    I also studied your AlphaImage and it's really great. It's just that I'll gradually reduce my dependence on the Windows platform so I don't plan to spend time learning GDIPlus.

    Quote Originally Posted by LaVolpe View Post
    A concern would be the amount of images you may be caching. This won't be easy to implement. Why?

    Well, bitmaps can't be infinite in size. So if a very large number of images are added to the grid-image, that grid-image can't just magically keep growing. There will be a speed bump when needing to resize the grid-image, but it can be oversized initially to reduce continuous resizing. What happens when an image from that grid-image is no longer needed? One idea is to keep track of "empty/unused cells" within the grid-image and append new images to those cells.

    If using something like above, I wouldn't suggest caching the grid-image items using some static backcolor -- keep them 32bpp with alpha channel. That way, should user change background of your grid control, you don't need to rebuild the grid-image. Additionally, theoretically, your grid-image could be used for multiple grid controls, different backcolors. Just a thought.
    Sorry, I didn't express what I mean. There are a lot of pictures that are the same, but they need to be rendered to different grid cells, and I'll cache those pictures that need to be reused.

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

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    Quote Originally Posted by dreammanor View Post
    I also studied your AlphaImage and it's really great. It's just that I'll gradually reduce my dependence on the Windows platform so I don't plan to spend time learning GDIPlus.
    Both the AlphaImage control and stdPicEx2 class rely on GDI+, mostly for rendering options/quality, but also for loading PNG/TIF.

    Olaf's library I think uses libpng (O/S independent) for PNGs & don't know if RC5 loads TIFs, but that isn't a concern for you. From his examples, it does appear that RC5 will do simple things like blending & grayscaling, and your collection of samples should show how to do that. I think I saw a sample by him (in the codebank) that uses RC5 to build a grid-like collection of images too (something similar to what VB's PictureClip control does), but may be mistaken. In short, I think you have a vast majority of the RC5 code needed to do what you want without wasting time creating routines for DLLs you won't be using when project goes final. If still wanting to continue without studying up on RC5, I wouldn't concern yourself with speed improvements. After all, those improvements are likely to help APIs be more efficient -- APIs you may not be using down the road. Again, just a thought and good luck.

    When Olaf chimes into this thread, I think there is enough info for him to tailor his reply relative to his RC5 library.
    Last edited by LaVolpe; Jun 10th, 2018 at 11:57 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}

  10. #10

    Thread Starter
    PowerPoster
    Join Date
    Sep 2012
    Posts
    2,083

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    Quote Originally Posted by LaVolpe View Post
    Both the AlphaImage control and stdPicEx2 class rely on GDI+, mostly for rendering options/quality, but also for loading PNG/TIF.

    Olaf's library I think uses libpng (O/S independent) for PNGs & don't know if RC5 loads TIFs, but that isn't a concern for you. From his examples, it does appear that RC5 will do simple things like blending & grayscaling, and your collection of samples should show how to do that. I think I saw a sample by him (in the codebank) that uses RC5 to build a grid-like collection of images too (something similar to what VB's PictureClip control does), but may be mistaken. In short, I think you have a vast majority of the RC5 code needed to do what you want without wasting time creating routines for DLLs you won't be using when project goes final. If still wanting to continue without studying up on RC5, I wouldn't concern yourself with speed improvements. After all, those improvements are likely to help APIs be more efficient -- APIs you may not be using down the road. Again, just a thought and good luck.

    When Olaf chimes into this thread, I think there is enough info for him to tailor his reply relative to his RC5 library.
    My plan is to complete the grid control in the manner I'm familiar with. When I'm free, I'll use Cairo to rewrite this grid control.

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

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    Quote Originally Posted by dreammanor View Post
    My plan is to complete the grid control in the manner I'm familiar with. When I'm free, I'll use Cairo to rewrite this grid control.
    In that case, and if made up your mind to use the functions you posted in #1 above, you can optimize some of those routines. At first glance, maybe:

    When grayscaling, you are using calculations that use hardcoded grayscale ratios & multiplying. Well, you can build a cached lookup table "gLUT(0 to 255, 0 to 2) As Single" where the 0 to 2 portion contains values premultiplied by .3, .59, .11
    Then instead of:
    Code:
    gCol = CLng(DataSrc(i).rgbRed * 0.3) + DataSrc(i).rgbGreen * 0.59 + DataSrc(i).rgbBlue * 0.11
    it looks like:
    Code:
    gCol = gLUT(DataSrc(i).rgbRed, 0) + gLUT(DataSrc(i).rgbGreen, 1) + gLUT(DataSrc(i).rgbBlue, 2)
    Another optimization is to cache calculated values created in a loop when possible. For example, you have several loops that calculate some value based on the current pixel color. Well, if the next pixel is the same color as previous pixel, your loop will recalculate the same value again -- wasted cpu cycles if the value was already cached. Typically, I will cache the value at end of the loop and at beginning of the loop check if the current pixel was same color as previous pixel. If the same, simply use the cached value(s). If not, recalculate and recache. Understood? This can result in a significant speed improvement because many times, adjacent pixels are the same color for dozens or even hundreds of contiguous pixels.

    As others review your code in post #1, more suggestions may be offered.
    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}

  12. #12
    Fanatic Member DrUnicode's Avatar
    Join Date
    Mar 2008
    Location
    Natal, Brazil
    Posts
    631

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    This is a lightweight (18k) GDI+ class by Olaf Schmidt to load and render PNG/ICO/GIF/JPG.
    This should be all you need to cache and render transparent images in a grid.

    Code:
    Option Explicit
    
    Const cSpheres As String = "AMBER|CRIMSON|GRAPE|GRAPHITE|GREEN|MAGENTA|TEAL|YELLOW"
    
    Private Sub Form_Load()
      Dim GC As New cGDIPCache
      Dim i As Long
      Dim vSplit() As String
      vSplit = Split(cSpheres, "|")
      GC.AddImage "k", App.Path & "\Resources\FundoHP.jpg"
      GC.AlphaRenderTo Me.hDC, "K"
      For i = 0 To UBound(vSplit)
        GC.AddImage i, App.Path & "\Resources\" & vSplit(i) & ".png", 32, 32
        GC.AlphaRenderTo Me.hDC, i, 4 + 40 * i, 20
        GC.AlphaRenderTo Me.hDC, i, 10 + 40 * i, 60, 20, 20
        GC.AlphaRenderTo Me.hDC, i, 12 + 40 * i, 90, 16, 16
      Next
    End Sub
    Name:  cGDIPCache.png
Views: 1045
Size:  73.7 KB

    cGDIPCache.zip

  13. #13
    The Idiot
    Join Date
    Dec 2014
    Posts
    2,721

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    you should definitely check direct2d, now when we got it.
    it will automatically resize for you, has options for dpi and its very fast.

  14. #14
    Lively Member
    Join Date
    Oct 2015
    Posts
    93

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    you can check sources of those 2 projects:
    https://krzysiek1999.itch.io/knights-of-realm-game-demo
    https://krzysiek1999.itch.io/chessquest-concept-demo

    i use here two methods:
    2 jpg images way (with 1 mask image)
    Code:
    BitBlt Picture6.hdc, cursorXb * gridSIZE, cursorYb * gridSIZE, Picture8.Width, Picture8.Height, Picture9.hdc, 0, 0, vbSrcAnd
    BitBlt Picture6.hdc, cursorXb * gridSIZE, cursorYb * gridSIZE, Picture8.Width, Picture8.Height, Picture8.hdc, 0, 0, vbSrcPaint
    1 image way (tga with transparency)
    Code:
    AlphaBlend Picture6.hdc, xc(tempvariable6), yc(tempvariable6), gridSIZE * 3, gridSIZE * 1.8, HAlpha2, 0, 0, 592, 311, LBF2

  15. #15
    Frenzied Member
    Join Date
    Apr 2012
    Posts
    1,253

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    Olaf's done a good job of making sure that we can draw Cairo surfaces very easily to a given DC - not sure why you are not using that capability right now, to be honest. These surfaces can be created very easily from filenames and byte arrays, too - there's really not that much to it (mostly one-liners). I know that many of Olaf's demos centre around his own widget form (i.e. no DC drawing) but there is quite a lot of code here (from him and me) that doesn't. If, for example, you look at most of the controls that I have posted in the Code Bank you'll see that I am simply using Cairo to create a back-buffer (using a Cairo surface for that purpose) that, ultimately, gets drawn to a DC.

    It's about as painless as it gets, in my opinion...
    If you don't know where you're going, any road will take you there...

    My VB6 love-children: Vee-Hive and Vee-Launcher

  16. #16
    Frenzied Member
    Join Date
    Apr 2012
    Posts
    1,253

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    Here's one way of addressing your OP

    Code:
    Cairo.ImageList.AddImage "MyImage", Enter your ImagesPath Or point to a ByteArray here
    
    DrawImageToDC "MyImage", MyGridsDC, 50, 50, vbRed
    
    Private Sub DrawImageToDC(pImageKey As String, pDC As Long, pX As Long, pY As Long, pBackColour As Long)
        
        With Cairo.ImageList(pImageKey).CreateSimilar.CreateContext 'create a surface the same size as the image list item, and a context while we're at it
            .SetSourceColor pBackColour
            .Paint 'paint the background
            .RenderSurfaceContent pImageKey 'draw the imagelist item onto our surface
            .Surface.DrawToDC pDC, pX, pY 'draw the surface to the DC
        End With
    End Sub
    If you don't know where you're going, any road will take you there...

    My VB6 love-children: Vee-Hive and Vee-Launcher

  17. #17
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    What I'd recommend (to avoid any re-writing-efforts in the end) is, to implement the whole "Spread-Control"
    as a new (potentially platform-independent) RC5-Widget already in the first place.

    The Drawing would be much easier when you go that route
    (all done from inside the Widgets Paint-Event, which does not need to "know" any hDCs or require any Win32-APIs).

    Here is a small WireFrame-TestProject for such a Grid-Widget in a Zip:
    SpreadWidget.zip

    The above Demo has currently only about 100 lines in the cwSpread-Widget,
    already contains Scrollers, reacts to the MouseWheel and produces this output:


    HTH

    Olaf

  18. #18

    Thread Starter
    PowerPoster
    Join Date
    Sep 2012
    Posts
    2,083

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    Quote Originally Posted by LaVolpe View Post
    In that case, and if made up your mind to use the functions you posted in #1 above, you can optimize some of those routines. At first glance, maybe:

    When grayscaling, you are using calculations that use hardcoded grayscale ratios & multiplying. Well, you can build a cached lookup table "gLUT(0 to 255, 0 to 2) As Single" where the 0 to 2 portion contains values premultiplied by .3, .59, .11
    Then instead of:
    Code:
    gCol = CLng(DataSrc(i).rgbRed * 0.3) + DataSrc(i).rgbGreen * 0.59 + DataSrc(i).rgbBlue * 0.11
    it looks like:
    Code:
    gCol = gLUT(DataSrc(i).rgbRed, 0) + gLUT(DataSrc(i).rgbGreen, 1) + gLUT(DataSrc(i).rgbBlue, 2)
    Another optimization is to cache calculated values created in a loop when possible. For example, you have several loops that calculate some value based on the current pixel color. Well, if the next pixel is the same color as previous pixel, your loop will recalculate the same value again -- wasted cpu cycles if the value was already cached. Typically, I will cache the value at end of the loop and at beginning of the loop check if the current pixel was same color as previous pixel. If the same, simply use the cached value(s). If not, recalculate and recache. Understood? This can result in a significant speed improvement because many times, adjacent pixels are the same color for dozens or even hundreds of contiguous pixels.

    As others review your code in post #1, more suggestions may be offered.
    Thank you, LaVolpe. I have a question that I need to ask you. I'll post the test code later.

    Quote Originally Posted by baka View Post
    you should definitely check direct2d, now when we got it.
    it will automatically resize for you, has options for dpi and its very fast.
    Thank you, baka. I'll take the time to learn direct2d

    Quote Originally Posted by Krzysztof# View Post
    you can check sources of those 2 projects:
    https://krzysiek1999.itch.io/knights-of-realm-game-demo
    https://krzysiek1999.itch.io/chessquest-concept-demo

    i use here two methods:
    2 jpg images way (with 1 mask image)
    Code:
    BitBlt Picture6.hdc, cursorXb * gridSIZE, cursorYb * gridSIZE, Picture8.Width, Picture8.Height, Picture9.hdc, 0, 0, vbSrcAnd
    BitBlt Picture6.hdc, cursorXb * gridSIZE, cursorYb * gridSIZE, Picture8.Width, Picture8.Height, Picture8.hdc, 0, 0, vbSrcPaint
    1 image way (tga with transparency)
    Code:
    AlphaBlend Picture6.hdc, xc(tempvariable6), yc(tempvariable6), gridSIZE * 3, gridSIZE * 1.8, HAlpha2, 0, 0, 592, 311, LBF2
    Thank you, Krzysztof.

  19. #19

    Thread Starter
    PowerPoster
    Join Date
    Sep 2012
    Posts
    2,083

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    Quote Originally Posted by DrUnicode View Post
    This is a lightweight (18k) GDI+ class by Olaf Schmidt to load and render PNG/ICO/GIF/JPG.
    This should be all you need to cache and render transparent images in a grid.

    Code:
    Option Explicit
    
    Const cSpheres As String = "AMBER|CRIMSON|GRAPE|GRAPHITE|GREEN|MAGENTA|TEAL|YELLOW"
    
    Private Sub Form_Load()
      Dim GC As New cGDIPCache
      Dim i As Long
      Dim vSplit() As String
      vSplit = Split(cSpheres, "|")
      GC.AddImage "k", App.Path & "\Resources\FundoHP.jpg"
      GC.AlphaRenderTo Me.hDC, "K"
      For i = 0 To UBound(vSplit)
        GC.AddImage i, App.Path & "\Resources\" & vSplit(i) & ".png", 32, 32
        GC.AlphaRenderTo Me.hDC, i, 4 + 40 * i, 20
        GC.AlphaRenderTo Me.hDC, i, 10 + 40 * i, 60, 20, 20
        GC.AlphaRenderTo Me.hDC, i, 12 + 40 * i, 90, 16, 16
      Next
    End Sub
    Name:  cGDIPCache.png
Views: 1045
Size:  73.7 KB

    cGDIPCache.zip
    Thank you, DrUnicode. I tested your code, but I don't know if cGDIPCache can implement MaskColor feature?


    Quote Originally Posted by ColinE66 View Post
    Here's one way of addressing your OP

    Code:
    Cairo.ImageList.AddImage "MyImage", Enter your ImagesPath Or point to a ByteArray here
    
    DrawImageToDC "MyImage", MyGridsDC, 50, 50, vbRed
    
    Private Sub DrawImageToDC(pImageKey As String, pDC As Long, pX As Long, pY As Long, pBackColour As Long)
        
        With Cairo.ImageList(pImageKey).CreateSimilar.CreateContext 'create a surface the same size as the image list item, and a context while we're at it
            .SetSourceColor pBackColour
            .Paint 'paint the background
            .RenderSurfaceContent pImageKey 'draw the imagelist item onto our surface
            .Surface.DrawToDC pDC, pX, pY 'draw the surface to the DC
        End With
    End Sub
    Thank you, ColinE66. I tested your code. I'd like to know how to use Cairo to implement MaskColor feature?
    Last edited by dreammanor; Jun 12th, 2018 at 08:16 AM.

  20. #20
    Fanatic Member DrUnicode's Avatar
    Join Date
    Mar 2008
    Location
    Natal, Brazil
    Posts
    631

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    I tested your code, but I don't know if cGDIPCache can implement MaskColor feature?
    You could use "Public Function GetPicture" to return a StdPicture with BackColor.
    However, there is no need for a MaskColor at all for 32bpp PNG images. It will render transparent on any background.

  21. #21

    Thread Starter
    PowerPoster
    Join Date
    Sep 2012
    Posts
    2,083

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    Quote Originally Posted by Schmidt View Post
    What I'd recommend (to avoid any re-writing-efforts in the end) is, to implement the whole "Spread-Control"
    as a new (potentially platform-independent) RC5-Widget already in the first place.

    The Drawing would be much easier when you go that route
    (all done from inside the Widgets Paint-Event, which does not need to "know" any hDCs or require any Win32-APIs).

    Here is a small WireFrame-TestProject for such a Grid-Widget in a Zip:
    SpreadWidget.zip

    The above Demo has currently only about 100 lines in the cwSpread-Widget,
    already contains Scrollers, reacts to the MouseWheel and produces this output:


    HTH

    Olaf
    Very nice. RC5 is really amazing.

    In fact, from the beginning I knew that the spread control based on RC5 is the best solution. But the spread control I'm working on is very complicated and the time is very urgent. If I were to develop my spread control based on RC5, then I would have a lot of questions to ask you, which would inevitably disturb you. So, after careful consideration, I decided to use the traditional VB6 approach that I'm familiar with to develop my spread control. Now it's basically completed. There are only a few details that need to be optimized.

    This spread control took me 45 days (It took me 30 days to collect relevant information and write a lot of test code. The actual development took me 15 days). Though it currently only achieves 30% of the features of Farpoint Spread, it can already meet my needs.

    The next version of my spread control will be developed based on your SpreadWidget. I believe that RC5-based spread control can implement 100% of the features of Farpoint Spread. If I can achieve 150%-200% of the features of Farpoint Spread, maybe I can develop it into a commercial control, because Farpoint Spread has not been updated since a few years ago.

    Extremely grateful, Olaf.
    Last edited by dreammanor; Jun 12th, 2018 at 11:02 AM.

  22. #22

    Thread Starter
    PowerPoster
    Join Date
    Sep 2012
    Posts
    2,083

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    Quote Originally Posted by DrUnicode View Post
    You could use "Public Function GetPicture" to return a StdPicture with BackColor.
    However, there is no need for a MaskColor at all for 32bpp PNG images. It will render transparent on any background.
    My spread control not only needs to display PNGs, but also needs to display StdPictures. I need to make the StdPicture transparent according to the backcolor(MaskColor) of the spread cell.

  23. #23

    Thread Starter
    PowerPoster
    Join Date
    Sep 2012
    Posts
    2,083

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    I tested three methods, which come from DrUnicode, ColinE66, and jcButton. When performing 10,000 drawings, the test results are as follows:

    GDI+ : 3,715.61 msec
    Cairo: 844.44 msec
    jcButton: 156,219.50 msec

    Now my questions are:
    1. How to use Cairo or GDI+ to implement MaskColor feature?
    2. The jcButton can use the MaskColor to make a pictue transparent, but the picture has a white border around it. I'm wondering if there is an algorithm that can remove this white border? Maybe LaVolpe can solve this problem.
    3. How to increase the drawing speed of jcButton?
    Attached Images Attached Images  
    Attached Files Attached Files

  24. #24
    Frenzied Member
    Join Date
    Apr 2012
    Posts
    1,253

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    Aa you've discovered, mask colours don't really work that well when the image being masked blends in (at its edges) with the mask colour. Unless, of course, you are drawing the masked image onto the same colour background as the mask colour. But that defeats the purpose, of course.

    If I were you, I'd abandon the idea of trying to mask out backgrounds from bitmaps - they'll always suffer from this problem. Go with image formats that support an alpha channel...
    If you don't know where you're going, any road will take you there...

    My VB6 love-children: Vee-Hive and Vee-Launcher

  25. #25
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    It doesn't make sense to use a mask color _and_ remove the white border. if you need the white border gone, you need to paint to a white background - or use full alpha transparency.

    edit: Colin beat me to it...

    edit 2: a fun idea for an algorithm could be to convert the mask to a full alpha channel, and then use a smoothing filter on the alpha channel, to blend the edges, or something similar where the final alpha channel is a function of the mask of current and neighboring pixels.
    Last edited by DEXWERX; Jun 12th, 2018 at 11:15 AM.

  26. #26

    Thread Starter
    PowerPoster
    Join Date
    Sep 2012
    Posts
    2,083

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    Hi ColinE66 and DEXWERX, what you say makes sense. Maybe I really should abandon the MaskColor.

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

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    As others suggest: use higher quality formats that support alphablended edges. You will get nicer results.

    In the sample project you just posted, the sample image is simply a 24bpp bitmap; therefore, alphablending is not in play for that image. Removing the white area can be done several different ways: old fashioned use of multiple DCs (pre-Win2k) and relatively slow, TransparentBlt API, GDI+ with image attributes, RC5 may have a method also, and the option of using a separate mask with MaskBlt API.

    Another idea would be to convert the 24bpp to 32bpp alpha-supported format, but that may not be a speed improvement, or not a large one over other options. It will however, simplify things a bit -- if all images have valid alpha channels, use the same method for each image vs. different methods for images in different formats.
    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}

  28. #28

    Thread Starter
    PowerPoster
    Join Date
    Sep 2012
    Posts
    2,083

    Re: Fastest way to render transparent stdPictures or pngs to grid cells

    Quote Originally Posted by LaVolpe View Post
    As others suggest: use higher quality formats that support alphablended edges. You will get nicer results.

    In the sample project you just posted, the sample image is simply a 24bpp bitmap; therefore, alphablending is not in play for that image. Removing the white area can be done several different ways: old fashioned use of multiple DCs (pre-Win2k) and relatively slow, TransparentBlt API, GDI+ with image attributes, RC5 may have a method also, and the option of using a separate mask with MaskBlt API.

    Another idea would be to convert the 24bpp to 32bpp alpha-supported format, but that may not be a speed improvement, or not a large one over other options. It will however, simplify things a bit -- if all images have valid alpha channels, use the same method for each image vs. different methods for images in different formats.
    Thank you very much, LaVolpe. I'm going to take ColinE66's method now, that is, using Cairo to draw the stdPictues and PNGs to the spread cells, which should be the simplest and most efficient way.

  29. #29
    Frenzied Member
    Join Date
    Apr 2012
    Posts
    1,253

    Re: [RESOLVED] Fastest way to render transparent stdPictures or pngs to grid cells

    Another thing you might want to think about, if you are going the Cairo and hDC route, is to add your alpha-supported images and, then, immediately, create a version of them with a background colour that matches your grid. If the user (through some setting) picks a new BackColour, just re-initialise your images again.

    Something like this...

    Code:
    Option Explicit
    
    Private Sub Form_Load()
       Cairo.ImageList.AddImage "MyImage", "c:\splash.png"
       InitImageBackground "MyImage", vbRed
    End Sub
    
    Private Sub InitImageBackground(pImageKey As String, pBackColour As Long)
    Dim b() As Byte
        With Cairo.ImageList(pImageKey).CreateSimilar.CreateContext 'create a surface the same size as the image list item, and a context while we're at it
            .SetSourceColor pBackColour
            .Paint 'paint the background
            .RenderSurfaceContent pImageKey, 0, 0 'draw the imagelist item onto our surface
            .Surface.WriteContentToPngByteArray b
        End With
    
        Cairo.ImageList.AddImage pImageKey, b 'add an image with the same key; it will overwrite whatever is already there - not sure if this is a feature or a bug ;)
    
    End Sub
    
    Private Sub Command1_Click()
       Cairo.ImageList("MyImage").DrawToDC Me.hDC, 50, 50 ' we, earlier, gave this image the 'correct' back colour
    End Sub
    This will be much faster than my earlier code...
    If you don't know where you're going, any road will take you there...

    My VB6 love-children: Vee-Hive and Vee-Launcher

  30. #30
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,219

    Re: [RESOLVED] Fastest way to render transparent stdPictures or pngs to grid cells

    If it "has to be hDC-Drawing" - then one easy way to ensure speed and comfort via cairo
    (without having to resort to BackGround-pre-rendering of Cairo-ImageResources) -
    would be to create a Cairo-BackBuffer-Surface (either for the entire UserControl-area,
    or at least for "the current Row of Cells").

    This would ensure re-paints without flickering (no AutoRedraw would need to be enabled on the VB-Control) -
    and also allow a "more direct use" of the Cairo-DrawingCommands (on the BackBuffer).

    I've just tested this in your speed-comparison-project - and get a speedup-factor of 3 (compared to Colins original code):

    Code:
    Private Sub CmdSpeed2_Click()
        Cairo.ImageList.AddImage "MyImage", App.Path & "\GRAPE.png" 'let's just use the original PNG here from DrUnicodes-Zip
        
        Dim i As Long
        
        New_c.Timing True
        
          Picture2.ScaleMode = vbPixels 'we need the Containers Pixel-Dimensions, to create a properly sized BackBuf
          Dim Buf As cCairoSurface, CC As cCairoContext, BGPat As cCairoPattern 'define the 3 Helper-Objects
          Set Buf = Cairo.CreateSurface(Picture2.ScaleWidth, Picture2.ScaleHeight) 'create the BackBuf in the same size as the PicBox
          Set CC = Buf.CreateContext 'create the usual 'CC'-drawing-context on the BackBuf
          Set BGPat = Cairo.CreateSolidPatternLng(Picture2.BackColor) 'pre-create a solid-color-Pattern (outside the loop, to save some cycles)
          
          For i = 1 To 10000 'inside the loop, only CC-drawing-commands are used
              CC.Paint , BGPat 'clear the BackGround of the entire BackBuffer for the next round of drawings (with the pre-created Pattern as source)
              CC.RenderSurfaceContent "MyImage", 0, 0 'render an Alpha-Resource directly from the ImageList (at some Pixel-Offset)
          Next i
          
          Buf.DrawToDC Picture2.hdc 'if "done with all the Cells and Lines of the Grid", refresh the Container with the BackBuf-content
        
        MsgBox New_c.Timing(False)
    End Sub
    Somewhere in your Grid-control there should be some area, where you can apply the BackBuf-scheme easily to...

    Olaf

  31. #31
    Frenzied Member
    Join Date
    Apr 2012
    Posts
    1,253

    Re: [RESOLVED] Fastest way to render transparent stdPictures or pngs to grid cells

    Quote Originally Posted by Schmidt View Post
    If it "has to be hDC-Drawing" - then one easy way to ensure speed and comfort via cairo
    (without having to resort to BackGround-pre-rendering of Cairo-ImageResources) -
    would be to create a Cairo-BackBuffer-Surface (either for the entire UserControl-area,
    or at least for "the current Row of Cells").
    Yup. That was what I was saying in #15. And, if the user scrolls a single line (for example) you can salvage most of the previous backbuffer and re-use it for the next refresh, 'appending' the 'new' single row above or below it (depending on the scroll direction). I do this in Vee-Hive and every refresh is so fast that I added smooth scrolling with no 'stuttering' at all. Only a page-up or -down requires a completely new backbuffer.
    If you don't know where you're going, any road will take you there...

    My VB6 love-children: Vee-Hive and Vee-Launcher

  32. #32

  33. #33

    Thread Starter
    PowerPoster
    Join Date
    Sep 2012
    Posts
    2,083

    Re: [RESOLVED] Fastest way to render transparent stdPictures or pngs to grid cells

    Quote Originally Posted by ColinE66 View Post
    Another thing you might want to think about, if you are going the Cairo and hDC route, is to add your alpha-supported images and, then, immediately, create a version of them with a background colour that matches your grid. If the user (through some setting) picks a new BackColour, just re-initialise your images again.

    Something like this...

    Code:
    Option Explicit
    
    Private Sub Form_Load()
       Cairo.ImageList.AddImage "MyImage", "c:\splash.png"
       InitImageBackground "MyImage", vbRed
    End Sub
    
    Private Sub InitImageBackground(pImageKey As String, pBackColour As Long)
    Dim b() As Byte
        With Cairo.ImageList(pImageKey).CreateSimilar.CreateContext 'create a surface the same size as the image list item, and a context while we're at it
            .SetSourceColor pBackColour
            .Paint 'paint the background
            .RenderSurfaceContent pImageKey, 0, 0 'draw the imagelist item onto our surface
            .Surface.WriteContentToPngByteArray b
        End With
    
        Cairo.ImageList.AddImage pImageKey, b 'add an image with the same key; it will overwrite whatever is already there - not sure if this is a feature or a bug ;)
    
    End Sub
    
    Private Sub Command1_Click()
       Cairo.ImageList("MyImage").DrawToDC Me.hDC, 50, 50 ' we, earlier, gave this image the 'correct' back colour
    End Sub
    This will be much faster than my earlier code...
    Yes, the new code is much faster than the old code. Thank you very much, ColinE66.

  34. #34

    Thread Starter
    PowerPoster
    Join Date
    Sep 2012
    Posts
    2,083

    Re: [RESOLVED] Fastest way to render transparent stdPictures or pngs to grid cells

    Quote Originally Posted by Schmidt View Post
    If it "has to be hDC-Drawing" - then one easy way to ensure speed and comfort via cairo
    (without having to resort to BackGround-pre-rendering of Cairo-ImageResources) -
    would be to create a Cairo-BackBuffer-Surface (either for the entire UserControl-area,
    or at least for "the current Row of Cells").

    This would ensure re-paints without flickering (no AutoRedraw would need to be enabled on the VB-Control) -
    and also allow a "more direct use" of the Cairo-DrawingCommands (on the BackBuffer).

    I've just tested this in your speed-comparison-project - and get a speedup-factor of 3 (compared to Colins original code):

    Code:
    Private Sub CmdSpeed2_Click()
        Cairo.ImageList.AddImage "MyImage", App.Path & "\GRAPE.png" 'let's just use the original PNG here from DrUnicodes-Zip
        
        Dim i As Long
        
        New_c.Timing True
        
          Picture2.ScaleMode = vbPixels 'we need the Containers Pixel-Dimensions, to create a properly sized BackBuf
          Dim Buf As cCairoSurface, CC As cCairoContext, BGPat As cCairoPattern 'define the 3 Helper-Objects
          Set Buf = Cairo.CreateSurface(Picture2.ScaleWidth, Picture2.ScaleHeight) 'create the BackBuf in the same size as the PicBox
          Set CC = Buf.CreateContext 'create the usual 'CC'-drawing-context on the BackBuf
          Set BGPat = Cairo.CreateSolidPatternLng(Picture2.BackColor) 'pre-create a solid-color-Pattern (outside the loop, to save some cycles)
          
          For i = 1 To 10000 'inside the loop, only CC-drawing-commands are used
              CC.Paint , BGPat 'clear the BackGround of the entire BackBuffer for the next round of drawings (with the pre-created Pattern as source)
              CC.RenderSurfaceContent "MyImage", 0, 0 'render an Alpha-Resource directly from the ImageList (at some Pixel-Offset)
          Next i
          
          Buf.DrawToDC Picture2.hdc 'if "done with all the Cells and Lines of the Grid", refresh the Container with the BackBuf-content
        
        MsgBox New_c.Timing(False)
    End Sub
    Somewhere in your Grid-control there should be some area, where you can apply the BackBuf-scheme easily to...

    Olaf
    It's great. Now the picture drawing of my spread control is much faster than before. Thank you very much, Olaf.

  35. #35

    Thread Starter
    PowerPoster
    Join Date
    Sep 2012
    Posts
    2,083

    Re: [RESOLVED] Fastest way to render transparent stdPictures or pngs to grid cells

    Quote Originally Posted by The trick View Post
    Yes, I tested your example and it's great. I originally wanted to apply your button control to my little chat tool, but the development of my chat tool needs to be paused for a while, so I haven't studied your example code in depth. In addition, my knowledge of GDIPlus is very limited and modifying GDI+ code is somewhat difficult for me. Thank you very much, The trick.

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