TextureTarga.cpp

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2002  Ryan Nunn and The Pentagram Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 #include "pent_include.h"
00020 #include "TextureTarga.h"
00021 #include "IDataSource.h"
00022 
00023 struct TGA
00024 {
00025         uint32          Height;                                                                         // Height of Image
00026         uint32          Width;                                                                          // Width ofImage
00027         uint32          Bpp;                                                                            // Bits Per Pixel
00028         uint32          bytesPerPixel;
00029         uint32          Flags;
00030         bool            Flipped;
00031         bool            Compressed;
00032 
00033         void Read(IDataSource *ds)
00034         {
00035                 Width   = ds->read2();
00036                 Height  = ds->read2();
00037                 Bpp     = ds->read1();                                  
00038                 Flags = ds->read1();
00039 
00040                 Flipped = (Flags&(1<<5))?false:true;
00041                 bytesPerPixel   = Bpp / 8;
00042         }
00043 };
00044 
00045 static const uint8 uTGAcompare[12] = {0,0,2, 0,0,0,0,0,0,0,0,0};        // Uncompressed TGA Header
00046 static const uint8 cTGAcompare[12] = {0,0,10,0,0,0,0,0,0,0,0,0};        // Compressed TGA Header
00047 
00048 bool TextureTarga::Read(IDataSource *ds)
00049 {
00050         // TGA File Header
00051         uint8 header[12];                                                                               
00052 
00053         // TGA image data
00054         TGA tga;
00055 
00056         // Seek to start
00057         ds->seek(0);
00058 
00059         // Attempt to read 12 byte header from file
00060         ds->read(static_cast<uint8 *>(header), 12);
00061 
00062         // Is it uncompressed?
00063         //if(memcmp(uTGAcompare+1, header+1, 11) == 0) tga.Compressed = false;
00065         //else if(memcmp(cTGAcompare+1, header+1, 11) == 0) tga.Compressed = true;
00067         //else return false;                                                                                                                            
00068 
00069         // Colour Map? We don't support it
00070         if (header[1] != 0) return false;
00071 
00072         // Image type. Only True Colour image data
00073         if (header[2] == 2) tga.Compressed = false;
00074         else if (header[2] == 10) tga.Compressed = true;
00075         else return false;
00076 
00077         // Don't care about the other header data
00078 
00079         // Read TGA header
00080         tga.Read(ds);
00081 
00082         ds->skip(header[0]);
00083 
00084         // Set Width and Height
00085         width   = tga.Width;
00086         height  = tga.Height;
00087         format = TEX_FMT_STANDARD;
00088 
00089         // Make sure all information is valid
00090         if(width <= 0 || height <= 0 || (tga.Bpp != 24 && tga.Bpp !=32))
00091                 return false;
00092 
00093         // Allocate temporary buffer
00094         uint8 *temp_buffer      = new uint8[width * height * tga.bytesPerPixel];
00095 
00096         // Couldn't allocate
00097         if (!temp_buffer) return false;
00098 
00099         // Read it
00100         if (tga.Compressed)
00101         {
00102                 // Is compressed
00103                 uint8 *image = temp_buffer;
00104                 uint8 *end = temp_buffer + tga.bytesPerPixel * width * height;
00105 
00106                 while(image < end)
00107                 {
00108                         uint32 chunkheader = ds->read1();
00109 
00110                         // RAW (copy chunkheader+1 pixels)
00111                         if(chunkheader < 128)
00112                         {
00113                                 chunkheader = (chunkheader+1)*tga.bytesPerPixel;
00114 
00115                                 // Read chunkheader pixels
00116                                 ds->read(static_cast<uint8 *>(image), chunkheader);
00117 
00118                                 image += chunkheader;
00119                         }
00120                         // SINGLE COLOUR (duplicate colour for chunkheader-127 pixels)
00121                         else
00122                         {
00123                                 chunkheader = (chunkheader-127)*tga.bytesPerPixel;
00124 
00125                                 // Read the pixel
00126                                 static uint8 colorbuffer[4];
00127                                 ds->read(static_cast<uint8 *>(colorbuffer), tga.bytesPerPixel);
00128 
00129                                 uint8 *end_run = image + chunkheader;
00130 
00131                                 if(tga.bytesPerPixel == 4) {
00132                                         while (image < end_run) {
00133                                                 *image++ = colorbuffer[0];
00134                                                 *image++ = colorbuffer[1];
00135                                                 *image++ = colorbuffer[2];
00136                                                 *image++ = colorbuffer[3];
00137                                         }
00138                                 }
00139                                 else {
00140                                         while (image < end_run) {
00141                                                 *image++ = colorbuffer[0];
00142                                                 *image++ = colorbuffer[1];
00143                                                 *image++ = colorbuffer[2];
00144                                         }
00145                                 }
00146                         }
00147                 }
00148         }
00149         else
00150         {
00151                 // Is uncompressed
00152                 ds->read(static_cast<uint8 *>(temp_buffer), width * height * tga.bytesPerPixel);
00153         }
00154 
00155         // Create Actual Buffer
00156         buffer  = new uint32[width * height];
00157 
00158         // Couldn't allocate
00159         if (!buffer)
00160         {
00161                 delete [] temp_buffer;
00162                 return false;
00163         }
00164 
00165         // Convert TGA Format into Actual Format
00166         ConvertFormat(temp_buffer, tga);
00167 
00168         // Calc texture log2's 
00169         CalcLOG2s();
00170 
00171         // Free temp buffer and return
00172         delete [] temp_buffer;
00173         return true;
00174 }
00175 
00176 //
00177 // Convert the loaded buffer into something a little more useful
00178 //
00179 void TextureTarga::ConvertFormat(uint8 *src, TGA &tga)
00180 {
00181         // End iterations
00182         uint32 *dst = buffer;
00183         uint32 *end = buffer + width * height;
00184         uint32 line_size = width;
00185 
00186         uint32 src_line_inc = 0;
00187 
00188         if (tga.Flipped) {
00189                 src_line_inc = width * tga.bytesPerPixel * 2;
00190                 src = src + (height-1) * width * tga.bytesPerPixel;
00191         }
00192 
00193         while (dst < end) {
00194                 
00195                 uint32 *line_end = dst + line_size;
00196 
00197                 if (tga.Bpp == 32) while (dst < line_end) {
00198 
00199                         // extract RGB components, and pack them into an int
00200                         *dst++ = (src[0] << TEX32_B_SHIFT)
00201                                 | (src[1] << TEX32_G_SHIFT) 
00202                                 | (src[2] << TEX32_R_SHIFT) 
00203                                 | (src[3] << TEX32_A_SHIFT);
00204 
00205                         src += 4;
00206                 }
00207                 else if (tga.Bpp == 24) while (dst < line_end) {
00208 
00209                         // extract RGB components, and pack them into an int
00210                         *dst++ = (src[0] << TEX32_B_SHIFT)
00211                                 | (src[1] << TEX32_G_SHIFT) 
00212                                 | (src[2] << TEX32_R_SHIFT) 
00213                                 | (255 << TEX32_A_SHIFT);
00214 
00215                         src += 3;
00216                 }
00217 
00218                 src -= src_line_inc;
00219         }
00220 }

Generated on Fri Jul 27 22:27:42 2007 for pentagram by  doxygen 1.4.7