OpenGLES加载tga文件为纹理

来源:互联网 发布:好看围巾 知乎 编辑:程序博客网 时间:2024/04/28 19:24

tga文件分为压缩的和非压缩的。根据文件存储的格式不同,加载的方式也有些不一样,下面贴出代码,代码是从NEHE的教程中摘录来的。经过测试,能在OpenGLES中使用。代码中将用到几个结构体,也一起贴。

typedef struct         
{
 GLubyte * imageData;        
 GLuint bpp;          
 GLuint width;          
 GLuint height;          
 GLuint texID;          
 GLuint type;          
} TEXTURE; 

typedef struct
{
 GLubyte Header[12];         
} TGAHEADER;


typedef struct
{
 GLubyte  header[6];        
 GLuint  bytesPerPixel;       
 GLuint  imageSize;        
 GLuint  temp;         
 GLuint  type; 
 GLuint  Height;         
 GLuint  Width;         
 GLuint  Bpp;         
} TGA;

 

 TEXTURE m_Texture[2]; 
 TGAHEADER m_TGAHeader;         
 TGA m_TGA;

 

GLubyte uTGAcompare[12] = {0,0,2, 0,0,0,0,0,0,0,0,0};   //非压缩格式
GLubyte cTGAcompare[12] = {0,0,10,0,0,0,0,0,0,0,0,0};  //压缩格式

 

BOOL CTestDemoDlg::LoadTGA(TEXTURE * texture, char * filename)    
{
 FILE * fTGA;            
 fTGA = fopen(filename, "rb");        
 
 if(fTGA == NULL)           
 {
  ::MessageBox(NULL, "Could not open texture file", "ERROR", MB_OK); 
  return false;              
 }
 
 if(fread(&m_TGAHeader, sizeof(TGAHEADER), 1, fTGA) == 0)     
 {
  ::MessageBox(NULL, "Could not read file header", "ERROR", MB_OK);  
  if(fTGA != NULL)             
  {
   fclose(fTGA);             
  }
  return false;              
 }
 
 if(memcmp(uTGAcompare, &m_TGAHeader, sizeof(m_TGAHeader)) == 0)    
 {                  
  LoadUncompressedTGA(texture, filename, fTGA);      
 }
 else if(memcmp(cTGAcompare, &m_TGAHeader, sizeof(m_TGAHeader)) == 0)  
 {                  
  LoadCompressedTGA(texture, filename, fTGA);       
 }
 else                 
 {
  ::MessageBox(NULL, "TGA file be type 2 or type 10 ", "Invalid Image", MB_OK); 
  fclose(fTGA);
  return false;                
 }
 return true;               
}

