--- /dev/null
+// Copyright (C) 2002-2012 Nikolaus Gebhardt\r
+// This file is part of the "Irrlicht Engine".\r
+// For conditions of distribution and use, see copyright notice in irrlicht.h\r
+\r
+#include "CImageLoaderTGA.h"\r
+\r
+#ifdef _IRR_COMPILE_WITH_TGA_LOADER_\r
+\r
+#include "IReadFile.h"\r
+#include "os.h"\r
+#include "CColorConverter.h"\r
+#include "CImage.h"\r
+#include "irrString.h"\r
+\r
+\r
+namespace irr\r
+{\r
+namespace video\r
+{\r
+\r
+\r
+//! returns true if the file maybe is able to be loaded by this class\r
+//! based on the file extension (e.g. ".tga")\r
+bool CImageLoaderTGA::isALoadableFileExtension(const io::path& filename) const\r
+{\r
+ return core::hasFileExtension ( filename, "tga" );\r
+}\r
+\r
+\r
+//! loads a compressed tga.\r
+u8 *CImageLoaderTGA::loadCompressedImage(io::IReadFile *file, const STGAHeader& header) const\r
+{\r
+ // This was written and sent in by Jon Pry, thank you very much!\r
+ // I only changed the formatting a little bit.\r
+\r
+ s32 bytesPerPixel = header.PixelDepth/8;\r
+ s32 imageSize = header.ImageHeight * header.ImageWidth * bytesPerPixel;\r
+ u8* data = new u8[imageSize];\r
+ s32 currentByte = 0;\r
+\r
+ while(currentByte < imageSize)\r
+ {\r
+ u8 chunkheader = 0;\r
+ file->read(&chunkheader, sizeof(u8)); // Read The Chunk's Header\r
+\r
+ if(chunkheader < 128) // If The Chunk Is A 'RAW' Chunk\r
+ {\r
+ chunkheader++; // Add 1 To The Value To Get Total Number Of Raw Pixels\r
+\r
+ file->read(&data[currentByte], bytesPerPixel * chunkheader);\r
+ currentByte += bytesPerPixel * chunkheader;\r
+ }\r
+ else\r
+ {\r
+ // thnx to neojzs for some fixes with this code\r
+\r
+ // If It's An RLE Header\r
+ chunkheader -= 127; // Subtract 127 To Get Rid Of The ID Bit\r
+\r
+ s32 dataOffset = currentByte;\r
+ file->read(&data[dataOffset], bytesPerPixel);\r
+\r
+ currentByte += bytesPerPixel;\r
+\r
+ for(s32 counter = 1; counter < chunkheader; counter++)\r
+ {\r
+ for(s32 elementCounter=0; elementCounter < bytesPerPixel; elementCounter++)\r
+ data[currentByte + elementCounter] = data[dataOffset + elementCounter];\r
+\r
+ currentByte += bytesPerPixel;\r
+ }\r
+ }\r
+ }\r
+\r
+ return data;\r
+}\r
+\r
+\r
+\r
+//! returns true if the file maybe is able to be loaded by this class\r
+bool CImageLoaderTGA::isALoadableFileFormat(io::IReadFile* file) const\r
+{\r
+ if (!file)\r
+ return false;\r
+\r
+ STGAFooter footer;\r
+ memset(&footer, 0, sizeof(STGAFooter));\r
+ file->seek(file->getSize()-sizeof(STGAFooter));\r
+ file->read(&footer, sizeof(STGAFooter));\r
+ return (!strcmp(footer.Signature,"TRUEVISION-XFILE.")); // very old tgas are refused.\r
+}\r
+\r
+\r
+\r
+//! creates a surface from the file\r
+IImage* CImageLoaderTGA::loadImage(io::IReadFile* file) const\r
+{\r
+ STGAHeader header;\r
+ u32 *palette = 0;\r
+\r
+ file->read(&header, sizeof(STGAHeader));\r
+\r
+#ifdef __BIG_ENDIAN__\r
+ header.ColorMapLength = os::Byteswap::byteswap(header.ColorMapLength);\r
+ header.ImageWidth = os::Byteswap::byteswap(header.ImageWidth);\r
+ header.ImageHeight = os::Byteswap::byteswap(header.ImageHeight);\r
+#endif\r
+\r
+ // skip image identification field\r
+ if (header.IdLength)\r
+ file->seek(header.IdLength, true);\r
+\r
+ if (header.ColorMapType)\r
+ {\r
+ // create 32 bit palette\r
+ palette = new u32[ header.ColorMapLength];\r
+\r
+ // read color map\r
+ u8 * colorMap = new u8[header.ColorMapEntrySize/8 * header.ColorMapLength];\r
+ file->read(colorMap,header.ColorMapEntrySize/8 * header.ColorMapLength);\r
+\r
+ // convert to 32-bit palette\r
+ switch ( header.ColorMapEntrySize )\r
+ {\r
+ case 16:\r
+ CColorConverter::convert_A1R5G5B5toA8R8G8B8(colorMap, header.ColorMapLength, palette);\r
+ break;\r
+ case 24:\r
+ CColorConverter::convert_B8G8R8toA8R8G8B8(colorMap, header.ColorMapLength, palette);\r
+ break;\r
+ case 32:\r
+ CColorConverter::convert_B8G8R8A8toA8R8G8B8(colorMap, header.ColorMapLength, palette);\r
+ break;\r
+ }\r
+ delete [] colorMap;\r
+ }\r
+\r
+ // read image\r
+\r
+ u8* data = 0;\r
+\r
+ if ( header.ImageType == 1 || // Uncompressed, color-mapped images.\r
+ header.ImageType == 2 || // Uncompressed, RGB images\r
+ header.ImageType == 3 // Uncompressed, black and white images\r
+ )\r
+ {\r
+ const s32 imageSize = header.ImageHeight * header.ImageWidth * header.PixelDepth/8;\r
+ data = new u8[imageSize];\r
+ file->read(data, imageSize);\r
+ }\r
+ else\r
+ if(header.ImageType == 10)\r
+ {\r
+ // Runlength encoded RGB images\r
+ data = loadCompressedImage(file, header);\r
+ }\r
+ else\r
+ {\r
+ os::Printer::log("Unsupported TGA file type", file->getFileName(), ELL_ERROR);\r
+ delete [] palette;\r
+ return 0;\r
+ }\r
+\r
+ IImage* image = 0;\r
+\r
+ switch(header.PixelDepth)\r
+ {\r
+ case 8:\r
+ {\r
+ if (header.ImageType==3) // grey image\r
+ {\r
+ image = new CImage(ECF_R8G8B8,\r
+ core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));\r
+ if (image)\r
+ CColorConverter::convert8BitTo24Bit((u8*)data,\r
+ (u8*)image->getData(),\r
+ header.ImageWidth,header.ImageHeight,\r
+ 0, 0, (header.ImageDescriptor&0x20)==0);\r
+ }\r
+ else\r
+ {\r
+ image = new CImage(ECF_A1R5G5B5,\r
+ core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));\r
+ if (image)\r
+ CColorConverter::convert8BitTo16Bit((u8*)data,\r
+ (s16*)image->getData(),\r
+ header.ImageWidth,header.ImageHeight,\r
+ (s32*) palette, 0,\r
+ (header.ImageDescriptor&0x20)==0);\r
+ }\r
+ }\r
+ break;\r
+ case 16:\r
+ image = new CImage(ECF_A1R5G5B5,\r
+ core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));\r
+ if (image)\r
+ CColorConverter::convert16BitTo16Bit((s16*)data,\r
+ (s16*)image->getData(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0);\r
+ break;\r
+ case 24:\r
+ image = new CImage(ECF_R8G8B8,\r
+ core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));\r
+ if (image)\r
+ CColorConverter::convert24BitTo24Bit(\r
+ (u8*)data, (u8*)image->getData(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0, true);\r
+ break;\r
+ case 32:\r
+ image = new CImage(ECF_A8R8G8B8,\r
+ core::dimension2d<u32>(header.ImageWidth, header.ImageHeight));\r
+ if (image)\r
+ CColorConverter::convert32BitTo32Bit((s32*)data,\r
+ (s32*)image->getData(), header.ImageWidth, header.ImageHeight, 0, (header.ImageDescriptor&0x20)==0);\r
+ break;\r
+ default:\r
+ os::Printer::log("Unsupported TGA format", file->getFileName(), ELL_ERROR);\r
+ break;\r
+ }\r
+\r
+ delete [] data;\r
+ delete [] palette;\r
+\r
+ return image;\r
+}\r
+\r
+\r
+//! creates a loader which is able to load tgas\r
+IImageLoader* createImageLoaderTGA()\r
+{\r
+ return new CImageLoaderTGA();\r
+}\r
+\r
+\r
+} // end namespace video\r
+} // end namespace irr\r
+\r
+#endif\r
+\r
--- /dev/null
+// Copyright (C) 2002-2012 Nikolaus Gebhardt\r
+// This file is part of the "Irrlicht Engine".\r
+// For conditions of distribution and use, see copyright notice in irrlicht.h\r
+\r
+#ifndef __C_IMAGE_LOADER_TGA_H_INCLUDED__\r
+#define __C_IMAGE_LOADER_TGA_H_INCLUDED__\r
+\r
+#include "IrrCompileConfig.h"\r
+\r
+#include "IImageLoader.h"\r
+\r
+\r
+namespace irr\r
+{\r
+namespace video\r
+{\r
+\r
+#if defined(_IRR_COMPILE_WITH_TGA_LOADER_) || defined(_IRR_COMPILE_WITH_TGA_WRITER_)\r
+\r
+// byte-align structures\r
+#include "irrpack.h"\r
+\r
+ // these structs are also used in the TGA writer\r
+ struct STGAHeader{\r
+ u8 IdLength;\r
+ u8 ColorMapType;\r
+ u8 ImageType;\r
+ u8 FirstEntryIndex[2];\r
+ u16 ColorMapLength;\r
+ u8 ColorMapEntrySize;\r
+ u8 XOrigin[2];\r
+ u8 YOrigin[2];\r
+ u16 ImageWidth;\r
+ u16 ImageHeight;\r
+ u8 PixelDepth;\r
+ u8 ImageDescriptor;\r
+ } PACK_STRUCT;\r
+\r
+ struct STGAFooter\r
+ {\r
+ u32 ExtensionOffset;\r
+ u32 DeveloperOffset;\r
+ c8 Signature[18];\r
+ } PACK_STRUCT;\r
+\r
+// Default alignment\r
+#include "irrunpack.h"\r
+\r
+#endif // compiled with loader or reader\r
+\r
+#ifdef _IRR_COMPILE_WITH_TGA_LOADER_\r
+\r
+/*!\r
+ Surface Loader for targa images\r
+*/\r
+class CImageLoaderTGA : public IImageLoader\r
+{\r
+public:\r
+\r
+ //! returns true if the file maybe is able to be loaded by this class\r
+ //! based on the file extension (e.g. ".tga")\r
+ virtual bool isALoadableFileExtension(const io::path& filename) const _IRR_OVERRIDE_;\r
+\r
+ //! returns true if the file maybe is able to be loaded by this class\r
+ virtual bool isALoadableFileFormat(io::IReadFile* file) const _IRR_OVERRIDE_;\r
+\r
+ //! creates a surface from the file\r
+ virtual IImage* loadImage(io::IReadFile* file) const _IRR_OVERRIDE_;\r
+\r
+private:\r
+\r
+ //! loads a compressed tga. Was written and sent in by Jon Pry, thank you very much!\r
+ u8* loadCompressedImage(io::IReadFile *file, const STGAHeader& header) const;\r
+};\r
+\r
+#endif // compiled with loader\r
+\r
+} // end namespace video\r
+} // end namespace irr\r
+\r
+#endif\r
+\r