Archived

This topic is now archived and is closed to further replies.

BKStoltman

Getting the Color of a pixel on a DirectDrawSurface7?

Recommended Posts

This is probably a stupid question. But how do you get the color # or RGB of a pixel on a DirectDrawSurface7 using Visual Basic? I''m not sure if it makes a difference but I am using fullscreen mode. If you have an example I would greatly appreciate it. Thanks! Either post your reply here or E-Mail me at B_Stoltman@Hotmail.com

Share this post


Link to post
Share on other sites
The bit-depth doesn''t matter. Use the surface''s GetDC function, then use the windows function GetPixel to retrieve the color. Remember to release the DC once you''re done.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
This should help you out

Method 1: Set/GetLockedPixel
The first method is relatively easy, and fairly safe to use, but unfortunately much slower. You may have noticed that when setting the colour for various things it requires a long value? These methods allow you to retrieve the long value of a certain pixel, and set it again.



Sub ProcessMemory
Dim Colour as Long
Dim rArea as RECT
Dim ddsd as DDSURFACEDESC2

rArea.Bottom=480:rArea.Right=640

MainSurf.Lock rArea,ddsd, DDLOCK_WAIT,0
''We now have access to the memory. From now until the Unlock you are treading
''on thin ice......

''These are our two commands.
Colour=Mainsurf.GetLockedPixel(100,120)
Mainsurf.SetLockedPixel(100,120,Colour+10)

MainSurf.Unlock rArea

End Sub




Method 2: GetLockedArray
This is the complicated, difficult, dangerous and faster method to use. I have lost count of the number of times I locked up my computer playing around with this method. Basically, it passes back an array which points to the surface memory itself. You can then read/write to this array and the effects will be mirrored on the surface. Sounds simple. Two points of warning though:

If you write an invalid value to the array you will not get an error; and you will be very lucky if you get back into windows without restarting your computer. Values must be whole numbers and between 0 and 255.
If you write to a value outside the array you will not get an error, and you will probably have to restart your computer. This is basically a memory leak.
Then there is another problem - the debugger will not work whilst you are processing memory. Between the Surface.Lock and Surface.Unlock methods windows ceases execution, this is because directdraw takes the win16mutex which basically suspends windows. Because windows is effectively shut down you must do NOTHING complicated or invloved with other components. ie. No DLL calls, no file access and no running of other applications. Also, dont try anything clever inside directx, you can''t blit from or to a locked surface, and some other clever operations may well fail. This leads onto another point - the code must be flawless, if there is an error in the compiled version you can say goodbye to windows.

You may have had enough of the problems already, but the final problem is probably the most annoying. The data. The array will basically show you the raw data from a bitmap, so it''s fine if you understand that, otherwise (like me) it''s extremely difficult. Each entry in the array is a byte which means 0-255 (every colour is 0-255 you may have noticed). Each entry in the array represents one channel of the colour, NOT one pixel. using the RGB(x,x,x) statement will be fatal. This is fine if you aren''t interested in the colour of the pixel directly, but it is if you try setting the colour to be specific. If you only want to deform the current image, you can do that without paying much attention to the current value - you just run a formula through it.

Getting the Red/Green/Blue colour components can be extremely difficult. 16bit is a nightmare; 8, 24 and 32bit isn''t too difficult. Hopefully you understand how computers store data; there are 8bits to a byte, 1024 bytes to a kilobyte etc... Therefore; if our array is a collection of bytes, we need to get the correct bits out of it. For 8bit it is easy - each byte (8 bits to a byte) represents the colour; because 8 bit mode is palettised this value refers to the palette entry for that pixel. 16 bit can either be in 555 or 565 mode - where they are all 5 bits (less than a byte) and there is one bit spare; or they are all 5 bits and Green is 6 bits, with no bytes to spare. 24 bits are 3 bytes, so each set of three bytes in the array are the channels for the pixel. It tends to be organised in BGR format rather than RGB... 32 bits are 4 bytes (getting the hang of this yet?), this is because 32bit colour can have an alpha channel. The bytes are organised in the format ARGB - so unless you are interested in the alpha channel you can skip every 4th byte.

Here''s the code for accessing the surface memory using arrays:

Sub ProcessMemory
''Note: This is almost identical to the previous method...
Dim Colour as Long
Dim rArea as RECT
Dim ddsd as DDSURFACEDESC2
dim Pict() as Byte ''Note, there is NO boundaries specified

rArea.Bottom=480:rArea.Right=640

MainSurf.Lock rArea,ddsd, DDLOCK_WAIT,0
''We now have access to the memory. From now until the Unlock you are treading
''on thin ice......

MainSurf.GetLockedArray Pict

''You can now manipulate the array into whatever form you wish
''But remember the rules/warnings
''The array will still point to the memory until the Unlock command. After
''this point it becomes a normal VB array...

''It all goes in the form of Pict(x,y) = ??
''Even though two dimensions aren''t specified, they can be referenced like that.
''If you''re really clever you can access it as one linear block of memory...

MainSurf.Unlock rArea

End Sub

Share this post


Link to post
Share on other sites