graphicstools/gdi_tools/bmconv/PBMTOBM.CPP
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <assert.h>
       
    17 #include "BMCONV.H"
       
    18 
       
    19 EpocLoader::EpocLoader():
       
    20 	iPbmBits(NULL)
       
    21 	{}
       
    22 
       
    23 EpocLoader::~EpocLoader()
       
    24 	{
       
    25 	delete iPbmBits;
       
    26 	}
       
    27 
       
    28 int EpocLoader::EpocBitmapCount(char* aFileName, int& aCount, int& isRomFormat)
       
    29     {
       
    30 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
    31 	fstream file(aFileName, ios::in | ios::binary);
       
    32 #else //!__MSVCDOTNET__
       
    33 	fstream file(aFileName, ios::in | ios::binary | ios::nocreate);
       
    34 #endif //__MSVCDOTNET__
       
    35 
       
    36 	if (file.is_open()==0)
       
    37 		return Files;
       
    38 
       
    39 	long int wordbuffer;
       
    40 	file.read((char *)&wordbuffer,4);
       
    41 	if (file.gcount()!=4)
       
    42 		return SourceFile;
       
    43 	if (wordbuffer==KMultiBitmapRomImageUid)
       
    44 		{
       
    45 		// ROM format file - next 4 bytes are the number of bitmaps
       
    46 		isRomFormat=1;
       
    47 		}
       
    48 	else
       
    49 		{
       
    50 		if (wordbuffer!=KWriteOnceFileStoreUid)
       
    51 			return SourceFile;
       
    52 		isRomFormat=0;
       
    53 		file.read((char *)&wordbuffer,4);
       
    54 		if (file.gcount()!=4 || wordbuffer!=KMultiBitmapFileImageUid)
       
    55 			return SourceFile;
       
    56 		file.read((char *)&wordbuffer,4);
       
    57 		if (file.gcount()!=4 || wordbuffer!=0)
       
    58 			return SourceFile;
       
    59 		file.read((char *)&wordbuffer,4);
       
    60 		if (file.gcount()!=4 || wordbuffer!=KMultiBitmapFileImageChecksum)
       
    61 			return SourceFile;
       
    62 		file.read((char *)&wordbuffer,4);
       
    63 		if (file.gcount()!=4)
       
    64 			return SourceFile;
       
    65 		file.seekg(wordbuffer,ios::beg);
       
    66 		}
       
    67 	file.read((char *)&wordbuffer,4);
       
    68 	if (file.gcount()!=4)
       
    69 		return SourceFile;
       
    70 	aCount=wordbuffer;
       
    71 	return NoError;
       
    72     }
       
    73 
       
    74 int EpocLoader::LoadEpocBitmap(char* aFileName,int aIndex)
       
    75 	{
       
    76 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
    77 	fstream file(aFileName, ios::in | ios::binary);
       
    78 #else //!__MSVCDOTNET__
       
    79 	fstream file(aFileName, ios::in | ios::binary | ios::nocreate);
       
    80 #endif //__MSVCDOTNET__
       
    81 
       
    82 	if (file.is_open()==0)
       
    83 		return Files;
       
    84 
       
    85 	long int wordbuffer;
       
    86 	file.read((char *)&wordbuffer,4);
       
    87 	if (file.gcount()!=4)
       
    88 		return SourceFile;
       
    89 	file.close();
       
    90 
       
    91 	if (wordbuffer==KMultiBitmapRomImageUid)
       
    92 		return LoadRom(aFileName,aIndex);
       
    93 
       
    94 	return LoadFile(aFileName,aIndex);
       
    95 	}
       
    96 
       
    97 int EpocLoader::LoadFile(char* aFileName,int aIndex)
       
    98 	{
       
    99 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
   100 	fstream file(aFileName, ios::in | ios::binary);
       
   101 #else //!__MSVCDOTNET__
       
   102 	fstream file(aFileName, ios::in | ios::binary | ios::nocreate);
       
   103 #endif //__MSVCDOTNET__
       
   104 
       
   105 	if (file.is_open()==0)
       
   106 		return Files;
       
   107 
       
   108 	long int wordbuffer;
       
   109 	file.read((char *)&wordbuffer,4);
       
   110 	if (file.gcount()!=4 || wordbuffer!=KWriteOnceFileStoreUid)
       
   111 		return SourceFile;
       
   112 	file.read((char *)&wordbuffer,4);
       
   113 	if (file.gcount()!=4 || wordbuffer!=KMultiBitmapFileImageUid)
       
   114 		return SourceFile;
       
   115 	file.read((char *)&wordbuffer,4);
       
   116 	if (file.gcount()!=4 || wordbuffer!=0)
       
   117 		return SourceFile;
       
   118 	file.read((char *)&wordbuffer,4);
       
   119 	if (file.gcount()!=4 || wordbuffer!=KMultiBitmapFileImageChecksum)
       
   120 		return SourceFile;
       
   121 	file.read((char *)&wordbuffer,4);
       
   122 	if (file.gcount()!=4)
       
   123 		return SourceFile;
       
   124 	file.seekg(wordbuffer,ios::beg);
       
   125 	file.read((char *)&wordbuffer,4);
       
   126 	if (file.gcount()!=4)
       
   127 		return SourceFile;
       
   128 
       
   129 	int numsources=wordbuffer;
       
   130 	if (aIndex >= numsources)
       
   131 		return OutOfRange;
       
   132 	file.seekg(aIndex*4,ios::cur);
       
   133 	file.read((char *)&wordbuffer,4);
       
   134 	if (file.gcount()!=4)
       
   135 		return SourceFile;
       
   136 	file.seekg(wordbuffer,ios::beg);
       
   137 	int ret = DoLoadFile(file);
       
   138 	file.close();
       
   139 	return ret;
       
   140 	}
       
   141 
       
   142 int EpocLoader::LoadRom(char* aFileName,int aIndex)
       
   143 	{
       
   144 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
   145 	fstream file(aFileName, ios::in | ios::binary);
       
   146 #else //!__MSVCDOTNET__
       
   147 	fstream file(aFileName, ios::in | ios::binary | ios::nocreate);
       
   148 #endif //__MSVCDOTNET__
       
   149 
       
   150 	if (file.is_open()==0)
       
   151 		return Files;
       
   152 
       
   153 	long int wordbuffer;
       
   154 	file.read((char *)&wordbuffer,4);
       
   155 	if (file.gcount()!=4)
       
   156 		return SourceFile;
       
   157 	if (wordbuffer!=KMultiBitmapRomImageUid)
       
   158 		return SourceFile;
       
   159 	file.read((char *)&wordbuffer,4);
       
   160 	if (file.gcount()!=4)
       
   161 		return SourceFile;
       
   162 	if (aIndex>=wordbuffer)
       
   163 		return OutOfRange;
       
   164 	file.seekg(aIndex*4,ios::cur);
       
   165 	file.read((char *)&wordbuffer,4);
       
   166 	if (file.gcount()!=4)
       
   167 		return SourceFile;
       
   168 	file.seekg(wordbuffer,ios::beg);
       
   169 	int ret=DoLoadRom(file);
       
   170 	file.close();
       
   171 	return ret;
       
   172 	}
       
   173 
       
   174 int EpocLoader::DoLoadFile(fstream& aFile)
       
   175 	{
       
   176 	long size = sizeof(SEpocBitmapHeader);
       
   177 	aFile.read((char *)&iPbmHeader,size);
       
   178 	if (aFile.gcount()!=size)
       
   179 		return SourceFile;
       
   180 	iOriginalPbmHeader = iPbmHeader;
       
   181 	size=iPbmHeader.iBitmapSize-iPbmHeader.iStructSize;
       
   182 
       
   183 	iPbmBits=new char[size];
       
   184 	if (iPbmBits==NULL)
       
   185 		return NoMemory;
       
   186 	memset(iPbmBits,0xff,size);
       
   187 	aFile.read(iPbmBits,size);
       
   188 	aFile.close();
       
   189 	if (aFile.gcount() != size)
       
   190 		return SourceFile;
       
   191 
       
   192 	if (iPbmHeader.iCompression != ENoBitmapCompression)
       
   193 		{
       
   194 		return Decompress(size);
       
   195 		}
       
   196 
       
   197 	return NoError;
       
   198 	}
       
   199 
       
   200 int EpocLoader::DoLoadRom(fstream& aFile)
       
   201 	{
       
   202 	Bitmap bmp;
       
   203 	long size=sizeof(Bitmap);
       
   204 	aFile.read((char*)&bmp,size);
       
   205 	if (aFile.gcount() != size)
       
   206 		return SourceFile;
       
   207 
       
   208 	size = bmp.iHeader.iBitmapSize - sizeof(SEpocBitmapHeader);
       
   209 	iPbmBits = new char[size];
       
   210 	if (iPbmBits == NULL)
       
   211 		return NoMemory;
       
   212 	memset(iPbmBits,0xff,size);
       
   213 
       
   214 	aFile.read(iPbmBits,size);
       
   215 	if (aFile.gcount() != size)
       
   216 		return SourceFile;
       
   217 	iPbmHeader = bmp.iHeader;
       
   218 	iOriginalPbmHeader = iPbmHeader;
       
   219 
       
   220 	if (iPbmHeader.iCompression != ENoBitmapCompression)
       
   221 		{
       
   222 		return Decompress(size);
       
   223 		}
       
   224 
       
   225 	return NoError;
       
   226 	}
       
   227 
       
   228 int EpocLoader::Decompress(int aSize)
       
   229 	{
       
   230 	int byteWidth = BitmapUtils::ByteWidth(iPbmHeader.iWidthInPixels,iPbmHeader.iBitsPerPixel);
       
   231 	int expandedsize = byteWidth * iPbmHeader.iHeightInPixels;
       
   232 	char* newbits = new char[expandedsize];
       
   233 	if (newbits == NULL)
       
   234 		return NoMemory;
       
   235 	memset(newbits,0xff,expandedsize);
       
   236 	int ret = NoError;
       
   237 	switch (iPbmHeader.iCompression)
       
   238 		{
       
   239 	case EByteRLECompression:
       
   240 		ret = ExpandByteRLEData(newbits,expandedsize,iPbmBits,aSize);
       
   241 		break;
       
   242 	case ETwelveBitRLECompression:
       
   243 		ret = ExpandTwelveBitRLEData(newbits,expandedsize,iPbmBits,aSize);
       
   244 		break;
       
   245 	case ESixteenBitRLECompression:
       
   246 		ret = ExpandSixteenBitRLEData(newbits,expandedsize,iPbmBits,aSize);
       
   247 		break;
       
   248 	case ETwentyFourBitRLECompression:
       
   249 		ret = ExpandTwentyFourBitRLEData(newbits,expandedsize,iPbmBits,aSize);
       
   250 		break;
       
   251 	case EThirtyTwoUBitRLECompression:
       
   252 		ret = ExpandThirtyTwoUBitRLEData(newbits,expandedsize,iPbmBits,aSize);
       
   253 		break;
       
   254 	case EThirtyTwoABitRLECompression:
       
   255 		ret = ExpandThirtyTwoABitRLEData(newbits,expandedsize,iPbmBits,aSize);
       
   256 		break;
       
   257 	default:
       
   258 		ret = UnknownCompression;
       
   259 		break;
       
   260 		}
       
   261 	delete iPbmBits;
       
   262 	iPbmBits = newbits;
       
   263 	iPbmHeader.iCompression = ENoBitmapCompression;
       
   264 	iPbmHeader.iBitmapSize += expandedsize-aSize;
       
   265 	return ret;
       
   266 	}
       
   267 
       
   268 int EpocLoader::ExpandByteRLEData(char* aDest,int aDestSize,char* aSrce,int aSrceSize)
       
   269 	{
       
   270 	char* srcelimit=aSrce+aSrceSize;
       
   271 	char* destlimit=aDest+aDestSize;
       
   272 	while(aSrce<srcelimit && aDest<destlimit)
       
   273 		{
       
   274 		char count=*aSrce++;
       
   275 		if (count<0)
       
   276 			{
       
   277 			int runLength=-count;
       
   278 			memcpy(aDest,aSrce,runLength);
       
   279 			aSrce+=runLength;
       
   280 			aDest+=runLength;
       
   281 			}
       
   282 		else
       
   283 			{
       
   284 			char value=*aSrce++;
       
   285 			while(count>=0)
       
   286 				{
       
   287 				*aDest++=value;
       
   288 				count--;
       
   289 				}
       
   290 			}
       
   291 		}
       
   292 	if (aSrce!=srcelimit || aDest!=destlimit)
       
   293 		return DecompressionError;
       
   294 	return NoError;
       
   295 	}
       
   296 
       
   297 int EpocLoader::ExpandTwelveBitRLEData(char* aDest,int aDestSizeInBytes,char* aSrce,int aSrceSizeInBytes)
       
   298 	{
       
   299 	unsigned short* srcePtr = (unsigned short*)aSrce;
       
   300 	unsigned short* destPtr = (unsigned short*)aDest;
       
   301 	unsigned short* srcePtrLimit = srcePtr + (aSrceSizeInBytes / 2);
       
   302 	unsigned short* destPtrLimit = destPtr + (aDestSizeInBytes / 2);
       
   303 
       
   304 	while (srcePtr < srcePtrLimit && destPtr < destPtrLimit)
       
   305 		{
       
   306 		unsigned short value = *srcePtr++;
       
   307 		int runLength = (value >> 12) + 1;
       
   308 		value &= 0x0fff;
       
   309 
       
   310 		for (;runLength > 0;runLength--)
       
   311 			*destPtr++ = value;
       
   312 		}
       
   313 
       
   314 	if (srcePtr != srcePtrLimit || destPtr != destPtrLimit)
       
   315 		return DecompressionError;
       
   316 
       
   317 	return NoError;
       
   318 	}
       
   319 
       
   320 int EpocLoader::ExpandSixteenBitRLEData(char* aDest,int aDestSizeInBytes,char* aSrce,int aSrceSizeInBytes)
       
   321 	{
       
   322 	char* srcePtrLimit = aSrce + aSrceSizeInBytes;
       
   323 	unsigned short* destPtr = (unsigned short*)aDest;
       
   324 	unsigned short* destPtrLimit = destPtr + (aDestSizeInBytes / 2);
       
   325 
       
   326 	while (aSrce < srcePtrLimit && destPtr < destPtrLimit)
       
   327 		{
       
   328 		int runLength = *aSrce++;
       
   329 
       
   330 		if (runLength >= 0)
       
   331 			{
       
   332 			unsigned short value = *((unsigned short*)(aSrce));
       
   333 			aSrce += 2;
       
   334 			for (runLength++; runLength > 0; runLength--)
       
   335 				*destPtr++ = value;
       
   336 			}
       
   337 		else
       
   338 			{
       
   339 			runLength = -runLength;
       
   340 			int byteLength = runLength * 2;
       
   341 			memcpy(destPtr,aSrce,byteLength);
       
   342 			aSrce += byteLength;
       
   343 			destPtr += runLength;
       
   344 			}
       
   345 		}
       
   346 
       
   347 	if (aSrce != srcePtrLimit || destPtr != destPtrLimit)
       
   348 		return DecompressionError;
       
   349 
       
   350 	return NoError;
       
   351 	}
       
   352 
       
   353 int EpocLoader::ExpandTwentyFourBitRLEData(char* aDest,int aDestSizeInBytes,char* aSrce,int aSrceSizeInBytes)
       
   354 	{
       
   355 	char* srcePtrLimit = aSrce + aSrceSizeInBytes;
       
   356 	char* destPtrLimit = aDest + aDestSizeInBytes;
       
   357 
       
   358 	while (aSrce < srcePtrLimit && aDest < destPtrLimit)
       
   359 		{
       
   360 		int runLength = *aSrce++;
       
   361 
       
   362 		if (runLength >= 0)
       
   363 			{
       
   364 			char component1 = *aSrce++;
       
   365 			char component2 = *aSrce++;
       
   366 			char component3 = *aSrce++;
       
   367 			for (runLength++; runLength > 0; runLength--)
       
   368 				{
       
   369 				*aDest++ = component1;
       
   370 				*aDest++ = component2;
       
   371 				*aDest++ = component3;
       
   372 				}
       
   373 			}
       
   374 		else
       
   375 			{
       
   376 			runLength = -runLength;
       
   377 			int byteLength = runLength * 3;
       
   378 			memcpy(aDest,aSrce,byteLength);
       
   379 			aSrce += byteLength;
       
   380 			aDest += byteLength;
       
   381 			}
       
   382 		}
       
   383 
       
   384 	if (aSrce != srcePtrLimit || aDest != destPtrLimit)
       
   385 		return DecompressionError;
       
   386 
       
   387 	return NoError;
       
   388 	}
       
   389 
       
   390 /** The function decodes 24-bit compressed pixel buffer into the 32-bit buffer, where top bytes are unused*/
       
   391 int EpocLoader::ExpandThirtyTwoUBitRLEData(char* aDest,int aDestSizeInBytes,char* aSrce,int aSrceSizeInBytes)
       
   392 	{
       
   393 	char* srcePtrLimit = aSrce + aSrceSizeInBytes;
       
   394 	char* destPtrLimit = aDest + aDestSizeInBytes;
       
   395 
       
   396 	while (aSrce < srcePtrLimit && aDest < destPtrLimit)
       
   397 		{
       
   398 		int runLength = *aSrce++;
       
   399 
       
   400 		if (runLength >= 0)
       
   401 			{
       
   402 			char component1 = *aSrce++;
       
   403 			char component2 = *aSrce++;
       
   404 			char component3 = *aSrce++;
       
   405 			for (runLength++; runLength > 0; runLength--)
       
   406 				{
       
   407 				*aDest++ = component1;
       
   408 				*aDest++ = component2;
       
   409 				*aDest++ = component3;
       
   410 				aDest++;
       
   411 				}
       
   412 			}
       
   413 		else 
       
   414 			{
       
   415 			runLength = -runLength;
       
   416 			for(int ii = 0; ii < runLength; ii++)
       
   417 				{
       
   418 				memcpy(aDest,aSrce,3);
       
   419 				aSrce += 3;
       
   420 				aDest += 4;
       
   421 				}
       
   422 			}
       
   423 		}
       
   424 
       
   425 	if (aSrce != srcePtrLimit || aDest != destPtrLimit)
       
   426 		return DecompressionError;
       
   427 
       
   428 	return NoError;
       
   429 	}
       
   430 
       
   431 /** The function decodes 32-bit compressed pixel buffer into the 32-bit buffer, where top bytes are alpha channel*/
       
   432 int EpocLoader::ExpandThirtyTwoABitRLEData(char* aDest,int aDestSizeInBytes,char* aSrce,int aSrceSizeInBytes)
       
   433 	{
       
   434 	char* srcePtrLimit = aSrce + aSrceSizeInBytes;
       
   435 	char* destPtrLimit = aDest + aDestSizeInBytes;
       
   436 
       
   437 	while (aSrce < srcePtrLimit && aDest < destPtrLimit)
       
   438 		{
       
   439 		int runLength = *aSrce++;
       
   440 
       
   441 		if (runLength >= 0)
       
   442 			{
       
   443 			char component1 = *aSrce++;
       
   444 			char component2 = *aSrce++;
       
   445 			char component3 = *aSrce++;
       
   446 			char component4 = *aSrce++;
       
   447 			for (runLength++; runLength > 0; runLength--)
       
   448 				{
       
   449 				*aDest++ = component1;
       
   450 				*aDest++ = component2;
       
   451 				*aDest++ = component3;
       
   452 				*aDest++ = component4;
       
   453 				}
       
   454 			}
       
   455 		else 
       
   456 			{
       
   457 			runLength = -runLength;
       
   458 			memcpy(aDest,aSrce,4*runLength);
       
   459 			aSrce += 4*runLength;
       
   460 			aDest += 4*runLength;
       
   461 			}
       
   462 		}
       
   463 
       
   464 	if (aSrce != srcePtrLimit || aDest != destPtrLimit)
       
   465 		return DecompressionError;
       
   466 
       
   467 	return NoError;
       
   468 	}
       
   469 
       
   470 TRgb EpocLoader::GetPixel(int aXCoord,int aYCoord)
       
   471 	{
       
   472 	unsigned char col;
       
   473 	aXCoord%=iPbmHeader.iWidthInPixels;
       
   474 	aYCoord%=iPbmHeader.iHeightInPixels;
       
   475 	int byteWidth = BitmapUtils::ByteWidth(iPbmHeader.iWidthInPixels,iPbmHeader.iBitsPerPixel);
       
   476 	int yOffset = aYCoord * byteWidth;
       
   477 
       
   478 	switch(iPbmHeader.iBitsPerPixel)
       
   479 		{
       
   480 		case 1:
       
   481 			col = iPbmBits[yOffset + (aXCoord / 8)];
       
   482 			col >>= (aXCoord&7);
       
   483 			return TRgb::Gray2(col & 1);
       
   484 		case 2:
       
   485 			col = iPbmBits[yOffset + (aXCoord / 4)];
       
   486 			col = (unsigned char)(col>>(2*(aXCoord%4)));
       
   487 			return TRgb::Gray4(col & 3);
       
   488 		case 4:
       
   489 			col = iPbmBits[yOffset + (aXCoord / 2)];
       
   490 			if (aXCoord & 1)
       
   491 				col >>= 4;
       
   492 			col &= 0xf;
       
   493 			if (iPbmHeader.iColor==EColorBitmap)
       
   494 				return TRgb::Color16(col);
       
   495 			else
       
   496 				return TRgb::Gray16(col);
       
   497 		case 8:
       
   498 			col=iPbmBits[yOffset + aXCoord];
       
   499 			if (iPbmHeader.iColor==EColorBitmap)
       
   500 				return TRgb::Color256(col);
       
   501 			else
       
   502 				return TRgb::Gray256(col);
       
   503 		case 12:
       
   504 		case 16:
       
   505 			{
       
   506 			unsigned short* shortPtr = (unsigned short*)&iPbmBits[yOffset + (aXCoord * 2)];
       
   507 			if (iPbmHeader.iBitsPerPixel == 12)
       
   508 				return TRgb::Color4K(*shortPtr);
       
   509 			else
       
   510 				return TRgb::Color64K(*shortPtr);
       
   511 			}
       
   512 		case 24:
       
   513 			{
       
   514 			char* pixelPtr = iPbmBits + yOffset + (aXCoord * 3);
       
   515 			TRgb pixelColor;
       
   516 			pixelColor.iBlue = *pixelPtr++;
       
   517 			pixelColor.iGreen = *pixelPtr++;
       
   518 			pixelColor.iRed = *pixelPtr;
       
   519 			return pixelColor;
       
   520 			}
       
   521 		case 32:
       
   522 			{
       
   523 			char* pixelPtr = iPbmBits + yOffset + (aXCoord * 4);
       
   524 			TRgb pixelColor;
       
   525 			pixelColor.iBlue = *pixelPtr++;
       
   526 			pixelColor.iGreen = *pixelPtr++;
       
   527 			pixelColor.iRed = *pixelPtr++;
       
   528 			pixelColor.iSpare = *pixelPtr;
       
   529 			return pixelColor;
       
   530 			}
       
   531 		default:
       
   532 			return TRgb(0);
       
   533 		}
       
   534 	}
       
   535 
       
   536 unsigned char EpocLoader::GetAlpha(int aXCoord,int aYCoord)
       
   537 	{
       
   538 	aXCoord%=iPbmHeader.iWidthInPixels;
       
   539 	aYCoord%=iPbmHeader.iHeightInPixels;
       
   540 	int byteWidth = BitmapUtils::ByteWidth(iPbmHeader.iWidthInPixels,iPbmHeader.iBitsPerPixel);
       
   541 	int yOffset = aYCoord * byteWidth;
       
   542 
       
   543 	assert(iPbmHeader.iBitsPerPixel == 32); // this method must only be called for 32bpp bitmaps!
       
   544 
       
   545 	char* pixelPtr = iPbmBits + yOffset + (aXCoord * 4);
       
   546 	pixelPtr += 3; // skip over RGB
       
   547 	unsigned char col = *pixelPtr;
       
   548 	return col;	
       
   549 	}
       
   550 
       
   551 int EpocLoader::SaveBitmap(char* aFileName)
       
   552 	{
       
   553 	TBitmapFileHeader fileheader;
       
   554 	TBitmapInfoHeader bmpHeader;
       
   555 	char* bmpBits;
       
   556 
       
   557 	bmpHeader.biSize = sizeof(TBitmapInfoHeader);
       
   558 	bmpHeader.biWidth = iPbmHeader.iWidthInPixels;
       
   559 	bmpHeader.biHeight = iPbmHeader.iHeightInPixels;
       
   560 	bmpHeader.biPlanes = 1;
       
   561 	bmpHeader.biBitCount = 24;
       
   562 	bmpHeader.biCompression = 0;
       
   563 	bmpHeader.biSizeImage = 0;
       
   564 	bmpHeader.biXPelsPerMeter = 0;
       
   565 	bmpHeader.biYPelsPerMeter = 0;
       
   566 	bmpHeader.biClrUsed = 0;
       
   567 	bmpHeader.biClrImportant = 0;
       
   568 
       
   569 	long byteWidth = ((bmpHeader.biWidth * 3) + 3) & ~3;
       
   570 	long destlength = bmpHeader.biHeight * byteWidth;
       
   571 
       
   572 	fileheader.bfType = 'B'+('M'<<8);
       
   573 	fileheader.bfSize = sizeof(TBitmapFileHeader)+sizeof(TBitmapInfoHeader)+destlength;
       
   574 	fileheader.bfReserved1 = 0;
       
   575 	fileheader.bfReserved2 = 0;
       
   576 	fileheader.bfOffBits = sizeof(TBitmapFileHeader)+sizeof(TBitmapInfoHeader);
       
   577 
       
   578 	bmpBits = new char[destlength];
       
   579 	if (bmpBits == NULL)
       
   580 		return NoMemory;
       
   581 	memset(bmpBits,0xff,destlength);
       
   582 
       
   583 	for(long y=0;y<bmpHeader.biHeight;y++)
       
   584 		{
       
   585 		char* dest=&bmpBits[(bmpHeader.biHeight-y-1)*byteWidth];
       
   586 		for(long x=0;x<bmpHeader.biWidth;x++)
       
   587 			{
       
   588 			TRgb pixel=GetPixel(x,y);
       
   589 			*dest++=pixel.iBlue;
       
   590 			*dest++=pixel.iGreen;
       
   591 			*dest++=pixel.iRed;
       
   592 			}
       
   593 		}
       
   594 
       
   595 	fstream file(aFileName, ios::out | ios::binary);
       
   596 
       
   597 	if (file.is_open()==0)
       
   598 		{
       
   599 		delete bmpBits;
       
   600 		return DestFile;
       
   601 		}
       
   602 
       
   603 	file.write((char *)&fileheader,sizeof(TBitmapFileHeader));
       
   604 	file.write((char *)&bmpHeader,sizeof(TBitmapInfoHeader));
       
   605 	file.write((char *)bmpBits,destlength);
       
   606 	file.close();
       
   607 
       
   608 	delete bmpBits;
       
   609 
       
   610 	if (iPbmHeader.iColor == EColorBitmapAlpha || iPbmHeader.iColor ==EColorBitmapAlphaPM)
       
   611 		SaveAlpha(aFileName);
       
   612 	return NoError;
       
   613 	}
       
   614 
       
   615 
       
   616 int EpocLoader::SaveAlpha(char* aFileName)
       
   617 	{
       
   618 	TBitmapFileHeader fileheader;
       
   619 	TBitmapInfoHeader alphaHeader;
       
   620 
       
   621 	alphaHeader.biSize = sizeof(TBitmapInfoHeader);
       
   622 	alphaHeader.biWidth = iPbmHeader.iWidthInPixels;
       
   623 	alphaHeader.biHeight = iPbmHeader.iHeightInPixels;
       
   624 	alphaHeader.biPlanes = 1;
       
   625 	alphaHeader.biBitCount = 8;
       
   626 	alphaHeader.biCompression = 0;
       
   627 	alphaHeader.biSizeImage = 0;
       
   628 	alphaHeader.biXPelsPerMeter = 0;
       
   629 	alphaHeader.biYPelsPerMeter = 0;
       
   630 	alphaHeader.biClrUsed = 256;
       
   631 	alphaHeader.biClrImportant = 0;
       
   632 
       
   633 	const long paletteSize = 1024;
       
   634 
       
   635 	// ensure bytes-per-scanline is a large enough multiple of 4
       
   636 	long byteWidth = (alphaHeader.biWidth + 3) & ~3; 
       
   637 	long destlength = alphaHeader.biHeight * byteWidth;
       
   638 	alphaHeader.biSizeImage = destlength;
       
   639 
       
   640 	fileheader.bfType = 'B'+('M'<<8);
       
   641 	fileheader.bfSize = sizeof(TBitmapFileHeader)+sizeof(TBitmapInfoHeader)+paletteSize+destlength;
       
   642 	fileheader.bfReserved1 = 0;
       
   643 	fileheader.bfReserved2 = 0;
       
   644 	fileheader.bfOffBits = sizeof(TBitmapFileHeader)+sizeof(TBitmapInfoHeader)+paletteSize;
       
   645 
       
   646 	// we need to output the grayscale palette before the actual alpha data as this is an 8bpp BMP
       
   647 	char* palette = new char[paletteSize]; // 256 colors x 4bytes/color (r,g,b,unused)
       
   648 	if (palette == NULL)
       
   649 		return NoMemory;
       
   650 	memset(palette,0,paletteSize);
       
   651 	char* pEnt = palette;
       
   652 	for (long p=0;p<256;++p)
       
   653 		{
       
   654 		unsigned char col = (unsigned char)p;
       
   655 		*pEnt++=col;
       
   656 		*pEnt++=col;
       
   657 		*pEnt++=col;
       
   658 		pEnt++;
       
   659 		}
       
   660 
       
   661 	char* alphaBits = new char[destlength];
       
   662 	if (alphaBits == NULL)
       
   663 		{
       
   664 		delete [] palette;
       
   665 		return NoMemory;
       
   666 		}
       
   667 	memset(alphaBits,0,destlength);
       
   668 
       
   669 	for(long y=0;y<alphaHeader.biHeight;y++)
       
   670 		{
       
   671 		char* dest=&alphaBits[(alphaHeader.biHeight-y-1)*byteWidth];
       
   672 		for(long x=0;x<alphaHeader.biWidth;x++)
       
   673 			{
       
   674 			unsigned char alphaVal=GetAlpha(x,y);
       
   675 			*dest++=alphaVal;
       
   676 			}
       
   677 		}
       
   678 
       
   679 	int fileNameLen = strlen(aFileName);
       
   680 	char* alphaFileName = new char[fileNameLen + 7];// -alpha suffix is 6 chars, plus NUL termination
       
   681 	if (alphaFileName == NULL)
       
   682 		{
       
   683 		delete [] palette;
       
   684 		delete [] alphaBits;
       
   685 		return NoMemory;
       
   686 		}
       
   687 	int dotPos = -1;
       
   688 	for (int i = 0; i < fileNameLen; ++i)
       
   689 		if (aFileName[i]=='.')
       
   690 			dotPos=i;
       
   691 	int prefixLen = (dotPos>=0?dotPos:fileNameLen);
       
   692 	memcpy(alphaFileName,aFileName,prefixLen);
       
   693 	const char* suffix = "-alpha";
       
   694 	memcpy(alphaFileName+prefixLen,suffix,6);
       
   695 	if (dotPos>=0)
       
   696 		memcpy(alphaFileName+prefixLen+6,aFileName+dotPos,fileNameLen-dotPos);
       
   697 	*(alphaFileName + fileNameLen + 6) = '\0';
       
   698 	fstream file(alphaFileName, ios::out | ios::binary);
       
   699 	if (file.is_open()==0)
       
   700 		{
       
   701 		delete [] alphaFileName;
       
   702 		delete [] alphaBits;
       
   703 		delete [] palette;
       
   704 		return DestFile;
       
   705 		}
       
   706 
       
   707 	file.write((char *)&fileheader,sizeof(TBitmapFileHeader));
       
   708 	file.write((char *)&alphaHeader,sizeof(TBitmapInfoHeader));
       
   709 	file.write((char *)palette,paletteSize);
       
   710 	file.write((char *)alphaBits,destlength);
       
   711 	file.close();
       
   712 
       
   713 	delete [] alphaFileName;
       
   714 	delete [] alphaBits;
       
   715 	delete [] palette;
       
   716 	return NoError;
       
   717 	}
       
   718 
       
   719 int EpocLoader::DupBitmap(SEpocBitmapHeader*& aPbm)
       
   720 	{
       
   721 	char* newPbm = new char[iPbmHeader.iBitmapSize];
       
   722 	if (newPbm == NULL)
       
   723 		return NoMemory;
       
   724 	memcpy(newPbm, &iPbmHeader, sizeof(SEpocBitmapHeader));
       
   725 	memcpy(newPbm+sizeof(SEpocBitmapHeader), iPbmBits, iPbmHeader.iBitmapSize - sizeof(SEpocBitmapHeader));
       
   726 	aPbm = (SEpocBitmapHeader*)newPbm;
       
   727 	return NoError;
       
   728 	}
       
   729 
       
   730 /**
       
   731 Validates an mbm files bitmap information to ensure that the length of each bitmaps matches their location
       
   732 within the file. Also checks that the number of bitmap offsets available matches the number of bitmaps.
       
   733 
       
   734 @param aFilename The mbm file to be validated
       
   735 @return An error code from the Errors enumeration
       
   736  */
       
   737 int EpocLoader::ValidateEpocBitmap(char* aFilename)
       
   738 	{
       
   739 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
   740 	fstream file(aFilename, ios::in | ios::binary);
       
   741 #else //!__MSVCDOTNET__
       
   742 	fstream file(aFilename, ios::in | ios::binary | ios::nocreate);
       
   743 #endif //__MSVCDOTNET__
       
   744 	if (file.is_open()==0)
       
   745 		return Files;
       
   746 
       
   747 	long int wordbuffer;
       
   748 	int isRomFormat;
       
   749 	
       
   750 	file.read((char *)&wordbuffer,4);
       
   751 	if (file.gcount()!=4)
       
   752 		return SourceFile;
       
   753 	if (wordbuffer==KMultiBitmapRomImageUid)
       
   754 		{
       
   755 		//Validation not implemented for ROM only files.
       
   756 		}
       
   757 	else
       
   758 		{
       
   759 		if (wordbuffer!=KWriteOnceFileStoreUid)
       
   760 			return SourceFile;
       
   761 		isRomFormat=0;
       
   762 		file.read((char *)&wordbuffer,4);
       
   763 		if (file.gcount()!=4 || wordbuffer!=KMultiBitmapFileImageUid)
       
   764 			return SourceFile;
       
   765 		file.read((char *)&wordbuffer,4);
       
   766 		if (file.gcount()!=4 || wordbuffer!=0)
       
   767 			return SourceFile;
       
   768 		file.read((char *)&wordbuffer,4);
       
   769 		if (file.gcount()!=4 || wordbuffer!=KMultiBitmapFileImageChecksum)
       
   770 			return SourceFile;
       
   771 		file.read((char *)&wordbuffer,4);
       
   772 		if (file.gcount()!=4)
       
   773 			return SourceFile;
       
   774 		//The 5th byte is a pointer to the footer containing the number of bitmaps
       
   775 		//and the offset from the beginning of the file each begins at.
       
   776 		int footerPos = wordbuffer;
       
   777 		
       
   778 		file.seekg(footerPos,ios::beg);
       
   779 		
       
   780 		file.read((char *)&wordbuffer, 4);
       
   781 		if (file.gcount()!=4)
       
   782 			return SourceFile;
       
   783 		
       
   784 		int numBitmaps = wordbuffer;
       
   785 
       
   786 		int bmpOffset[numBitmaps+1];
       
   787 		
       
   788 		for (int i = 0; i < numBitmaps; i++)
       
   789 			{
       
   790 			file.read((char *)&wordbuffer,4);
       
   791 					if (file.gcount()!=4)
       
   792 						return SourceFile;
       
   793 			bmpOffset[i] = wordbuffer;
       
   794 			}
       
   795 		
       
   796 		//The byte at the end of the last bitmap is the location of the footer
       
   797 		bmpOffset[numBitmaps] = footerPos;
       
   798 		
       
   799 		//Check length of a bitmap is reflected in the difference between the offsets
       
   800 		for (int i = 0 ; i < numBitmaps ; i++)
       
   801 			{
       
   802 			file.seekg(bmpOffset[i]);
       
   803 			
       
   804 			//Read the length of this bitmap
       
   805 			file.read((char *)&wordbuffer,4);
       
   806 				if (file.gcount()!=4)
       
   807 					return SourceFile;
       
   808 
       
   809 			//Validate length against offsets of this & next bmp
       
   810 			if (bmpOffset[i+1]-wordbuffer != bmpOffset[i])
       
   811 				return SourceFile;
       
   812 			}
       
   813 		}
       
   814 	return NoError;
       
   815 	}