The MASM Forum Archive 2004 to 2012

General Forums => The Laboratory => Topic started by: Jimg on February 16, 2009, 01:47:52 AM

Title: Graphics
Post by: Jimg on February 16, 2009, 01:47:52 AM
This is probably going to be a long messy post so I'll apologize in advance.

I'm getting ready to plot some irregular curves, so I realized I finally have to use something other than setpixel to get acceptable speed.
So I set up a program to test various ways of doing things, and I'm not happy with the results.

What I did was use an area of 500 pixels wide by 100 pixels tall.  I tested creating a normal compatible bitmap/dc, and also using CreateDIBSection and selecting it into a dc.

I did my drawing on a memory dc and blitted the final result to a dialog for visual confirmation.

Here is the results of my timing tests-
AuthenticAMD  Family 7  Model 10  Stepping 0
AMD Name String: AMD Athlon(tm) XP 3000+
Features: FPU TSC CX8 CMOV FXSR MMX SSE

Method: Min
Iterations: 5
        Clocks   Description
Test 1  1469     draw with pen
Test 2  2677     draw with pen on DIB
Test 11 134      fill background using FillRect with brush
Test 12 95663    fill background using FillRect with brush on DIB
Test 13 89159    fill background using direct access on DIB
Test 21 133      line using FillRect and Brush
Test 22 2013     line using FillRect and Brush on DIB
Test 31 754300   line using setpixel
Test 32 416543   line using setpixel on DIB
Test 33 1509     line using direct access to bitmap on DIB
Test 41 2091     bitblt from normal memory dc to dialog dc
Test 42 177706   bitblt from DIB dc to dialog dc


While setting each pixel for a line is 499 times faster in my tests, which is exactly what I was trying to accomplish, it seems that filling the area with a color for background is 665 times slower, and the blit from the memory dc to the dialog dc is 85 times slower.

So I'm thinking I must have some incompatibility between my DIB and my dialog.

Here's the parameters I used:
.data
bih BITMAPINFOHEADER <sizeof BITMAPINFOHEADER, \
  mwidth,  \;biWidth
  -mheight, \;biHeight
  1,       \;biPlanes WORD
  32,      \;biBitCount WORD
  BI_RGB,  \;biCompression
  0,       \;biSizeImage
  0,       \;biXPelsPerMeter
  0,       \;biYPelsPerMeter
  0,       \;biClrUsed
  0 >      ;biClrImportant

My dialog is TrueColor, which I believe is 32 bit, so is there some other settings for the BITMAPINFOHEADER that will speed this thing up?

My setup for drawing on the compatible memory dc is
Setup1 proc
    .if mbuff==0
        inv GetProcessHeap
        mov hHeap,eax
        inv HeapAlloc,hHeap,HEAP_ZERO_MEMORY,2048
        mov mbuff,eax
        inv CreateFontIndirect,addr deffont  ; 10 pt small
        mov hfont,eax
    .endif
    .if mdc
        inv DeleteDC,mdc
        inv DeleteObject,mbmp
    .endif
    ;inv GetClientRect,hWin,addr crect    ; get the size needed for the bitmap
    inv GetDC,hWin  ; get dc's
    mov hdc,eax
    inv CreateCompatibleDC,hdc      ; create dc for hidden buffer
    mov mdc,eax
    inv SelectObject,mdc,hfont
    inv SetBkMode,mdc,TRANSPARENT
    inv CreateCompatibleBitmap,hdc, mwidth, mheight ; make a hidden buffer of the appropriate size
    mov mbmp,eax
    inv SelectObject, mdc, mbmp
    inv DeleteObject,eax        ; delete old bitmap

ret
Setup1 endp

and for drawing on the DIB is
Setup2 proc
    .if mbuff==0
        inv GetProcessHeap
        mov hHeap,eax
        inv HeapAlloc,hHeap,HEAP_ZERO_MEMORY,2048
        mov mbuff,eax
        inv CreateFontIndirect,addr deffont  ; 10 pt small
        mov hfont,eax
    .endif
    .if mdc
        inv DeleteDC,mdc
        inv DeleteObject,mbmp
    .endif
    inv GetDC,hWin  ; get dc's
    mov hdc,eax
    inv CreateCompatibleDC,hdc      ; create dc for hidden buffer
    mov mdc,eax
    inv CreateDIBSection,mdc,addr bih,DIB_RGB_COLORS,addr mbits,0,0
    mov mbmp,eax
    inv SelectObject,mdc,eax
    inv DeleteObject,eax        ; delete old bitmap
    inv SelectObject,mdc,hfont
    inv SetBkMode,mdc,TRANSPARENT

ret
Setup2 endp

example tests of filling the background-
Test11:
    Desc 'fill background using FillRect with brush'
    call Setup1
    inv makbrush,Red
    BeginCounter
        inv FillRect,mdc,addr rr,hbrush
    EndCounter
    call Wrapup1
    ret
   
Test12:
    Desc 'fill background using FillRect with brush on DIB'
    call Setup2
    inv makbrush,Blue
    BeginCounter
        inv FillRect,mdc,addr rr,hbrush
    EndCounter
    call Wrapup2
    ret
   
Test13:
    Desc 'fill background using direct access on DIB'
    call Setup2
    BeginCounter
        mov edi,mbits
        mov ecx,mwidth*mheight
        mov eax,Yellow
        rep stosd
    EndCounter
    call Wrapup2
    ret

etc.

Does anyone see any way to speed these things up?

Is there some way to get the address of the bitmap for the memory dc and write to it directly rather than using a DIB?







[attachment deleted by admin]
Title: Re: Graphics
Post by: Jimg on February 16, 2009, 05:09:26 PM
I added a few more tests above for text output.

Test51  32120    DrawText
Test52  107594   DrawText on DIB
Test54  958      simple ExtTextOut
Test55  96840    simple ExtTextOut on DIB
Test57  982      simple TextOut
Test58  97263    simple TextOut on DIB


DrawText is only 3.3 times slower, but slowest overall.   TextOut is 99 times slower, and ExtTextOut is 101 times slower. 

I've also noticed that when I put colors directly using the dib, red comes out as blue, blue comes out as red, yellow comes out as cyan, and cyan comes out as yellow. ??

Anyways, I anxiously await some graphics guru explaining what I'm doing wrong with this DIB to make it so sloooooow.
Title: Re: Graphics
Post by: Jimg on February 16, 2009, 05:38:45 PM
I added a gdiFlush after each test to try to get better timings.  It slowed down the really fast fillrects, and made the ratios not quite so bad, but I'm not really sure if its a valid thing to do for a time test.

Method: Min
Iterations: 100
        Clocks   Description
