Click here to Skip to main content
15,886,362 members
Articles / Desktop Programming / MFC

Achieving PostScript and Wmf outputs for OpenGL

Rate me:
Please Sign up or sign in to vote.
4.96/5 (42 votes)
9 Jun 2003 402K   10.7K   137  
This article explains how to generate resolution independent versions of 3D meshes rendered by OpenGL/MFC programs, i.e. how to export the rendering results to vectorial formats such as encapsulated postscript (EPS) and Windows enhanced metafile (EMF) formats. The main goal consists of being able to
//********************************************
// Texture.cpp
//********************************************
// class CTexture
//********************************************
// alliez@usc.edu
// 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 = (unsigned short)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<m_Height;j++)
		for(unsigned int i=0;i<m_Width;i++)
		{
			pixel = m_pData[m_WidthByte32*j+i*BytePerPixel+2];
			m_pData[m_WidthByte32*j+i*BytePerPixel+2] = m_pData[m_WidthByte32*j+i*BytePerPixel];
			m_pData[m_WidthByte32*j+i*BytePerPixel] = pixel;
		}
	return 1;
}

//////////////////////////////////////////////
//////////////////////////////////////////////
// DUPLICATE
//////////////////////////////////////////////
//////////////////////////////////////////////

//********************************************
// Extract
//********************************************
int CTexture::Extract(int left,
											int top,
											int right,
											int bottom)
{
	ASSERT(IsValid());

	// Saturate
	if(right == -1)
		right = m_Width-1;
	if(bottom == -1)
		bottom = m_Height-1;

	// Check
	if(left >= 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<NewHeight;j++)
		for(i=0;i<NewWidth;i++)
			for(k=0;k<BytePerPixel;k++)
				pData[NewWidthByte32*j+i*BytePerPixel+k] = m_pData[m_WidthByte32*(m_Height-1-(j+top))+(i+left)*BytePerPixel+k];

	// Replace datas
	delete [] m_pData;
	m_pData = pData;
	m_Width = NewWidth;
	m_WidthByte32 = NewWidthByte32;
	m_Height = NewHeight;

	UpdateHeader();

	return 1;
}


//********************************************
// DuplicateMirror
//********************************************
int CTexture::DuplicateMirror(int left,
															int top,
															int right,
															int bottom)
{

	if(!Extract(left,top,right,bottom))
		return 0;

	left = 0;
	right = m_Width-1;
	top = 0;
	bottom = m_Height-1;

	int NewWidth = 2*m_Width;
	int NewWidthByte32 = WidthByte32(NewWidth,m_Depth);
	int NewHeight = 2*m_Height;
	int BytePerPixel = m_Depth / 8;
	int i,j,k;

	TRACE("Start duplicate mirror...\n");
	TRACE("New width : %d\n",NewWidth);
	TRACE("New widthbyte32 : %d\n",NewWidthByte32);
	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;
		}

	// o o
	// x o
	for(j=0;j<NewHeight/2;j++)
		for(i=0;i<NewWidth/2;i++)
			for(k=0;k<BytePerPixel;k++)
				pData[NewWidthByte32*j+i*BytePerPixel+k] = m_pData[m_WidthByte32*(bottom-(j+top))+(i+left)*BytePerPixel+k];
	// o o
	// o x
	for(j=0;j<NewHeight/2;j++)
		for(i=NewWidth/2;i<NewWidth;i++)
			for(k=0;k<BytePerPixel;k++)
				pData[NewWidthByte32*j+i*BytePerPixel+k] = m_pData[m_WidthByte32*(bottom-(j+top))+(right-(i-NewWidth/2+left))*BytePerPixel+k];
	// x o
	// o o
	for(j=NewHeight/2;j<NewHeight;j++)
		for(i=0;i<NewWidth/2;i++)
			for(k=0;k<BytePerPixel;k++)
				pData[NewWidthByte32*j+i*BytePerPixel+k] = m_pData[m_WidthByte32*(j-NewHeight/2+top)+(i+left)*BytePerPixel+k];
	// o x
	// o o
	for(j=NewHeight/2;j<NewHeight;j++)
		for(i=NewWidth/2;i<NewWidth;i++)
			for(k=0;k<BytePerPixel;k++)
				pData[NewWidthByte32*j+i*BytePerPixel+k] = m_pData[m_WidthByte32*(j-NewHeight/2+top)+(right-(i-NewWidth/2+left))*BytePerPixel+k];

	// Replace datas
	delete [] m_pData;
	m_pData = pData;
	m_Width = NewWidth;
	m_WidthByte32 = NewWidthByte32;
	m_Height = NewHeight;

	UpdateHeader();

	return 1;
}




