gfxconversion/bmconv_s60/src/MAINFUNC.CPP
changeset 0 f453ebb75370
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gfxconversion/bmconv_s60/src/MAINFUNC.CPP	Tue Feb 02 01:11:11 2010 +0200
@@ -0,0 +1,652 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+#if defined(__MSVCDOTNET__) || defined(__TOOLS2__) || defined(__CW32__)
+#include <ostream>
+#include <iostream>
+using namespace std;
+#else //!__MSVCDOTNET__ && !__TOOLS2__ && !__CW32__
+#pragma warning(disable: 4100)
+#pragma warning(disable: 4511)
+#pragma warning(disable: 4512)
+#pragma warning(disable: 4530)
+#pragma warning(disable: 4663)
+#pragma warning(disable: 4710)
+#pragma warning(disable: 4786)
+#pragma warning(disable: 4800)
+#include <ostream.h>
+#endif //__MSVCDOTNET__
+
+#include "TOOLSVER.H"
+#include "BMCONV.H"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string>
+
+const int KMaxPaletteFileLen = 256;
+
+#ifdef __linux__
+const char* DefaultPaletteFileSearchLocations[] =
+{
+    "/epoc32/include/mw/ThirdPartyBitmap.pal",
+    "/epoc32/include/middleware/ThirdPartyBitmap.pal",
+    "/epoc32/include/ThirdPartyBitmap.pal"
+};
+#else
+const char* DefaultPaletteFileSearchLocations[] =
+{
+    "\\epoc32\\include\\mw\\ThirdPartyBitmap.pal",
+    "\\epoc32\\include\\middleware\\ThirdPartyBitmap.pal",
+    "\\epoc32\\include\\ThirdPartyBitmap.pal"
+};
+#endif
+
+/**
+Returns an informative error message, the result of the program actions performed.
+@return Informative error string
+@param aErrorNumber The error returned from the actions performed
+@param aDestfile The multiple bitmap store file name
+@param aDestCreated True if the multiple bitmap store has been created/modified
+*/
+
+char* ErrorMessage(int aErrorNumber, char* aDestfile=NULL, bool aDestCreated=false)
+	{
+	// Remove the multiple bitmap store if it has been created/modified during an fstream session and there has been an error
+	if(aDestfile && (aErrorNumber != NoError) && (aDestCreated == true))
+		{
+		remove(aDestfile);
+		}
+
+	switch(aErrorNumber)
+		{
+		case NoError:
+			return "Success.";
+		case NoMemory:
+			return "Out of memory.";
+		case Arg:
+			return "Bad argument.";
+		case Files:
+			return "File does not exist";
+		case SourceFile:
+			return "Bad source file(s).";
+		case DestFile:
+			return "Bad destination file(s).";
+		case CommandFile:
+			return "Bad command file.";
+		case OutOfRange:
+			return "Number of sources/targets mismatch.";
+		case TooManyArgs:
+			return "Too many arguments.";
+		case UnknownCompression:
+			return "Unknown source compression type.";
+		case CompressionError:
+			return "Compression error.";
+		case DecompressionError:
+			return "Decompression error.";
+		case Bpp:
+			return "Invalid bitmap mode specified.";
+		case PaletteFile:
+			return "Bad palette file.";
+		case PaletteSupportNotImplemented:
+			return "Palettes not supported";
+		case AlphaFiles:
+			return "Alpha bitmap file does not exist";
+		case AlphaDimensions:
+			return "Alpha channel bitmap's dimensions don't match pixel bitmap's dimensions.";
+		case AlphaBpp:
+			return "Alpha channel bitmap must be 8bpp.";
+		default:
+			return "Unknown error!";
+		};
+	}
+
+void Header()
+	{
+	cout << "\n";
+	cout << "\n";
+	cout << "BMCONV S60 version "<< version << ".\n";
+	}
+	
+void Report(int aError)
+	{
+	Header();
+	cout << ErrorMessage(aError) << "\n";
+	}
+
+/**
+Compiliation information to print to the user at the end of the program.
+@param aQuiet Flag if the user selected quiet output mode
+@param aError The error returned from the actions performed
+@param aType The multiple bitmap store type created
+@param aDestfile The multiple bitmap store file name
+@param aBitmapFiles The array of bitmaps used
+@param aNumFiles The amount of bitmaps used
+@param aDestCreated True if the multiple bitmap store has been created/modified
+*/
+
+void CompilationReport(int aQuiet,int aError,TStoreType aType,char* aDestfile,TSourceFile* aBitmapFiles,int aNumFiles, bool aDestCreated)
+	{	
+	if(!aQuiet || aError)
+		{
+		Header();
+		cout << "Compiling...\n";
+		if(aType!=ENoStore)
+			cout << "Multiple bitmap store type: ";
+		if(aType==EFileStore)
+			cout << "File store" << "\n";
+		else if(aType==ERomStore)
+			cout << "ROM image store" << "\n";
+		else if(aType==ECompressedRomStore)
+			cout << "Compressed ROM image store" << "\n";
+		if(aDestfile!=NULL)
+			cout << "Epoc file: " << aDestfile << "\n\n";
+		for(int count=0;count<aNumFiles;count++)
+			{
+			cout << "Bitmap file " << count+1 << "	: ";
+			aBitmapFiles[count].WriteCompileInfo(cout);
+			cout << endl;
+			}
+		cout << ErrorMessage(aError, aDestfile, aDestCreated) << "\n";
+		}
+	}
+	
+void DecompilationReport(int aError,char* aDestfile,char** aBitmapFiles,int aNumFiles)
+	{	
+	Header();
+	cout << "Decompiling...\n";
+	if(aDestfile!=NULL)
+		cout << "Epoc file: " << aDestfile << "\n\n";
+	for(int count=0;count<aNumFiles;count++)
+		{
+		cout << "Bitmap file " << count+1 << "	: ";
+		cout << aBitmapFiles[count] << "\n";
+		}
+	cout << ErrorMessage(aError) << "\n";
+	}
+	
+void Usage()
+    {
+	cout << "\n";
+	cout << "BMCONV S60 version "<< version << ".\n";
+	cout << "Symbian OS multiple bitmap file/rom store conversion program.\n";
+	cout << "Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.";
+	cout << "\n";
+	cout << "\n";
+	cout << "Usage:\n";
+	cout << "BMCONV [-r|-s|-n] [-hfilename] [-q] [-pfilename] epocfile [OPT]bmp_1 ... [OPT]bmp_n\n";
+	cout << "BMCONV [-r|-s|-n] [-q] [-pfilename] epocfile -mepocfile2\n";
+	cout << "BMCONV -u epocfile bmp_1 [... bmp_n]\n";
+	cout << "BMCONV -v epocfile\n";
+	cout << "BMCONV commandfile\n";
+	cout << "\n";
+	cout << " -r specifies a ROM image destination file,\n";
+	cout << " -s specifies a compressed ROM image file,\n";
+	cout << " -n disables bitmap File Store compression,\n";
+	cout << " the default is a compressed File Store file.\n\n";
+	cout << " -q specifies quiet mode - only errors are reported.\n\n";
+	cout << " -hfilename specifies the filename for the automatic\n";
+	cout << " generation of a header file for inclusion into code.\n\n";
+	cout << " -pfilename gives the filename of a palette file containing 256 hex\n";
+	cout << " numbers (0x00BBGGRR) specifying the palette for 8bpp colour bitmaps.\n";
+	cout << " (Omission results in the use of a default palette.)\n\n";
+	cout << " OPT may be one of -1, -2, -4, -8, -c4, -c8, -c12, -c16, -c24 -c32 -c32a\n";
+	cout << " specifying bits per pixel and grey-scale-colour, or -mepocfile2\n";
+	cout << " to specify an existing multiple bitmap file. default is -2.\n\n";
+	cout << " To avoid ambiguity when specifying -c32 with a bitmap file whose name\n";
+	cout << " begins with an 'a', use a relative or direct directory reference\n";
+	cout << " e.g. -c32.\\abitmap.bmp or -c32c:\\abitmap.bmp\n";
+	cout << " Directory names must not include spaces.\n\n";
+	cout << " -c32a specifies use of an alpha channel in a 32bpp bitmap. Alpha data\n";
+	cout << " is supplied in a separate 8bpp bmp file with identical dimensions to\n";
+	cout << " the pixel data. This file must be named as bmp_n with the suffix '-alpha'\n";
+	cout << " e.g. if bmp_1 is 'my.bmp' then the file 'my-alpha.bmp' is required in the\n";
+	cout << " same directory.  The alpha file does not need to be specified.\n\n";
+	cout << " epocfile specifies the epoc multi-bitmap file name.\n";
+	cout << " bmp_n specifies the nth bitmap file name.\n\n";
+	cout << " -u decompiles epocfile to bmp_1,...,bmp_n.\n";
+	cout << " If an alpha channel is present then a further, 8bpp file is output for \n";
+	cout << " the alpha data, named with an '-alpha' suffix as described above.\n\n";
+	cout << " -v displays a summary of the bitmaps in epocfile\n";
+	cout << " otherwise bmp_1,...,bmp_n are compiled to epocfile\n\n";
+	cout << " commandfile specifies a file containing the commandline\n";
+	cout << " with commands separated by spaces or newlines.\n\n";
+	cout << " When bmconv is used on Windows, options may start with '/' or '-'\n";
+	}
+
+int IsWhiteSpace(char aCharacter)
+	{
+	return(aCharacter==' ' || aCharacter=='\n' || aCharacter=='\r' || aCharacter==0x1a);
+	}
+
+int ProcessCommandFile(char* aCommandFileName,char** aArgPtrs,int& aNumArgs)
+    {
+	struct stat fileinfo;
+	if (stat(aCommandFileName,&fileinfo)==-1)
+		return CommandFile;
+
+	int filesize=fileinfo.st_size;
+	if (filesize==0)
+		return NoError;
+#if defined(__MSVCDOTNET__) || defined(__TOOLS2__) || defined(__CW32__)
+	fstream commandfile(aCommandFileName, ios::in | ios::binary);
+#else //!__MSVCDOTNET__
+	fstream commandfile(aCommandFileName, ios::in | ios::binary | ios::nocreate);
+#endif //__MSVCDOTNET__
+	if(!commandfile.is_open())
+		return CommandFile;
+
+	char* commandData=new char[filesize+1];
+	if(commandData==NULL)
+		return NoMemory;
+
+	memset(commandData,0,filesize+1);
+	commandfile.read(commandData,filesize);
+	commandData[filesize]='\0';
+
+	char* commandptr = (char*)commandData;
+	char* commandptrLimit = (char*)(commandData + filesize);
+	while (commandptr < commandptrLimit)
+		{
+		if(*commandptr=='/' && *(commandptr+1)=='/')
+			while(*commandptr!='\n' && *commandptr!='\r' && commandptr < commandptrLimit)
+				*commandptr++=' ';
+		else if (*commandptr==0x1a)
+			*commandptr++=' ';
+		commandptr++;
+		}
+
+	commandptr = (char*)commandData;
+	while (commandptr < commandptrLimit)
+		{
+		while(IsWhiteSpace(*commandptr) && commandptr < commandptrLimit)
+			*commandptr++='\0';
+		if (commandptr == commandptrLimit)
+			break;
+		aArgPtrs[aNumArgs]=commandptr;
+        if ( (*commandptr == '/') && (*(commandptr+1) == 'p'||*(commandptr+1) == 'P') && (*(commandptr+2) == '"') )
+            {
+            commandptr+=3;
+            while(*commandptr != '"')
+                commandptr++;
+            *commandptr=' ';
+            
+            }
+		while(!IsWhiteSpace(*commandptr) && commandptr < commandptrLimit)
+			commandptr++;
+		if (commandptr == commandptrLimit)
+			break;
+		aNumArgs++;
+		}
+
+	commandfile.close();
+	return NoError;
+    }
+
+int Decompile(int aArgc,int aNumArgs,char** aArgPtrs)
+	{
+	int ret=OutOfRange;
+	char* destfilename=aArgPtrs[1];
+
+	if(aArgc>=4 || aArgc==2)
+		{
+		for(int count=2;count<aNumArgs;count++)
+			{
+			EpocLoader pl;
+			ret=pl.LoadEpocBitmap(destfilename,count-2);
+			if(!ret) ret=pl.SaveBitmap(aArgPtrs[count]);
+			if(ret) break;
+			}
+		DecompilationReport(ret,destfilename,&aArgPtrs[2],aNumArgs-2);
+		}
+	else
+		DecompilationReport(ret,NULL,NULL,0);
+
+	return ret;
+	}
+
+const char* AddEpocRootTo(std::string& aBuf, const std::string& aName)
+	{ 
+	int nameLen = aName.length();
+	int rootLen = 0;
+	aBuf = ""; // Clear old contents
+	char* epocroot = getenv("EPOCROOT");
+	if (epocroot)
+		{
+		rootLen = strlen(epocroot);
+		if (nameLen+rootLen < KMaxPaletteFileLen)
+			{
+			if( rootLen > 0 && epocroot[rootLen-1] == '\\')
+			    {
+			    aBuf = std::string(epocroot, rootLen-1);
+			    }
+			else if( rootLen > 0 )
+			    {
+			    aBuf = std::string(epocroot);
+			    }
+			}
+		}
+	aBuf += aName;
+	return aBuf.c_str();
+	}
+
+bool FileExists( const char* aFileName )
+{
+  struct stat fileInfo;   
+  int retVal = 0; 
+
+  // Try to get file attributes to see if the file exists or not:
+  retVal = stat( aFileName, &fileInfo); 
+  return retVal == 0;
+}
+
+const char* DefaultPaletteFileName(std::string& aBuf)
+    {
+    const char* palettefilename = NULL;    
+    int numOfSearchLocations = sizeof(DefaultPaletteFileSearchLocations)/sizeof(char*);
+    
+    for( int i = 0; i < numOfSearchLocations; ++i )
+        {
+        palettefilename = AddEpocRootTo(aBuf, DefaultPaletteFileSearchLocations[i]);
+        if( FileExists( palettefilename))
+            {
+            return palettefilename;
+            }
+        }
+    
+    return NULL;
+    }
+
+int Compile(int aNumArgs,int aArgArraySize, char** aArgPtrs)
+	{
+	TStoreType storeType = EFileStore;
+	int compression = 1;
+	int quiet = 0;
+	char* headerfilename = NULL;
+	char paletteBuf[KMaxPaletteFileLen];
+	memset(paletteBuf, 0, KMaxPaletteFileLen);
+	std::string paletteStr;	
+	const char* defaultPalettefile = DefaultPaletteFileName(paletteStr);
+	char* palettefilename = NULL;
+	char* destfilename = NULL;
+	int ret = OutOfRange;
+	bool aDestCreated = false;
+
+	for(int argnum=0;argnum<aNumArgs;argnum++)
+		{
+		if(aArgPtrs[argnum] && (aArgPtrs[argnum][0] == OPTCHAR || aArgPtrs[argnum][0]==ALTERNATE_OPTCHAR))
+			{
+			if(aArgPtrs[argnum][1]=='r' || aArgPtrs[argnum][1]=='R')
+				{
+				if(storeType==ECompressedRomStore)
+					{
+					ret=TooManyArgs;
+					CompilationReport(quiet,ret,storeType,NULL,NULL,0,aDestCreated);
+					return ret;
+					}
+				storeType=ERomStore;
+				aArgPtrs[argnum] = NULL;
+				}
+			else if(aArgPtrs[argnum][1]=='s' || aArgPtrs[argnum][1]=='S')
+				{
+				if(storeType==ERomStore)
+					{
+					ret=TooManyArgs;
+					CompilationReport(quiet,ret,storeType,NULL,NULL,0,aDestCreated);
+					return ret;
+					}
+				storeType=ECompressedRomStore;
+				aArgPtrs[argnum] = NULL;
+				}
+			else if(aArgPtrs[argnum][1]=='n' || aArgPtrs[argnum][1]=='N')
+				{
+				compression=0;
+				aArgPtrs[argnum] = NULL;
+				}
+			else if(aArgPtrs[argnum][1]=='h' || aArgPtrs[argnum][1]=='H')
+				{
+				headerfilename = &aArgPtrs[argnum][2];
+				aArgPtrs[argnum] = NULL;
+				}
+			else if(aArgPtrs[argnum][1]=='q' || aArgPtrs[argnum][1]=='Q')
+				{
+				if (getenv("BMCONV_NOT_QUIET") == 0)
+					quiet=1;
+				aArgPtrs[argnum] = NULL;
+				}
+			else if(aArgPtrs[argnum][1]=='p' || aArgPtrs[argnum][1]=='P')
+				{
+				palettefilename = &aArgPtrs[argnum][2];
+                if (*palettefilename=='"')
+                    {
+                    palettefilename+=1;
+                    }
+				aArgPtrs[argnum] = NULL;
+				}
+			}
+		else
+			break;		// the RNHQP arguments must precede the output filename
+		}
+
+	if( palettefilename == NULL )
+	    {
+	    // Palette file not given in arguments. If the default palette file
+	    // was found, use it, otherwise return error.
+	    if( defaultPalettefile != NULL )
+	        {
+	        memcpy(paletteBuf, defaultPalettefile, strlen(defaultPalettefile));
+	        palettefilename = paletteBuf;
+	        }
+	    else
+	        {
+	        // Palettefile not given in arguments nor found from default locations:
+	        ret = PaletteFile;
+	        CompilationReport(quiet,ret,storeType,NULL,NULL,0,aDestCreated);
+	        return ret;
+	        }
+	    }
+	int firstsource=0;
+	while(firstsource<aArgArraySize && aArgPtrs[firstsource]==NULL)
+		firstsource++;
+	if(firstsource==aArgArraySize) firstsource=0;
+	destfilename=aArgPtrs[firstsource];
+	firstsource++;
+	int numsources=firstsource;
+	while(numsources<aArgArraySize && aArgPtrs[numsources]!=NULL)
+		numsources++;
+	if(numsources==aArgArraySize) numsources=0;
+	numsources-=firstsource;
+
+	TSourceFile* sources = 0;
+
+	if (numsources > 0)
+		{
+		sources = new TSourceFile[numsources];
+		for (int ii=0; ii<numsources; ii++)
+			sources[ii].FileName() = aArgPtrs[firstsource + ii];
+		BitmapCompiler mp(sources,numsources);
+		ret = mp.Compile(storeType,compression,destfilename,headerfilename,palettefilename);
+		aDestCreated = true;		// The multiple bitmap store has been created/modified
+		}
+
+	CompilationReport(quiet,ret,storeType,destfilename,sources,aNumArgs-firstsource,aDestCreated);
+	delete [] sources;
+
+	return ret;
+	}
+
+void GetInfo(char* aSourceFile)
+	{
+	Header();
+
+	EpocLoader pl;
+	int numSources=-1;
+	int romFormat=0;
+	int ret = pl.EpocBitmapCount(aSourceFile, numSources, romFormat);
+	if (ret)
+		{
+		cout << "Problem reading number of bitmaps \n";
+		cout << ErrorMessage(ret) << "\n";
+		return;
+		}
+
+	cout << aSourceFile << " is a " << (romFormat? "ROM image":"File store") 
+		<< " containing " << numSources << ((numSources==1)? " bitmap\n":" bitmaps\n");
+
+	for (int count = 0;count<numSources;count++)
+		{
+		ret = pl.LoadEpocBitmap(aSourceFile,count);
+		if (ret == OutOfRange)
+			break;
+		cout << "\n";
+		if (ret)
+			{
+			cout << "Problem loading bitmap number " << count << "\n";
+			cout << ErrorMessage(ret) << "\n";
+			break;
+			}
+		else
+			{
+			SEpocBitmapHeader h = pl.Header();
+			cout << "Bitmap " << count + 1 << " information:\n";
+			cout << "Pixel size " << h.iWidthInPixels << " x " << h.iHeightInPixels << "\n";
+			cout << "Twips size " << h.iWidthInTwips << " x " << h.iHeightInTwips << "\n";
+			cout << h.iBitsPerPixel << " Bpp ";
+			if (h.iColor == EColorBitmap)
+				cout << "Colour";
+			else if (h.iColor == EColorBitmapAlpha)
+				cout << "Colour with alpha channel";
+			else if(h.iColor == EMonochromeBitmap)
+				cout << "Monochrome";
+			else
+				cout << "Unknown colour format";
+			cout << "\n";
+			if (h.iPaletteEntries > 0)
+				cout << "Palette entries " << h.iPaletteEntries;
+
+			int byteSize = BitmapUtils::ByteWidth(h.iWidthInPixels,h.iBitsPerPixel) * h.iHeightInPixels;
+			int compressionRatio = 0;
+			if (byteSize > 0)
+				compressionRatio = (h.iBitmapSize - sizeof(SEpocBitmapHeader)) * 100 / byteSize;
+
+			switch (h.iCompression)
+				{
+			case ENoBitmapCompression:
+				cout << "No compression\n";
+				break;
+			case EByteRLECompression:
+				cout << "Bytewise RLE compression " << compressionRatio << "%\n";
+				break;
+			case ETwelveBitRLECompression:
+				cout << "12 bit RLE compression " << compressionRatio << "%\n";
+				break;
+			case ESixteenBitRLECompression:
+				cout << "16 bit RLE compression " << compressionRatio << "%\n";
+				break;
+			case ETwentyFourBitRLECompression:
+				cout << "24 bit RLE compression " << compressionRatio << "%\n";
+				break;
+			case EThirtyTwoUBitRLECompression:
+				cout << "unsigned 32 bit RLE compression (no alpha channel) " << compressionRatio << "%\n";
+				break;
+			case EThirtyTwoABitRLECompression:
+				cout << "unsigned 32 bit RLE compression (with alpha channel) " << compressionRatio << "%\n";
+				break;
+		//	case ERLECompressionLast: // Added to supress unhandled switch warning
+			default:
+				break;
+				}
+			}
+		}
+
+	cout << "\n";
+	}
+
+class TAutoPtr
+	{
+public:
+	TAutoPtr(char** aPtr) :
+		iPtr(aPtr)
+		{
+		}
+	~TAutoPtr()
+		{
+		delete iPtr;
+		}
+private:
+	char** iPtr;
+	};
+
+int main(int argc,char* argv[],char* [])
+    {
+	if (argc <= 1)
+		{
+		Usage();
+		return 0;
+		}
+
+	int optMaxCnt = argc;
+
+	if(argc==2) // The single argument must be a command file name
+		{
+		struct stat fileinfo;
+		if (stat(argv[1],&fileinfo)==-1)
+			{
+			Report(CommandFile);
+			return 0;
+			}
+		optMaxCnt = fileinfo.st_size;
+		}
+
+	char** argptrs = new char*[optMaxCnt];
+	if(!argptrs)
+		{
+		Report(NoMemory);
+		return 0;
+		}
+	TAutoPtr autoPtr(argptrs);
+	memset(argptrs, 0, optMaxCnt * sizeof(char*));
+
+	int numargs = 0;
+	if(argc>2) // Explicit arguments are present
+		{
+		for(int count=0;count<argc-1;count++)
+			argptrs[count]=argv[count+1];
+		numargs = argc-1;
+		}
+	else // The single argument must be a command file name
+		{
+		int ret = ProcessCommandFile(argv[1],argptrs,numargs);
+		if (ret)
+			{
+			Report(ret);
+			return 0;
+			}
+		}
+
+	if ((argptrs[0]!=NULL && (argptrs[0][0]==OPTCHAR || argptrs[0][0]==ALTERNATE_OPTCHAR)) && (argptrs[0][1]=='u' || argptrs[0][1]=='U')) {
+		return Decompile(argc,numargs,argptrs); }
+
+	if ((argptrs[0]!=NULL && (argptrs[0][0]==OPTCHAR || argptrs[0][0]==ALTERNATE_OPTCHAR)) && (argptrs[0][1]=='v' || argptrs[0][1]=='V'))
+		{
+		GetInfo(argptrs[1]);
+		return 0;
+		}
+
+	return Compile(numargs,optMaxCnt,argptrs);
+    }
+