Test1   1756     draw with pen
Test2   2910     draw with pen on DIB
Test11  2392     fill background using FillRect with brush
Test12  95879    fill background using FillRect with brush on DIB
Test13  89880    fill background using direct access on DIB
Test21  2406     line using FillRect and Brush
Test22  2138     line using FillRect and Brush on DIB
Test31  689430   line using setpixel
Test32  377303   line using setpixel on DIB
Test33  1812     line using direct access to bitmap on DIB
Test41  2294     bitblt from normal memory dc to dialog dc
Test42  204577   bitblt from DIB dc to dialog dc
Test51  32124    DrawText
Test52  107037   DrawText on DIB
Test54  15243    simple ExtTextOut
Test55  90417    simple ExtTextOut on DIB
Test57  14931    simple TextOut
Test58  90756    simple TextOut on DIB

Ratios, Dib/non-Dib

1.6 draw with pen
40  fill background using FillRect with brush
.88 line using FillRect and Brush
.54 line using setpixel
89  bitblt to dialog dc
3.3 DrawText
5.9 simple ExtTextOut
6.  simple TextOut
Title: Re: Graphics
Post by: PBrennick on February 16, 2009, 10:12:07 PM
Of course, you realize that if you pre-define colors in the data section, you must reverse them? Its an Endian thing.

For example:

BgColor         dd  0B0FFFFh            ; A light yellow [Red=255, Green=255 and Blue=176]


Notice that B0h (for blue) is first.

Paul
Title: Re: Graphics
Post by: Jimg on February 16, 2009, 10:18:17 PM
Thanks Paul.
Yeah, I just used Red, Blue, Green from windows.inc so I suspected that was it, but the cyan/yellow thing really got me.

Title: Re: Graphics
Post by: japheth on February 16, 2009, 10:22:30 PM
Quote from: Jimg on February 16, 2009, 01:47:52 AM
Does anyone see any way to speed these things up?

I'm no GDI expert, but AFAIR you shouldn't call CreateDIBSection with a memory DC, it should be called with a screen DC.

other things which probably can be improved:

- the handle returned by GetDC is to be freed with ReleaseDC().
- when a bitmap is selected in a memory DC, it isn't necessary to delete the default 1x1 bitmap which is returned.
Title: Re: Graphics
Post by: Jimg on February 16, 2009, 11:02:51 PM
Quote from: japheth on February 16, 2009, 10:22:30 PM
I'm no GDI expert, but AFAIR you shouldn't call CreateDIBSection with a memory DC, it should be called with a screen DC.
Makes sense to me.  So I changed it to inv CreateDIBSection,hdc,...  but it didn't seem to make any difference
Quote
other things which probably can be improved:
- the handle returned by GetDC is to be freed with ReleaseDC().
Sorry, it was hidden in the wrapup proc called after each test-
Wrapup1 proc
    .if mdc
        inv BitBlt,hdc,10,10,500,100,mdc,0,0,SRCCOPY
        inv DeleteDC,mdc
        inv DeleteObject,mbmp
        inv ReleaseDC,hWin,hdc
    .endif
    call delbrush   
ret
Wrapup1 endp
Quote
Quote
- when a bitmap is selected in a memory DC, it isn't necessary to delete the default 1x1 bitmap which is returned.
Fixed.
Title: Re: Graphics
Post by: MichaelW on February 17, 2009, 12:57:28 AM
Why use a DIB?
Title: Re: Graphics
Post by: Jimg on February 17, 2009, 02:02:40 AM
I want to plot some irregular curves in simulated realtime, and setpixel is just too slow.

(and now I'm hoping you'll say "Well just use xxxxapi to access the bytes of the DDB".)
Title: Re: Graphics
Post by: NightWare on February 17, 2009, 02:14:05 AM
just obtain the start address (the fisrt pixel), you have defined 32 bits colors so you will be easily able to code your own setpixel function...
Title: Re: Graphics
Post by: donkey on February 17, 2009, 02:32:23 AM
Quote from: MichaelW on February 17, 2009, 12:57:28 AM
Why use a DIB?

A SetPixel function with a 32 bit DIB section is fairly simple, for execution speed reasons the Set/GetPixel functions require that the width and height of the bitmap are passed to them, this is so that they don't have to waste time calculating them each call.

A couple of functions in GoAsm syntax:

SetDIBPixel FRAME x,y,pDIBits,width,height,color

mov eax,[width]
mov ecx,[height]

cmp [x],eax
jae >.EXIT

cmp [y],ecx
jae >.EXIT

sub ecx,[y]
dec ecx
mul ecx
shl eax,2 ; adjust for DWORD size
mov edx,eax

mov eax,[x]
shl eax,2 ; adjust for DWORD size
add eax,edx

add eax,[pDIBits] ; add the offset to the DIB bit
mov ecx,[color]
mov D[eax],ecx

.EXIT
RET
ENDF

GetDIBPixel FRAME x,y,pDIBits,width,height

mov eax,[width]
mov ecx,[height]

sub ecx,[y]
dec ecx
mul ecx
shl eax,2 ; adjust for DWORD size
push eax ; push the result onto the stack

mov eax,[x]
shl eax,2 ; adjust for DWORD size
pop ecx ; pop the scan line offset off the stack
add eax,ecx

add eax,[pDIBits] ; add the offset to the DIB bit
mov eax,[eax]

RET
ENDF


With these 2 base functions you can do just about anything...

/*
DIBDrawEllipse
Draws an ellipse
Parameters
hDIB = Handle to a 32bit DIB section
centerx = x coordinate of the center point
centery = y coordinate of the center point
a = x radius
b = y radius
color = line color
Returns the original bitmap handle, original is modified
*/

DIBDrawEllipse FRAME hDIB,xc,yc,a,b,color
uses edi,esi,ebx
LOCAL a2,b2 :D
LOCAL crit1,crit2,crit3 :D
LOCAL t,dxt,d2xt,dyt,d2yt :D
LOCAL temp1,temp2,temp3,temp4,temp5,temp6,y :D
LOCAL dibs :BITMAP

; Format the color
mov eax,[color]
bswap eax
shr eax,8
mov [color],eax

invoke GetObjectA,[hDIB],SIZEOF BITMAP,offset dibs

mov ebx, [a]
mov ecx, ebx
imul ecx, ebx
mov esi, [b]
mov edi, esi

mov eax, ecx
imul edi, esi
cdq
and edx, 3
add eax, edx
sar eax, 2

mov D[temp6],0
neg eax
and ebx, -2147483647
mov [y], esi
mov [b2], edi
jns >
dec ebx
or ebx, -2
inc ebx
:
sub eax, ebx
sub eax, edi
mov [crit1], eax

mov eax, edi
cdq
and edx, 3
add eax, edx
sar eax, 2
mov edx, esi
neg eax
and edx, -2147483647
jns >
dec edx
or edx, -2
inc edx
:
sub eax, edx
mov [temp3], eax
sub eax, ecx
mov [crit2], eax

mov eax, ecx
imul eax, esi

mov edi, eax
neg edi
mov ebx, eax
neg ebx
shl edi, 1

