Jump to content
  • Advertisement

Archived

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

webmunkey

Copying TextureBuffer to UCHAR *

This topic is 6039 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Yeah, I know this probably a dumb question, but I''m going to ask it. How can I read the pixel values of IDirect3DTexture8 struct and copy them to a unsigned char *? Thanks, -Jesse

Share this post


Link to post
Share on other sites
Advertisement
IDirect3DTexture8::LockRect

you get back a structure with a void pointer to the data and the pitch of the surface (distance in bytes between consecutive horizontal lines). cast the pointer to UCHAR and copy line by line.

Share this post


Link to post
Share on other sites
So just off the top of my head, I'd do something along the lines of:
UCHAR *surface;
D3DLOCKED_RECT gStruct;
TextureBuffer->LockRect(0, &gStruct, NULL, NULL);
memcpy(surface, (UCHAR *)gStruct.pBits, sizeof(gStruct));
TextureBuffer->UnlockRect(NULL);

Hmm, would that work? Something looks fishy...
Thanks,
-Jesse

Edited by - webmunkey on November 9, 2001 11:24:44 PM

Share this post


Link to post
Share on other sites
Not exactly. You have to use one memcpy per row, because you are not guaranteed that rows are contiguous -- thats why you get the pitch (pitch is sometimes NOT equal to width). I assume you already know the surface width, hieght, and depth.

    
UCHAR *b = new UCHAR [surfaceWidth*surfaceHieght*bytesPerPixel];
D3DLOCKED_RECT r;
surface->LockRect(r, NULL,D3DLOCK_READONLY); //should check error code

for (int y=0; y < surfaceHieght; y++)
memcpy ((void*)b,(r.pBits+r.Pitch*y),r.Pitch); //if you use memcpy it wants void *

surface->UnlockLockRect();



Edited by - invective on November 9, 2001 12:15:16 AM

Share this post


Link to post
Share on other sites
Oh, okay, I see now. Thanks,
-Jesse

How many programmers does it take to change a light bulb?
None. It''s a hardware problem.

Share this post


Link to post
Share on other sites
Ahh, wait, isn''t Pitch an int? So, wouldn''t I get an error if I tried to add the two? I could convert pBits to an int and the then cast the entire statement to const void *, but I might loose information. What do you think?
Thanks,
-Jesse

Share this post


Link to post
Share on other sites
You can always add an integer to any pointer type except pointer-to-void. Adding 1 to a pointer advances the pointer to the ''next item'' (for a byte-pointer this would mean an advancement of 1 byte; for a 32-bit-int-pointer it would mean the pointer is advanced 4 bytes; etc.).

Share this post


Link to post
Share on other sites
no, when you add to a void pointer it always adds one byte per number -- if you cast to int* then you have to divide by sizeof (int) because of the way pointer arithmatic works -- it always advances by sizeof(pointertype) bytes, or 4 for integers on win32. Pitch is specified in bytes. Its correct as written, but cast everything to char, then add, then cast it back to void if that makes it easier for you to understand.

char * pbits = (char *) r.pBits;

memcpy ((void*)b,(void*)(pbits+r.Pitch*y),r.Pitch)

pointer math example:

int *p=something;
*(p+4)=1; //same as p[4]=1

that means that the pointer is advanced by 16 bytes and then dereferenced, because each int is 4 bytes wide.

void *p=something;
p+=4; //advances p by only 4 bytes because void is always incremented one byte at a time

Share this post


Link to post
Share on other sites
Hmm, it''s not working in the game... The debuger fails when I try to exit and it is obvious the heightmap isn''t correct.
  
uchar *height_map_ptr = NULL;
// load in height map

hRet = D3DXCreateTextureFromFile(pID3DDevice, "heightd2.bmp", &HeightMap);
if (hRet != D3D_OK)
InitFail(hWnd, hRet, "Error loading bitmap!");

height_map_ptr = new UCHAR[HFIELD_WIDTH * HFIELD_HEIGHT * 24];

D3DLOCKED_RECT gSurface;
HeightMap->LockRect(0, &gSurface, NULL, D3DLOCK_READONLY);

char *pBits = (char *)gSurface.pBits;

for (int i = 0; i < HFIELD_HEIGHT; i++)
memcpy((void *)height_map_ptr, (void *)(pBits + gSurface.Pitch * i), gSurface.Pitch);

HeightMap->UnlockRect(NULL);

It compliles without error; however, inside the game the heightmap is flawed. I think that this because the heightmap is being filled with very high arbitrary number which means that something is going wrong inside of the load heightmap function. Sorry to be such a newbie, but thanks for your help so far,
-Jesse

Share this post


Link to post
Share on other sites
oops, forgot to mention you need to adjust your destination pointer too, otherwise you are copying everything over line one!
note you adjust by width of the image, not pitch of the surface.

memcpy((void *)(height_map_ptr+width*i), (void *)(pBits + gSurface.Pitch * i), gSurface.Pitch);

also, this is very large:

height_map_ptr = new UCHAR[HFIELD_WIDTH * HFIELD_HEIGHT * 24];

if you want a 24 bit image, it is 24 bits * 1/8 bytes per bit, or 3 bytes per pixel, not 24.

height_map_ptr = new UCHAR[HFIELD_WIDTH * HFIELD_HEIGHT * 3];

finally, if you have photoshop, consider converting your image to grayscale and saving as .raw. this gives you 1 byte per pixel (which is usually enough), and its just a byte dump, so you can read it like:

BYTE * pbHieghtField = new BYTE [ width * hieght ];

std::ifstream file;
file.open (filename, std::ios::binary );
file.read ( (char *)pbHieghtField, width * hieght );
file.close();

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!