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.