BOOL CTestDemoDlg::LoadUncompressedTGA(TEXTURE * texture, char * filename, FILE * fTGA) 
{                   
 if(fread(m_TGA.header, sizeof(m_TGA.header), 1, fTGA) == 0)     
 {          
  ::MessageBox(NULL, "Could not read info header", "ERROR", MB_OK);  
  if(fTGA != NULL)             
  {
   fclose(fTGA);             
  }
  return false;              
 } 

 texture->width  = m_TGA.header[1] * 256 + m_TGA.header[0];     
 texture->height = m_TGA.header[3] * 256 + m_TGA.header[2];     
 texture->bpp = m_TGA.header[4];          
 m_TGA.Width  = texture->width;          
 m_TGA.Height = texture->height;          
 m_TGA.Bpp  = texture->bpp;           

 if((texture->width <= 0) || (texture->height <= 0) || ((texture->bpp != 24) && (texture->bpp !=32))) 
 {
  ::MessageBox(NULL, "Invalid texture information", "ERROR", MB_OK); 
  if(fTGA != NULL)             
  {
   fclose(fTGA);             
  }
  return false;              
 }

 if(texture->bpp == 24)             
 {
  texture->type = GL_RGB;           
 }
 else                 
 {
  texture->type = GL_RGBA;           
 }

 m_TGA.bytesPerPixel = (m_TGA.Bpp / 8);         
 m_TGA.imageSize  = (m_TGA.bytesPerPixel * m_TGA.Width * m_TGA.Height);  
 texture->imageData = (GLubyte *)malloc(m_TGA.imageSize);     

 if(texture->imageData == NULL)           
 {
  ::MessageBox(NULL, "Could not allocate memory for image", "ERROR", MB_OK); 
  fclose(fTGA);              
  return false;              
 }

 if(fread(texture->imageData, 1, m_TGA.imageSize, fTGA) != m_TGA.imageSize) 
 {
  ::MessageBox(NULL, "Could not read image data", "ERROR", MB_OK);  
  if(texture->imageData != NULL)          
  {
   free(texture->imageData);          
  }
  fclose(fTGA);              
  return false;              
 }

 // Byte Swapping Optimized By Steve Thomas
 for(GLuint cswap = 0; cswap < (int)m_TGA.imageSize; cswap += m_TGA.bytesPerPixel)
 {
  texture->imageData[cswap] ^= texture->imageData[cswap+2] ^=
  texture->imageData[cswap] ^= texture->imageData[cswap+2];
 }

 fclose(fTGA);               
 return true;               
}

