www.pudn.com > opengldemo1.zip > Texture.cpp


//******************************************** 
// Texture.cpp 
//******************************************** 
// class CTexture 
//******************************************** 
// pierre.alliez@cnet.francetelecom.fr 
// 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; 
	} 
 
	// 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 
// Accept only 24 or 32 bits 
// Size : 2^n x 2^m 
//******************************************** 
int CTexture::ReadFileRAW(char *filename, 
													unsigned int width, 
													unsigned int height, 
													unsigned int depth) 
{ 
 
	ASSERT(width>0); 
	ASSERT(height>0); 
	ASSERT(depth>0); 
	ASSERT(depth%8==0); 
	ASSERT(depth/8==3 || depth/8==4); 
 
	// Check for valid 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; 
	} 
 
	// Alloc (does call Free before) 
	if(!Alloc(width,height,depth)) 
	{ 
		AfxMessageBox("Insuffisant memory"); 
		file.Close(); 
		return 0; 
	} 
 
	// Image reading 
	TRY 
	{ 
		file.Read(m_pData,m_Width*m_Height*depth/8); 
	} 
	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; 
 
	return 1; 
} 
 
////////////////////////////////////////////// 
////////////////////////////////////////////// 
// FILE SAVING 
////////////////////////////////////////////// 
////////////////////////////////////////////// 
 
