📄 imageload.cpp
字号:
#include "ImageLoad.h"
//-----------------------------------------
// 函数名称:ImageLoad::ImageLoad - public
// 描述:缺省构造函数
// 参数;None
// 返回:None
//-----------------------------------------
ImageLoad::ImageLoad():m_strTexturePath(),
m_uiTextureID(0),m_FileType(INVALID),m_pTextureSurface(NULL),
m_pData(NULL),m_iWidth(0),m_iHeight(0){}
//--------------------------------------------
// 函数名称:ImageLoad::CopyCnotrol - private
// 描述:拷贝控制辅助函数
// 参数;rhs - 用于进行复制的对象
// 返回:None
//--------------------------------------------
GLvoid ImageLoad::CopyCnotrol(const ImageLoad &rhs)
{
// 根据被复制ImageLoad的m_pTextureSurface的情况进行合理地复制
if (rhs.m_pTextureSurface != NULL)
{
SDL_Surface *pTempSurface = new SDL_Surface(*(rhs.m_pTextureSurface)); // 复制SDL表面
delete m_pTextureSurface;
m_pTextureSurface = pTempSurface;
}
else
{
delete m_pTextureSurface;
m_pTextureSurface = NULL;
}
if (rhs.m_pData != NULL)
{
size_t length = _mbsnlen( rhs.m_pData, sizeof(rhs.m_pData) ) + 1; // 保存字符的长度
GLubyte *pTemp = new GLubyte[length]; // 分配内存
_mbsncpy(pTemp, rhs.m_pData, length); // 复制数据
delete [] m_pData;
m_pData = pTemp;
}
else
{
delete [] m_pData;
m_pData = NULL;
}
}
//----------------------------------------
// 函数名称:ImageLoad::ImageLoad - public
// 描述:复制构造函数
// 参数;rhs - 用于进行复制的对象
// 返回:None
//----------------------------------------
ImageLoad::ImageLoad(const ImageLoad &rhs):m_strTexturePath(rhs.m_strTexturePath),
m_uiTextureID(rhs.m_uiTextureID),m_FileType(rhs.m_FileType),m_iWidth(rhs.m_iWidth),
m_iHeight(rhs.m_iHeight)
{
m_pTextureSurface = NULL; // 兼容代码,使得可调用
m_pData = NULL; // CopyCnotrol避免代码重复
CopyCnotrol(rhs);
}
//-----------------------------------------------
// 函数名称:ImageLoad::operator =操作符 - public
// 描述:"="操作符
// 参数;rhs - 用于进行赋值的对象
// 返回:ImageLoad &类对象自身的引用
//-----------------------------------------------
ImageLoad &ImageLoad::operator =(const ImageLoad &rhs)
{
m_strTexturePath = rhs.m_strTexturePath;
m_uiTextureID = rhs.m_uiTextureID;
m_FileType = rhs.m_FileType;
m_iWidth = rhs.m_iWidth;
m_iHeight = rhs.m_iHeight;
CopyCnotrol(rhs);
return *this;
}
//-----------------------------------------------
// 函数名称:ImageLoad::CheckFileType - private
// 描述:检测纹理文件类型
// 参数;None
// 返回:GL_FALSE - 纹理文件类型是符号要求的
// GL_TRUE - 纹理文件类型是不符号要求的
//-----------------------------------------------
GLboolean ImageLoad::CheckFileType()
{
string strExtent = m_strTexturePath.substr(m_strTexturePath.size() - 3);
strExtent[0] = toupper(strExtent[0]);
strExtent[1] = toupper(strExtent[1]);
strExtent[2] = toupper(strExtent[2]);
if (strExtent == "BMP")
{
m_FileType = BMP;
}
else if (strExtent == "TGA")
{
m_FileType = TGA;
}
else if (strExtent == "JPG")
{
m_FileType = JPG;
}
else if (strExtent == "PCX")
{
m_FileType = PCX;
}
else
{
cout << "纹理文件类型不符合要求!" << endl;
return GL_FALSE;
}
return GL_TRUE;
}
//-------------------------------------------
// 函数名称:ImageLoad::LoadTexture - private
// 描述:载入纹理文件
// 参数;None
// 返回:GL_TRUE - 成功栽入纹理
// GL_FALSE - 载入纹理失败
//-------------------------------------------
GLboolean ImageLoad::LoadTexture()
{
// 根据纹理文件的类型载入纹理
if (m_FileType == PCX)
{
if (LoadPcxTexture() != GL_TRUE)
{
cout << "载入PCX纹理失败!" << endl;
return GL_FALSE;
}
}
else // 纹理文件类型为Bmp,Tga,Jpg
{
m_pTextureSurface = IMG_Load(m_strTexturePath.c_str());
if (m_pTextureSurface == NULL)
{
cout << "载入Bmp,Tga,Jpg纹理失败!" << endl;
return GL_FALSE;
}
// 调整图像数据,使其能正确显示
if (m_FileType == BMP || m_FileType == TGA)
{
// 颜色模式:colorMode -> 3 = BGR, 4 = BGRA
GLint iPixComponent = m_pTextureSurface->format->BitsPerPixel/8;
GLint iImageSize = m_pTextureSurface->w * m_pTextureSurface->h * iPixComponent; // 得到图像的大小
// 位图像数据分配内存
GLubyte *m_pData = static_cast<GLubyte*> (m_pTextureSurface->pixels);
// 将BGR转换为RGB,以使得OpenGL可以读此图像数据
GLubyte ubTemp;
for (int i = 0; i < iImageSize; i += iPixComponent)
{
ubTemp = m_pData[i];
m_pData[i] = m_pData[i + 2];
m_pData[i + 2] = ubTemp;
}
}
}
return GL_TRUE;
}
//----------------------------------------------
// 函数名称:ImageLoad::LoadPcxTexture - private
// 描述:载入Pcx纹理文件
// 参数;None
// 返回:GL_TRUE - 生成Pcx纹理成功
// GL_FALSE - 生成Pcx纹理失败
//----------------------------------------------
GLboolean ImageLoad::LoadPcxTexture()
{
GLint i,j; // 循环索引临时变量
FILE *pFile = NULL;
GLint iTemp = 0;
GLint iIndex = 0;
GLint iRepeatNumber = 0;
GLubyte ubMinX = 0;
GLubyte ubMinY = 0;
GLubyte ubMaxX = 0;
GLubyte ubMaxY = 0;
pFile = fopen(m_strTexturePath.c_str(), "rb");
if(pFile == NULL)
{
return GL_FALSE;
}
// 读取第一个字符
iTemp = getc(pFile);
// 测试它是10
if(iTemp != 10)
{
fclose(pFile);
return GL_FALSE;
}
// 再读取一个符
iTemp = getc(pFile);
// 测试它是5
if(iTemp != 5)
{
fclose(pFile);
return GL_FALSE;
}
// 读取两个不需要的字符
fgetc(pFile);
fgetc(pFile);
// 读取一个字符,左移8位,位与然后赋值
ubMinX = fgetc(pFile); ubMinX |= fgetc(pFile) << 8;
ubMinY = fgetc(pFile); ubMinY |= fgetc(pFile) << 8;
ubMaxX = fgetc(pFile); ubMaxX |= fgetc(pFile) << 8;
ubMaxY = fgetc(pFile); ubMaxY |= fgetc(pFile) << 8;
// 得到纹理宽度和高度(以字节为单位)
m_iWidth = ubMaxX - ubMinX + 1;
m_iHeight = ubMaxY - ubMinY + 1;
// 为纹理数据分配内存
m_pData = new GLubyte[m_iWidth*m_iHeight];
// 跳过文件头
fseek(pFile, 128, SEEK_SET);
// Read in the image. We are reading in color indexes and using that to look up the
// color values from the palette that we will read in later.
while(iIndex < (m_iWidth*m_iHeight))
{
// Read in a character.
iTemp = getc(pFile);
// Test if it is > than 0xbf...
if(iTemp > 0xbf)
{
// If so we calculate the number of repeats this color repeats in a row.
iRepeatNumber = 0x3f & iTemp;
// Read in the color index value.
iTemp = getc(pFile);
// For the number of times this color repeats save its color index.
for(i = 0; i < iRepeatNumber; ++i)
{
m_pData[iIndex++] = iTemp;
}
}
else
{
// Else save the color index.
m_pData[iIndex++] = iTemp;
}
// Flush the stream.
fflush(stdout);
}
// 异常处理
GLubyte *pPalette = NULL;
GLubyte *unscaledImage = NULL;
try
{
// Allocate memory for the pallete.
pPalette = new GLubyte[768];
// Allocate some temp data for the unscaled image.
unscaledImage = new GLubyte[m_iWidth*m_iHeight*4];
}
catch (...)
{
fclose(pFile);
delete [] pPalette;
delete [] unscaledImage;
CleanUp(); // 释放资源
throw; // 继续抛出异常
}
// Move the file pointer so we can get the palette. The palette is the last bit of data.
fseek(pFile, -769, SEEK_END);
// Read in a character.
iTemp = getc(pFile);
// This must be a 12 or there is an error.
if(iTemp != 12)
{
fclose(pFile);
delete [] pPalette;
delete [] m_pData;
m_pData = NULL;
return GL_FALSE;
}
// Else we read in the palette.
for(i = 0; i < 768; ++i)
{
iTemp = getc(pFile);
pPalette[i] = iTemp;
}
// Close the file.
fclose(pFile);
// Create the image by grabing the colors from the palette.
for(i = 0; i < m_iHeight; ++i)
{
for(j = 0; j < m_iWidth; ++j)
{
unscaledImage[4*(i*m_iWidth + j) + 0] = pPalette[3*m_pData[i*m_iWidth + j] + 0];
unscaledImage[4*(i*m_iWidth + j) + 1] = pPalette[3*m_pData[i*m_iWidth + j] + 1];
unscaledImage[4*(i*m_iWidth + j) + 2] = pPalette[3*m_pData[i*m_iWidth + j] + 2];
unscaledImage[4*(i*m_iWidth + j) + 3] = static_cast<GLubyte> (255);
}
}
// Delete what is in the image.
if(m_pData != NULL)
{
delete [] pPalette;
delete [] m_pData;
m_pData = unscaledImage;
}
return GL_TRUE;
}
//----------------------------------------------
// 函数名称:ImageLoad::GenerateTexture - public
// 描述:生成纹理
// 参数;texturePath - 纹理文件路径
// 返回:GL_TRUE - 生成纹理成功
// GL_FALSE - 生成纹理失败
//----------------------------------------------
GLboolean ImageLoad::GenerateTexture(const string &texturePath)
{
// 记录纹理文件路径
m_strTexturePath = texturePath;
// 检测纹理文件类型
if (CheckFileType() != GL_TRUE)
{
return GL_FALSE;
}
// 载入纹理
if (LoadTexture() != GL_TRUE)
{
return GL_FALSE;
}
// 分配纹理对象
glGenTextures(1, &m_uiTextureID);
// 载入纹理数据并设置参数
glBindTexture(GL_TEXTURE_2D, m_uiTextureID);
// 设置纹理过滤器
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// 设置纹理环境
glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
// 生成纹理
// 根据纹理文件的类型来生成纹理
if (m_FileType == BMP || m_FileType == JPG)
{
gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGB, m_pTextureSurface->w, m_pTextureSurface->h,
GL_RGB, GL_UNSIGNED_BYTE, (GLubyte*) m_pTextureSurface->pixels);
}
else if (m_FileType == PCX) // 纹理文件类型为PCX
{
gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA, m_iWidth, m_iHeight,
GL_RGBA, GL_UNSIGNED_BYTE, m_pData);
}
else // 纹理文件类型为TGA
{
gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA, m_pTextureSurface->w, m_pTextureSurface->h,
GL_RGBA, GL_UNSIGNED_BYTE, (GLubyte*) m_pTextureSurface->pixels);
}
return GL_TRUE;
}
//-------------------------------------
// 函数名称:ImageLoad::CleanUp - public
// 描述:释放资源
// 参数;None
// 返回:None
//-------------------------------------
GLvoid ImageLoad::CleanUp()
{
// 释放内存
if (m_pTextureSurface !=NULL)
{
SDL_FreeSurface(m_pTextureSurface);
m_pTextureSurface = NULL;
}
if (m_uiTextureID != 0)
{
glDeleteTextures(1,&m_uiTextureID);
m_uiTextureID = 0;
}
if (m_pData != NULL)
{
delete [] m_pData;
m_pData = NULL;
}
// 设置相关成员数据
m_strTexturePath = "";
m_FileType = INVALID;
m_iWidth = m_iHeight = 0;
}
//-------------------------------------------------
// 名称:ImageLoad::SetPositionPixelColor - public
// 描述:设置指定位置纹理像素的颜色值
// 参数;x,y - 指定纹利像素的位置
// red,green,blue - 为此纹理像素所设置的颜色值
// 返回:None
//-------------------------------------------------
GLvoid ImageLoad::SetPositionPixelColor(GLint x, GLint y, GLubyte red, GLubyte green, GLubyte blue)
{
// 只对Bmp,Tga,Jpg纹理进行次操作
if (m_FileType == PCX)
{
// 错误信息:不可针对PCX文件进行此操作
return;
}
// 设置指定位置的纹理颜色
if (m_pTextureSurface != NULL && x < m_pTextureSurface->w && y < m_pTextureSurface->h)
{
// 因为使用SDL载入的纹理颜色数据是倒过来的,所以作设置位置调整
GLubyte ubBpp = m_pTextureSurface->format->BitsPerPixel/8; // 得到每此纹理每像素使用的字节数
GLubyte *surfaceData = static_cast<GLubyte*> (m_pTextureSurface->pixels);
surfaceData[ (m_pTextureSurface->w*(m_pTextureSurface->h - y - 1) + x)*ubBpp ] = red;
surfaceData[ (m_pTextureSurface->w*(m_pTextureSurface->h - y - 1) + x)*ubBpp + 1] = green;
surfaceData[ (m_pTextureSurface->w*(m_pTextureSurface->h - y - 1) + x)*ubBpp + 2 ] = blue;
}
}
//-------------------------------------------------
// 名称:ImageLoad::GetPositionPixelColor - public
// 描述:返回指定位置纹理像素的颜色值
// 参数;x,y - 指定纹利像素的位置
// red,green,blue - 记录此纹理像素所设置的颜色值
// 返回:None
//-------------------------------------------------
GLvoid ImageLoad::GetPositionPixelColor(GLint x, GLint y, GLubyte &red, GLubyte &green, GLubyte &blue) const
{
// 只对Bmp,Tga,Jpg纹理进行次操作
if (m_FileType == PCX)
{
// 错误信息:不可针对PCX文件进行此操作
return;
}
// 设置指定位置的纹理颜色
if (m_pTextureSurface != NULL && x < m_pTextureSurface->w && y < m_pTextureSurface->h)
{
// 因为使用SDL载入的纹理颜色数据是倒过来的,所以作设置位置调整
GLubyte ubBpp = m_pTextureSurface->format->BitsPerPixel/8; // 得到每此纹理每像素使用的字节数
GLubyte *surfaceData = static_cast<GLubyte*> (m_pTextureSurface->pixels);
red = surfaceData[ (m_pTextureSurface->w*(m_pTextureSurface->h - y - 1) + x)*ubBpp ];
green = surfaceData[ (m_pTextureSurface->w*(m_pTextureSurface->h - y - 1) + x)*ubBpp + 1 ];
blue = surfaceData[ (m_pTextureSurface->w*(m_pTextureSurface->h - y - 1) + x)*ubBpp + 2 ];
}
}
//-------------------------------------
// 名称:ImageLoad::GetWidth - public
// 描述:返回纹理宽度
// 参数;None
// 返回:GLint - 纹理宽度
//-------------------------------------
GLint ImageLoad::GetWidth() const
{
if (m_FileType != PCX)
{
return m_pTextureSurface->w;
}
else
{
return m_iWidth;
}
}
//------------------------------------
// 名称:ImageLoad::GetHeight - public
// 描述:返回纹理高度
// 参数;None
// 返回:GLint - 纹理高度
//------------------------------------
GLint ImageLoad::GetHeight() const
{
if (m_FileType != PCX)
{
return m_pTextureSurface->h;
}
else
{
return m_iHeight;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -