// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include #include "nel/misc/file.h" #include "nel/misc/bitmap.h" #include "nel/misc/path.h" #include "nel/misc/debug.h" #include #include "../s3tc_compressor_lib/s3tc_compressor.h" using namespace NLMISC; using namespace std; #define TGA8 8 #define TGA16 16 #define PNG8 108 #define PNG16 116 #define NOT_DEFINED 0xff bool sameType(const std::string &sFileNameDest, uint8 algo); bool dataCheck(const std::string &sFileNameSrc, const std::string &FileNameDest, uint8 algo); std::string getOutputFileName(const std::string &inputFileName); void writeInstructions(); uint8 getType(const std::string &sFileNameDest) { uint32 dds; FILE *f = fopen(sFileNameDest.c_str(),"rb"); if(f==NULL) { return NOT_DEFINED; } CS3TCCompressor::DDS_HEADER h; if (fread(&dds,1,4,f) != 4) { fclose(f); return NOT_DEFINED; } #ifdef NL_BIG_ENDIAN NLMISC_BSWAP32(dds); #endif if (fread(&h,sizeof(CS3TCCompressor::DDS_HEADER),1,f) != 1) { fclose(f); return NOT_DEFINED; } if(fclose(f)) { cerr<0) { return DXT1A; } if(h.ddpf.dwFourCC==MAKEFOURCC('D','X', 'T', '3')) { return DXT3; } if(h.ddpf.dwFourCC==MAKEFOURCC('D','X', 'T', '5')) { return DXT5; } return NOT_DEFINED; } bool sameType(const std::string &sFileNameDest, uint8 &algo, bool wantMipMap) { uint32 dds; FILE *f = fopen(sFileNameDest.c_str(),"rb"); if(f==NULL) { return false; } CS3TCCompressor::DDS_HEADER h; if (fread(&dds,1,4,f) != 4) { fclose(f); return false; } if (fread(&h,sizeof(::DDS_HEADER),1,f) != 1) { fclose(f); return false; } if(fclose(f)) { cerr<0) algoOk=true; break; case DXT3: if(h.ddpf.dwFourCC==MAKEFOURCC('D','X', 'T', '3')) algoOk=true; break; case DXT5: if(h.ddpf.dwFourCC==MAKEFOURCC('D','X', 'T', '5')) algoOk=true; break; } if(!algoOk) return false; // Test Mipmap. bool fileHasMipMap= (h.dwFlags&DDSD_MIPMAPCOUNT) && (h.dwMipMapCount>1); if(fileHasMipMap==wantMipMap) return true; return false; } bool dataCheck(const std::string &sFileNameSrc, const std::string &sFileNameDest, uint8& algo, bool wantMipMap) { if (!CFile::fileExists(sFileNameSrc)) { cerr << "Can't open file " << sFileNameSrc << endl; return false; } if (!CFile::fileExists(sFileNameDest)) { return false; // destination file doesn't exist yet } uint32 lastWriteTime1 = CFile::getFileModificationDate(sFileNameSrc); uint32 lastWriteTime2 = CFile::getFileModificationDate(sFileNameDest); if(lastWriteTime1 > lastWriteTime2) { return false; } if (lastWriteTime1 < lastWriteTime2) { if(!sameType(sFileNameDest, algo, wantMipMap)) { return false; // file exists but a new compression type is required } } return true; } void writeInstructions() { cout< [-o ] [-a ] [-m]"<=argc) return false; OptOutputFileName= argv[i]; } // Algo. else if(!strcmp(argv[i], "-a")) { i++; if(i>=argc) return false; if(!strcmp(argv[i],"1")) OptAlgo = DXT1; else if(!strcmp(argv[i],"1A")) OptAlgo = DXT1A; else if(!strcmp(argv[i],"1a")) OptAlgo = DXT1A; else if(!strcmp(argv[i],"3")) OptAlgo = DXT3; else if(!strcmp(argv[i],"5")) OptAlgo = DXT5; else if(!strcmp(argv[i],"tga16")) OptAlgo = TGA16; else if(!strcmp(argv[i],"tga8")) OptAlgo = TGA8; else if(!strcmp(argv[i],"png16")) OptAlgo = PNG16; else if(!strcmp(argv[i],"png8")) OptAlgo = PNG8; else { cerr<<"Algorithm unknown : "<>2; } } } // *************************************************************************** int main(int argc, char **argv) { CApplicationContext applicationContext; uint8 algo; // Parse Command Line. //==================== if(argc<2) { writeInstructions(); return 0; } if(!strcmp(argv[1],"/?")) { writeInstructions(); return 0; } if(!strcmp(argv[1],"-?")) { writeInstructions(); return 0; } if(!parseOptions(argc, argv)) { writeInstructions(); return 0; } // Reading TGA or PNG and converting to RGBA //==================================== CBitmap picTga; CBitmap picTga2; CBitmap picSrc; std::string inputFileName(argv[1]); if(inputFileName.find("_usercolor") RGBASrc = picTga.getPixels(); CObjectVector RGBASrc2; CObjectVector RGBADest; RGBADest.resize(height*width*4); uint dstRGBADestId= 0; // UserColor //=========== /* // Checking if option "usercolor" has been used std::string userColorFileName; if(argc>4) { if(strcmp("-usercolor",argv[4])==0) { if(argc!=6) { writeInstructions(); return; } userColorFileName = argv[5]; } else { writeInstructions(); return; } } */ // Checking if associate usercolor file exists std::string userColorFileName; std::string::size_type pos = inputFileName.rfind("."); if (pos == std::string::npos) { // name whithout extension userColorFileName = inputFileName + "_usercolor"; } else { // append input filename extension userColorFileName = inputFileName.substr(0,pos) + "_usercolor" + inputFileName.substr(pos); } // Reading second Tga for user color, don't complain if _usercolor is missing NLMISC::CIFile input2; if (CPath::exists(userColorFileName) && input2.open(userColorFileName)) { picTga2.load(input2); uint32 height2 = picTga2.getHeight(); uint32 width2 = picTga2.getWidth(); nlassert(width2==width); nlassert(height2==height); picTga2.convertToType (CBitmap::RGBA); RGBASrc2 = picTga2.getPixels(); NLMISC::CRGBA *pRGBASrc = (NLMISC::CRGBA*)&RGBASrc[0]; NLMISC::CRGBA *pRGBASrc2 = (NLMISC::CRGBA*)&RGBASrc2[0]; for(uint32 i = 0; i0) { Rtm= Rt*At / Atm; Gtm= Gt*At / Atm; Btm= Bt*At / Atm; } // Else special case: At==0, and Lt==1. else { Rtm= Gtm= Btm= 0; } // copy to buffer. sint r,g,b,a; r= (sint)floor(Rtm*255+0.5f); g= (sint)floor(Gtm*255+0.5f); b= (sint)floor(Btm*255+0.5f); a= (sint)floor(Atm*255+0.5f); clamp(r, 0,255); clamp(g, 0,255); clamp(b, 0,255); clamp(a, 0,255); RGBADest[dstRGBADestId++]= r; RGBADest[dstRGBADestId++]= g; RGBADest[dstRGBADestId++]= b; RGBADest[dstRGBADestId++]= a; } } } else RGBADest = RGBASrc; // Copy to the dest bitmap. picSrc.resize(width, height, CBitmap::RGBA); picSrc.getPixels(0)= RGBADest; // Resize the destination bitmap ? while (Reduce != 0) { dividSize (picSrc); Reduce--; } // 8 or 16 bits TGA or PNG ? if ((algo == TGA16) || (algo == TGA8) || (algo == PNG16) || (algo == PNG8)) { // Saving TGA or PNG file //================= NLMISC::COFile output; if(!output.open(outputFileName)) { cerr<<"Can't open output file "<