Archived

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

bark

Loading textures into IDirect3DTexture8 without D3DX

Recommended Posts

Hello! I'm writing my own texture class which loads a bitmap and then copies the data to IDirect3DTexture8 surface. Everything seems to be fine, except that everything is blue (bluescale or something How can i get the proper colors? What I am missing? I hope someone could help me!
    

// THIS IS HOW I'M LOADING THE BITMAP DATA


	BITMAPFILEHEADER header;
        image.read((char*)&header, sizeof(header)); //read header

	BITMAPINFO info;
	image.read((char*)&info, sizeof(info)); //read info

	unsigned char * Bitmap = new unsigned char [info.bmiHeader.biSizeImage]; 
	file.seekg(header.bfOffBits); //go to start of image data

	file.read(Bitmap, info.bmiHeader.biSizeImage); //read data

	file.close(); //close file


  

      
// and this is how i'm putting it to a texture

IDirect3DSurface8 *BitmapTexture;
 Device->CreateTexture(bitmapwidth, bitmapheight, 0, 0, 
			D3DFMT_X8R8G8B8             , D3DPOOL_MANAGED, &BitmapTexture);
D3DLOCKED_RECT D3D_LR;
BitmapTexture->LockRect( 0, &D3D_LR, 0, 0 );

DWORD * Dst = (DWORD *)((char *)D3D_LR.pBits + D3D_LRR.Pitch);

	for (i = 0,j = 0; i < bitmapwidth * bitmapheight; i +=3, j++)
	{
		// BGR NOT RGB

		Dst[i] = (DWORD)Bitmap[i+2];
		Dst[i+1] = (DWORD)Bitmap[i+1];
		Dst[i+2] = (DWORD)Bitmap[i+0];
	}

	BitmapTexture->UnlockRect (0);

    
Thank you! Edited by - bark on June 29, 2001 7:00:22 PM

Share this post


Link to post
Share on other sites
Well, I havent posted in ages, but this is an easy problem, you need to store the r value (i+2) and use something like:

int temp_b = r;
r = i+2;
g = i+1;
b = temp_b;

otherwise, you change the value, and then use the changed value!

Also, you don''t need to change green, because it is in the middle of the triplet.

Share this post


Link to post
Share on other sites
uhm... in case you didn't notice it, I AM already doing so

i'm not using any changed value (or am i just blind?)


and oh btw. even if i did
   
Dst[i] = rand() % 256;
Dst[i+1] = rand() % 256;
Dst[i+2] = rand() % 256;

it just gives me bluescale!


thanks anyway!




Edited by - bark on June 29, 2001 7:13:35 PM

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Maybe it''s too late but the index for the surface has to use the surfaces pitch value in some way (not at the start - hm, this offset may be the reason for the blue...). Anyway, try the following:

for ( y = 0; y < surfHeight; y++ )
{
Dst = (BYTE*)( *)((BYTE*)D3D_LR.pBits + y * D3D_LRR.Pitch );
for ( x = 0; x < surfWidth; x++ )
{
Dst[ x ] = ...;
}
}

Hope this helps somehow,
Bjørn.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Duh, it''s far too late here

Anyway, supplement to my previous post:

Use BYTE* for Dest, else you''ll setting the lower 8 bits of a 16 bit value.

Bjørn.

Share this post


Link to post
Share on other sites
G''day!

As someone already pointed out, having Dst as a DWORD is what''s causing the blue-scale effect. You''re iterating through seperate pixelswhen you do the Dst, Dst[i+1] not altering components of an individual pixel.

Also, even though you''re requesting a D3DFMT_X8R8G8B8 texture, it''s not guaranteed that you''ll get it. You should test what''s being created.

Also, start your pointer at D3D_LR.pBits and add the pitch after you''ve processed each line (bitmap width). Pitch is the offset required to move to the beginning of the next ''line''.


Stay Casual,

Ken
Drunken Hyena

Share this post


