Announcement

Collapse
No announcement yet.

GetPixel SetPixel DirectX replacement?

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

  • Patrice Terrier
    replied
    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>

    Leave a comment:


  • Tom Hanlin
    replied
    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

    Leave a comment:


  • Patrice Terrier
    replied
    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>

    Leave a comment:


  • Semen Matusovski
    replied
    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
    ------------------

    Leave a comment:


  • Patrice Terrier
    replied
    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>

    Leave a comment:


  • Chris Boss
    replied
    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.


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

    Leave a comment:


  • Patrice Terrier
    replied
    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>

    Leave a comment:


  • Eric Pearson
    replied
    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>

    Leave a comment:


  • Eric Pearson
    replied
    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>

    Leave a comment:


  • Patrice Terrier
    replied
    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).]

    Leave a comment:


  • Semen Matusovski
    replied
    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.

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

    Leave a comment:


  • Chris Boss
    replied
    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.


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

    Leave a comment:


  • Patrice Terrier
    started a topic GetPixel SetPixel DirectX replacement?

    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>
Working...
X