//********************************************
// DuplicateRepeatWidth
//********************************************
int CTexture::DuplicateRepeatWidth(int left,
																	 int top,
																	 int right,
																	 int bottom)
{
	if(!Extract(left,top,right,bottom))
		return 0;

	left = 0;
	right = m_Width-1;
	top = 0;
	bottom = m_Height-1;

	int NewWidth = 2*m_Width;
	int NewWidthByte32 = WidthByte32(NewWidth,m_Depth);
	int NewHeight = m_Height;
	int BytePerPixel = m_Depth / 8;
	int i,j,k;

	TRACE("Start duplicate mirror...\n");
	TRACE("New width : %d\n",NewWidth);
	TRACE("New widthbyte32 : %d\n",NewWidthByte32);
	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;
		}

	// x o
	for(j=0;j<NewHeight;j++)
		for(i=0;i<NewWidth/2;i++)
			for(k=0;k<BytePerPixel;k++)
				pData[NewWidthByte32*j+i*BytePerPixel+k] = m_pData[m_WidthByte32*(bottom-(j+top))+(i+left)*BytePerPixel+k];
	// o x
	for(j=0;j<NewHeight;j++)
		for(i=NewWidth/2;i<NewWidth;i++)
			for(k=0;k<BytePerPixel;k++)
				pData[NewWidthByte32*j+i*BytePerPixel+k] = m_pData[m_WidthByte32*(bottom-(j+top))+(i-NewWidth/2+left)*BytePerPixel+k];

	// Replace datas
	delete [] m_pData;
	m_pData = pData;
	m_Width = NewWidth;
	m_WidthByte32 = NewWidthByte32;
	m_Height = NewHeight;

	UpdateHeader();

	return 1;
}





//////////////////////////////////////////////
//////////////////////////////////////////////
// ALPHA
//////////////////////////////////////////////
//////////////////////////////////////////////

//********************************************
// SetAlphaLayer
//********************************************
int CTexture::SetAlphaLayer(unsigned char alpha) // 0 - 255
{
	// Check
	if(!IsValid())
		return 0;

	if(m_Depth != 32)
		return 0;

	// Fill alpha layer 
	int size = m_Width * m_Height;
	for(int i=0;i<4*size;i+=4)
		m_pData[i+3] = alpha;

	return 1;
}

//********************************************
// AddAlphaLayer
//********************************************
int CTexture::AddAlphaLayer(unsigned char alpha) // 0 - 255
{
	// Check
	if(!IsValid())
		return 0;

	// Has soon alpha
	if(HasAlpha())
		return SetAlphaLayer(alpha);

	// Alloc memory
	unsigned char *pData = new unsigned char[4*m_Width*m_Height];
	if(pData == NULL)
		{
		AfxMessageBox("CTexture::AddAlphaLayer : insuffisant memory");
		return 0;
		}

	// Fill new data
	int size = m_Width * m_Height;
	int BytePerPixel = m_Depth / 8;
	ASSERT(size > 0);
	for(int i=0;i<size;i++)
	{
		pData[4*i+0] = m_pData[BytePerPixel*i+0];
		pData[4*i+1] = m_pData[BytePerPixel*i+1];
		pData[4*i+2] = m_pData[BytePerPixel*i+2];
		pData[4*i+3] = alpha;
	}

	// Set new depth
	m_Depth = 32;

	// Replace datas
	delete [] m_pData;
	m_pData = pData;

	return 1;
}