test esi, esi
lea edx, [ecx+ecx]
mov D[dxt], 0
mov [d2yt], edx
jl >>.EXIT
mov [temp1], eax
mov eax, [yc]
lea edx, [eax+esi]
neg ecx
sub eax, esi
mov [temp4], edx
mov [temp5], ecx
mov esi, eax

align 4
.WHILELOOP
mov eax,[temp6]
cmp eax, [a]
jg >>.EXIT

mov ecx, [temp4]
mov eax, [xc]
add eax, [temp6]
invoke SetDIBPixel,eax,ecx,[dibs.bmBits],[dibs.bmWidth], \
[dibs.bmHeight],[color]

mov eax,[temp6]
test eax, eax
jne >C0
mov eax, [y]
test eax, eax
je >C1 ;
C0:
mov eax, [xc]
sub eax, [temp6]
mov [temp2],eax
invoke SetDIBPixel,eax,esi,[dibs.bmBits],[dibs.bmWidth], \
[dibs.bmHeight],[color]

mov eax,[temp6]
test eax, eax
je >C1
mov eax, [y]
test eax, eax
je >C1
mov edx, [xc]
mov eax,[temp6]
lea eax, [edx+eax]
invoke SetDIBPixel,eax,esi,[dibs.bmBits],[dibs.bmWidth], \
[dibs.bmHeight],[color]

mov eax, [temp4]
mov ecx, [temp2]
invoke SetDIBPixel,ecx,eax,[dibs.bmBits],[dibs.bmWidth], \
[dibs.bmHeight],[color]

C1:
mov ecx, [b2]
mov eax, [crit1]
mov edx, ecx
imul edx, [temp6]
add edx, ebx
cmp edx, eax
jle >C3
mov eax, [temp1]
lea edx, [eax+ebx]
cmp edx, [temp3]
jle >C3

mov edx, ebx
sub edx, eax
cmp edx, [crit2]
jle >C2

mov ecx, [y]
mov edx, [temp5]
dec ecx
mov [y], ecx
mov ecx,[temp4]
inc esi
dec ecx
mov [temp4], ecx
mov ecx, [d2yt]
add eax, edx
add edi, ecx
mov [temp1], eax
add ebx, edi

jmp >.DONE
C2:
lea edx,[ecx+ecx]
mov ecx,[dxt]
add ecx, edx

mov edx,[y]
inc D[temp6]
dec edx
mov [y], edx
mov edx, [temp4]
inc esi
dec edx
mov [temp4], edx
add eax, [temp5]
add edi, [d2yt]
mov [temp1], eax
mov [dxt], ecx
lea eax, [edi+ecx]
jmp >
C3:
mov eax, [dxt]
add ecx, ecx
inc D[temp6]
add eax, ecx
mov [dxt], eax
:
add ebx, eax
.DONE

mov eax, [y]
test eax, eax
jge <<.WHILELOOP
.EXIT

mov eax,[hDIB]
ret
ENDF
Title: Re: Graphics
Post by: Jimg on February 17, 2009, 03:05:48 AM
Quote from: NightWare on February 17, 2009, 02:14:05 AM
just obtain the start address (the fisrt pixel), you have defined 32 bits colors so you will be easily able to code your own setpixel function...
Exactly.  If I can get the address of the bits in the bitmap, I can do anything in the way of laying down dots to draw whatever.  The problem for me, is to get the address of the dang bitmap.  As you can see by all my above tests, using a DIB is much slower than using a device dependent bitmap such as the one associated with a dialog.  I drew a line on the DIB with no problem, and it's very fast, but all the other functions like filling the whole background with a color is much, much slower than using fillrect on a DDB.  And particularly disturbing is how long it takes to blit from the dc with the DIB to the dc of the dialog compared to blitting from a simple memory dc to the dialog.
Title: Re: Graphics
Post by: donkey on February 17, 2009, 03:12:36 AM
Quote from: Jimg on February 17, 2009, 03:05:48 AM
The problem for me, is to get the address of the dang bitmap.

LOCAL dibs :BITMAP
invoke GetObjectA,[hDIB],SIZEOF BITMAP,offset dibs

// dibs.bmBits is the address of the bitmap pixels

Never known a DDB to be faster in any way than a DIB, could be the functions you wrote, it should always be faster using direct to memory functions.

Edit: BTW you can use PatBlt to fill a rectangle, much faster than FillRect.

invoke CreateSolidBrush,[Fill]
invoke SelectObject,[memdc],eax
mov [fillbrush],eax

invoke PatBlt,[memdc],[rect.left],[rect.top], \
[rect.right],[rect.bottom],PATCOPY

invoke SelectObject,[memdc],[fillbrush]
invoke DeleteObject,eax
Title: Re: Graphics
Post by: Jimg on February 17, 2009, 03:38:46 AM
Ok, you threw me by saying dib everywhere.  I'll try to get the address of the much faster (see my tests above) ddb.
Title: Re: Graphics
Post by: donkey on February 17, 2009, 03:47:47 AM
Quote from: Jimg on February 17, 2009, 03:38:46 AM
Ok, you threw me by saying dib everywhere.  I'll try to get the address of the much faster (see my tests above) ddb.

Hi JimG, your tests aside, I have tested this to death as have many others. In cases like Greyscaling the direct to memory approach was nearly 10x faster than GDI or GDI+. There are always exceptions where one usage runs a bit slow but that is a matter of implementation, direct to memory as a rule is always faster when properly done. The only exception to this rule is Blt'ing, because it can make use of the GPU it can be faster if hardware accel. is turned on.

http://www.masm32.com/board/index.php?topic=2640.msg20956#msg20956

Quote from: MSDNWindows 95 and Windows NT 3.5 and later support DIBSections. DIBSections are the fastest and easiest to manipulate, giving the speed of DDBs with direct access to the DIB bits.
Title: Re: Graphics
Post by: Jimg on February 17, 2009, 04:16:51 AM
Well, getobject didn't work.  It returned everything except bmBits which came back zero.  sigh.
Title: Re: Graphics
Post by: donkey on February 17, 2009, 04:28:37 AM
Hi JimG,

Then you have not passed a valid handle to it, it will not work with a device dependent bitmap only a DIB section created with the CreateDIBSection function.

http://msdn.microsoft.com/en-us/library/aa932477.aspx

QuoteIf hgdiobj identifies a bitmap created by calling CreateDIBSection, and the specified buffer is large enough, the GetObject function returns a DIBSECTION structure. In addition, the bmBits member of the BITMAP structure contained within the DIBSECTION structure will contain a pointer to the bitmap's bit values.

If hgdiobj identifies a bitmap created by any other means, GetObject returns only the width, height, and color format information of the bitmap and the pointer to the bitmap's bit values will be NULL. You can only access the bitmap's bits if they are in a device-independent bitmap.

