1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
\r
2 // This file is part of the "Irrlicht Engine".
\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
\r
5 #include "CImageLoaderTGA.h"
\r
7 #ifdef _IRR_COMPILE_WITH_TGA_LOADER_
\r
9 #include "IReadFile.h"
\r
11 #include "CColorConverter.h"
\r
13 #include "irrString.h"
\r
22 //! returns true if the file maybe is able to be loaded by this class
\r
23 //! based on the file extension (e.g. ".tga")
\r
24 bool CImageLoaderTGA::isALoadableFileExtension(const io::path& filename) const
\r
26 return core::hasFileExtension ( filename, "tga" );
\r
30 //! loads a compressed tga.
\r
31 u8 *CImageLoaderTGA::loadCompressedImage(io::IReadFile *file, const STGAHeader& header) const
\r
33 // This was written and sent in by Jon Pry, thank you very much!
\r
34 // I only changed the formatting a little bit.
\r
36 s32 bytesPerPixel = header.PixelDepth/8;
\r
37 s32 imageSize = header.ImageHeight * header.ImageWidth * bytesPerPixel;
\r
38 u8* data = new u8[imageSize];
\r
39 s32 currentByte = 0;
\r
41 while(currentByte < imageSize)
\r
44 file->read(&chunkheader, sizeof(u8)); // Read The Chunk's Header
\r
46 if(chunkheader < 128) // If The Chunk Is A 'RAW' Chunk
\r
48 chunkheader++; // Add 1 To The Value To Get Total Number Of Raw Pixels
\r
50 file->read(&data[currentByte], bytesPerPixel * chunkheader);
\r
51 currentByte += bytesPerPixel * chunkheader;
\r
55 // thnx to neojzs for some fixes with this code
\r
57 // If It's An RLE Header
\r
58 chunkheader -= 127; // Subtract 127 To Get Rid Of The ID Bit
\r
60 s32 dataOffset = currentByte;
\r
61 file->read(&data[dataOffset], bytesPerPixel);
\r
63 currentByte += bytesPerPixel;
\r
65 for(s32 counter = 1; counter < chunkheader; counter++)
\r
67 for(s32 elementCounter=0; elementCounter < bytesPerPixel; elementCounter++)
\r
68 data[currentByte + elementCounter] = data[dataOffset + elementCounter];
\r
70 currentByte += bytesPerPixel;
\r
80 //! returns true if the file maybe is able to be loaded by this class
\r
81 bool CImageLoaderTGA::isALoadableFileFormat(io::IReadFile* file) const
\r
87 memset(&footer, 0, sizeof(STGAFooter));
\r
88 file->seek(file->getSize()-sizeof(STGAFooter));
\r
89 file->read(&footer, sizeof(STGAFooter));
\r
90 return (!strcmp(footer.Signature,"TRUEVISION-XFILE.")); // very old tgas are refused.
\r
95 //! creates a surface from the file
\r
96 IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const
\r
101 file->read(&header, sizeof(STGAHeader));
\r
103 #ifdef __BIG_ENDIAN__
\r
104 header.ColorMapLength = os::Byteswap::byteswap(header.ColorMapLength);
\r
105 header.ImageWidth = os::Byteswap::byteswap(header.ImageWidth);
\r
106 header.ImageHeight = os::Byteswap::byteswap(header.ImageHeight);
\r
109 // skip image identification field
\r
110 if (header.IdLength)
\r
111 file->seek(header.IdLength, true);
\r
113 if (header.ColorMapType)
\r
115 // create 32 bit palette
\r
116 palette = new u32[ header.ColorMapLength];
\r
119 u8 * colorMap = new u8[header.ColorMapEntrySize/8 * header.ColorMapLength];
\r
120 file->read(colorMap,header.ColorMapEntrySize/8 * header.ColorMapLength);
\r
122 // convert to 32-bit palette
\r
123 switch ( header.ColorMapEntrySize )
\r
126 CColorConverter::convert_A1R5G5B5toA8R8G8B8(colorMap, header.ColorMapLength, palette);
\r
129 CColorConverter::convert_B8G8R8toA8R8G8B8(colorMap, header.ColorMapLength, palette);
\r
132 CColorConverter::convert_B8G8R8A8toA8R8G8B8(colorMap, header.ColorMapLength, palette);
\r
135 delete [] colorMap;
\r
142 if ( header.ImageType == 1 || // Uncompressed, color-mapped images.
\r
143 header.ImageType == 2 || // Uncompressed, RGB images
\r
144 header.ImageType == 3 // Uncompressed, black and white images
\r
147 const s32 imageSize = header.ImageHeight * header.ImageWidth * header.PixelDepth/8;
\r
148 data = new u8[imageSize];
\r
149 file->read(data, imageSize);
\r
152 if(header.ImageType == 10)
\r
154 // Runlength encoded RGB images
\r
155 data = loadCompressedImage(file, header);
\r
159 os::Printer::log("Unsupported TGA file type", file->getFileName(), ELL_ERROR);
\r
166 switch(header.PixelDepth)
\r
170 if (header.ImageType==3) // grey image
\r
172 image = new CImage(ECF_R8G8B8,
\r
173 core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
\r
175 CColorConverter::convert8BitTo24Bit((u8*)data,
\r
176 (u8*)image->getData(),
\r
177 header.ImageWidth,header.ImageHeight,
\r
178 0, 0, (header.ImageDescriptor&0x20)==0);
\r
182 image = new CImage(ECF_A1R5G5B5,
\r
183 core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
\r
185 CColorConverter::convert8BitTo16Bit((u8*)data,
\r
186 (s16*)image->getData(),
\r
187 header.ImageWidth,header.ImageHeight,
\r
189 (header.ImageDescriptor&0x20)==0);
\r
194 image = new CImage(ECF_A1R5G5B5,
\r
195 core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
\r
197 CColorConverter::convert16BitTo16Bit((s16*)data,
\r
198 (s16*)image->getData(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0);
\r
201 image = new CImage(ECF_R8G8B8,
\r
202 core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
\r
204 CColorConverter::convert24BitTo24Bit(
\r
205 (u8*)data, (u8*)image->getData(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0, true);
\r
208 image = new CImage(ECF_A8R8G8B8,
\r
209 core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));
\r
211 CColorConverter::convert32BitTo32Bit((s32*)data,
\r
212 (s32*)image->getData(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0);
\r
215 os::Printer::log("Unsupported TGA format", file->getFileName(), ELL_ERROR);
\r
226 //! creates a loader which is able to load tgas
\r
227 IImageLoader* createImageLoaderTGA()
\r
229 return new CImageLoaderTGA();
\r
233 } // end namespace video
\r
234 } // end namespace irr
\r