// *************************************************************************** int main(int argc, char **argv) { 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")<inputFileName.length()) { return 0; } NLMISC::CIFile input; if(!input.open(inputFileName)) { cerr<<"Can't open input file "<<inputFileName<<endl; return 1; } uint8 imageDepth = picTga.load(input); if(imageDepth==0) { cerr<<"Can't load file : "<<inputFileName<<endl; return 1; } if(imageDepth!=16 && imageDepth!=24 && imageDepth!=32 && imageDepth!=8) { cerr<<"Image not supported : "<<imageDepth<<endl; return 1; } input.close(); uint32 height = picTga.getHeight(); uint32 width= picTga.getWidth(); picTga.convertToType (CBitmap::RGBA); // Output file name and algo. //=========================== std::string outputFileName; if (!OptOutputFileName.empty()) outputFileName = OptOutputFileName; else outputFileName = getOutputFileName(inputFileName); // Check dest algo if (OptAlgo==NOT_DEFINED) OptAlgo = getType (outputFileName.c_str()); // Choose Algo. if(OptAlgo!=NOT_DEFINED) { algo= OptAlgo; } else { if(imageDepth==24) algo = DXT1; else algo = DXT5; } // Data check //=========== if(dataCheck(inputFileName.c_str(),outputFileName.c_str(), OptAlgo, OptMipMap)) { cout<<outputFileName<<" : a recent dds file already exists"<<endl; return 0; } // Vectors for RGBA data CObjectVector<uint8> RGBASrc = picTga.getPixels(); CObjectVector<uint8> RGBASrc2; CObjectVector<uint8> 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 NLMISC::CIFile input2; if (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; i<width*height; i++) { // If no UserColor, must take same RGB, and keep same Alpha from src1 !!! So texture can have both alpha // userColor and other alpha usage. if(pRGBASrc2[i].A==255) { RGBADest[dstRGBADestId++]= pRGBASrc[i].R; RGBADest[dstRGBADestId++]= pRGBASrc[i].G; RGBADest[dstRGBADestId++]= pRGBASrc[i].B; RGBADest[dstRGBADestId++]= pRGBASrc[i].A; } else { // Old code. /*uint8 F = (uint8) ((float)pRGBASrc[i].R*0.3 + (float)pRGBASrc[i].G*0.56 + (float)pRGBASrc[i].B*0.14); uint8 Frgb; if((F*pRGBASrc2[i].A/255)==255) Frgb = 0; else Frgb = (255-pRGBASrc2[i].A)/(255-F*pRGBASrc2[i].A/255); RGBADest[dstRGBADestId++]= Frgb*pRGBASrc[i].R/255; RGBADest[dstRGBADestId++]= Frgb*pRGBASrc[i].G/255; RGBADest[dstRGBADestId++]= Frgb*pRGBASrc[i].B/255; RGBADest[dstRGBADestId++]= F*pRGBASrc[i].A/255;*/ // New code: use new restrictions from IDriver. float Rt, Gt, Bt, At; float Lt; float Rtm, Gtm, Btm, Atm; // read 0-1 RGB pixel. Rt= (float)pRGBASrc[i].R/255; Gt= (float)pRGBASrc[i].G/255; Bt= (float)pRGBASrc[i].B/255; Lt= Rt*0.3f + Gt*0.56f + Bt*0.14f; // take Alpha from userColor src. At= (float)pRGBASrc2[i].A/255; Atm= 1-Lt*(1-At); // If normal case. if(Atm>0) { 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 "<<outputFileName<<endl; return 1; } try { if (algo == TGA16) { picSrc.writeTGA (output, 16); } else if (algo == TGA8) { picSrc.convertToType(CBitmap::Luminance); picSrc.writeTGA (output, 8); } else if (algo == PNG16) { picSrc.writePNG (output, 16); } else if (algo == PNG8) { picSrc.convertToType(CBitmap::Luminance); picSrc.writePNG (output, 8); } } catch(NLMISC::EWriteError &e) { cerr<<e.what()<<endl; return 1; } output.close(); } else { // Compress //=========== // log. std::string algostr; switch(algo) { case DXT1: algostr = "DXTC1"; break; case DXT1A: algostr = "DXTC1A"; break; case DXT3: algostr = "DXTC3"; break; case DXT5: algostr = "DXTC5"; break; } cout<<"compressing ("<<algostr<<") "<<inputFileName<<" to "<<outputFileName<<endl; // Saving compressed DDS file // ================= NLMISC::COFile output; if(!output.open(outputFileName)) { cerr<<"Can't open output file "<<outputFileName<<endl; return 1; } try { CS3TCCompressor comp; comp.compress(picSrc, OptMipMap, algo, output); } catch(NLMISC::EWriteError &e) { cerr<<e.what()<<endl; return 1; } output.close(); } return 0; }