Sign in to follow this  
sofakng

What is the formula for reading a pixel? (eg. using pitch and format?)

Recommended Posts

Let's say I have a D3DLOCKED_RECT record and I want to read a single pixel. What is the formula? The D3DLOCKED_RECT contains a Pitch variable and a pointer to a pixel structure. I'm pretty sure I need to multiply the (x, y) by the pitch but I'm not sure. I'm using Delphi, so any generic formula would be very helpful (as opposed to a C++ pointer-math formula). Also, if my back-buffer format is XRGB, then is it stored the opposite way in memory? (eg. BGRX) Thanks for your help!

Share this post


Link to post
Share on other sites

function GetPixel(X, Y: Integer): TD3DColor;

var
Scanline: PD3DColor;

begin
Integer(Scanline) := Integer(LockedRect.pBits) + Y*LockedRect.Pitch+X*4;
Result := Scanline^ or $FF000000; // forces alpha = 255
end;

procedure SetPixel(Color: TD3DColor; X, Y: Integer);

var
Scanline: PD3DColor;

begin
Integer(Scanline) := Integer(LockedRect.pBits) + Y*LockedRect.Pitch+X*4;
Scanline^ := Color;
end;


LockedRect.Pitch is usually larger than surface_with*SizeOf(TD3DColor)

Share this post


Link to post
Share on other sites
Woah, thanks for the perfect answer!!!

If I understand correctly, surfaces (and textures) must be a power of 2 (or is it multiple of 2?) so is that why pitch doesn't always equal pixel_format * width?

If I use a power of 2 (eg. 512) and I'm using X8R8G8B8 (32 bit pixels), then would the pitch be 32 * 512 = 16384 or is there something I'm missing? (what would happen if the surface is only 500 pixels wide?)

EDIT: Why do you force alpha to 255? Wouldn't it be more useful to see the real value?

[Edited by - sofakng on August 14, 2007 5:39:45 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by sofakng
Woah, thanks for the perfect answer!!!

If I understand correctly, surfaces (and textures) must be a power of 2 (or is it multiple of 2?) so is that why pitch doesn't always equal pixel_format * width?

If I use a power of 2 (eg. 512) and I'm using X8R8G8B8 (32 bit pixels), then would the pitch be 32 * 512 = 16384 or is there something I'm missing? (what would happen if the surface is only 500 pixels wide?)

EDIT: Why do you force alpha to 255? Wouldn't it be more useful to see the real value?


Surfaces doesn't need to have dimensions in power of 2:s. But if you want to create a full mip-map chain you need to have that. I think power of 2 surfaces are a bit more effective too. You are wrong about your guesses about pitch, most often pitch and width of a surface is exactly the same. I don't get what you mean by your last sentence, you don't have to force alpha into 255?

Share this post


Link to post
Share on other sites
Quote:
Original post by sofakng
If I understand correctly, surfaces (and textures) must be a power of 2 (or is it multiple of 2?) so is that why pitch doesn't always equal pixel_format * width?

Pitch is the number of bytes per scanline, and is not necessarily equal to width * pixelformat_bytes. Direct3D may add padding pixels to each scanline. The formula for accessing each pixel is:

address = (pitch * y) + x * pixelformat_bytes.



Quote:
Original post by sofakng
EDIT: Why do you force alpha to 255? Wouldn't it be more useful to see the real value?

Since you are using X8R8G8B8, the pixel's alpha can be any arbitrary value.

Share this post


Link to post
Share on other sites
Lifepower is right. As he said in X8R8G8B8 the alpha can be any value, in my case I prefer setting it to 255 (fully opaque) so it doesn't affect any future operations. If you are sure it doesn't matter, just remove the OR'ing, or you might want it to be a given fixed value with this:


Result := (Scanline^ and $00FFFFFF) or $xx000000; // forces alpha = $xx (replace "xx" by two digit hex number)

Share this post


Link to post
Share on other sites
Ahhh, OK. I see what you're saying.

I'm having another strange problem though.

Every _other_ click I get real data or all zeros.

For example,

The first call to GetPixel(0, 0) shows me ARGB(0, 100, 200, 50) but the second click to GetPixel(0, 0) shows me ARGB(0, 0, 0, 0) and then the third call goes back to (0, 100, 200, 50), and the forth call goes to (0, 0, 0, 0).

It's alternating between the real values and all zeros.

I'm getting the backbuffer like this:

res := Devices[0].Dev9.GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, Surface);

(inside my OnClick on my Delphi form event)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this