www.pudn.com > racecar.zip > TGATexture.pas


//--------------------- 
// TGA Texture Loading Unit. 
// 
// Written by Michael Pote. 
// Adapted from Nehe TGA loader. 
// 
// michaelpote@worldonline.co.za 
// -------------------- 
unit TGATexture; 
 
interface 
 
uses 
  Windows, 
  Messages, 
  Sysutils, 
  OpenGL; 
 
 
function LoadTGA(filename : string; var TexId: glUint; Mipmap:boolean) : boolean;			// Loads A TGA File Into Memory 
 
implementation 
 
procedure glGenTextures(n: GLsizei; var textures: GLuint); stdcall; external 'opengl32.dll'; 
procedure glBindTexture(target: GLenum; texture: GLuint); stdcall; external 'opengl32.dll'; 
 
type TextureImage = record										// Structure Name 
	imageData : PChar;										// Image Data (Up To 32 Bits) 
	bpp : GLuint;											// Image Color Depth In Bits Per Pixel. 
	width : GLuint;											// Image Width 
	height : GLuint;											// Image Height 
	texID : GLuint; 
     end; 
 
function LoadTGA( filename : string; var TexId: glUint; MipMap: boolean) : boolean;			// Loads A TGA File Into Memory 
const 
  TGAheader : array [0..11] of GLubyte = (0,0,2,0,0,0,0,0,0,0,0,0);	// Uncompressed TGA Header 
  TGAComheader : array [0..11] of GLubyte = (0,0,10,0,0,0,0,0,0,0,0,0);	// Compressed TGA Header 
 
var 
  TGAcompare : array [0..11] of GLubyte;								// Used To Compare TGA Header 
  header : array [0..5] of GLubyte;									// First 6 Useful Bytes From The Header 
  bytesPerPixel : GLuint;					// Holds Number Of Bytes Per Pixel Used In The TGA File 
  imageSize : GLuint;									// Used To Store The Image Size When Setting Aside Ram 
  i : GLuint;										// Temporary Variable 
 
  Tm: Char; 
  Texture:  TextureImage; 
  tgafile : integer; 
 
  PixelCount, CurrentPixel, CurrentByte: gluInt; 
  ColorBuffer: Pchar; 
  ChunkHeader: gluByte; 
  Counter, Ret: integer; 
 
  gltype : GLuint;								// Set The Default GL Mode To RBGA (32 BPP) 
  Compressed:boolean; 
 
