News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

SetDIBits example

Started by zemtex, December 13, 2011, 10:26:07 AM

Previous topic - Next topic

zemtex

Hi.

I have tried using SetDIBits but it doesn't work as expected. I didn't give much effort trying to make it work but I read somewhere it has a bug. Does anyone have a working example, GDI and GDI+ set/get pixel functions are too slow, I need to use SetDIBits for plotting pixels manually.

Preferably an example where you create a DIB color array and then plot a few pixels, then use SetDIBits to plot it to a bitmap and then to screen.

I could use GDI+ lockbits, but unfortunately I am working on a hBitmap not a GpBitmap they are not compatible.
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

donkey

Hi zemtex,

Can't say as I have ever used SetDIBits but as a suggestion if you are using a DIB anyway why not convert it to 32bpp and write directly to the DIB's memory. That is the approach I used in graphics.lib, its much faster than the two tiered approach of writing to memory then copying to a different location (GetObject will give a pointer to the DIB btis). Ofcourse I don't know if your particular application can use this method but it did work well for me. You would (possibly) need the ConvertToDIB32 and SetDIBPixel functions modified to suit your needs but they are fairly straightforward functions and should be easy to adapt to whatever you require. As usual, they are free to use and modify for any purpose whatever (including commercial software) with or without acknowledgement.

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

qWord

Quote from: zemtex on December 13, 2011, 10:26:07 AM
I could use GDI+ lockbits, but unfortunately I am working on a hBitmap not a GpBitmap they are not compatible.
For DIBs you can use: invoke GdipCreateBitmapFromHBITMAP,hBitmap,0,ADDR image
FPU in a trice: SmplMath
It's that simple!

MichaelW

I posted an example here that uses a DIB as a drawing surface for a fast set-pixel routine, and SetDIBits to copy the bitmap bits from the DIB to a DDB for display.
eschew obfuscation

zemtex

#4
These pixel routines are extremely fast  :U

I made my own routine, I didn't copy yours it was only after that I noticed mine had one less instruction, if it matters, you can copy mine if you want. Register dependencies goes in the toilet

OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
align 4
PlotPixel PROC x:DWORD, y:DWORD, farge:DWORD
   mov eax, [esp+8]    
   mov ecx, 1920
   mul ecx         
   mov edx, bitdataptr
   mov ecx, [esp+4]    
   add eax, ecx
   mov ecx, [esp+12]
   mov [edx+eax*4], ecx
   ret 12
PlotPixel ENDP
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef

Here is another routine for plotting pixels by using registers for coordinates and stack for color. set ecx to x value and eax to y value, and push color on stack.
Like this:

   mov ecx, 1024-1
   mov eax, 768-1
   INVOKE PlotPixelR, 0FF00FF00h
-----------------------------------------------------------------------
; ecx = x   eax = y
OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE
align 4
PlotPixelR PROC color:DWORD
   mov edx, 1920
   mul edx
   add eax, ecx
   mov edx, bitdataptr
   mov ecx, [esp+4]
   mov [edx+eax*4], ecx
   ret 4
PlotPixelR ENDP
OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef


I made a quick macro for clearing the screen, avvoiding function calls.

ClrDib MACRO BitDataPtr:REQ, Farge:REQ, FreeReg:REQ
   mov FreeReg, edi
   mov ecx, 1920*1200
   mov eax, Farge
   mov edi, BitDataPtr
   rep stosd
   mov edi, FreeReg
ENDM
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

zemtex

Btw, I experience a bit of a flicker from time to time. I never get flickering usually when dealing with memDC and ScreenDC using DDB's. But when I use a DIB section I experience flicker from time to time. Is this structure "OK" ?



It is very rare I might add. I think I know what the problem is, I added some test drawing code in a WM_TIMER just for a quick look at the results, the timer might be overlapping WM_PAINT, I added a critical section and it seems to be solved. The code is not supposed to be in a WM_TIMER but it was just for testing purposes.
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

zemtex

Here is an example of pixel throughput using the register variant of PlotPixelR. 100,000 pixels on WM_MOUSEMOVE, remember to move your mouse very slowly as the resolution of your mouse is much higher than the potential framerate.
I forgot to modify the 1920 constant, so you have to change that to your own screen resolution hehe. Search and replace, lol.

If your resolution is not 1920x1200 don't run the program.  :toothy
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

jj2007

It could be accelerated a little bit  :wink

(Hint: it's not MasmBasic that speeds it up - but Antariy could tell you where to search...)

Intel(R) Celeron(R) M CPU        420  @ 1.60GHz (SSE3)
145775  cycles for Masm32
69828   cycles for MasmBasic

145032  cycles for Masm32
69398   cycles for MasmBasic

MichaelW

Quote from: zemtex on December 14, 2011, 11:09:20 AM
Btw, I experience a bit of a flicker from time to time. I never get flickering usually when dealing with memDC and ScreenDC using DDB's. But when I use a DIB section I experience flicker from time to time. Is this structure "OK" ?

My DIB code has no flicker that I can see. For it the DIB consists of a BITMAPINFO structure and a buffer for the DIB bits, both in allocated memory. The DIB is not selected into anything and there is no BitBlt operation. For each frame FastSetPixel is used to update the DIB bits and then SetDIBits is used to copy them to the DDB, then an InvalidateRect and the WM_PAINT handler does the rest.
eschew obfuscation

zemtex

jjl2007, I am sure there is a whole lot of things that can be optimized in there, but do tell because I need to learn this.

MichaelW, the flicker is totally gone, It was because I put the code in a WM_TIMER during a quick test I did, once I removed it the flicker was gone.  :U
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

jj2007

Quote from: zemtex on December 15, 2011, 06:35:57 AM
jjl2007, I am sure there is a whole lot of things that can be optimized in there, but do tell because I need to learn this.

Ok, the point is that MasmBasic's Rand() is about twice as fast as nrandom. If you use none of them, your code will be a factor 14 faster than the original - it's the random generator that is slow... :bg

zemtex

#11
That's ok, it is only temporary. I have created another putpixel routine which uses registers only. I fixed a few tearing problems that occurs when there are excessive WM_PAINT messages in the middle of pixel computations. I put computations in a separate thread and added a critical section to synchronize between them. Screen resolution can now be set in the constant field. No longer need to use mouse movement to update screen. If you have a faster random routine, I can implement it if you have the code somewhere. I have the mersenne twister algorithm here somewhere too.

I measure it to 100 million pixels in 218 ms without using random function (clean mode). 458 pixels per microsecond. With that speed I can fill 43 screens of 1920x1200 in the same amount of time. I can fill exactly 200 full screens at 1920x1200 in a second by plotting pixels clean. It is more than acceptable, in most situations you would never do that anyway. But the main problem is not frame rate, the main problem is the remaining time and processing power left over for other functions. There should be a maximum cpu idle time leftover for other functions, that is why faster is always better of course.
I have been puzzling with lego bricks all my life. I know how to do this. When Peter, at age 6 is competing with me, I find it extremely neccessary to show him that I can puzzle bricks better than him, because he is so damn talented that all that is called rational has gone haywire.

Farabi

I dont know but OpenGL and DX7 is faster on this pixel function, but OpenGL copy pixel is very slow. I never know that copying from VRAM is slower on Windows, On syslinux it was fast, you can use it directly using the pointer provided by VESA or using Hardware Port.
Those who had universe knowledges can control the world by a micro processor.
http://www.wix.com/farabio/firstpage

"Etos siperi elegi"