You can use the BITMAP structure for DIB sections as well, the bmBits will contain the pointer to the bit values.
Title: Re: Graphics
Post by: NightWare on February 17, 2009, 04:31:52 AM
donkey is right, the difference between DDB and DIB is the informations used, DDB use existing infos (essentially BITMAPINFO structure). DIB use his own informations. but here you have defined only 1 serie... there is a problem somewhere with your speed test...

plus, by looking of Setup1 proc, you create a COMPATIBLE BITMAP, so you know where all infos are, coz a bitmap is composed of [BITMAPFILEHEADER]+[BITMAPINFOHEADER]+[RGBQUAD x dup]+[Pixels]
Title: Re: Graphics
Post by: donkey on February 17, 2009, 04:34:46 AM
This will create a bitmap that can be used with the GetObject function...

CreateIndependantBitmap FRAME hDC,SizeX,SizeY
LOCAL bmi :BITMAPINFO
LOCAL ppvBits :D

mov D[bmi.bmiHeader.biSize],SIZEOF BITMAPINFOHEADER
mov eax,[SizeX]
mov [bmi.bmiHeader.biWidth],eax
mov eax,[SizeY]
mov D[bmi.bmiHeader.biHeight],eax
mov W[bmi.bmiHeader.biPlanes],1
mov W[bmi.bmiHeader.biBitCount],32
mov D[bmi.bmiHeader.biCompression],BI_RGB
invoke CreateDIBSection,[hDC],ADDR bmi,DIB_RGB_COLORS,ADDR ppvBits,NULL,NULL

push eax
invoke GdiFlush
pop eax
ret

ENDF
Title: Re: Graphics
Post by: Jimg on February 17, 2009, 05:28:07 AM
If you look at the code I posted, I was already using CreateDibSection to create a bitmap.  This is the one I tested against the compatible bitmap.  That's how I discovered how much slower the DIB was.
Title: Re: Graphics
Post by: Mark Jones on February 17, 2009, 06:42:09 AM
Tried sDraw? Nice inc+lib. Ultrano mentioned it was also available on the asmcommunity forum.

http://www.masm32.com/board/index.php?topic=6514.0
Title: Re: Graphics
Post by: Jimg on February 17, 2009, 05:23:50 PM
Quote from: NightWare on February 17, 2009, 04:31:52 AM
donkey is right, the difference between DDB and DIB is the informations used, DDB use existing infos (essentially BITMAPINFO structure). DIB use his own informations. but here you have defined only 1 serie... there is a problem somewhere with your speed test...
I don't understand what you mean when you say " here you have defined only 1 serie..."

Quoteplus, by looking of Setup1 proc, you create a COMPATIBLE BITMAP, so you know where all infos are, coz a bitmap is composed of [BITMAPFILEHEADER]+[BITMAPINFOHEADER]+[RGBQUAD x dup]+[Pixels]
When I create a compatible bitmap, all I get back are a handle.  If I feed the handle into GETOBJECT, I get back the correct information as to width,height,type,planes, and bitspixel.  For bmBits, I get back a zero, so I don't know the starting address.

I've come to the conclusion that this is all a colossal waste of time anyway.  If the procedure isn't clearly documented somewhere on MSDN, I don't really want to use it.   I'm sure my tests are correct, if not, please point out the mistaken instructions.  I apologize for my giant mess of a timing test, but it really helped me see what was actually going on.

Anyway, thanks all for your patience and time, I'll go crawl back in my hole now.
Title: Re: Graphics
Post by: japheth on February 17, 2009, 05:45:12 PM
Quote from: Jimg on February 17, 2009, 05:23:50 PM
Quoteplus, by looking of Setup1 proc, you create a COMPATIBLE BITMAP, so you know where all infos are, coz a bitmap is composed of [BITMAPFILEHEADER]+[BITMAPINFOHEADER]+[RGBQUAD x dup]+[Pixels]
When I create a compatible bitmap, all I get back are a handle.  If I feed the handle into GETOBJECT, I get back the correct information as to width,height,type,planes, and bitspixel.  For bmBits, I get back a zero, so I don't know the starting address.
Yes, you won't get a pointer to the pixels of a DDB. AFAIK this is by design, because this abstraction level allowed GDI to support the old 4bit color-plane modes of the EGA/VGA without API extension.

As far as GDI is concerned there is one option which wasn't mentioned so far: one can use the SetDIBitsToDevice() function instead of CreateDIBSection() + BitBlt(). I've seen several programs using it, so I'm sure it isn't anything exotic, but I have no own experiences.

Title: Re: Graphics
Post by: Jimg on February 17, 2009, 06:25:20 PM
p.s.  Thank you Donkey, PatBlt is absolutely faster than FillRect :thumbu

with GdiFlush after each test
        Clocks   Description
Test11  2349     fill background using FillRect with brush
Test12  1650     fill background using PatBlt with brush
Test13  96001    fill background using FillRect with brush on DIB
Test14  89930    fill background using direct access on DIB
Test15  95194    fill background using PatBlt with brush on DIB
Test21  2395     line using FillRect and Brush
Test22  1674     line using PatBlt and Brush
Test23  2228     line using FillRect and Brush on DIB
Test24  1586     line using PatBlt and Brush on DIB


without GdiFlush after each test
        Clocks   Description
Test11  134      fill background using FillRect with brush
Test12  64       fill background using PatBlt with brush
Test13  95720    fill background using FillRect with brush on DIB
Test14  89163    fill background using direct access on DIB
Test15  94868    fill background using PatBlt with brush on DIB
Test21  133      line using FillRect and Brush
Test22  64       line using PatBlt and Brush
Test23  1875     line using FillRect and Brush on DIB
Test24  1263     line using PatBlt and Brush on DIB
Title: Re: Graphics
Post by: MichaelW on February 17, 2009, 06:30:35 PM
Jim,

The reason I asked why use a DIB was that your results show FillRect to be fast with a DDB. How about using a set pixel routine based on FillRect (specifying a one-pixel rectangle) on a DDB? If I assume a worst case of 133 cycles per call, and that the line in your tests is 500 pixels long, the resulting 66500 cycles is more than 11 times faster than using SetPixel on a DDB and more than 6 times faster than using SetPixel on a DIB. And since FillRect runs in 133 cycles for a 500-pixel line it could not have much overhead, so reducing the number of pixels drawn to one should speed it up considerably.

And now that I see your most recent results, read FillRect above as PatBlt.

Title: Re: Graphics
Post by: Jimg on February 17, 2009, 07:26:50 PM
Quote from: MichaelW on February 17, 2009, 06:30:35 PM
Jim,

The reason I asked why use a DIB was that your results show FillRect to be fast with a DDB. How about using a set pixel routine based on FillRect (specifying a one-pixel rectangle) on a DDB? If I assume a worst case of 133 cycles per call, and that the line in your tests is 500 pixels long, the resulting 66500 cycles is more than 11 times faster than using SetPixel on a DDB and more than 6 times faster than using SetPixel on a DIB. And since FillRect runs in 133 cycles for a 500-pixel line it could not have much overhead, so reducing the number of pixels drawn to one should speed it up considerably.