begin 
  Compressed := False; 
  glType := GL_RGBA; 
 
  tgafile := FileOpen(filename, fmOpenReadWrite); 
 
  Ret := FileRead(tgafile, TGAcompare, sizeof(TGAcompare)); 
 
  if ( 
      (tgafile = -1) or								// Does File Even Exist? 
      (Ret <> sizeof(TGAcompare))	// Are There 12 Bytes To Read? 
     ) 
  then 
  begin 
    //ShowError(10, 'TGATexture.LoadTGA', False); 
    if (tgafile = -1) then									// Did The File Even Exist? *Added Jim Strong* 
    begin 
      result := false;									// Return False 
      exit; 
    end 
    else 
    begin 
      fileclose(tgafile);									// If Anything Failed, Close The File 
      result := false;									// Return False 
      exit; 
    end; 
  end; 
 
  if (CompareMem(@TGAheader, @TGAcompare, sizeof(TGAheader)) = false)	                // Does The Header Match What We Want? 
  Then 
  begin //File is not uncompressed... 
 
   if (CompareMem(@TGAComheader, @TGAcompare, sizeof(TGAComheader)) = True)	                // Does The Header Match What We Want? 
   Then 
   Begin 
      Compressed := True; 
   end 
   else 
   Begin 
     i := 0; 
     //ShowError(17, 'TGATexture.LoadTGA', False); 
     if (tgafile = -1) then									// Did The File Even Exist? *Added Jim Strong* 
     begin 
       result := false;									// Return False 
       exit; 
     end 
     else 
     begin 
       fileclose(tgafile);									// If Anything Failed, Close The File 
       result := false;									// Return False 
       exit; 
     end; 
    end; 
 
  end 
  else 
  begin 
   Compressed := False; 
  end; 
 
   if (FileRead(tgafile, header, sizeof(header)) <> sizeof(header)) then 
   begin 
     //ShowError(10, 'TGATexture.LoadTGA', False); 
     if (tgafile = -1) then									// Did The File Even Exist? *Added Jim Strong* 
     begin 
       result := false;									// Return False 
       exit; 
     end 
     else 
     begin 
       fileclose(tgafile);									// If Anything Failed, Close The File 
       result := false;									// Return False 
       exit; 
     end; 
   end; 
 
  texture.width  := header[1] * 256 + header[0];			// Determine The TGA Width	(highbyte*256+lowbyte) 
  texture.height := header[3] * 256 + header[2];			// Determine The TGA Height	(highbyte*256+lowbyte) 
 
  if (texture.width <= 0)	or								// Is The Width Less Than Or Equal To Zero 
     (texture.height <= 0)	or								// Is The Height Less Than Or Equal To Zero 
     ((header[4] <> 24) and (header[4] <> 32)) then					// Is The TGA 24 or 32 Bit? 
  begin 
    //ShowError(11, 'TGATexture.LoadTGA', False); 
    fileclose(tgafile);										// If Anything Failed, Close The File 
    result := false;										// Return False 
    exit; 
  end; 
 
  texture.bpp	:= header[4];							// Grab The TGA's Bits Per Pixel (24 or 32) 
  bytesPerPixel	:= texture.bpp div 8;						// Divide By 8 To Get The Bytes Per Pixel 
  imageSize	:= texture.width * texture.height * bytesPerPixel;	// Calculate The Memory Required For The TGA Data 
 
 
  GetMem(texture.imageData, imageSize);		// Reserve Memory To Hold The TGA Data 
  //Setlength(texture.imagedata, imagesize); 
  if Not Compressed then 
  begin 
   if (texture.imageData = nil) or	       // Does The Storage Memory Exist? 
      (fileread(tgafile, texture.imageData^, integer(imageSize)) <> imageSize)	// Does The Image Size Match The Memory Reserved? 
      then 
      begin 
        if (texture.imageData <> nil)						// Was Image Data Loaded 
           then freemem(texture.imageData);						// If So, Release The Image Data 
 
        fileclose(tgafile);										// Close The File 
        //ShowError(10, 'TGATexture.LoadTGA', False); 
        result := false;										// Return False 
        exit; 
      end; 
 
    i := 0; 
    while i < imageSize do 
    with texture do 
    begin 
     Tm := ImageData[I+2]; 
     imageData[i+2] := imageData[i];					// Set The 3rd Byte To The Value In 'temp' (1st Byte Value) 
     imageData[i] := Tm;                          // Set The 1st Byte To The Value Of The 3rd Byte 
 
     i := i + bytesPerPixel; 
    end; 
 
 end 
 else  //COMPRESSED TGA'S 
 begin 
   PixelCount := texture.width * Texture.Height; 
   CurrentPixel := 0; 
   CurrentByte := 0; 
   GetMem(ColorBuffer, BytesPerPixel); 
 
   Repeat 
      ChunkHeader := 0; 
      if FileRead(tgaFile, ChunkHeader, sizeof(gluByte)) = 0 then 
      begin 
        //ERROR reading Chunk! 
        fileclose(tgafile);										// Close The File 
        //ShowError(18, 'TGATexture.LoadTGA', False); 
        result := false;										// Return False 
        exit; 
      end; 
 
 
      if ChunkHeader < 128 then 
      begin 
         ChunkHeader := ChunkHeader + 1; 
         For Counter := 0 to ChunkHeader-1 do 
         begin 
            if fileRead(tgafile, ColorBuffer^, BytesPerPixel) <> BytesPerPixel then 
            begin 
             fileclose(tgafile);										// Close The File 
             //ShowError(19, 'TGATexture.LoadTGA(ColorBuffer)', False); 
             result := false;										// Return False 
             exit; 
            end; 
 
            Texture.imageData[CurrentByte] := (ColorBuffer[2]); 
            Texture.imageData[CurrentByte+1] := (ColorBuffer[1]); 
            Texture.imageData[CurrentByte+2] := (ColorBuffer[0]); 
            if BytesPerPixel = 4 then 
            Texture.imageData[CurrentByte+3] := (ColorBuffer[3]); 
 
            CurrentByte := CurrentByte + bytesPerPixel; 
            inc(CurrentPixel); 
            if CurrentPixel > PixelCount then 
            begin 
             fileclose(tgafile);										// Close The File 
             //ShowError(18, 'TGATexture.LoadTGA', False); 
             result := false;										// Return False 
             exit; 
            end; 
         end; 
      end 
      else //Chunkheader > 128 
      begin 
         ChunkHeader := ChunkHeader - 128; 
         if fileRead(tgafile, ColorBuffer^, BytesPerPixel) <> BytesPerPixel then 
         begin 
          fileclose(tgafile);										// Close The File 
          //ShowError(19, 'TGATexture.LoadTGA(Load RLE)', False); 
          result := false;										// Return False 
          exit; 
         end; 
         For Counter := 0 to ChunkHeader do 
         begin 
            Texture.imageData[CurrentByte] := ColorBuffer[2]; 
            Texture.imageData[CurrentByte+1] := ColorBuffer[1]; 
            Texture.imageData[CurrentByte+2] := ColorBuffer[0]; 
            if BytesPerPixel = 4 then 
            Texture.imageData[CurrentByte+3] := ColorBuffer[3]; 
 
            CurrentByte := CurrentByte + bytesPerPixel; 
            inc(CurrentPixel); 
         end; 
 
      end; 
   Until CurrentPixel >= PixelCount; 
 end; 
 fileclose (tgafile);											// Close The File 
 
  // Build A Texture From The Data 
 
  glGenTextures(1, texture.texID);					// Generate OpenGL texture IDs 
 
  if texture.bpp = 24 then									// Was The TGA 24 Bits 
            gltype := GL_RGB 
            else 
            gltype := GL_RGBA;										// If So Set The 'type' To GL_RGB 
 
  glBindTexture(GL_TEXTURE_2D, texture.texID);			        // Bind Our Texture 
  if MipMap then 
  begin 
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);	// Linear Filtered 
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST);	// Linear Filtered 
  gluBuild2DMipMaps(GL_TEXTURE_2D, 3,texture.width, texture.height, glType, GL_UNSIGNED_BYTE, Texture.Imagedata); 
  end 
  else 
  begin 
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);	// Linear Filtered 
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);	// Linear Filtered 
  glTexImage2D(GL_TEXTURE_2D, 0, gltype, texture.width, texture.height, 0, gltype, GL_UNSIGNED_BYTE, texture.imageData); 
  end; 
 
  TexId := Texture.texID; 
  result := true;											// Texture Building Went Ok, Return True 
end; 
 
 
end.