Jump to content
  • Advertisement
Sign in to follow this  
becoolnike

How to load a pcx texture?

This topic is 4094 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

Advertisement
i already know how to handle the pcx format. but my question is how to load a texture file format that is not supported. any way to lock a texture with direct3d ?

Share this post


Link to post
Share on other sites
Yes, you can create an empty texture (IDirect3DDevice9::CreateTexture) and then lock it and write data into it.

Depending on the reason to load a pcx file, I'd suggest one of two things:

If your reason is that you want wide support for user supplied formats, I'd suggest using a generic image loading library, and locking and writing into textures.

If your reason is that you happen to have pcx files which you want to load, and your applications will come with them, simply use an image conversion program (such as Irfanview) to convert into a format that's supported.

Share this post


Link to post
Share on other sites
Some code from my texture class (Ancient, may or may not work):

#pragma pack(push, 1)
struct PCXHeader
{
unsigned char byManufacturer;
unsigned char byVersion;
unsigned char byEncoding;
unsigned char byBPP;
unsigned short xMin;
unsigned short yMin;
unsigned short xMax;
unsigned short yMax;
unsigned short xDPI;
unsigned short yDPI;
unsigned char byPalette[48];
unsigned char byReserved;
unsigned char byPlanes;
unsigned short nBytesPerLine;
unsigned short nPaletteType;
unsigned short nScreenX;
unsigned short nScreenY;
unsigned char byFiller[54];
};
#pragma pack(pop)

bool CTexture::AttemptManualLoad(const void* pData, size_t dwLen)
{
// Is it PCX?
if(dwLen < 128+768+1) // 128 byte header, 768 byte palette, 1 byte palette ID
{
// Nope. That's all we know
return false;
}

// Check if PCX header is valid
// Validate manufacturer, reserved byte and estimate scanline len
const PCXHeader* pHeader = (const PCXHeader*)pData;
if((pHeader->byManufacturer != 10) || (pHeader->byReserved != 0))
return false;
else if(pHeader->nBytesPerLine < pHeader->byBPP/8 * (pHeader->xMax-pHeader->xMin + 1))
return false;
else if(pHeader->byVersion != 5) // Version 5 means a palette
{
CLog::DebugFormat("CTexture::AttemptManualLoad(): File might be a PCX file, but has no palette\n");
return false;
}
else if(pHeader->byEncoding != 1)
{
CLog::DebugFormat("CTexture::AttemptManualLoad(): File might be a PCX file, but has unknown encoding\n");
return false;
}
else if(pHeader->byBPP > 32)
{
CLog::DebugFormat("CTexture::AttemptManualLoad(): File might be a PCX file, but has invalid BPP\n");
return false;
}
else if(pHeader->byPlanes != 1)
{
CLog::DebugFormat("CTexture::AttemptManualLoad(): Only supports PCX files with 1 colour plane\n");
return false;
}

// Check palette ID
const BYTE* pbyPalette = (const BYTE*)pData + dwLen - 769;
if(*pbyPalette++ != 12)
{
CLog::DebugFormat("CTexture::AttemptManualLoad(): Invalid palette ID\n");
return false;
}

// Lets assume it's a PCX then. Determine image size, and allocate data
DWORD dwWidth = pHeader->xMax-pHeader->xMin + 1;
DWORD dwHeight = pHeader->yMax-pHeader->yMin + 1;
BYTE* pbyImage = NEW BYTE[pHeader->nBytesPerLine*dwHeight];
if(!pbyImage)
{
CLog::ErrorFormat("Out of Memory!\n");
return false;
}
const BYTE* pbyData = (const BYTE*)pData + sizeof(PCXHeader);
PALETTEENTRY* pPalette = NEW PALETTEENTRY[256];
if(!pPalette)
{
delete[] pbyImage;
CLog::ErrorFormat("Out of Memory!\n");
return false;
}

// Extract palette
for(int i=0; i<256; ++i)
{
pPalette.peRed = *pbyPalette++;
pPalette.peGreen = *pbyPalette++;
pPalette.peBlue = *pbyPalette++;
pPalette.peFlags = 0;
}

// Decompress scanlines
for(DWORD y=0; y<dwHeight; ++y)
{
DWORD xOfs = 0;
int nRemain = pHeader->nBytesPerLine;
do {
int nCount;
if(((*pbyData) & 0xc0) == 0xc0)
nCount = (*pbyData++) & 0x3F;
else
nCount = 1;

if(nCount > nRemain)
break;
for(int x=0; x<nCount; ++x)
{
pbyImage[pHeader->nBytesPerLine*y + xOfs] = *pbyData;
++xOfs;
}
pbyData++;
nRemain -= nCount;
} while(nRemain > 0);
}

// Create texture
if(!Create(dwWidth, dwHeight, 1))
{
delete[] pPalette;
delete[] pbyImage;
return false;
}

// Get the top level surface
LPDIRECT3DSURFACE9 pSurface;
HRESULT hResult = m_pTexture->GetSurfaceLevel(0, &pSurface);
if(FAILED(hResult) || !pSurface)
{
m_pTexture->Release();
m_pTexture = NULL;
m_dwWidth = m_dwRealWidth = 0;
m_dwHeight = m_dwRealHeight = 0;
delete[] pPalette;
delete[] pbyImage;
CLog::ErrorLog("IDirect3DTexture9::GetSurfaceLevel() failed. Error: "+GetDXError(hResult)+"\n");
return false;
}

// Load the decompressed image into it
RECT rc;
rc.left = 0;
rc.top = 0;
rc.right = dwWidth;
rc.bottom = dwHeight;
hResult = D3DXLoadSurfaceFromMemory(pSurface, NULL, NULL, pbyImage, D3DFMT_P8, pHeader->nBytesPerLine,
pPalette, &rc, D3DX_FILTER_NONE, 0xffff00ff);
pSurface->Release();
delete[] pPalette;
delete[] pbyImage;
if(FAILED(hResult))
{
CLog::ErrorLog("D3DXLoadSurfaceFromMemory() failed. Error: "+GetDXError(hResult)+"\n");
return false;
}

return true;
}

bool CTexture::Create(DWORD dwWidth, DWORD dwHeight, DWORD dwMipLevels, D3DPOOL thePool/*=D3DPOOL_MANAGED*/)
{
HRESULT hResult;

// Grab the device and texture format
LPDIRECT3DDEVICE9 pDevice = CD3DDevice::Get().GetDevice();
D3DFORMAT fmTextures = CD3DDevice::Get().GetTextureFormat();

// Create the texture surface
hResult = pDevice->CreateTexture(dwWidth, dwHeight, dwMipLevels, 0, fmTextures, thePool, &m_pTexture, NULL);
if(FAILED(hResult))
{
CLog::ErrorLog("IDirect3DDevice9::CreateTexture() failed. Error: "+GetDXError(hResult)+"\n");
return false;
}

// Save details and return success
m_dwWidth = m_dwRealWidth = dwWidth;
m_dwHeight = m_dwRealHeight = dwHeight;
return true;
}


The AttemptManualLoad() takes a pointer to the data in the file, and the length of the data. Appologies for the mess of singletons and annoying 'C' prefixes [smile]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

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

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!