And now that I see your most recent results, read FillRect above as PatBlt.
If I understood your question correctly, the reason, and the only reason I considered using a DIB was to plot irregular curves.  Direct access to a DIB is much, much faster than setpixel in this case.  Every other operation seems to be faster on a DDB.  Since I will also be "plotting" a bunch of grid lines, I was concerned about how much slower it was on a DIB.  In reality, its insignificant if it takes 1800 cycles rather than 134 is for drawing each grid line.  I'm still unhappy that it takes 95000 cycles to fill the background on a DIB vs. worse case 2350 on a DDB, but again, in reality, it will never be noticed.  And I'm still unhappy that it takes 179000 cycles to blit a 100x500 DIB to the dialog vs. worse case 2300 for a DDB, but still again, it will never be noticed.  So what it boils down to, is that I'm letting the raw numbers bother me and not seeing reality.  Yes, DIB's are much slower than DDB's, regardless of what others have tried to tell me, but it Just Doesn't Matter.  If there is some way to make the DIB's faster, or to be able to put directly to a DDB, I would still like to know, but I'm done losing sleep over it :bg

p.s.  I'll run your one pixel test, but I don't have high hopes :wink

pps.  And here's the results
        Clocks   Description
Test31  741509   line using setpixel (on DDB)
Test34  475206   line using PatBlt one pixel at a time in place of setpixel (on DDB)
Test33  2304     line using direct access to bitmap on DIB
So yes, it's good to know that PatBlt is faster than setpixel, thanks.

ppps.  I've updated the test program in my first post for all new tests.
Title: Re: Graphics
Post by: Jimg on February 19, 2009, 03:58:49 PM
I finally ran the tests on my old celeron laptop with minimal memory and graphics card. Unexpectedly, the results were similar to the amd.
cpu1: Mobile Intel(R) Celeron(R) CPU 2.00GHz (Family 15 Model 2 Step 7) SSE2                   
cpu2: AMD Athlon(tm) XP 3000+ (Family 7 Model 10 Step 0) SSE1                                 
                                                                                               
Method: Min                                                                                   
Iterations: 100                                                                               
        Clocks          Description                                                           
        cpu1    cpu2                                                                           
Test1   6640    1417    draw with pen                                                         
Test2   3444    2587    draw with pen on DIB                                                   
Test11  208     135     fill background using FillRect with brush                             
Test12  100     64      fill background using PatBlt with brush                               
Test13  157412  95606   fill background using FillRect with brush on DIB                       
Test14  112884  89161   fill background using direct access on DIB                             
Test15  144776  94870   fill background using PatBlt with brush on DIB                         
Test21  220     134     line using FillRect and Brush                                         
Test22  100     64      line using PatBlt and Brush                                           
Test23  3500    1864    line using FillRect and Brush on DIB                                   
Test24  1944    1258    line using PatBlt and Brush on DIB                                     
Test31  2298796 702092  line using setpixel                                                   
Test32  763076  370507  line using setpixel on DIB                                             
Test33  3992    1510    line using direct access to bitmap on DIB                             
Test34  1691708 477564  line using PatBlt one pixel at a time in place of setpixel             
Test41  5304    1988    bitblt from normal memory dc to dialog dc                             
Test42  325492  188096  bitblt from DIB dc to dialog dc                                       
Test51  127904  31328   DrawText                                                               
Test52  66420   50373   DrawText on DIB                                                       
Test54  1264    960     simple ExtTextOut                                                     
Test55  41984   34932   simple ExtTextOut on DIB                                               
Test57  1244    950     simple TextOut                                                         
Test58  40780   34844   simple TextOut on DIB                                                 
Test63  208     134     fill background using FillRect with brush                             
Test64  132     122     fill background using PatBlt with brush, SelectOBject in timing loop   


My apologies to anyone who downloaded the previous version of the program that didn't print results to the results file.

Title: Re: Graphics
Post by: Jimg on April 06, 2009, 06:53:06 PM
After screwing around for a month and a half, I just discovered this whole thing was a waste of time.

To write directly to a device dependent bitmap, you just get the address and do it.  No need for a dib or dibsection.

Just do a GetObject.  The address of the  bits in in the parameter BITMAP.bmBits

Why didn't anyone tell me this when I was floundering around so badly?
Title: Re: Graphics
Post by: dedndave on April 06, 2009, 07:09:53 PM
I would be interested in seeing some source to plot curves, Jim
I am new to 32-bit and would like to learn from your efforts
Title: Re: Graphics
Post by: Jimg on April 06, 2009, 08:58:38 PM
That's actually my next step.  So far, anything that could go wrong, has.
Every time I run into a problem, it takes days to find a solution.
95% of my time is taken writing 2% of the code.
And EVERY time, it the windows api that is poorly documented or not documented at all.
The other 98% of the code is easy.
The actual graphing should be pretty easy (unless you want alpha blended smooth (blurry) curves  :lol)
I'll certainly post something when I have something worth posting.
Title: Re: Graphics
Post by: Jimg on April 06, 2009, 09:55:07 PM
And after a little more digging, the answer to my previous questions is-

The documentation says it doesn't return bmBits for a non-dib.

Testing shows otherwise.

Is this yet another case of incorrect windows api documentation?
Title: Re: Graphics
Post by: NightWare on April 06, 2009, 10:01:21 PM
Quote from: Jimg on April 06, 2009, 06:53:06 PM
After screwing around for a month and a half, I just discovered this whole thing was a waste of time... ...Is this yet another case of incorrect windows api documentation?
it's a bit more complicate, you MUST fill structures of information to allow the use of functions. beside, for 32bits it can appear easy, but for 16/24bits screens or data, it's another story... it's why dib sections are supposed to be used...  :wink
Title: Re: Graphics
Post by: BogdanOntanu on April 06, 2009, 10:12:52 PM
Quote from: Jimg on April 06, 2009, 09:55:07 PM
And after a little more digging, the answer to my previous questions is-

The documentation says it doesn't return bmBits for a non-dib.

Testing shows otherwise.

Is this yet another case of incorrect windows api documentation?

IF the documentation states that it should not return a valid value in  bmBits member THEN it is possible that this will be the case on any new version or on any new Windows update... and in this case your program will stop working.

It is better to respect the official recommendations even if testing shows otherwise.
Title: Re: Graphics
Post by: Rainstorm on April 07, 2009, 05:17:54 PM
I've been trying out some GDI & bitmap related stuff too.
Bitmaps are stored usually as DIBs is that right ?... - so if a file has to be opened & worked on.. - I open it  then edit its as a DDB, then save it back again to disk as a DIB. - is this the usual procedure.. ? if not.. what's the usual way of doing this.

