]> git.lizzy.rs Git - irrlicht.git/commitdiff
Readd TGA format support (#64)
authorROllerozxa <temporaryemail4meh+github@gmail.com>
Mon, 13 Sep 2021 19:21:26 +0000 (21:21 +0200)
committerGitHub <noreply@github.com>
Mon, 13 Sep 2021 19:21:26 +0000 (21:21 +0200)
include/IrrCompileConfig.h
source/Irrlicht/CImageLoaderTGA.cpp [new file with mode: 0644]
source/Irrlicht/CImageLoaderTGA.h [new file with mode: 0644]
source/Irrlicht/CMakeLists.txt

index e0550fac0a2ac13c9683e3c4ace2edd759b70492..32f247b5affd15617d2a1b79bff1d9868452e3f4 100644 (file)
@@ -400,6 +400,11 @@ B3D, MS3D or X meshes */
 #ifdef NO_IRR_COMPILE_WITH_PNG_LOADER_\r
 #undef _IRR_COMPILE_WITH_PNG_LOADER_\r
 #endif\r
+//! Define _IRR_COMPILE_WITH_TGA_LOADER_ if you want to load .tga files\r
+#define _IRR_COMPILE_WITH_TGA_LOADER_\r
+#ifdef NO_IRR_COMPILE_WITH_TGA_LOADER_\r
+#undef _IRR_COMPILE_WITH_TGA_LOADER_\r
+#endif\r
 \r
 //! Define _IRR_COMPILE_WITH_JPG_WRITER_ if you want to write .jpg files\r
 #define _IRR_COMPILE_WITH_JPG_WRITER_\r
diff --git a/source/Irrlicht/CImageLoaderTGA.cpp b/source/Irrlicht/CImageLoaderTGA.cpp
new file mode 100644 (file)
index 0000000..c9b3a9d
--- /dev/null
@@ -0,0 +1,237 @@
+// 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
diff --git a/source/Irrlicht/CImageLoaderTGA.h b/source/Irrlicht/CImageLoaderTGA.h
new file mode 100644 (file)
index 0000000..8ea0246
--- /dev/null
@@ -0,0 +1,82 @@
+// 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
index 0c8033c90b4ed5877ee97f1579be178885885f9a..961e55416d87090c93700d5fe65a08e978e1f77f 100644 (file)
@@ -171,6 +171,7 @@ set(IRRIMAGEOBJ
        CImageLoaderBMP.cpp
        CImageLoaderJPG.cpp
        CImageLoaderPNG.cpp
+       CImageLoaderTGA.cpp
        CImageWriterJPG.cpp
        CImageWriterPNG.cpp
 )