//********************************************
// Texture.cpp
//********************************************
// class CTexture
//********************************************
//
[email protected]
// Created : 17/12/97
// Modified : 19/12/97
//********************************************
#include "stdafx.h"
#include "math.h"
#include "Texture.h"
//////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////
//********************************************
// Constructor
//********************************************
CTexture::CTexture()
{
m_pData = NULL;
m_Width = 0;
m_WidthByte32 = 0;
m_Height = 0;
m_Depth = 0;
m_FileName = _T("");
}
//********************************************
// Destructor
//********************************************
CTexture::~CTexture()
{
Free();
}
//////////////////////////////////////////////
// DATAS
//////////////////////////////////////////////
//********************************************
// Alloc
//********************************************
int CTexture::Alloc(unsigned int width,
unsigned int height,
unsigned int depth)
{
Free();
unsigned int BytePerPixel = (unsigned int)(depth / 8);
unsigned int Width32 = WidthByte32(width,depth);
// Only rgb and rgba modes
ASSERT(BytePerPixel == 3 ||
BytePerPixel == 4);
m_pData = new unsigned char [Width32 * height];
if(m_pData == NULL)
{
TRACE("CTexture::Alloc : Insuffisant memory\n");
AfxMessageBox("CTexture::Alloc : Insufisant memory");
return 0;
}
// Set members variables
m_Width = width;
m_WidthByte32 = Width32;
m_Height = height;
m_Depth = depth;
UpdateHeader();
return 1;
}
//********************************************
// Free
//********************************************
void CTexture::Free()
{
if(m_pData != NULL)
{
delete [] m_pData;
m_pData = NULL;
}
m_Width = 0;
m_Height = 0;
m_Depth = 0;
}
//////////////////////////////////////////////
//////////////////////////////////////////////
// FILE READING
//////////////////////////////////////////////
//////////////////////////////////////////////
//********************************************
// ReadFile
// Redirection
//********************************************
int CTexture::ReadFile(char *filename,
unsigned int width,
unsigned int height,
unsigned int depth)
{
// Cleanup
Free();
// Storage
m_FileName = filename;
// Extension
CString string = filename;
string.MakeLower();
TRACE("CTexture::ReadFile : file : %s\n",filename);
CString extension = string.Right(4);
// Redirection BMP
if(extension == ".bmp")
return ReadFileBMP(filename);
// Redirection RAW
if(extension == ".raw")
return ReadFileRAW(filename,width,height,depth);
// Unrecognized file format
CString message;
message.Format("CTexture::ReadFile : invalid file redirection : %s\n",filename);
AfxMessageBox(string);
return 0;
}
//********************************************
// ReadFileBMP (*.bmp)
//********************************************
// Read windows bmp files
// Accept only 24 bits
// Size : 2^n x 2^m
//********************************************
int CTexture::ReadFileBMP(char *filename)
{
// Check for valid bmp file
CFile file;
CFileException ex;
// Try to open file
if(!file.Open(filename, CFile::modeRead | CFile::typeBinary,&ex))
{
#ifdef _DEBUG
afxDump << "File could not be opened " << ex.m_cause << "\n";
#endif
AfxMessageBox("Unable to open file for reading");
return 0;
}
// File header
BITMAPFILEHEADER FileHeader;
TRY
{
file.Read(&FileHeader,sizeof(BITMAPFILEHEADER));
}
CATCH(CFileException, e)
{
#ifdef _DEBUG
afxDump << "Error during reading " << e->m_cause << "\n";
#endif
AfxMessageBox("Error during reading file header");
file.Close();
return 0;
}
END_CATCH
TRACE("FileHeader.bfType : %d\n",FileHeader.bfType);
TRACE("FileHeader.bfSize : %d\n",FileHeader.bfSize);
TRACE("FileHeader.bfReserved1 : %d\n",FileHeader.bfReserved1);
TRACE("FileHeader.bfReserved2 : %d\n",FileHeader.bfReserved2);
TRACE("FileHeader.bfOffBits : %d\n",FileHeader.bfOffBits);
// Is it a Windows BMP file ? (BM)
WORD sign = ((WORD) ('M' << 8) | 'B');
if(FileHeader.bfType != sign)
{
AfxMessageBox("Invalid BMP file");
file.Close();
return 0;
}
// Image header
TRY
{
file.Read(&m_Header,sizeof(BITMAPINFOHEADER));
}
CATCH(CFileException, e)
{
#ifdef _DEBUG
afxDump << "Error during reading " << e->m_cause << "\n";
#endif
AfxMessageBox("Error during reading image header");
file.Close();
return 0;
}
END_CATCH
// DEBUG
TRACE("\n");
TRACE("**** IMAGE HEADER :\n");
TRACE("**** biSize : %d\n",m_Header.biSize);
TRACE("**** biWidth : %d\n",m_Header.biWidth);
TRACE("**** biHeight : %d\n",m_Header.biHeight);
TRACE("**** biPlanes : %d\n",m_Header.biPlanes);
TRACE("**** biBitCount : %d\n",m_Header.biBitCount);
TRACE("**** biCompression : %d\n",m_Header.biCompression);
TRACE("**** biSizeImage : %d\n",m_Header.biSizeImage);
TRACE("**** biXPelsPerMeter : %d\n",m_Header.biXPelsPerMeter);
TRACE("**** biYPelsPerMeter : %d\n",m_Header.biYPelsPerMeter);
TRACE("**** biClrUsed : %d\n",m_Header.biClrUsed);
TRACE("**** biClrImportant : %d\n",m_Header.biClrImportant);
// 24 bits ?
if(m_Header.biPlanes != 1 ||
m_Header.biBitCount != 24)
{
AfxMessageBox("Texture file must have 24 bits depth");
file.Close();
return 0;
}
//
// Non ho capito perche' ma molti editor settano a 0 biSizeImage !
//
if( !m_Header.biSizeImage ){
UINT nStride = (m_Header.biWidth * (m_Header.biBitCount/8) + 1) & (~1); // Stride is the BMP's bytes per row.
m_Header.biSizeImage = nStride * m_Header.biHeight;
}
// Alloc (does call Free before)
Free();
m_pData = new unsigned char[m_Header.biSizeImage];
if(m_pData == NULL)
{
AfxMessageBox("Insuffisant memory");
file.Close();
return 0;
}
// Update datas
m_Width = m_Header.biWidth;
m_Height = m_Header.biHeight;
m_Depth = m_Header.biBitCount;
// Image reading
TRY
{
file.Read(m_pData,m_Header.biSizeImage);
}
CATCH(CFileException, e)
{
#ifdef _DEBUG
afxDump << "Error during reading " << e->m_cause << "\n";
#endif
AfxMessageBox("Error during reading image");
file.Close();
return 0;
}
END_CATCH
// Close file
file.Close();
// Success, also set FileName
m_FileName = filename;
UpdateWidthByte32();
return 1;
}
//********************************************
// UpdateWidthByte32
//********************************************
void CTexture::UpdateWidthByte32()
{
m_WidthByte32 = WidthByte32(m_Width,m_Depth);
}
//********************************************
// WidthByte32
//********************************************
unsigned int CTexture::WidthByte32(unsigned int width,
unsigned int depth)
{
// 32 bits alignment (4 bytes)
int rest=(width*depth/8)%4;
if(rest != 0)
return (width*depth/8 + 4-rest);
else
return (width*depth/8);
}
//********************************************
// UpdateHeader
//********************************************
void CTexture::UpdateHeader()
{
UpdateWidthByte32();
m_Header.biWidth = m_Width;
m_Header.biHeight = m_Height;
m_Header.biSizeImage = m_WidthByte32 * m_Height;
m_Header.biSize = 40;
m_Header.biPlanes = 1;
m_Header.biBitCount = m_Depth;
m_Header.biCompression = 0;
m_Header.biXPelsPerMeter = 0;
m_Header.biYPelsPerMeter = 0;
m_Header.biClrUsed = 0;
m_Header.biClrImportant = 0;
}
//********************************************
// ReadFileRAW (*.raw)
//********************************************
// Read raw files