Announcement

Collapse
No announcement yet.

GetPixel SetPixel DirectX replacement?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • GetPixel SetPixel DirectX replacement?

    I am looking for a fast GetPixel/SetPixel replacement.

    Do you know if there are any DirectX functions to perform the same purpose?



    -------------
    Patrice Terrier
    mailto[email protected][email protected]</A>
    Patrice Terrier
    www.zapsolution.com
    www.objreader.com
    Addons: GDImage.DLL 32/64-bit (Graphic library), WinLIFT.DLL 32/64-bit (Skin Engine).

  • #2
    Patrice;

    The problem with DirectX functions is that they "don't work" with a regular DC, like the GDI. DirectX has its own method of creating an area to draw on which means you have to use DirectX completely or the GDI completely. Normally, they are not mixed together.

    While I have seen a development tool that mixes DirectX and GDI drawing together, this "hybrid" combination of GDI and DirectX is actually slower than either DirectX or GDI alone. A conversion process must be added to make them work together.

    Unless you are ready to go 100% DirectX, you will have to stick with the GDI.

    I think that when using the GDI, using DIB functions to draw is faster than using SetPixel. SetPixel is terribly slow. Likely the higher GDI functions don't use SetPixel, but another undocumented API call. Functions that draw a line or a Rectangle are always faster than using your own that draw with SetPixel.

    Also, don't most "fast" graphic apps draw first to a memory DC and then always BitBlt to the window DC ? Drawing directly to a Windows DC with lower level GDI functions is always slow.


    ------------------
    Chris Boss
    Computer Workshop
    Developer of "EZGUI"
    http://cwsof.com
    http://twitter.com/EZGUIProGuy

    Comment


    • #3
      patrice --
      don't know about directx, but there is one interesting technique, which i found on codeguru.com (if necessary, i will post links).
      you can see this technique in action in http://www.powerbasic.com/support/pb...ad.php?t=22687
      (replacement of slowly getpixel).

      shortly, idea is following.
      imagine that you want to retrieve all pixels of hmem2dc.
      1)create dib-section of the same size and select it into hmem1dc.
      2) bitblt hmem2dc -> hmem1dc (%srccopy)
      after this you can have direct access using bm.bmbits of dib-section.
      i should add, that after discussion with florent, it's looks, that it's better to add globallock/unlock for handle of dib-section.

      ------------------

      Comment


      • #4
        Indeed what I want is to speed up this as much as possible

        Code:
        FUNCTION GetRValue?(BYVAL Colr&)
            FUNCTION = (Colr& AND &H000000FF???)
        END FUNCTION
        
        FUNCTION GetGValue?(BYVAL Colr&)
            SHIFT RIGHT Colr&, 8
            FUNCTION = (Colr& AND &H000000FF???)
        END FUNCTION
        
        FUNCTION GetBValue?(BYVAL Colr&)
            SHIFT RIGHT Colr&, 16
            FUNCTION = (Colr& AND &H000000FF???)
        END FUNCTION
        
        FUNCTION skTransRGB&(BYVAL hDC1&, BYVAL x1&, BYVAL y1&, BYVAL hDC2&, BYVAL x2&, BYVAL y2&, BYVAL Percent&) EXPORT
                
          ' Get the color of the first picture and extract the r&,g&,b& values
            Colr1& = GetPixel(hDC1&, x1&, y1&)
            r1& = GetRValue(Colr1&)
            b1& = GetBValue(Colr1&)
            g1& = GetGValue(Colr1&)
               
          ' Get the color of the second picture and extract the r&,g&,b& values
            Colr2& = GetPixel(hDC2&, x2&, y2&)
            r2& = GetRValue(Colr2&)
            b2& = GetBValue(Colr2&)
            g2& = GetGValue(Colr2&)
        
          ' Mix the colors based on the specified percent& to create a new color
          ' that's a perfect combination of the previous two
            Complement& = 100 - percent&
            r& = ((Complement& * r1&) + (percent& * r2&)) \ 100
            g& = ((Complement& * g1&) + (percent& * g2&)) \ 100
            b& = ((Complement& * b1&) + (percent& * b2&)) \ 100
            
            FUNCTION = RGB(r&, g&, b&)
                
        END FUNCTION
        
        ' Performs transluscency
        SUB skTransLusBlt(BYVAL hDC&, _
                       BYVAL xDest&, BYVAL yDest&, BYVAL nWidth&, BYVAL nHeight&, _
                       BYVAL hSrcBMP&, _
                       BYVAL xSrc&, BYVAL ySrc&, _
                       BYVAL Percent&) EXPORT
        '   hDC&           Destination device context
        '   xDest&, yDest& Upper-left destination coordinates (pixels)
        '   nWidth&        Width of destination
        '   nHeight&       Height of destination
        '   hSrcBMP&       Handle of the source bitmap
        '   xSrc&, ySrc&   Upper-left source coordinates (pixels)
        '   Percent&       Tansluscency percentage
        '
        '   32-Bit Transluscency BitBlt Function
            
            REGISTER x&, y&               
        
            hSrcDC& = CreateCompatibleDC(hDC&)
            CALL SelectObject(hSrcDC&, hSrcBMP&)
            
            '*'IF TransColor& < 0 THEN TransColor& = GetPixel(hSrcDC&, 0, 0)
            
            ResultDC& = CreateCompatibleDC(hDC&)
            hResultBmp& = CreateCompatibleBitmap(hDC&, nWidth&, nHeight&)
            hDestPrevBmp& = SelectObject(ResultDC&, hResultBmp&)
            CALL BitBlt(ResultDC&, 0, 0, nWidth&, nHeight&, hDC&, xDest&, yDest&, %SRCCOPY)
        
            '*'WasPercent& = Percent&
            FOR x& = xDest& TO nWidth& - 1
                FOR y& = yDest& TO nHeight& - 1
                    '*'IF GetPixel(hSrcDC&, x&, y&) = TransColor& THEN Percent& = 0
                    PixelColr& = skTransRGB(hDC&, x&, y&, hSrcDC&, x&, y&, Percent&)
                    CALL SetPixel(ResultDC&, x&, y&, PixelColr&)
                    '*'Percent& = WasPercent&
                NEXT
            NEXT
        
          ' Display transparent bitmap on background.
            CALL BitBlt(hDC&, xDest&, yDest&, nWidth&, nHeight&, ResultDC&, 0, 0, %SRCCOPY)
        
          ' Select original objects back.
            CALL SelectObject(ResultDC&, hDestPrevBmp&)
        
          ' Deallocate system resources.
            CALL DeleteObject(hResultBmp&)
            CALL DeleteDC(ResultDC&)
            CALL DeleteDC(hSrcDC&)
        
        END SUB
        ------------------
        Patrice Terrier
        mailto[email protected][email protected]</A>

        [This message has been edited by Patrice Terrier (edited June 15, 2000).]
        Patrice Terrier
        www.zapsolution.com
        www.objreader.com
        Addons: GDImage.DLL 32/64-bit (Graphic library), WinLIFT.DLL 32/64-bit (Skin Engine).

        Comment


        • #5
          Patrice --

          If speed is more important than anything else, you might compare your SHIFT-based functions to these:

          Code:
          FUNCTION GetRValue?(BYVAL Colr&)
              FUNCTION = (Colr& AND &h0000FF&)
          END FUNCTION
          FUNCTION GetGValue?(BYVAL Colr&)
              FUNCTION = (Colr& AND &h00FF00&) \ &h100&
          END FUNCTION
          FUNCTION GetBValue?(BYVAL Colr&)
              FUNCTION = (Colr& AND &hFF0000&) \ &h10000&
          END FUNCTION
          I think they'll be faster, according to my old notes.

          For that matter, I'd get rid of the functions altogether, at least in the speed-critical sections of code. Hard-code the AND operations where you need them, to avoid the speed penalty of calling a function. This is especially true because your functions are returning BYTE values, which are handled more slowly than LONGs.

          Also, have you looked at the SetPixelV function? It is faster than SetPixel, and since you are not using the return value anyway, you may as well use SetPixelV.

          -- Eric



          ------------------
          Perfect Sync: Perfect Sync Development Tools
          Email: mailto:[email protected][email protected]</A>

          "Not my circus, not my monkeys."

          Comment


          • #6
            Patrice --

            If you really want to go "industrial strength"...

            Instead of getting and processing the pixels one by one, you might consider using the GetDIBits API to get the two bitmaps and place them into two buffers where you can access the pixels as LONG values. If I'm not mistaken (it's been a while since I used GetDIBits) you can specify the data format that you want the API to put in the buffers, so you would be able to use LONGs regardless of the color depth of the display.

            Once you have two buffers that contain the bitmaps, you could go crazy with the processing. Use pointers, or whatever you need to do, to optimize for speed. Then when all of the pixels have been processed, BitBlt them as a block to the visible DC.

            I'm making it sound easier than it is. {G} GetDIBits can be a nightmare to work with. But once you got it working, it should fly compared to get-pixel-draw-pixel. At least theoretically...

            -- Eric

            ------------------
            Perfect Sync: Perfect Sync Development Tools
            Email: mailto:[email protected][email protected]</A>

            "Not my circus, not my monkeys."

            Comment


            • #7
              Eric --

              I have used also assembly to speed-up things but I don't feel comfortable with it

              I will also try to use SetPixelV.

              FUNCTION GetBValue?(BYVAL nColor&) EXPORT
              DIM F AS INTEGER
              ! mov AL, Byte Ptr nColor&[2]
              ! xor AH, AH
              ! mov F, AX
              FUNCTION = CBYT(F)
              END FUNCTION
              FUNCTION GetGValue?(BYVAL nColor&) EXPORT
              DIM F AS INTEGER
              ! mov AL, Byte Ptr nColor&[1]
              ! xor AH, AH
              ! mov F, AX
              FUNCTION = CBYT(F)
              END FUNCTION
              FUNCTION GetRValue?(BYVAL nColor&) EXPORT
              DIM F AS INTEGER
              ! mov AL, Byte Ptr nColor&[0]
              ! xor AH, AH
              ! mov F, AX
              FUNCTION = CBYT(F)
              END FUNCTION

              Thanks to all of you for your suggestions !


              ------------------
              Patrice Terrier
              mailto[email protected][email protected]</A>
              Patrice Terrier
              www.zapsolution.com
              www.objreader.com
              Addons: GDImage.DLL 32/64-bit (Graphic library), WinLIFT.DLL 32/64-bit (Skin Engine).

              Comment


              • #8
                Patrice;

                SetPixelV is definitely faster than SetPixel. SetPixel "returns" the actual color value used (which may be different than the color requested), whereas SetPixelV does not. This means less processing , so it is faster.

                SetPixel likely was never intended for fast graphics drawing, pixel by pixel. The optimum way to draw pixel by pixel is to do it in a memory DC using DIBs and then BitBlt it back into the Windows DC.

                If you must draw directly into the Windows DC, pixel by pixel, then try using the LineTo function and when ever the number of pixels of the same color is > 1 you will get a speed increase because of drawing multiple pixels at once.


                ------------------
                Chris Boss
                Computer Workshop
                Developer of "EZGUI"
                http://cwsof.com
                http://twitter.com/EZGUIProGuy

                Comment


                • #9
                  Chris --

                  >>Try using the LineTo function and when ever the number of pixels of the same color is > 1 you will get a speed increase because of drawing multiple pixels at once.

                  Using "LineTo" in order to perform a run length of pixels could not be used in most situation because the function must match pixels from 2 distincts DC that do not use linear colors.

                  Among things, I plan to use transluscency to produce a perfect shadow behind any type of WinLIFT's windows.

                  If you want I can send you a example (with source code) of my TRANSLUS demo program, this will help you to understand the effect I want to perform, and why I need it to be very fast.







                  ------------------
                  Patrice Terrier
                  mailto[email protected][email protected]</A>
                  Patrice Terrier
                  www.zapsolution.com
                  www.objreader.com
                  Addons: GDImage.DLL 32/64-bit (Graphic library), WinLIFT.DLL 32/64-bit (Skin Engine).

                  Comment


                  • #10
                    Patrice --
                    try this.
                    Of course, for "industrial" purpose, it's necessary to use Assembler in cycles.
                    Code:
                       #Compile Exe
                       #Register None
                       #Dim All
                       #Include "win32api.inc"
                       #Resource "gt1.pbr" ' #1 #2
                       
                       Function MixColor (hWndDst As Long, hWndSrc1 As Long, hWndSrc2 As Long, percent As Long) As Long
                          Register i As Long, j As Long
                          Dim k As Long, p1 As Long, p2 As Long
                          Dim rc As RECT, pWidth As Long, pHeight As Long
                          Dim hWnd(2) As Long, Bm(2) As BITMAP, hTmpBmp(2) As Long, hDC(2) As Long, hTmpDC(2) As Long
                          Dim bmi As BITMAPINFO, pBits0 As Byte Ptr, pBits1 As Byte Ptr, pBits2 As Byte Ptr
                          
                          hWnd(0) = hWndDst: hWnd(1) = hWndSrc1: hWnd(2) = hWndSrc2
                          For k = 2 To 0 Step -1
                             hDC(k) = GetDC(hWnd(k))
                             hTmpDC(k) = CreateCompatibleDC (hDC(k))
                             If k = 2 Then
                                GetClientRect hWnd(k), rc
                                pWidth = rc.nRight - rc.nLeft
                                pHeight = rc.nBottom - rc.nTop
                                bmi.bmiHeader.biSize = SizeOf(bmi.bmiHeader)
                                bmi.bmiHeader.biWidth = pWidth
                                bmi.bmiHeader.biHeight = pHeight
                                bmi.bmiHeader.biPlanes = 1
                                bmi.bmiHeader.biBitCount = 32
                                bmi.bmiHeader.biCompression = %BI_RGB
                             End If
                             hTmpBmp(k) = CreateDIBSection(hTmpDC(k), bmi, %DIB_RGB_COLORS, 0, 0, 0)
                             GlobalLock hTmpBmp(k): SelectObject hTmpDC(k), hTmpBmp(k)
                             If k <> 0 Then BitBlt hTmpDC(k), 0, 0, pWidth, pHeight, hDC(k), 0, 0, %SRCCOPY
                             GetObject hTmpBmp(k), SizeOf(bm(k)), bm(k)
                             If k = 0 Then pBits0 = bm(k).bmBits Else _
                             If k = 1 Then pBits1 = bm(k).bmBits Else pBits2 = bm(k).bmBits
                             p1 = 100 - percent: p2 = percent
                             If k = 0 Then
                                For j = pHeight - 1 To 0 Step - 1
                                   For i = 0 To pWidth - 1
                                      @pBits0[2] = ((p1 * @pBits1[2] + p2 * @pBits2[2])) \ 100
                                      @pBits0[1] = ((p1 * @pBits1[1] + p2 * @pBits2[1])) \ 100
                                      @pBits0[0] = ((p1 * @pBits1[0] + p2 * @pBits2[0])) \ 100
                                      pBits0 = pBits0 + 4: pBits1 = pBits1 + 4: pBits2 = pBits2 + 4
                                   Next
                                Next
                                BitBlt hDC(k), 0, 0, pWidth, pHeight, hTmpDC(k), 0, 0, %SRCCOPY
                             End If
                          Next
                          For k = 0 To 2: ReleaseDC hWnd(k), hDC(k): DeleteDC hTmpDC(k): _
                             DeleteObject hTmpBmp(k): Next
                       End Function
                      
                       CallBack Function DlgProc
                          Select Case CbMsg
                             Dim t1 As Single, t2 As Single
                             Case %WM_COMMAND
                                If CbCtl = 104 Then
                                   t1 = Timer
                                   MixColor GetDlgItem(CbHndl, 103), GetDlgItem(CbHndl, 101), _
                                            GetDlgItem(CbHndl, 102), 40
                                   t2 = Timer
                                   SetWindowText CbHndl, Format$(1000 * (t2 - t1), "# ms")
                                End If
                          End Select
                       End Function
                    
                       Function PbMain
                          Dim hDlg As Long
                          Dialog New 0, "", , , 420, 400, %WS_CAPTION Or %WS_SYSMENU To hDlg
                          Control Add ImageX, hDlg, 101, "#1", 10, 10,  400, 100
                          Control Add ImageX, hDlg, 102, "#2", 10, 120, 400, 100
                          Control Add Label, hDlg, 103, "", 10, 240, 400, 100
                          Control Add Button, hDlg, 104, "Mix", 10, 360, 400, 15
                          Dialog Show Modal hDlg Call DlgProc
                       End Function
                    ------------------

                    Comment


                    • #11
                      Semen --

                      The full source code of the demo has been posted to you.
                      I will try your code as soon as I can.

                      Looks like you have a permanent link to this forum

                      Thank you.

                      ------------------
                      Patrice Terrier
                      mailto[email protected][email protected]</A>
                      Patrice Terrier
                      www.zapsolution.com
                      www.objreader.com
                      Addons: GDImage.DLL 32/64-bit (Graphic library), WinLIFT.DLL 32/64-bit (Skin Engine).

                      Comment


                      • #12
                        GetPixel and SetPixel are inherently inefficient. There's a fair amount of overhead involved in making an API call. For pixel operations, where you're liable to have a great many pixels, you will get the most significant improvements by bypassing these operations altogether. Optimizing relatively fast local operations like GetRValue is not going to have any noticeable effect until you get rid of the real bottleneck. The suggestions here to get a DIB and deal with it directly are fully sensible.

                        ------------------
                        Tom Hanlin
                        PowerBASIC Staff

                        Comment


                        • #13
                          Hi all of you.

                          Thank you everybody for your suggestions.

                          Things are already done using DIB and pointers, the overall speed is now very good, thus this thread is over.



                          ------------------
                          Patrice Terrier
                          mailto[email protected][email protected]</A>
                          Patrice Terrier
                          www.zapsolution.com
                          www.objreader.com
                          Addons: GDImage.DLL 32/64-bit (Graphic library), WinLIFT.DLL 32/64-bit (Skin Engine).

                          Comment

                          Working...
                          X