Sign in to follow this  

How to load a pcx texture?

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

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[i].peRed = *pbyPalette++;
pPalette[i].peGreen = *pbyPalette++;
pPalette[i].peBlue = *pbyPalette++;
pPalette[i].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

This topic is 3726 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.

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