BOOL CTestDemoDlg::LoadCompressedTGA(TEXTURE * texture, char * filename, FILE * fTGA)  
{
 if(fread(m_TGA.header, sizeof(m_TGA.header), 1, fTGA) == 0)     
 {
  ::MessageBox(NULL, "Could not read info header", "ERROR", MB_OK);  
  if(fTGA != NULL)             
  {
   fclose(fTGA);             
  }
  return false;              
 }

 texture->width  = m_TGA.header[1] * 256 + m_TGA.header[0];     
 texture->height = m_TGA.header[3] * 256 + m_TGA.header[2];     
 texture->bpp = m_TGA.header[4];          
 m_TGA.Width  = texture->width;          
 m_TGA.Height  = texture->height;          
 m_TGA.Bpp   = texture->bpp;           

 if((texture->width <= 0) || (texture->height <= 0) || ((texture->bpp != 24) && (texture->bpp !=32))) 
 {
  ::MessageBox(NULL, "Invalid texture information", "ERROR", MB_OK); 
  if(fTGA != NULL)             
  {
   fclose(fTGA);             
  }
  return false;              
 }

 m_TGA.bytesPerPixel = (m_TGA.Bpp / 8);         
 m_TGA.imageSize  = (m_TGA.bytesPerPixel * m_TGA.Width * m_TGA.Height);  
 texture->imageData = (GLubyte *)malloc(m_TGA.imageSize);     

 if(texture->imageData == NULL)           
 {
  ::MessageBox(NULL, "Could not allocate memory for image", "ERROR", MB_OK); 
  fclose(fTGA);              
  return false;              
 }

 GLuint pixelcount = m_TGA.Height * m_TGA.Width;       
 GLuint currentpixel = 0;            
 GLuint currentbyte = 0;            
 GLubyte * colorbuffer = (GLubyte *)malloc(m_TGA.bytesPerPixel);   

 do
 {
  GLubyte chunkheader = 0;           

  if(fread(&chunkheader, sizeof(GLubyte), 1, fTGA) == 0)    
  {
   ::MessageBox(NULL, "Could not read RLE header", "ERROR", MB_OK); 
   if(fTGA != NULL)            
   {
    fclose(fTGA);            
   }
   if(texture->imageData != NULL)         
   {
    free(texture->imageData);         
   }
   return false;             
  }

  if(chunkheader < 128)            
  {                 
   chunkheader++;             
   for(short counter = 0; counter < chunkheader; counter++)  
   {
    if(fread(colorbuffer, 1, m_TGA.bytesPerPixel, fTGA) != m_TGA.bytesPerPixel)
    {
     ::MessageBox(NULL, "Could not read image data", "ERROR", MB_OK);  

     if(fTGA != NULL)             
     {
      fclose(fTGA);             
     }

     if(colorbuffer != NULL)            
     {
      free(colorbuffer);            
     }

     if(texture->imageData != NULL)          
     {
      free(texture->imageData);          
     }

     return false;              
    }
                      
    texture->imageData[currentbyte  ] = colorbuffer[2];       
    texture->imageData[currentbyte + 1 ] = colorbuffer[1];
    texture->imageData[currentbyte + 2 ] = colorbuffer[0];

    if(m_TGA.bytesPerPixel == 4)            
    {
     texture->imageData[currentbyte + 3] = colorbuffer[3];    
    }

    currentbyte += m_TGA.bytesPerPixel;          
    currentpixel++;               

    if(currentpixel > pixelcount)           
    {
     ::MessageBox(NULL, "Too many pixels read", "ERROR", NULL);   

     if(fTGA != NULL)             
     {
      fclose(fTGA);             
     } 

     if(colorbuffer != NULL)            
     {
      free(colorbuffer);            
     }

     if(texture->imageData != NULL)          
     {
      free(texture->imageData);          
     }

     return false;              
    }
   }
  }
  else                   
  {
   chunkheader -= 127;               
   if(fread(colorbuffer, 1, m_TGA.bytesPerPixel, fTGA) != m_TGA.bytesPerPixel)  
   { 
    ::MessageBox(NULL, "Could not read from file", "ERROR", MB_OK);   

    if(fTGA != NULL)              
    {
     fclose(fTGA);              
    }

    if(colorbuffer != NULL)             
    {
     free(colorbuffer);             
    }

    if(texture->imageData != NULL)           
    {
     free(texture->imageData);           
    }

    return false;               
   }

   for(short counter = 0; counter < chunkheader; counter++)     
   {                   
    texture->imageData[currentbyte  ] = colorbuffer[2];     
    texture->imageData[currentbyte + 1 ] = colorbuffer[1];
    texture->imageData[currentbyte + 2 ] = colorbuffer[0];

    if(m_TGA.bytesPerPixel == 4)            
    {
     texture->imageData[currentbyte + 3] = colorbuffer[3];    
    }

    currentbyte += m_TGA.bytesPerPixel;          
    currentpixel++;               

    if(currentpixel > pixelcount)           
    {
     ::MessageBox(NULL, "Too many pixels read", "ERROR", NULL);   

     if(fTGA != NULL)             
     {
      fclose(fTGA);             
     } 

     if(colorbuffer != NULL)            
     {
      free(colorbuffer);            
     }

     if(texture->imageData != NULL)          
     {
      free(texture->imageData);          
     }

     return false;              
    }
   }
  }
 }

 while(currentpixel < pixelcount);             
 fclose(fTGA);                  
 return true;                  
}

 

int CTestDemoDlg::LoadGLTextures()         // 载入位图(调用上面的代码)并转换成纹理
{
 int Status=FALSE;            // 状态指示器
 if (LoadTGA(&m_Texture[0], "Data/Uncompressed.tga") &&
  LoadTGA(&m_Texture[1], "Data/Compressed.tga"))
 {
  Status=TRUE;           
  
  for (int loop=0; loop<2; loop++)       // 循环加载所有的图像s
  {
   glGenTextures(1, &m_Texture[loop].texID);    // 创建纹理
   glBindTexture(GL_TEXTURE_2D, m_Texture[loop].texID);
   glTexImage2D(GL_TEXTURE_2D, 0, 3, m_Texture[loop].width, m_Texture[loop].height, 0, GL_RGB, GL_UNSIGNED_BYTE, m_Texture[loop].imageData);
   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
   
   if (m_Texture[loop].imageData)       // 释放分配的内存
   {
    free(m_Texture[loop].imageData);     
   }
  }
 }

原创粉丝点击