//******************************************** 
// SaveFile 
// Redirection 
//******************************************** 
int CTexture::SaveFile(char *filename) 
{ 
	CString string = filename; 
	string.MakeLower(); 
	TRACE("CTexture::SaveFile : file : %s\n",filename); 
 
	CString extension = string.Right(4); 
 
	// Redirection RAW 
	if(extension == ".raw") 
		return SaveFileRAW(filename); 
 
	// Redirection BMP 
	if(extension == ".bmp") 
		return SaveFileBMP(filename); 
 
	// Unrecognized file format 
	CString message; 
	message.Format("CTexture::SaveFile : invalid file redirection : %s\n",filename); 
	AfxMessageBox(message); 
 
	return 0; 
} 
 
 
//******************************************** 
// SaveFileRAW 
//******************************************** 
int CTexture::SaveFileRAW(char *filename) 
{ 
	// Check for valid image 
	if((m_Width * m_Height * m_Depth) == 0) 
		{ 
		AfxMessageBox("CTexture::SaveFileRAW : invalid image"); 
		return 0; 
		} 
 
	// Check for valid file 
	CFile file; 
	CFileException ex; 
	 
	// Try to open file 
	if(!file.Open(filename, CFile::modeWrite | CFile::typeBinary,&ex)) 
	{ 
		#ifdef _DEBUG 
		  afxDump << "File could not be opened " << ex.m_cause << "\n"; 
		#endif 
		AfxMessageBox("Unable to open file for writing"); 
		return 0; 
	} 
 
	// Image writing 
	TRY 
	{ 
		file.Write(m_pData,m_Width*m_Height*m_Depth/8); 
	} 
	CATCH(CFileException, e) 
	{ 
		#ifdef _DEBUG 
				afxDump << "Error during writing " << e->m_cause << "\n"; 
		#endif 
		AfxMessageBox("Error during writing image"); 
		file.Close(); 
		return 0; 
	} 
	END_CATCH 
 
	// Close file 
  file.Close(); 
 
	return 1; 
} 
 
 
//******************************************** 
// SaveFileBMP (*.bmp) 
//******************************************** 
// Save windows bmp files 
// Accept only 24 bits 
//******************************************** 
int CTexture::SaveFileBMP(char *filename) 
{ 
	if(!IsValid()) 
		return 0; 
 
	if(m_Depth != 24) 
		return 0; 
 
	// Check for valid bmp file 
	CFile file; 
	CFileException ex; 
	 
	// Try to open file 
	if(!file.Open(filename,CFile::modeCreate | CFile::modeWrite | CFile::typeBinary,&ex)) 
	{ 
		#ifdef _DEBUG 
		  afxDump << "File could not be opened " << ex.m_cause << "\n"; 
		#endif 
		AfxMessageBox("Unable to open file for writing"); 
		return 0; 
	} 
 
	// File header 
	BITMAPFILEHEADER FileHeader; 
  WORD sign = ((WORD) ('M' << 8) | 'B'); 
	FileHeader.bfType = sign; 
  FileHeader.bfSize = 14 + 40 + m_WidthByte32*m_Height;  
  FileHeader.bfReserved1 = 0;  
  FileHeader.bfReserved2 = 0;  
  FileHeader.bfOffBits = 54;  
 
	TRACE("\nSave BMP File...\n"); 
	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); 
 
	TRY 
	{ 
		file.Write(&FileHeader,sizeof(BITMAPFILEHEADER)); 
	} 
	CATCH(CFileException, e) 
	{ 
		#ifdef _DEBUG 
				afxDump << "Error during writing " << e->m_cause << "\n"; 
		#endif 
		AfxMessageBox("Error during writing file header"); 
		file.Close(); 
		return 0; 
	} 
	END_CATCH 
 
	// Image header 
	TRY 
	{ 
		file.Write(&m_Header,sizeof(BITMAPINFOHEADER)); 
	} 
	CATCH(CFileException, e) 
	{ 
		#ifdef _DEBUG 
				afxDump << "Error during writing " << e->m_cause << "\n"; 
		#endif 
		AfxMessageBox("Error during writing 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); 
 
	// Image writing 
	TRY 
	{ 
		file.Write(m_pData,m_Header.biSizeImage); 
	} 
	CATCH(CFileException, e) 
	{ 
		#ifdef _DEBUG 
				afxDump << "Error during writing " << e->m_cause << "\n"; 
		#endif 
		AfxMessageBox("Error during writing image"); 
		file.Close(); 
		return 0; 
	} 
	END_CATCH 
 
	// Close file 
  file.Close(); 
 
	return 1; 
} 
 
 
 
 
////////////////////////////////////////////// 
////////////////////////////////////////////// 
// CHECKING 
////////////////////////////////////////////// 
////////////////////////////////////////////// 
 
//******************************************** 
// IsValid 
//******************************************** 
int CTexture::IsValid() 
{ 
	int success = 0; 
	success = (m_Depth == 24) || (m_Depth == 32); 
	success &= (m_Width != 0); 
	success &= (m_Height != 0); 
	success &= (m_pData != NULL); 
	if(!success) 
		{ 
		TRACE("\n"); 
		TRACE("Invalid texture\n"); 
		TRACE("Width  : %d\n",m_Width); 
		TRACE("Height : %d\n",m_Height); 
		TRACE("Depth  : %d\n",m_Depth); 
		TRACE("Data   : %x\n",m_pData); 
		} 
	return success; 
} 
 
 
//******************************************** 
// HigherPowerOfTwo 
//******************************************** 
int CTexture::HigherPowerOfTwo(int value) 
{ 
	ASSERT(value > 0); 
	if(value <= 0) 
		return value; 
 
	int power = 1; 
	int x = 0; 
 
	while(1) 
	{ 
		x = (int)pow(2,power); 
		if(x >= value) 
			return x; 
		power++; 
	} 
 
	return value; 
} 
 
//******************************************** 
// LowerPowerOfTwo 
//******************************************** 
int CTexture::LowerPowerOfTwo(int value) 
{ 
	ASSERT(value > 0); 
	if(value <= 0) 
		return value; 
 
	int power = 1; 
	int x = 0; 
 
	while(1) 
	{ 
		x = (int)pow(2,power); 
		if(x >= value) 
			return (int)pow(2,power-1); 
		power++; 
	} 
 
	return value; 
} 
 
//******************************************** 
// SameSize 
//******************************************** 
int CTexture::SameSize(CTexture *pTexture) 
{ 
	int success = (m_Width == pTexture->GetWidth()); 
	success &= (m_Height == pTexture->GetHeight()); 
	return success; 
} 
 
 
//******************************************** 
// Flip BGR to RGB 
//******************************************** 
int CTexture::BGRtoRGB(void) 
{ 
	if(!IsValid()) 
		return 0; 
 
	unsigned char pixel; 
	int BytePerPixel = m_Depth/8; 
	for(unsigned int j=0;j= right || top >= bottom) 
		return 0; 
	if(left < 0  || left >= (int)m_Width ||  
		 right < 0 || right >= (int)m_Width) 
		return 0; 
	if(top < 0  || top >= (int)m_Height ||  
		 bottom < 0 || bottom >= (int)m_Height) 
		return 0; 
 
	int NewWidth = right-left+1; 
	int NewWidthByte32 = WidthByte32(NewWidth,m_Depth); 
	int NewHeight = bottom-top+1; 
	int BytePerPixel = m_Depth / 8; 
	int i,j,k; 
 
	TRACE("Start extracting...\n"); 
	TRACE("New width : %d\n",NewWidth); 
	TRACE("New height : %d\n",NewHeight); 
 
	ASSERT(NewWidth>=1); 
	ASSERT(NewHeight>=1); 
 
	// Alloc 
	unsigned char *pData = new unsigned char[NewWidthByte32*NewHeight]; 
	if(pData == NULL) 
		{ 
		AfxMessageBox("Insuffisant memeory"); 
		return 0; 
		} 
 
	for(j=0;j=1); 
	ASSERT(NewHeight>=1); 
 
	// Alloc 
	unsigned char *pData = new unsigned char[NewWidthByte32*NewHeight]; 
	if(pData == NULL) 
		{ 
		AfxMessageBox("Insuffisant memeory"); 
		return 0; 
		} 
 
	// o o 
	// x o 
	for(j=0;j=1); 
	ASSERT(NewHeight>=1); 
 
	// Alloc 
	unsigned char *pData = new unsigned char[NewWidthByte32*NewHeight]; 
	if(pData == NULL) 
		{ 
		AfxMessageBox("Insuffisant memeory"); 
		return 0; 
		} 
 
	// x o 
	for(j=0;j 0); 
	for(int i=0;iIsValid()) 
		return 0; 
 
	if(!SameSize(pTexture)) 
		return 0; 
 
	if(!AddAlphaLayer(0)) 
		return 0; 
 
	// Fill new data 
	unsigned char *pData = pTexture->GetData(); 
	int size = m_Width * m_Height; 
	int BytePerPixel = pTexture->GetDepth() / 8; 
	ASSERT(size > 0); 
	for(int i=0;im_hDC, 
		                       xOffset, 
													 yOffset, 
													 width, 
													 height, 
													 0, 
													 0, 
													 0, 
													 m_Height, 
													 GetData(), 
													 (CONST BITMAPINFO *)&m_Header, 
													 DIB_RGB_COLORS); 
} 
 
//******************************************** 
// ReadBuffer 
//******************************************** 
int CTexture::ReadBuffer(unsigned char *buffer,  
												 int width,  
												 int height,  
												 int depth) 
{ 
	if(buffer == NULL) 
		return 0; 
 
	if(!Alloc(width,height,depth)) 
		return 0; 
 
	int BytePerPixel = depth / 8; 
 
	for(int j=0;j=0); 
	ASSERT(y=0); 
	int BytePerPixel = m_Depth / 8; 
	// Grey scale 
	if(BytePerPixel == 1) 
		return (int)m_pData[m_WidthByte32*y + x];  
	else // 24 or 32 bits (alpha layer) 
		return (int)((int)m_pData[m_WidthByte32*y + x*BytePerPixel+0]+  
		             (int)m_pData[m_WidthByte32*y + x*BytePerPixel+1]+ 
								 (int)m_pData[m_WidthByte32*y + x*BytePerPixel+2])/3; 
} 
 
 
 
// ** EOF **