Example #1
0
// ***************************************************************************
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;
}