gfxconversion/bmconv_s60/src/MAINFUNC.CPP
changeset 0 f453ebb75370
equal deleted inserted replaced
-1:000000000000 0:f453ebb75370
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__) || defined(__CW32__)
       
    19 #include <ostream>
       
    20 #include <iostream>
       
    21 using namespace std;
       
    22 #else //!__MSVCDOTNET__ && !__TOOLS2__ && !__CW32__
       
    23 #pragma warning(disable: 4100)
       
    24 #pragma warning(disable: 4511)
       
    25 #pragma warning(disable: 4512)
       
    26 #pragma warning(disable: 4530)
       
    27 #pragma warning(disable: 4663)
       
    28 #pragma warning(disable: 4710)
       
    29 #pragma warning(disable: 4786)
       
    30 #pragma warning(disable: 4800)
       
    31 #include <ostream.h>
       
    32 #endif //__MSVCDOTNET__
       
    33 
       
    34 #include "TOOLSVER.H"
       
    35 #include "BMCONV.H"
       
    36 #include <sys/types.h>
       
    37 #include <sys/stat.h>
       
    38 #include <stdio.h>
       
    39 #include <string>
       
    40 
       
    41 const int KMaxPaletteFileLen = 256;
       
    42 
       
    43 #ifdef __linux__
       
    44 const char* DefaultPaletteFileSearchLocations[] =
       
    45 {
       
    46     "/epoc32/include/mw/ThirdPartyBitmap.pal",
       
    47     "/epoc32/include/middleware/ThirdPartyBitmap.pal",
       
    48     "/epoc32/include/ThirdPartyBitmap.pal"
       
    49 };
       
    50 #else
       
    51 const char* DefaultPaletteFileSearchLocations[] =
       
    52 {
       
    53     "\\epoc32\\include\\mw\\ThirdPartyBitmap.pal",
       
    54     "\\epoc32\\include\\middleware\\ThirdPartyBitmap.pal",
       
    55     "\\epoc32\\include\\ThirdPartyBitmap.pal"
       
    56 };
       
    57 #endif
       
    58 
       
    59 /**
       
    60 Returns an informative error message, the result of the program actions performed.
       
    61 @return Informative error string
       
    62 @param aErrorNumber The error returned from the actions performed
       
    63 @param aDestfile The multiple bitmap store file name
       
    64 @param aDestCreated True if the multiple bitmap store has been created/modified
       
    65 */
       
    66 
       
    67 char* ErrorMessage(int aErrorNumber, char* aDestfile=NULL, bool aDestCreated=false)
       
    68 	{
       
    69 	// Remove the multiple bitmap store if it has been created/modified during an fstream session and there has been an error
       
    70 	if(aDestfile && (aErrorNumber != NoError) && (aDestCreated == true))
       
    71 		{
       
    72 		remove(aDestfile);
       
    73 		}
       
    74 
       
    75 	switch(aErrorNumber)
       
    76 		{
       
    77 		case NoError:
       
    78 			return "Success.";
       
    79 		case NoMemory:
       
    80 			return "Out of memory.";
       
    81 		case Arg:
       
    82 			return "Bad argument.";
       
    83 		case Files:
       
    84 			return "File does not exist";
       
    85 		case SourceFile:
       
    86 			return "Bad source file(s).";
       
    87 		case DestFile:
       
    88 			return "Bad destination file(s).";
       
    89 		case CommandFile:
       
    90 			return "Bad command file.";
       
    91 		case OutOfRange:
       
    92 			return "Number of sources/targets mismatch.";
       
    93 		case TooManyArgs:
       
    94 			return "Too many arguments.";
       
    95 		case UnknownCompression:
       
    96 			return "Unknown source compression type.";
       
    97 		case CompressionError:
       
    98 			return "Compression error.";
       
    99 		case DecompressionError:
       
   100 			return "Decompression error.";
       
   101 		case Bpp:
       
   102 			return "Invalid bitmap mode specified.";
       
   103 		case PaletteFile:
       
   104 			return "Bad palette file.";
       
   105 		case PaletteSupportNotImplemented:
       
   106 			return "Palettes not supported";
       
   107 		case AlphaFiles:
       
   108 			return "Alpha bitmap file does not exist";
       
   109 		case AlphaDimensions:
       
   110 			return "Alpha channel bitmap's dimensions don't match pixel bitmap's dimensions.";
       
   111 		case AlphaBpp:
       
   112 			return "Alpha channel bitmap must be 8bpp.";
       
   113 		default:
       
   114 			return "Unknown error!";
       
   115 		};
       
   116 	}
       
   117 
       
   118 void Header()
       
   119 	{
       
   120 	cout << "\n";
       
   121 	cout << "\n";
       
   122 	cout << "BMCONV S60 version "<< version << ".\n";
       
   123 	}
       
   124 	
       
   125 void Report(int aError)
       
   126 	{
       
   127 	Header();
       
   128 	cout << ErrorMessage(aError) << "\n";
       
   129 	}
       
   130 
       
   131 /**
       
   132 Compiliation information to print to the user at the end of the program.
       
   133 @param aQuiet Flag if the user selected quiet output mode
       
   134 @param aError The error returned from the actions performed
       
   135 @param aType The multiple bitmap store type created
       
   136 @param aDestfile The multiple bitmap store file name
       
   137 @param aBitmapFiles The array of bitmaps used
       
   138 @param aNumFiles The amount of bitmaps used
       
   139 @param aDestCreated True if the multiple bitmap store has been created/modified
       
   140 */
       
   141 
       
   142 void CompilationReport(int aQuiet,int aError,TStoreType aType,char* aDestfile,TSourceFile* aBitmapFiles,int aNumFiles, bool aDestCreated)
       
   143 	{	
       
   144 	if(!aQuiet || aError)
       
   145 		{
       
   146 		Header();
       
   147 		cout << "Compiling...\n";
       
   148 		if(aType!=ENoStore)
       
   149 			cout << "Multiple bitmap store type: ";
       
   150 		if(aType==EFileStore)
       
   151 			cout << "File store" << "\n";
       
   152 		else if(aType==ERomStore)
       
   153 			cout << "ROM image store" << "\n";
       
   154 		else if(aType==ECompressedRomStore)
       
   155 			cout << "Compressed ROM image store" << "\n";
       
   156 		if(aDestfile!=NULL)
       
   157 			cout << "Epoc file: " << aDestfile << "\n\n";
       
   158 		for(int count=0;count<aNumFiles;count++)
       
   159 			{
       
   160 			cout << "Bitmap file " << count+1 << "	: ";
       
   161 			aBitmapFiles[count].WriteCompileInfo(cout);
       
   162 			cout << endl;
       
   163 			}
       
   164 		cout << ErrorMessage(aError, aDestfile, aDestCreated) << "\n";
       
   165 		}
       
   166 	}
       
   167 	
       
   168 void DecompilationReport(int aError,char* aDestfile,char** aBitmapFiles,int aNumFiles)
       
   169 	{	
       
   170 	Header();
       
   171 	cout << "Decompiling...\n";
       
   172 	if(aDestfile!=NULL)
       
   173 		cout << "Epoc file: " << aDestfile << "\n\n";
       
   174 	for(int count=0;count<aNumFiles;count++)
       
   175 		{
       
   176 		cout << "Bitmap file " << count+1 << "	: ";
       
   177 		cout << aBitmapFiles[count] << "\n";
       
   178 		}
       
   179 	cout << ErrorMessage(aError) << "\n";
       
   180 	}
       
   181 	
       
   182 void Usage()
       
   183     {
       
   184 	cout << "\n";
       
   185 	cout << "BMCONV S60 version "<< version << ".\n";
       
   186 	cout << "Symbian OS multiple bitmap file/rom store conversion program.\n";
       
   187 	cout << "Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.";
       
   188 	cout << "\n";
       
   189 	cout << "\n";
       
   190 	cout << "Usage:\n";
       
   191 	cout << "BMCONV [-r|-s|-n] [-hfilename] [-q] [-pfilename] epocfile [OPT]bmp_1 ... [OPT]bmp_n\n";
       
   192 	cout << "BMCONV [-r|-s|-n] [-q] [-pfilename] epocfile -mepocfile2\n";
       
   193 	cout << "BMCONV -u epocfile bmp_1 [... bmp_n]\n";
       
   194 	cout << "BMCONV -v epocfile\n";
       
   195 	cout << "BMCONV commandfile\n";
       
   196 	cout << "\n";
       
   197 	cout << " -r specifies a ROM image destination file,\n";
       
   198 	cout << " -s specifies a compressed ROM image file,\n";
       
   199 	cout << " -n disables bitmap File Store compression,\n";
       
   200 	cout << " the default is a compressed File Store file.\n\n";
       
   201 	cout << " -q specifies quiet mode - only errors are reported.\n\n";
       
   202 	cout << " -hfilename specifies the filename for the automatic\n";
       
   203 	cout << " generation of a header file for inclusion into code.\n\n";
       
   204 	cout << " -pfilename gives the filename of a palette file containing 256 hex\n";
       
   205 	cout << " numbers (0x00BBGGRR) specifying the palette for 8bpp colour bitmaps.\n";
       
   206 	cout << " (Omission results in the use of a default palette.)\n\n";
       
   207 	cout << " OPT may be one of -1, -2, -4, -8, -c4, -c8, -c12, -c16, -c24 -c32 -c32a\n";
       
   208 	cout << " specifying bits per pixel and grey-scale-colour, or -mepocfile2\n";
       
   209 	cout << " to specify an existing multiple bitmap file. default is -2.\n\n";
       
   210 	cout << " To avoid ambiguity when specifying -c32 with a bitmap file whose name\n";
       
   211 	cout << " begins with an 'a', use a relative or direct directory reference\n";
       
   212 	cout << " e.g. -c32.\\abitmap.bmp or -c32c:\\abitmap.bmp\n";
       
   213 	cout << " Directory names must not include spaces.\n\n";
       
   214 	cout << " -c32a specifies use of an alpha channel in a 32bpp bitmap. Alpha data\n";
       
   215 	cout << " is supplied in a separate 8bpp bmp file with identical dimensions to\n";
       
   216 	cout << " the pixel data. This file must be named as bmp_n with the suffix '-alpha'\n";
       
   217 	cout << " e.g. if bmp_1 is 'my.bmp' then the file 'my-alpha.bmp' is required in the\n";
       
   218 	cout << " same directory.  The alpha file does not need to be specified.\n\n";
       
   219 	cout << " epocfile specifies the epoc multi-bitmap file name.\n";
       
   220 	cout << " bmp_n specifies the nth bitmap file name.\n\n";
       
   221 	cout << " -u decompiles epocfile to bmp_1,...,bmp_n.\n";
       
   222 	cout << " If an alpha channel is present then a further, 8bpp file is output for \n";
       
   223 	cout << " the alpha data, named with an '-alpha' suffix as described above.\n\n";
       
   224 	cout << " -v displays a summary of the bitmaps in epocfile\n";
       
   225 	cout << " otherwise bmp_1,...,bmp_n are compiled to epocfile\n\n";
       
   226 	cout << " commandfile specifies a file containing the commandline\n";
       
   227 	cout << " with commands separated by spaces or newlines.\n\n";
       
   228 	cout << " When bmconv is used on Windows, options may start with '/' or '-'\n";
       
   229 	}
       
   230 
       
   231 int IsWhiteSpace(char aCharacter)
       
   232 	{
       
   233 	return(aCharacter==' ' || aCharacter=='\n' || aCharacter=='\r' || aCharacter==0x1a);
       
   234 	}
       
   235 
       
   236 int ProcessCommandFile(char* aCommandFileName,char** aArgPtrs,int& aNumArgs)
       
   237     {
       
   238 	struct stat fileinfo;
       
   239 	if (stat(aCommandFileName,&fileinfo)==-1)
       
   240 		return CommandFile;
       
   241 
       
   242 	int filesize=fileinfo.st_size;
       
   243 	if (filesize==0)
       
   244 		return NoError;
       
   245 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__) || defined(__CW32__)
       
   246 	fstream commandfile(aCommandFileName, ios::in | ios::binary);
       
   247 #else //!__MSVCDOTNET__
       
   248 	fstream commandfile(aCommandFileName, ios::in | ios::binary | ios::nocreate);
       
   249 #endif //__MSVCDOTNET__
       
   250 	if(!commandfile.is_open())
       
   251 		return CommandFile;
       
   252 
       
   253 	char* commandData=new char[filesize+1];
       
   254 	if(commandData==NULL)
       
   255 		return NoMemory;
       
   256 
       
   257 	memset(commandData,0,filesize+1);
       
   258 	commandfile.read(commandData,filesize);
       
   259 	commandData[filesize]='\0';
       
   260 
       
   261 	char* commandptr = (char*)commandData;
       
   262 	char* commandptrLimit = (char*)(commandData + filesize);
       
   263 	while (commandptr < commandptrLimit)
       
   264 		{
       
   265 		if(*commandptr=='/' && *(commandptr+1)=='/')
       
   266 			while(*commandptr!='\n' && *commandptr!='\r' && commandptr < commandptrLimit)
       
   267 				*commandptr++=' ';
       
   268 		else if (*commandptr==0x1a)
       
   269 			*commandptr++=' ';
       
   270 		commandptr++;
       
   271 		}
       
   272 
       
   273 	commandptr = (char*)commandData;
       
   274 	while (commandptr < commandptrLimit)
       
   275 		{
       
   276 		while(IsWhiteSpace(*commandptr) && commandptr < commandptrLimit)
       
   277 			*commandptr++='\0';
       
   278 		if (commandptr == commandptrLimit)
       
   279 			break;
       
   280 		aArgPtrs[aNumArgs]=commandptr;
       
   281         if ( (*commandptr == '/') && (*(commandptr+1) == 'p'||*(commandptr+1) == 'P') && (*(commandptr+2) == '"') )
       
   282             {
       
   283             commandptr+=3;
       
   284             while(*commandptr != '"')
       
   285                 commandptr++;
       
   286             *commandptr=' ';
       
   287             
       
   288             }
       
   289 		while(!IsWhiteSpace(*commandptr) && commandptr < commandptrLimit)
       
   290 			commandptr++;
       
   291 		if (commandptr == commandptrLimit)
       
   292 			break;
       
   293 		aNumArgs++;
       
   294 		}
       
   295 
       
   296 	commandfile.close();
       
   297 	return NoError;
       
   298     }
       
   299 
       
   300 int Decompile(int aArgc,int aNumArgs,char** aArgPtrs)
       
   301 	{
       
   302 	int ret=OutOfRange;
       
   303 	char* destfilename=aArgPtrs[1];
       
   304 
       
   305 	if(aArgc>=4 || aArgc==2)
       
   306 		{
       
   307 		for(int count=2;count<aNumArgs;count++)
       
   308 			{
       
   309 			EpocLoader pl;
       
   310 			ret=pl.LoadEpocBitmap(destfilename,count-2);
       
   311 			if(!ret) ret=pl.SaveBitmap(aArgPtrs[count]);
       
   312 			if(ret) break;
       
   313 			}
       
   314 		DecompilationReport(ret,destfilename,&aArgPtrs[2],aNumArgs-2);
       
   315 		}
       
   316 	else
       
   317 		DecompilationReport(ret,NULL,NULL,0);
       
   318 
       
   319 	return ret;
       
   320 	}
       
   321 
       
   322 const char* AddEpocRootTo(std::string& aBuf, const std::string& aName)
       
   323 	{ 
       
   324 	int nameLen = aName.length();
       
   325 	int rootLen = 0;
       
   326 	aBuf = ""; // Clear old contents
       
   327 	char* epocroot = getenv("EPOCROOT");
       
   328 	if (epocroot)
       
   329 		{
       
   330 		rootLen = strlen(epocroot);
       
   331 		if (nameLen+rootLen < KMaxPaletteFileLen)
       
   332 			{
       
   333 			if( rootLen > 0 && epocroot[rootLen-1] == '\\')
       
   334 			    {
       
   335 			    aBuf = std::string(epocroot, rootLen-1);
       
   336 			    }
       
   337 			else if( rootLen > 0 )
       
   338 			    {
       
   339 			    aBuf = std::string(epocroot);
       
   340 			    }
       
   341 			}
       
   342 		}
       
   343 	aBuf += aName;
       
   344 	return aBuf.c_str();
       
   345 	}
       
   346 
       
   347 bool FileExists( const char* aFileName )
       
   348 {
       
   349   struct stat fileInfo;   
       
   350   int retVal = 0; 
       
   351 
       
   352   // Try to get file attributes to see if the file exists or not:
       
   353   retVal = stat( aFileName, &fileInfo); 
       
   354   return retVal == 0;
       
   355 }
       
   356 
       
   357 const char* DefaultPaletteFileName(std::string& aBuf)
       
   358     {
       
   359     const char* palettefilename = NULL;    
       
   360     int numOfSearchLocations = sizeof(DefaultPaletteFileSearchLocations)/sizeof(char*);
       
   361     
       
   362     for( int i = 0; i < numOfSearchLocations; ++i )
       
   363         {
       
   364         palettefilename = AddEpocRootTo(aBuf, DefaultPaletteFileSearchLocations[i]);
       
   365         if( FileExists( palettefilename))
       
   366             {
       
   367             return palettefilename;
       
   368             }
       
   369         }
       
   370     
       
   371     return NULL;
       
   372     }
       
   373 
       
   374 int Compile(int aNumArgs,int aArgArraySize, char** aArgPtrs)
       
   375 	{
       
   376 	TStoreType storeType = EFileStore;
       
   377 	int compression = 1;
       
   378 	int quiet = 0;
       
   379 	char* headerfilename = NULL;
       
   380 	char paletteBuf[KMaxPaletteFileLen];
       
   381 	memset(paletteBuf, 0, KMaxPaletteFileLen);
       
   382 	std::string paletteStr;	
       
   383 	const char* defaultPalettefile = DefaultPaletteFileName(paletteStr);
       
   384 	char* palettefilename = NULL;
       
   385 	char* destfilename = NULL;
       
   386 	int ret = OutOfRange;
       
   387 	bool aDestCreated = false;
       
   388 
       
   389 	for(int argnum=0;argnum<aNumArgs;argnum++)
       
   390 		{
       
   391 		if(aArgPtrs[argnum] && (aArgPtrs[argnum][0] == OPTCHAR || aArgPtrs[argnum][0]==ALTERNATE_OPTCHAR))
       
   392 			{
       
   393 			if(aArgPtrs[argnum][1]=='r' || aArgPtrs[argnum][1]=='R')
       
   394 				{
       
   395 				if(storeType==ECompressedRomStore)
       
   396 					{
       
   397 					ret=TooManyArgs;
       
   398 					CompilationReport(quiet,ret,storeType,NULL,NULL,0,aDestCreated);
       
   399 					return ret;
       
   400 					}
       
   401 				storeType=ERomStore;
       
   402 				aArgPtrs[argnum] = NULL;
       
   403 				}
       
   404 			else if(aArgPtrs[argnum][1]=='s' || aArgPtrs[argnum][1]=='S')
       
   405 				{
       
   406 				if(storeType==ERomStore)
       
   407 					{
       
   408 					ret=TooManyArgs;
       
   409 					CompilationReport(quiet,ret,storeType,NULL,NULL,0,aDestCreated);
       
   410 					return ret;
       
   411 					}
       
   412 				storeType=ECompressedRomStore;
       
   413 				aArgPtrs[argnum] = NULL;
       
   414 				}
       
   415 			else if(aArgPtrs[argnum][1]=='n' || aArgPtrs[argnum][1]=='N')
       
   416 				{
       
   417 				compression=0;
       
   418 				aArgPtrs[argnum] = NULL;
       
   419 				}
       
   420 			else if(aArgPtrs[argnum][1]=='h' || aArgPtrs[argnum][1]=='H')
       
   421 				{
       
   422 				headerfilename = &aArgPtrs[argnum][2];
       
   423 				aArgPtrs[argnum] = NULL;
       
   424 				}
       
   425 			else if(aArgPtrs[argnum][1]=='q' || aArgPtrs[argnum][1]=='Q')
       
   426 				{
       
   427 				if (getenv("BMCONV_NOT_QUIET") == 0)
       
   428 					quiet=1;
       
   429 				aArgPtrs[argnum] = NULL;
       
   430 				}
       
   431 			else if(aArgPtrs[argnum][1]=='p' || aArgPtrs[argnum][1]=='P')
       
   432 				{
       
   433 				palettefilename = &aArgPtrs[argnum][2];
       
   434                 if (*palettefilename=='"')
       
   435                     {
       
   436                     palettefilename+=1;
       
   437                     }
       
   438 				aArgPtrs[argnum] = NULL;
       
   439 				}
       
   440 			}
       
   441 		else
       
   442 			break;		// the RNHQP arguments must precede the output filename
       
   443 		}
       
   444 
       
   445 	if( palettefilename == NULL )
       
   446 	    {
       
   447 	    // Palette file not given in arguments. If the default palette file
       
   448 	    // was found, use it, otherwise return error.
       
   449 	    if( defaultPalettefile != NULL )
       
   450 	        {
       
   451 	        memcpy(paletteBuf, defaultPalettefile, strlen(defaultPalettefile));
       
   452 	        palettefilename = paletteBuf;
       
   453 	        }
       
   454 	    else
       
   455 	        {
       
   456 	        // Palettefile not given in arguments nor found from default locations:
       
   457 	        ret = PaletteFile;
       
   458 	        CompilationReport(quiet,ret,storeType,NULL,NULL,0,aDestCreated);
       
   459 	        return ret;
       
   460 	        }
       
   461 	    }
       
   462 	int firstsource=0;
       
   463 	while(firstsource<aArgArraySize && aArgPtrs[firstsource]==NULL)
       
   464 		firstsource++;
       
   465 	if(firstsource==aArgArraySize) firstsource=0;
       
   466 	destfilename=aArgPtrs[firstsource];
       
   467 	firstsource++;
       
   468 	int numsources=firstsource;
       
   469 	while(numsources<aArgArraySize && aArgPtrs[numsources]!=NULL)
       
   470 		numsources++;
       
   471 	if(numsources==aArgArraySize) numsources=0;
       
   472 	numsources-=firstsource;
       
   473 
       
   474 	TSourceFile* sources = 0;
       
   475 
       
   476 	if (numsources > 0)
       
   477 		{
       
   478 		sources = new TSourceFile[numsources];
       
   479 		for (int ii=0; ii<numsources; ii++)
       
   480 			sources[ii].FileName() = aArgPtrs[firstsource + ii];
       
   481 		BitmapCompiler mp(sources,numsources);
       
   482 		ret = mp.Compile(storeType,compression,destfilename,headerfilename,palettefilename);
       
   483 		aDestCreated = true;		// The multiple bitmap store has been created/modified
       
   484 		}
       
   485 
       
   486 	CompilationReport(quiet,ret,storeType,destfilename,sources,aNumArgs-firstsource,aDestCreated);
       
   487 	delete [] sources;
       
   488 
       
   489 	return ret;
       
   490 	}
       
   491 
       
   492 void GetInfo(char* aSourceFile)
       
   493 	{
       
   494 	Header();
       
   495 
       
   496 	EpocLoader pl;
       
   497 	int numSources=-1;
       
   498 	int romFormat=0;
       
   499 	int ret = pl.EpocBitmapCount(aSourceFile, numSources, romFormat);
       
   500 	if (ret)
       
   501 		{
       
   502 		cout << "Problem reading number of bitmaps \n";
       
   503 		cout << ErrorMessage(ret) << "\n";
       
   504 		return;
       
   505 		}
       
   506 
       
   507 	cout << aSourceFile << " is a " << (romFormat? "ROM image":"File store") 
       
   508 		<< " containing " << numSources << ((numSources==1)? " bitmap\n":" bitmaps\n");
       
   509 
       
   510 	for (int count = 0;count<numSources;count++)
       
   511 		{
       
   512 		ret = pl.LoadEpocBitmap(aSourceFile,count);
       
   513 		if (ret == OutOfRange)
       
   514 			break;
       
   515 		cout << "\n";
       
   516 		if (ret)
       
   517 			{
       
   518 			cout << "Problem loading bitmap number " << count << "\n";
       
   519 			cout << ErrorMessage(ret) << "\n";
       
   520 			break;
       
   521 			}
       
   522 		else
       
   523 			{
       
   524 			SEpocBitmapHeader h = pl.Header();
       
   525 			cout << "Bitmap " << count + 1 << " information:\n";
       
   526 			cout << "Pixel size " << h.iWidthInPixels << " x " << h.iHeightInPixels << "\n";
       
   527 			cout << "Twips size " << h.iWidthInTwips << " x " << h.iHeightInTwips << "\n";
       
   528 			cout << h.iBitsPerPixel << " Bpp ";
       
   529 			if (h.iColor == EColorBitmap)
       
   530 				cout << "Colour";
       
   531 			else if (h.iColor == EColorBitmapAlpha)
       
   532 				cout << "Colour with alpha channel";
       
   533 			else if(h.iColor == EMonochromeBitmap)
       
   534 				cout << "Monochrome";
       
   535 			else
       
   536 				cout << "Unknown colour format";
       
   537 			cout << "\n";
       
   538 			if (h.iPaletteEntries > 0)
       
   539 				cout << "Palette entries " << h.iPaletteEntries;
       
   540 
       
   541 			int byteSize = BitmapUtils::ByteWidth(h.iWidthInPixels,h.iBitsPerPixel) * h.iHeightInPixels;
       
   542 			int compressionRatio = 0;
       
   543 			if (byteSize > 0)
       
   544 				compressionRatio = (h.iBitmapSize - sizeof(SEpocBitmapHeader)) * 100 / byteSize;
       
   545 
       
   546 			switch (h.iCompression)
       
   547 				{
       
   548 			case ENoBitmapCompression:
       
   549 				cout << "No compression\n";
       
   550 				break;
       
   551 			case EByteRLECompression:
       
   552 				cout << "Bytewise RLE compression " << compressionRatio << "%\n";
       
   553 				break;
       
   554 			case ETwelveBitRLECompression:
       
   555 				cout << "12 bit RLE compression " << compressionRatio << "%\n";
       
   556 				break;
       
   557 			case ESixteenBitRLECompression:
       
   558 				cout << "16 bit RLE compression " << compressionRatio << "%\n";
       
   559 				break;
       
   560 			case ETwentyFourBitRLECompression:
       
   561 				cout << "24 bit RLE compression " << compressionRatio << "%\n";
       
   562 				break;
       
   563 			case EThirtyTwoUBitRLECompression:
       
   564 				cout << "unsigned 32 bit RLE compression (no alpha channel) " << compressionRatio << "%\n";
       
   565 				break;
       
   566 			case EThirtyTwoABitRLECompression:
       
   567 				cout << "unsigned 32 bit RLE compression (with alpha channel) " << compressionRatio << "%\n";
       
   568 				break;
       
   569 		//	case ERLECompressionLast: // Added to supress unhandled switch warning
       
   570 			default:
       
   571 				break;
       
   572 				}
       
   573 			}
       
   574 		}
       
   575 
       
   576 	cout << "\n";
       
   577 	}
       
   578 
       
   579 class TAutoPtr
       
   580 	{
       
   581 public:
       
   582 	TAutoPtr(char** aPtr) :
       
   583 		iPtr(aPtr)
       
   584 		{
       
   585 		}
       
   586 	~TAutoPtr()
       
   587 		{
       
   588 		delete iPtr;
       
   589 		}
       
   590 private:
       
   591 	char** iPtr;
       
   592 	};
       
   593 
       
   594 int main(int argc,char* argv[],char* [])
       
   595     {
       
   596 	if (argc <= 1)
       
   597 		{
       
   598 		Usage();
       
   599 		return 0;
       
   600 		}
       
   601 
       
   602 	int optMaxCnt = argc;
       
   603 
       
   604 	if(argc==2) // The single argument must be a command file name
       
   605 		{
       
   606 		struct stat fileinfo;
       
   607 		if (stat(argv[1],&fileinfo)==-1)
       
   608 			{
       
   609 			Report(CommandFile);
       
   610 			return 0;
       
   611 			}
       
   612 		optMaxCnt = fileinfo.st_size;
       
   613 		}
       
   614 
       
   615 	char** argptrs = new char*[optMaxCnt];
       
   616 	if(!argptrs)
       
   617 		{
       
   618 		Report(NoMemory);
       
   619 		return 0;
       
   620 		}
       
   621 	TAutoPtr autoPtr(argptrs);
       
   622 	memset(argptrs, 0, optMaxCnt * sizeof(char*));
       
   623 
       
   624 	int numargs = 0;
       
   625 	if(argc>2) // Explicit arguments are present
       
   626 		{
       
   627 		for(int count=0;count<argc-1;count++)
       
   628 			argptrs[count]=argv[count+1];
       
   629 		numargs = argc-1;
       
   630 		}
       
   631 	else // The single argument must be a command file name
       
   632 		{
       
   633 		int ret = ProcessCommandFile(argv[1],argptrs,numargs);
       
   634 		if (ret)
       
   635 			{
       
   636 			Report(ret);
       
   637 			return 0;
       
   638 			}
       
   639 		}
       
   640 
       
   641 	if ((argptrs[0]!=NULL && (argptrs[0][0]==OPTCHAR || argptrs[0][0]==ALTERNATE_OPTCHAR)) && (argptrs[0][1]=='u' || argptrs[0][1]=='U')) {
       
   642 		return Decompile(argc,numargs,argptrs); }
       
   643 
       
   644 	if ((argptrs[0]!=NULL && (argptrs[0][0]==OPTCHAR || argptrs[0][0]==ALTERNATE_OPTCHAR)) && (argptrs[0][1]=='v' || argptrs[0][1]=='V'))
       
   645 		{
       
   646 		GetInfo(argptrs[1]);
       
   647 		return 0;
       
   648 		}
       
   649 
       
   650 	return Compile(numargs,optMaxCnt,argptrs);
       
   651     }
       
   652