You are not logged in. You can browse in the PowerBASIC Community, but you must click Login (top right) before you can post. If this is your first visit, check out the FAQ or Sign Up.
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.
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.
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.
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...
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
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.
>>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 --
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
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.
We process personal data about users of our site, through the use of cookies and other technologies, to deliver our services, and to analyze site activity. For additional details, refer to our Privacy Policy.
By clicking "I AGREE" below, you agree to our Privacy Policy and our personal data processing and cookie practices as described therein. You also acknowledge that this forum may be hosted outside your country and you consent to the collection, storage, and processing of your data in the country where this forum is hosted.
Comment