Link to post
Share on other sites
Well, thank you!
I have now colors but now another problem appeared: I get wide black "lines" and the texture does not look correct... any idea how''s this?
i use following code (almost straight from the Bjørn''s code)

  
BYTE *Dst;
for ( y = 0; y < Bitmap.height; y++ )
{
Dst = (BYTE*)((BYTE*)DR.pBits + y * DR.Pitch );
for ( x = 0; x < Bitmap.width; x++ )
{
Dst[ x ] = Bitmap.data[x];;
}

}


btw. why it''s
Dst = (BYTE*)( *)((BYTE*)D3D_LR.pBits + y * D3D_LRR.Pitch );
?
that (*) gives me compile error.

anyway, thanks again for all answers and i hope someone could answer to this also

Share this post


Link to post
Share on other sites
Hi,

okay, the additonal ( *) was a typo =)

The inner loop should look like this (in case it's a D3DFMT_X8R8G8B8 surface):
  
for ( y = 0; y < Bitmap.height; y++ )
{
Dst = (BYTE*)((BYTE*)DR.pBits + y * DR.Pitch );
i = 0;
for ( x = 0; x < 3*Bitmap.width; x += 3 )
{
// Set RGB

Dst[i+0] = Bitmap[x+0];
Dst[i+1] = Bitmap[x+1];
Dst[i+2] = Bitmap[x+2];
// Skip the X8 part

i += 4;
}
}

the 3 in 3*Bitmap.width is used in assumption that the bitmap data is stored in RGB order (without padding).

IIRC, it's possible, that the data has a padding byte - it's stored in the header. It's also possible that the btmap is stored upside down. If you have the DX7 sdk at hand, take a look at the d3dframe lib (esp. \samples\multimedia\d3dim\src\d3dframe\d3dtextr.cpp).

Hope this help,
Bjørn.

Edited by - Boki on June 30, 2001 3:19:43 PM

Share this post


Link to post
Share on other sites
Here''s a routine for doing it:

HRESULT CTexture::Load(TCHAR *szFile)
{

UCHAR * bmp;
int i, j;
HRESULT hr;

LoadBitmap(&bmp, szFile);

hr = g_pd3dDevice->CreateTexture(m_biWidth, m_biHeight, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &m_pTex);

if (FAILED(hr))
return E_FAIL;

D3DLOCKED_RECT lr;

hr = m_pTex->LockRect(0, &lr, NULL, 0);
if (FAILED(hr))
return E_FAIL;

int iBmpOffset = 0, iTexOffset = 0;

// Points to lower left corner of rect.
UCHAR* pRect = (UCHAR*) lr.pBits;

// 24-bit bmp file: Rows contain 3 bytes per pixel but total
// bytes per row is a multiple of 4 with padding at the end if
// necessary.

int iBmpBytesPerRow = (m_biWidth * 3) + (m_biWidth % 4);

for (i = 0; i < m_biHeight; i++)
{

iBmpOffset = (i * iBmpBytesPerRow);

for (j = 0; j < m_biWidth; j++) {

// Blue
pRect[iTexOffset + 4*j + 0] = bmp[iBmpOffset + 0];
// Green
pRect[iTexOffset + 4*j + 1] = bmp[iBmpOffset + 1];
// Red
pRect[iTexOffset + 4*j + 2] = bmp[iBmpOffset + 2];
// Alpha
pRect[iTexOffset + 4*j + 3] = 0xFF;

iBmpOffset += 3;

}

iTexOffset += lr.Pitch;

}

hr = m_pTex->UnlockRect(0);
if (FAILED(hr))
return E_FAIL;

free(bmp);

return S_OK;

}

Share this post


Link to post
Share on other sites
Ah yes, thanks again, Bjørn. There isn''t wide black lines anymore, but one error still remains: the texture doesn''t look right! actually it just look like colored lines. I didn''t have this problem in my first method (scroll to the very beginning of the page): the texture looked ok but it just was bluescale... so any idea what could be causing this? i only see colored lines and the colors are actually not even the same colors! This is strange (check picture: here!)


i''m sorry, i''m just plain stupid with all these loader things

Share this post


Link to post
Share on other sites