From 597441ca33d97d5ed75f570d3211fe56f5c14076 Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Mon, 13 Apr 2020 20:42:57 +0100 Subject: [PATCH] Add option to treat all TGA files as TGA 1.0 Some files which are malformed TGA 2.0 files are technically valid TGA 1.0 files. For example, an image that just happened to have pixel data matching the TGA 2.0 footer or files created by buggy TGA 2.0 writers and were only ever fed to TGA 1.0 readers. --- src/osgPlugins/tga/ReaderWriterTGA.cpp | 95 ++++++++++++++------------ 1 file changed, 50 insertions(+), 45 deletions(-) diff --git a/src/osgPlugins/tga/ReaderWriterTGA.cpp b/src/osgPlugins/tga/ReaderWriterTGA.cpp index 7249bfe29..4819de94a 100644 --- a/src/osgPlugins/tga/ReaderWriterTGA.cpp +++ b/src/osgPlugins/tga/ReaderWriterTGA.cpp @@ -339,7 +339,8 @@ unsigned char * simage_tga_load(std::istream& fin, int *width_ret, int *height_ret, -int *numComponents_ret) +int *numComponents_ret, +bool ignoreTGA2Fields) { unsigned char header[18]; unsigned char footer[26]; @@ -382,50 +383,54 @@ int *numComponents_ret) fin.seekg(-26, std::ios::end); endOfImage = fin.tellg() + (std::streamoff)26; - fin.read((char*)footer, 26); - if (fin.gcount() != 26) - { - tgaerror = ERR_READ; - return NULL; - } - // TGA footer signature is null-terminated, so works like a C string - if (strcmp((char*)&footer[8], "TRUEVISION-XFILE.") == 0) + if (!ignoreTGA2Fields) { - endOfImage -= 26; - unsigned int extensionAreaOffset = getInt32(&footer[0]); - unsigned int developerAreaOffset = getInt32(&footer[4]); - - if (extensionAreaOffset != 0) + fin.read((char*)footer, 26); + if (fin.gcount() != 26) { - endOfImage = std::min(endOfImage, (std::streampos)extensionAreaOffset); - - // We only need the last few fields of the extension area - fin.seekg(extensionAreaOffset + 482); - unsigned char extensionAreaBuffer[13]; - fin.read((char*)extensionAreaBuffer, 13); - if (fin.gcount() != 13) - { - tgaerror = ERR_READ; - return NULL; - } - - unsigned int colorCorrectionOffset = getInt32(&extensionAreaBuffer[0]); - unsigned int postageStampOffset = getInt32(&extensionAreaBuffer[4]); - unsigned int scanLineOffset = getInt32(&extensionAreaBuffer[8]); - - if (colorCorrectionOffset != 0) - endOfImage = std::min(endOfImage, (std::streampos)colorCorrectionOffset); - if (postageStampOffset != 0) - endOfImage = std::min(endOfImage, (std::streampos)postageStampOffset); - if (scanLineOffset != 0) - endOfImage = std::min(endOfImage, (std::streampos)scanLineOffset); - - attributeType = (AttributeType) extensionAreaBuffer[12]; + tgaerror = ERR_READ; + return NULL; } - if (developerAreaOffset != 0) - endOfImage = std::min(endOfImage, (std::streampos)developerAreaOffset); + // TGA footer signature is null-terminated, so works like a C string + if (strcmp((char*)&footer[8], "TRUEVISION-XFILE.") == 0) + { + endOfImage -= 26; + unsigned int extensionAreaOffset = getInt32(&footer[0]); + unsigned int developerAreaOffset = getInt32(&footer[4]); + + if (extensionAreaOffset != 0) + { + endOfImage = std::min(endOfImage, (std::streampos)extensionAreaOffset); + + // We only need the last few fields of the extension area + fin.seekg(extensionAreaOffset + 482); + unsigned char extensionAreaBuffer[13]; + fin.read((char*)extensionAreaBuffer, 13); + if (fin.gcount() != 13) + { + tgaerror = ERR_READ; + return NULL; + } + + unsigned int colorCorrectionOffset = getInt32(&extensionAreaBuffer[0]); + unsigned int postageStampOffset = getInt32(&extensionAreaBuffer[4]); + unsigned int scanLineOffset = getInt32(&extensionAreaBuffer[8]); + + if (colorCorrectionOffset != 0) + endOfImage = std::min(endOfImage, (std::streampos)colorCorrectionOffset); + if (postageStampOffset != 0) + endOfImage = std::min(endOfImage, (std::streampos)postageStampOffset); + if (scanLineOffset != 0) + endOfImage = std::min(endOfImage, (std::streampos)scanLineOffset); + + attributeType = (AttributeType)extensionAreaBuffer[12]; + } + + if (developerAreaOffset != 0) + endOfImage = std::min(endOfImage, (std::streampos)developerAreaOffset); + } } fin.seekg(18); @@ -804,14 +809,14 @@ class ReaderWriterTGA : public osgDB::ReaderWriter virtual const char* className() const { return "TGA Image Reader"; } - ReadResult readTGAStream(std::istream& fin) const + ReadResult readTGAStream(std::istream& fin, bool ignoreTGA2Fields) const { unsigned char *imageData = NULL; int width_ret; int height_ret; int numComponents_ret; - imageData = simage_tga_load(fin,&width_ret,&height_ret,&numComponents_ret); + imageData = simage_tga_load(fin, &width_ret, &height_ret, &numComponents_ret, ignoreTGA2Fields); if (imageData==NULL) return ReadResult::FILE_NOT_HANDLED; @@ -852,9 +857,9 @@ class ReaderWriterTGA : public osgDB::ReaderWriter return readImage(file, options); } - virtual ReadResult readImage(std::istream& fin,const Options* =NULL) const + virtual ReadResult readImage(std::istream& fin, const Options* options = NULL) const { - return readTGAStream(fin); + return readTGAStream(fin, options && options->getOptionString().find("IGNORE_TGA_2_FIELDS") != std::string::npos); } virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const @@ -867,7 +872,7 @@ class ReaderWriterTGA : public osgDB::ReaderWriter osgDB::ifstream istream(fileName.c_str(), std::ios::in | std::ios::binary); if(!istream) return ReadResult::FILE_NOT_HANDLED; - ReadResult rr = readTGAStream(istream); + ReadResult rr = readTGAStream(istream, options && options->getOptionString().find("IGNORE_TGA_2_FIELDS") != std::string::npos); if(rr.validImage()) rr.getImage()->setFileName(file); return rr; }