thanks
Title: Re: Graphics
Post by: Jimg on April 07, 2009, 05:50:20 PM
I find the terminology confusing myself.  Bitmaps on disk are Bitmaps.  There is no dib or ddb, they are just bitmaps in the correct format.  The first d stands for device, and there is no device.
Their colors and form may happen to be compatible with the screen, but don't rely on it.

The procedure for editing really depends upon what you want to do.  Normally, you are not supposed to edit a ddb directly, you are supposed to only make changes to a ddb by loading it into a device context and using the gdi procedures.   As far as writing a bitmap back out of a DC to a file, I haven't done that yet, we will have to get one of the graphics gurus to give us an example.

If you just want to make some simple changes, you can work directly on the bitmap file itself without using gdi.

What kind of things are you trying to do to the bitmap?
Title: Re: Graphics
Post by: dedndave on April 07, 2009, 06:26:18 PM
wow - all this sounds overly compicated - lol
is this the directX interface ?
Title: Re: Graphics
Post by: Rainstorm on April 07, 2009, 06:41:58 PM
thanks for the response. - I get the part about making changes to the DDB via a device context.
jimq wrote..
QuoteWhat kind of things are you trying to do to the bitmap?
maybe just some basic GDI editing/drawing with a pen or something, & then to save it -Just want to get a general idea about that whole part

>> dendave , its in the GDI section in the SDK

- Jimq, About it being stored as a DIB, these are some excerpts from the SDK that give that impression.
QuoteBitmaps should be saved in a file that uses the established bitmap file format and assigned a name with the three-character .bmp extension.
this format seems to be the same as the DIB format with the same structures. - maybe just the BITMAPFILEHEADER, is not mentioned there
QuoteThe DIB file format was designed to ensure that bitmapped graphics created using one application can be loaded and displayed in another application, retaining the same appearance as the original.
if its meant to be used as such, it would brobably be stored with that format too.. or at least in a form taht retains the format, also
QuoteIf you are writing an application that stores a bitmap image in a file, you should use the bitmap file format described in Bitmap Storage.
(which is the same as the DIB format)

jmq wrote
QuoteAs far as writing a bitmap back out of a DC to a file, I haven't done that yet, we will have to get one of the graphics gurus to give us an example.
just glanced, There's an example in the SDK, after a quick look.. it seems they first use CreateFile to create the file then initialize the DIB structures..(including the BITMAPFILEHEADER structure) & pass them to WriteFile .

they say this too,(the example uses the BITMAPINFO structure)
QuoteNote that the BITMAPINFO structure cannot be used with either a BITMAPV4HEADER or a BITMAPV5HEADER structure.
which was kinda confusing
Title: Re: Graphics
Post by: Jimg on April 07, 2009, 08:13:52 PM
Looks like you're well on your way.  Have fun :U
Title: Re: Graphics
Post by: Rainstorm on April 07, 2009, 09:52:25 PM
not really, still hazy on the whole topic..& could do with some directions..   : )  & would like to know the usual ways people use for doing this,  whether the bitmap after opening is converted into a DDB for GDI operations.
Title: Re: Graphics
Post by: Jimg on April 07, 2009, 11:10:46 PM
I would like to know also.  I know several ways, but most of them are really ugly.  From OleLoadPicturePath with the ugly, confusing com syntax, to gdiplus, with ridiculous object nonsense and complication.

I would say the best way, if you are working on an actual .bmp bitmap and not .png or some later format, would be the LoadImage api.  It's straightforward, and you can get either a dib or ddb in one shot.
Title: Re: Graphics
Post by: Darrel on April 17, 2009, 02:46:18 AM
fyi:  When I started working on bitmaps, I found CreateDIBSection gives me direct access to the bits. As things have developed I do quite a bit of manipulation of the bits, so this seems to be the easiest approach. I'm not sure of speed. I had some queries on the speed of some of my drawing procedures. Now I do all my manipulation of bits in the background, some are bitmaps some are in hdc's and some are just blocks of memory, depending on the procedure in use. With the amount of manipulation I'm doing I am definitely interested if there is a faster approach.

Good day,

Darrel
Title: Re: Graphics
Post by: Jimg on April 17, 2009, 12:49:57 PM
After finally listening to NightWare and using a dibsection, I think it is definitely the best way.  My only problem with the process is the final step, the SetDIBitsToDevice call to put the results to the screen.

If I'm doing the whole bitmap of the same size as the screen, no problem.  If I'm trying to do some random block move, e.g. a 100 pixel square from the middle of the source dib to the upper right of the screen, it take about ten trial and error step before I get it right.  I just don't understand the parameters in SetDIBitsToDevice. -

hdc,XDest,YDest  are ok, no problems

dwWidth - Specifies the width, in logical units, of the DIB.
dwHeight - Specifies the height, in logical units, of the DIB.

  Aren't these values the number of bits wide and high you want to copy, not the "width of the DIB" itself?

XSrc - Specifies the x-coordinate, in logical units, of the lower-left corner of the DIB.

  is this one always zero as the description implies or the actual first pixel horzontally you want to copy?

YSrc - Specifies the y-coordinate, in logical units, of the lower-left corner of the DIB.

  This one is always a guess.  Is it zero?  Is it the height,  Is it something else?

uStartScan - Specifies the starting scan line in the DIB.

  Again, always a trial and error.  What is this value?

cScanLines - Specifies the number of DIB scan lines contained in the array pointed to by the lpvBits parameter.

  Isn't this values just the height.  Isn't it always in the lpbmi BITMAPINFO structure?


Ugh!

Title: Re: Graphics
Post by: NightWare on April 17, 2009, 10:59:12 PM
Quote from: Jimg on April 17, 2009, 12:49:57 PM
dwWidth/dwHeight

Aren't these values the number of bits wide and high you want to copy, not the "width of the DIB" itself?
it's the number of PIXELS in the dib CONCERNED by the work (can be 8/16/24/32 bits depending of the format), you need to define them (the limits of your WORK).

Quote from: Jimg on April 17, 2009, 12:49:57 PM
XSrc/YSrc

is this one always zero as the description implies or the actual first pixel horzontally you want to copy?
This one is always a guess.  Is it zero?  Is it the height,  Is it something else?
here both represent the start coords (always in pixels, from 0 to (width/height)-1), for the transformation of the dib (your source) to the ddb (display device).

Quote from: Jimg on April 17, 2009, 12:49:57 PM
uStartScan/cScanLines

Again, always a trial and error.  What is this value?
Isn't this values just the height.  Isn't it always in the lpbmi BITMAPINFO structure?
here it looks like it's simply the height limits for the display, honestly i've never played a lot with this parameter, all i can say is : with half the height of the dib, it display the first half part of the dib (in the second part of the display, so i suppose the ddb consider the last display line as the first scanline...)
so, in brief :

XDest/YDest   = DESTINATION start coords
dwWidth/dwHeight   = SOURCE width/height TO PROCESS (not necesseraly all the area)
XSrc/YSrc   = SOURCE start coords
uStartScan/cScanLines   = DESTINATION height limits