//********************************************
// PutAlpha
// From RGB to grey scales, then alpha layer
//********************************************
int CTexture::PutAlpha(CTexture *pTexture) 
{
	// Check
	if(!IsValid())
		return 0;
	if(!pTexture->IsValid())
		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;i<size;i++)
		m_pData[4*i+3] = (unsigned char)(((int)pData[BytePerPixel*i+0]+
		                                 (int)pData[BytePerPixel*i+1]+
																		 (int)pData[BytePerPixel*i+2])/3);

	return 1;
}

//////////////////////////////////////////////
//////////////////////////////////////////////
// DISPLAY
//////////////////////////////////////////////
//////////////////////////////////////////////

//********************************************
// Draw
//********************************************
int CTexture::Draw(CDC *pDC,
									 int xOffset,
									 int yOffset,
									 int width,
									 int height)
{
	// Checking
	if(!IsValid())
	  return 0;

	// Flags	
	if(width == -1)
		width = m_Width;
	if(height == -1)
		height = m_Height;

	// Painting
	return SetDIBitsToDevice(pDC->m_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<height;j++)
		for(int i=0;i<width;i++)
			for(int k=0;k<BytePerPixel;k++)
			{
				m_pData[m_WidthByte32*j + i*BytePerPixel+k] = 
				  buffer[(width*j+i)*BytePerPixel+k];
				//TRACE("pixel : %d\n",(int)buffer[(width*j+i)*BytePerPixel+k]);
			}

	return 1;
}

//********************************************
// ReadBuffer
//********************************************
int CTexture::ReadBuffer(float *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<height;j++)
		for(int i=0;i<width;i++)
			for(int k=0;k<BytePerPixel;k++)
			{
				ASSERT(buffer[(width*j+i)*BytePerPixel+k] <= 1.0f);
				ASSERT(buffer[(width*j+i)*BytePerPixel+k] >= 0.0f);
				m_pData[m_WidthByte32*j + i*BytePerPixel+k] = (BYTE)(255.0f * buffer[(width*j+i)*BytePerPixel+k]);
			}

	return 1;
}

//********************************************
// Grey
//********************************************
int CTexture::Grey(unsigned int x,
									 unsigned int y)
{
	ASSERT(x<m_Width && x>=0);
	ASSERT(y<m_Height && 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;
}

//********************************************
// Color
//********************************************
void CTexture::Color(unsigned int x,
 									   unsigned int y, 
										 unsigned char *pRed,
										 unsigned char *pGreen,
										 unsigned char *pBlue)
{
	ASSERT(x<m_Width && x>=0);
	ASSERT(y<m_Height && y>=0);
	int BytePerPixel = m_Depth / 8;
	// Grey scale
	if(BytePerPixel == 1)
	{
		*pRed = m_pData[m_WidthByte32*y + x]; 
		*pGreen = m_pData[m_WidthByte32*y + x]; 
		*pBlue = m_pData[m_WidthByte32*y + x]; 
	}
	else // 24 or 32 bits (alpha layer)
	{
		*pRed = m_pData[m_WidthByte32*y + x*BytePerPixel]; 
		*pGreen = m_pData[m_WidthByte32*y + x*BytePerPixel+1]; 
		*pBlue = m_pData[m_WidthByte32*y + x*BytePerPixel+2]; 
	}
}


HANDLE CTexture::ExportHandle()
{
	HANDLE handle;

	TRACE("Export handle...");
  // Process source handle size
  int size = sizeof(BITMAPINFOHEADER) + m_WidthByte32 * m_Height;
  // Alloc memory
	TRACE("alloc...");
  handle = (HANDLE)::GlobalAlloc (GHND,size);
  if(handle != NULL)
	{
		char *pData = (char *) ::GlobalLock((HGLOBAL)handle);
		TRACE("lock...");
		// Copy header
		TRACE("header...");
		memcpy(pData,&m_Header,sizeof(BITMAPINFOHEADER));
		// Copy datas
		TRACE("datas...");
		memcpy(pData+sizeof(BITMAPINFOHEADER),m_pData,m_WidthByte32*m_Height);
		// Unlock
		TRACE("unlock...");
		::GlobalUnlock((HGLOBAL)handle);
	}
	TRACE("ok\n");
	return handle;
}



// ** EOF **



By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
France France
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions