Reading pixel data from a texture

Started by
16 comments, last by craziecoder 15 years, 10 months ago
Thank you for all the help. I think there may be one major problem with the way I am reading the colors. Shouldn't I be reading it with the alpha being index + 3? So it should really look like

float alpha = (float)pColor[index + 3] / 255.0f;
float red = (float)pColor[index + 2] / 255.0f;
float green = (float)pColor[index + 1] / 255.0f;
float blue = (float)pColor[index] / 255.0f;
Advertisement
This is how am creating texture.

HRESULT hr = D3DXCreateTextureFromFileEx( GetDevice(), fileName, D3DX_DEFAULT, D3DX_DEFAULT, 1, 0,D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, D3DX_FILTER_NONE, D3DX_FILTER_NONE, D3DCOLOR_COLORVALUE( 0.0f, 0.0f, 0.0f, 1.0f ),
NULL, NULL, &m_texture );


This is my code for reading pixel data,
DWORD GetPixelColour( DWORD x, DWORD y )
{
D3DLOCKED_RECT rect;
HRESULT result = m_texture->LockRect(0, &rect, NULL, D3DLOCK_READONLY );
if( FAILED( result ))
OutputDebugString( "\nFailed to lock the texture...." );

const DWORD* pBits = (const DWORD*)rect.pBits;

DWORD pixData = pBits[y*rect.Pitch + x];
m_texture->UnlockRect(0);
return pixData;
}

This is the code to read pixel data ( as given above )

int iAlpha = (hex >> 24) & 0xFF;
int iRed = (hex >> 16) & 0xFF;
int iGreen = (hex >> 8) & 0xFF;
int iBlue = (hex >> 0) & 0xFF;

Even now am not getting proper values. Is there anything wrong? I have 3 textures. One Blue, one Red & one Green with 100% transparency in the center. I never get expected values.
Usually you want to make sure you shift your pitch by >>2 if you are dealing with D3DFMTA8R8G8B8.

Example:
DWORD pbits = (DWORD*)rect.pbits;
int shift = rect.pitch>>2;

Then you can just do this for the pixel color.
DWORD getPixel(int x,int y)
{
return pbits[y*shift+x];
}

//Remember that will return to you the RGBA pack into the DWORD you will need to do some shifting to extract it into component.

Example:
DWORD color = getPixel(0,0);
int alpha = ((color&0xff000000)>>24)
int red = ((color&0x00ff0000)>>16);
int green = ((color&0x0000ff00)>>8);
int blue = (color&0x000000ff);


//That is exactly how i do it in my engine, and it works like an charm.
Hi,
Thanx a ton.
after doing
rect.Pitch = rect.Pitch>>2;

It really works like a charm. Thanx a lot.
Quote:Original post by LeonPost
Thank you for all the help. I think there may be one major problem with the way I am reading the colors. Shouldn't I be reading it with the alpha being index + 3? So it should really look like

float alpha = (float)pColor[index + 3] / 255.0f;
float red = (float)pColor[index + 2] / 255.0f;
float green = (float)pColor[index + 1] / 255.0f;
float blue = (float)pColor[index] / 255.0f;
Nope, your texture data is D3DFMT_A8R8G8B8. So the pixels are laid out in ARGB order. The first byte you come to (at pColor[index + 0]) will be the alpha, the next will be red, the next green, and the next blue.

Quote:Original post by craziecoder
Even now am not getting proper values. Is there anything wrong? I have 3 textures. One Blue, one Red & one Green with 100% transparency in the center. I never get expected values.
What size is your source image? Is it a power of two? And what values are you getting? Also, I'd be inclined to add a return 0; if LockRect() fails. Spewing a debug message is fine, but it won't help you if it hangs on a machine where you're not monitoring debug output (Any end user).

Quote:Original post by BornToCode
Usually you want to make sure you shift your pitch by >>2 if you are dealing with D3DFMTA8R8G8B8.
That's incorrect. The pitch is the distance in bytes between scanlines, if you divide it by two, then in the best case you're only skipping half a scanline, and in the worst case you're going to be reading or writing into driver-reserved memory and crash the app.
Evil Steeve you are incorrect. I have being doing it like that for a long time and never ran into any issues. That is how it was done in DirectDraw and that is how it is done here.Also i use the same technique to create mask for my images and i never ran into any issues.
Quote:Original post by BornToCode
Evil Steeve you are incorrect. I have being doing it like that for a long time and never ran into any issues. That is how it was done in DirectDraw and that is how it is done here.Also i use the same technique to create mask for my images and i never ran into any issues.
Ah, I see - the pBits pointer is being used as a DWORD* which is 4 bytes wide. Technically, it's preferable to use a BYTE* to offset by y*pitch, then cast to a DWORD, since Pitch might not be a multiple of 4 (Although it's extremely unlikely).
My textures are non power of 2 textures. I get proper ARGB values as I set them in photoshop. Till now my application has never crashed. But I will surely add code for error detection as per Evil Steve`s suggestion.

This topic is closed to new replies.

Advertisement