i hope it help...  :wink
Title: Re: Graphics
Post by: Jimg on April 17, 2009, 11:41:47 PM
Here's an example from a program I'm working on.

What this is, is a custom cursor, 100 pixels square, white background with antialiased circles and grids in 256 color gray scale, used as an alpha channel to blend with the background.

I blend the cursor with the background (hidden buffer that drew the screen), and use SetDIBitsToDevice to copy to the screen.

On the next call, I copy a cursor sized block from the original full sized hidden buffer to the screen at the location of the cursor.

Note that all dibs were created with bih.biHeight set to the negative of the height wanted.


This copies the cursor/background blend to the screen:

    inv GetDC,hWin
    mov hdc,eax
    mov ecx,100         ; size of the dib
    sub ecx,prevmh      ; number of scan lines to show, starting from the top
    inv SetDIBitsToDevice,hdc,prevmcx,prevmcy,prevmw,prevmh,0,ecx,0,100,dibmc.bits,addr dibmc.bih,DIB_RGB_COLORS
    inv ReleaseDC,hWin,hdc

where:
prevmcx is the left x coordinate of where to put the cursor image
prevmcy is the upper y coordinate for the image
prevmw is the width of the cursor image, usually 100 unless we are at the edge of the screen
prevmh is the height of the cursor image, usually 100 unless overlapping top or bottom.
dibmc is a 100 x 100 dib.

Notice I have to subtract the height wanted from the dib height to get SrcY, which took a long time to figure out because it just doesn't make any sense to me.


To restore the screen back to it's original condition before drawing the cursor elsewhere,
I copy a cursor sized block from the orginal back buffer of size mwidth x mheight.

    inv GetDC,hWin  ; yes, remove our cursor from the screen
    mov hdc,eax
    mov esi,dibh1.bits  ; source is hidden buffer 1 in this case.
    mov edi,offset dibh1.bih
    mov ecx,mheight
    sub ecx,prevmcy
    sub ecx,prevmh       
    inv SetDIBitsToDevice,hdc,prevmcx,prevmcy,prevmw,prevmh,prevmcx,ecx,0,mheight,esi,edi,DIB_RGB_COLORS   
    inv ReleaseDC,hWin,hdc

In this case, uStartScan is zero, and
SrcY is the height of the dib minus upper y-coordinate minus the number of lines to copy.

This is not what I would call intuitively obvious.
Title: Re: Graphics
Post by: NightWare on April 18, 2009, 03:09:05 AM
for the copy :
>mov ecx,100         ; size of the dib
no, width or height of the dib, if you want, but not the size... plus why do you set this width/height for the Y source start ? should be zero... you copy from 0,0 to 99,99 no ? should be :
inv SetDIBitsToDevice,hdc,prevmcx,prevmcy,prevmw,prevmh,0,0,0,100,dibmc.bits,addr dibmc.bih,DIB_RGB_COLORS

dito for the restore code, should be :
inv SetDIBitsToDevice,hdc,prevmcx,prevmcy,prevmw,prevmh,0,0,0,100,dibh1.bits,addr dibh1.bih,DIB_RGB_COLORS

remember that the unique case where you don't have 0,0,0,height, it's when you don't start to copy from 0,0 coords of the source
Title: Re: Graphics
Post by: Jimg on April 18, 2009, 02:21:26 PM
Quote from: NightWare on April 18, 2009, 03:09:05 AM
for the copy :
>mov ecx,100         ; size of the dib
no, width or height of the dib, if you want, but not the size
yes, I added some quick comments before posting and blew it.
Quote... plus why do you set this width/height for the Y source start ? should be zero... you copy from 0,0 to 99,99 no ? should be :
inv SetDIBitsToDevice,hdc,prevmcx,prevmcy,prevmw,prevmh,0,0,0,100,dibmc.bits,addr dibmc.bih,DIB_RGB_COLORS
This is exactly what I tried the first time.  It works except at the top and bottom.
Quotedito for the restore code, should be :
inv SetDIBitsToDevice,hdc,prevmcx,prevmcy,prevmw,prevmh,0,0,0,100,dibh1.bits,addr dibh1.bih,DIB_RGB_COLORS
Again, exactly what I did the first time.  This doesn't work at all.  It just always copies the 100 x 100 square from the lower left corner.
Quoteremember that the unique case where you don't have 0,0,0,height, it's when you don't start to copy from 0,0 coords of the source
Yes, again, that's what I do.

I'll try to put together a simple test case later today.
Title: Re: Graphics
Post by: Jimg on April 18, 2009, 10:12:53 PM
Ok, here's a test program.

It's set up to do what I think you said.
Find method and change method and methodx to a 1 for the way I'm doing it now that works.

[attachment deleted by admin]
Title: Re: Graphics
Post by: NightWare on April 19, 2009, 12:41:34 AM
wow... you don't use the functions like it should... ok,

first, you shouldn't store the entire client area (only the 100*100 background, where the cursor will be drawn), it means that you MUST store the background JUST BEFORE drawing the cursor. why ? because the client area could change... here you use RECT.right/RECT.bottom of the client area for the width/height... and in the contrary you should use a RECT structure but with RECT.left/RECT.top for the coords and RECT.right should be RECT.left+width(100) and RECT.bottom should be RECT.top+height(100).

second, when you restore you MUST use the COORDS and SIZE of your backup (it means you must store/use them), coz in your example you restore the entire client area (minored by your position coords)... and of course, in a normal use the coords change, so here you can't restore them in a normal use of the function.

i understand better why it took you some time to obtain a good result, if you would have defined a RECT structure for the client area (the limits), AND a RECT structure for the cursor/background (your work) you would have completed your work considerably faster.
Title: Re: Graphics
Post by: Jimg on April 19, 2009, 01:32:37 AM
Quote from: NightWare on April 19, 2009, 12:41:34 AM
wow... you don't use the functions like it should... ok,

first, you shouldn't store the entire client area (only the 100*100 background, where the cursor will be drawn), it means that you MUST store the background JUST BEFORE drawing the cursor. why ? because the client area could change... here you use RECT.right/RECT.bottom of the client area for the width/height... and in the contrary you should use a RECT structure but with RECT.left/RECT.top for the coords and RECT.right should be RECT.left+width(100) and RECT.bottom should be RECT.top+height(100).
I do all my drawing and such on the full sized hidden buffer dibh1.  I copy it to the screen when needed.  There are no changes to the client area that I am not in control of.  At anytime I need to restore the client area, I can just copy the affected portion from the hidden buffer.  That's the whole purpose.
For the 100*100 cursor buffer, it just a temporary scratch dib to create a blend of the cursor with the background.  I could use a RECT to store coordinates, but since the api didn't call for it, I saw no reason to create the extra complexity.  Perhaps my attempt to make a small test program was confusing.
Quote
second, when you restore you MUST use the COORDS and SIZE of your backup (it means you must store/use them), coz in your example you restore the entire client area (minored by your position coords)... and of course, in a normal use the coords change, so here you can't restore them in a normal use of the function.
Now this is confusing.  What do you mean?  I'm only restoring a 100*100 area that I put the cursor in, not the whole screen.  I'm restoring it from the hidden back buffer, but only the portion needed.
Quote
i understand better why it took you some time to obtain a good result, if you would have defined a RECT structure for the client area (the limits), AND a RECT structure for the cursor/background (your work) you would have completed your work considerably faster.
Clearly I'm not understanding your point.  How could storing the values in a RECT structure make any difference.  They are just coordinates and sizes.  I prefer using using a name that is what is says, the width or height, which is what the api wants, rather than .right and .bottom which is definitely not what the api is asking for.  I only used a RECT at all because that's what GetClientRect required.  I really think all this confusion is because the documentation for SetDIBitsToDevice is so ambiguous, just like I was trying to say above.  I still don't know what they had in mine with all these parameters compared to a simple bitblt, but it certainly is confusing.

dwWidth  Specifies the width, in logical units, of the DIB.   Is this really the width of the dib, or just the number of pixels you want to transfer?

dwHeight Specifies the height, in logical units, of the DIB. Same here.

XSrc  Specifies the x-coordinate, in logical units, of the lower-left corner of the DIB.  This is always zero, unless it means the first pixel across the width to use, in which case, it is very poorly written.

YSrc  Specifies the y-coordinate, in logical units, of the lower-left corner of the DIB.  Why the lower left?

uStartScan  Specifies the starting scan line in the DIB.  Why would you need that?  I just told you the answer in YSrc.

cScanLines  Specifies the number of DIB scan lines contained in the array pointed to by the lpvBits parameter.   Why ask me this?  It that really what it wants?


I've seen some really badly designed and documented apis, but this is near the top of the list.


The bottom line is, it's the only tool available for the job (disregarding directx, etc.), and I'm going to figure out what these parameters really are and how to use them.
Title: Re: Graphics
Post by: NightWare on April 19, 2009, 01:48:44 AM
ok, i'm going to change your test code, for a normal use of the function, i will post it tomorrow  :wink
Title: Re: Graphics
Post by: NightWare on April 20, 2009, 02:25:49 AM
 :wink as promised, the code

in the code, SetDIBitsToDevice is only used once (for the win update), all the others you have included before were totally useless (coz you can't make a copy of the background with this function, it's in the sens Dib To Dc), and that confused me a lot... i've spent an afternoon to understand the logic behind everything... MWAAAAARGGGGG !!!! (i know, it's noisy, but i feel better now... :bg)

i haven't modified the alpha part, (spent enough time... i've just used a hack to simulate an alpha) so you will have to re-work it a bit...

EDIT : oops i've just seen i've forgotten to correct the paths, updated

[attachment deleted by admin]
Title: Re: Graphics
Post by: Jimg on April 20, 2009, 01:37:49 PM
Okay, you are copying every pixel every time.  Certainly I could have done that, but I wanted to update only the portion of the screen that was affected, not the whole screen.

You could see I already knew how to update the whole screen.

The point of my tirade, was that I wanted to know how to update just a portion of the screen as needed, and to do so it was difficult to figure out what the parameters should be.


I just did a time test, and with the 1248*718 area i'm using, it takes over 20000 cycles to update the whole screen but less than 700 to update a 100 x 100 square twice.
Title: Re: Graphics
Post by: NightWare on April 21, 2009, 02:42:36 AM
hmm... it seams it's complicate when you just include a portion, the problem comme from the height when you don't start at the 0 y coord. coz the DC is vertically reversed. this seams to work for the restore part :

mov edx,ClientArea.bottom
sub edx,BackUpPos.y
sub edx,BackUpSizes.y
    inv SetDIBitsToDevice,hDC,BackUpPos.x,BackUpPos.y,BackUpSizes.x,BackUpSizes.y,BackUpPos.x,edx,0,ClientArea.bottom,DibClient.pBits,ADDR DibClient.sBIH,DIB_RGB_COLORS


Title: Re: Graphics
Post by: Farabi on April 21, 2009, 06:53:33 AM
Hai,
Im using Nighware Blending function and Donkey Graphics Library.
Cool is not it?  :green

(http://omploader.org/vMWswaA/test.JPG)

Im uploading it to my FaceBook account as a video and I want to upload it to youtube but got no time. I created that video to impress my friend, and they are really impressed  :lol .
Title: Re: Graphics
Post by: UtillMasm on April 21, 2009, 09:37:43 AM
where's your video? :bg
Title: Re: Graphics
Post by: Farabi on April 21, 2009, 11:50:02 AM
It should be here soon http://www.youtube.com/watch?v=gcdpkwgN7hw I hope youtube able to process it.
Dont listen to the audio or translate it, it just me braging how smart I am  :green .
I forget to say thank you to donkey and nightware for their kindness and hardwork.

This is where facebook store it but I dont know can it be opened. http://www.facebook.com/v/1094820170800
And this video is about my face recognition test http://www.facebook.com/v/1095210940569
Title: Re: Graphics
Post by: Jimg on April 21, 2009, 04:49:26 PM
Quote from: NightWare on April 21, 2009, 02:42:36 AM
hmm... it seams it's complicate when you just include a portion, the problem comme from the height when you don't start at the 0 y coord. coz the DC is vertically reversed. this seams to work for the restore part :

mov edx,ClientArea.bottom
sub edx,BackUpPos.y
sub edx,BackUpSizes.y
    inv SetDIBitsToDevice,hDC,BackUpPos.x,BackUpPos.y,BackUpSizes.x,BackUpSizes.y,BackUpPos.x,edx,0,ClientArea.bottom,DibClient.pBits,ADDR DibClient.sBIH,DIB_RGB_COLORS


A slightly simpler method:
    mov ecx,y     ; starting scan line wanted
    add ecx,sizey ; number of scan lines from top to last line wanted
    inv SetDIBitsToDevice,hdc,x,y,sizex,sizey,x,y,y,ecx,dibbits,addr dibbih,DIB_RGB_COLORS
Title: Re: Graphics
Post by: NightWare on April 21, 2009, 10:07:40 PM
Quote from: Jimg on April 21, 2009, 04:49:26 PM
A slightly simpler method:
mov ecx,y ; starting scan line wanted
add ecx,sizey ; number of scan lines from top to last line wanted
inv SetDIBitsToDevice,hdc,x,y,sizex,sizey,x,y,y,ecx,dibbits,addr dibbih,DIB_RGB_COLORS

well seen jimg  :U

in fact the documentation of windows is correct, coz in "normal" use the first line is the last one (the -1/neg possibillity for the height is just an option, for a more readable/logical representation...). the problem is there is no warning about the possible use of the option.