fbs/fontandbitmapserver/sfbs/BITCOMP.CPP
changeset 0 5d03bc08d59c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fbs/fontandbitmapserver/sfbs/BITCOMP.CPP	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,2233 @@
+// Copyright (c) 1995-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:
+//
+
+#include <f32file.h>
+#include <s32file.h>
+#include <fbs.h>
+#include <bitmap.h>
+#include "UTILS.H"
+#include <e32hashtab.h>
+
+GLREF_C void Panic(TFbsPanic aPanic);
+
+void CBitwiseBitmap::DoInternalizeCompressedDataL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase,TBitmapfileCompression aCompression)
+	{
+	TInt destSizeInBytes = iHeader.iSizeInPixels.iHeight * iByteWidth;
+	TUint8* destPtr = (TUint8*)aBase;
+
+	// try to allocate memory for the compressed bitmap
+	TUint8* decompressionBuffer = (TUint8*)User::Alloc(aSrceSizeInBytes);
+
+	if (decompressionBuffer)
+		{
+		// read the compressed bitmap, then decompress
+		CleanupStack::PushL(decompressionBuffer);
+		aStream.ReadL(decompressionBuffer,aSrceSizeInBytes);
+		switch (aCompression)
+			{
+		case EByteRLECompression:
+			DoDecompressByteData(destPtr,destSizeInBytes,decompressionBuffer,aSrceSizeInBytes);
+			break;
+		case ETwelveBitRLECompression:
+			DoDecompressTwelveBitData(destPtr,destSizeInBytes,decompressionBuffer,aSrceSizeInBytes);
+			break;
+		case ESixteenBitRLECompression:
+			DoDecompressSixteenBitData(destPtr,destSizeInBytes,decompressionBuffer,aSrceSizeInBytes);
+			break;
+		case ETwentyFourBitRLECompression:
+			DoDecompressTwentyFourBitData(destPtr,destSizeInBytes,decompressionBuffer,aSrceSizeInBytes);
+			break;
+		case EThirtyTwoUBitRLECompression:
+			DoDecompressThirtyTwoUBitData(destPtr,destSizeInBytes,decompressionBuffer,aSrceSizeInBytes);
+			break;
+		case EThirtyTwoABitRLECompression:
+			DoDecompressThirtyTwoABitData(destPtr,destSizeInBytes,decompressionBuffer,aSrceSizeInBytes);
+			break;
+		default:
+			break;
+			}
+		CleanupStack::PopAndDestroy(); // decompressionBuffer
+		return;
+		}
+
+	// not enough heap to pre-load the source bitmap
+	switch (aCompression)
+		{
+	case EByteRLECompression:
+		DoDecompressByteDataAltL(aStream,aSrceSizeInBytes,aBase);
+		break;
+	case ETwelveBitRLECompression:
+		DoDecompressTwelveBitDataAltL(aStream,aSrceSizeInBytes,aBase);
+		break;
+	case ESixteenBitRLECompression:
+		DoDecompressSixteenBitDataAltL(aStream,aSrceSizeInBytes,aBase);
+		break;
+	case ETwentyFourBitRLECompression:
+		DoDecompressTwentyFourBitDataAltL(aStream,aSrceSizeInBytes,aBase);
+		break;
+	case EThirtyTwoUBitRLECompression:
+		DoDecompressThirtyTwoUBitDataAltL(aStream,aSrceSizeInBytes,aBase);
+		break;
+	case EThirtyTwoABitRLECompression:
+		DoDecompressThirtyTwoABitDataAltL(aStream,aSrceSizeInBytes,aBase);
+		break;
+	default:
+		break;
+		}
+	}
+
+void CBitwiseBitmap::DoDecompressByteData(TUint8* aDestBuffer,TInt aDestSize,TUint8* aSrceBuffer,TInt aSrceSize)
+	{
+	TUint8* srcePtr = aSrceBuffer;
+	TUint8* destPtr = aDestBuffer;
+	TUint8* srcePtrLimit = aSrceBuffer + aSrceSize;
+	TUint8* destPtrLimit = aDestBuffer + aDestSize;
+
+	while (srcePtr < srcePtrLimit && destPtr < destPtrLimit)
+		{
+		TInt8 count = *srcePtr++;
+
+		if (count >= 0)
+			{
+			const TInt numBytes = Min(count + 1, destPtrLimit - destPtr);
+			Mem::Fill(destPtr,numBytes,*srcePtr++);
+			destPtr += numBytes;
+			}
+		else
+			{
+			const TInt numBytes = Min(-count, destPtrLimit - destPtr);
+			Mem::Copy(destPtr,srcePtr,numBytes);
+			srcePtr += numBytes;
+			destPtr += numBytes;
+			}
+		}
+	__ASSERT_DEBUG(srcePtr == srcePtrLimit && destPtr == destPtrLimit,Panic(EFbsBitmapDecompressionError));
+	}
+
+void CBitwiseBitmap::DoDecompressByteDataAltL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase)
+	{
+	TInt destSizeInBytes = iHeader.iSizeInPixels.iHeight * iByteWidth;
+	TUint8* destPtr = (TUint8*)aBase;
+	TUint8* destPtrLimit = destPtr + destSizeInBytes;
+
+	while(aSrceSizeInBytes > 0 && destPtr < destPtrLimit)
+		{
+		TInt8 count = aStream.ReadInt8L();
+		aSrceSizeInBytes--;
+
+		if (count >= 0)
+			{
+			const TInt numBytes = Min(count + 1, destPtrLimit - destPtr);
+			TUint8 value = aStream.ReadUint8L();
+			aSrceSizeInBytes--;
+			Mem::Fill(destPtr,numBytes,value);
+			destPtr += numBytes;
+			}
+		else
+			{
+			const TInt numBytes = Min(-count, destPtrLimit - destPtr);
+			aStream.ReadL(destPtr,numBytes);
+			aSrceSizeInBytes -= numBytes;
+			destPtr += numBytes;
+			}
+		}
+	__ASSERT_DEBUG(aSrceSizeInBytes == 0 && destPtr == destPtrLimit,Panic(EFbsBitmapDecompressionError));
+	}
+
+/** Fills the 32bit pixels into the destination pointer
+This method uses the concept of Duff's Device 
+@param aDestPtr32 pointer to 32bit destination buffer.
+@param aCount Number of 32bit pixels to be copied.
+@param aValue32 32bit pixel data. */
+void CBitwiseBitmap::BitmapFill32(TUint32* aDestPtr32, TInt aCount, TUint32 aValue32)
+	{
+	__ASSERT_DEBUG(aCount > 0, Panic(EFbsBitmapDecompressionError));
+	if (aCount > 0)
+		{ // for performance loop is unrolled, using "Duff's Device" pattern
+		TInt blocksOf16 = aCount / 16;	// number of blocks of 16 full words to write
+		// the first iteration writes 1 to 15 words
+
+		switch (aCount & 0x0f)
+			{ // note that case statements intentionally cascade
+		case 0:
+write16dblPixels:	// second and subsequent iterations always write 16 words
+			--blocksOf16;
+			*aDestPtr32++ = aValue32;
+			//coverity [fallthrough]
+		case 15:
+			*aDestPtr32++ = aValue32;
+			//coverity [fallthrough]
+		case 14:
+			*aDestPtr32++ = aValue32;
+			//coverity [fallthrough]
+		case 13:
+			*aDestPtr32++ = aValue32;
+			//coverity [fallthrough]
+		case 12:
+			*aDestPtr32++ = aValue32;
+			//coverity [fallthrough]
+		case 11:
+			*aDestPtr32++ = aValue32;
+			//coverity [fallthrough]
+		case 10:
+			*aDestPtr32++ = aValue32;
+			//coverity [fallthrough]
+		case 9:
+			*aDestPtr32++ = aValue32;
+			//coverity [fallthrough]
+		case 8:
+			*aDestPtr32++ = aValue32;
+			//coverity [fallthrough]
+		case 7:
+			*aDestPtr32++ = aValue32;
+			//coverity [fallthrough]
+		case 6:
+			*aDestPtr32++ = aValue32;
+			//coverity [fallthrough]
+		case 5:
+			*aDestPtr32++ = aValue32;
+			//coverity [fallthrough]
+		case 4:
+			*aDestPtr32++ = aValue32;
+			//coverity [fallthrough]
+		case 3:
+			*aDestPtr32++ = aValue32;
+			//coverity [fallthrough]
+		case 2:
+			*aDestPtr32++ = aValue32;
+			//coverity [fallthrough]
+		case 1:
+			*aDestPtr32++ = aValue32;
+			}
+
+		if (blocksOf16 > 0)
+			{
+			goto write16dblPixels;
+			}
+		}
+	}
+
+/** Fills the 16bit pixels into the destination pointer
+This method uses the concept of Duff's Device 
+@param aDestPtr16 pointer to 16bit destination buffer.
+@param aCount Number of 16bit pixels to be copied.
+@param aValue16 16bit pixel data. */
+inline void CBitwiseBitmap::BitmapFill16(TUint16* aDestPtr16, TInt aCount, TUint16 aValue16)
+	{
+	// Call the 32-bit fill method if there at least 8 pixels to fill
+	if (aCount >= 8)
+		{
+		// first pixel is on half word address?
+		if (reinterpret_cast<TUint32>(aDestPtr16) & 2) 
+			{
+			*aDestPtr16++ = aValue16; 
+			--aCount; 
+			} 
+
+		// destPtr16 is now full Word aligned
+		const TInt countDoublePixels = aCount / 2;
+		TUint32* destPtr32 = (TUint32*) aDestPtr16;
+		BitmapFill32(destPtr32, countDoublePixels, (aValue16 << 16) | aValue16);
+
+		aCount -= countDoublePixels * 2;
+		if (aCount == 1)
+			{ // last pixel is on a half-word
+			aDestPtr16 += countDoublePixels * 2;
+			*aDestPtr16++ = aValue16; 
+			}
+		}
+	else
+		{ // less than 8 pixels to fill
+		switch (aCount)
+			{ // note that case statements intentionally cascade
+		case 7:
+			*aDestPtr16++ = aValue16; 
+		case 6:
+			*aDestPtr16++ = aValue16; 
+		case 5:
+			*aDestPtr16++ = aValue16; 
+		case 4:
+			*aDestPtr16++ = aValue16; 
+		case 3:
+			*aDestPtr16++ = aValue16; 
+		case 2:
+			*aDestPtr16++ = aValue16; 
+		case 1:
+			*aDestPtr16++ = aValue16; 
+		case 0: // nothing to do
+			;
+			}
+		}
+	}
+
+void CBitwiseBitmap::DoDecompressTwelveBitData(TUint8* aDestBuffer,TInt aDestSize,TUint8* aSrceBuffer,TInt aSrceSize)
+	{
+	TUint16* srcePtr = (TUint16*)aSrceBuffer;
+	TUint16* destPtr = (TUint16*)aDestBuffer;
+	TUint16* srcePtrLimit = srcePtr + (aSrceSize / 2);
+	TUint16* destPtrLimit = destPtr + (aDestSize / 2);
+
+	while (srcePtr < srcePtrLimit && destPtr < destPtrLimit)
+		{
+		TUint16 value = *srcePtr++;
+		TInt count = Min(value >> 12, destPtrLimit - destPtr);
+		value &= 0x0fff;
+
+		while (count >= 0)
+			{
+			*destPtr++ = value;
+			count--;
+			}
+		}
+
+	__ASSERT_DEBUG(srcePtr == srcePtrLimit && destPtr == destPtrLimit,Panic(EFbsBitmapDecompressionError));
+	}
+
+void CBitwiseBitmap::DoDecompressTwelveBitDataAltL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase)
+	{
+	TInt destSizeInBytes = iHeader.iSizeInPixels.iHeight * iByteWidth;
+	TUint16* destPtr = (TUint16*)aBase;
+	TUint16* destPtrLimit = destPtr + (destSizeInBytes / 2);
+
+	while(aSrceSizeInBytes > 0 && destPtr < destPtrLimit)
+		{
+		TUint16 value = aStream.ReadUint16L();
+		TInt count = Min(value >> 12, destPtrLimit - destPtr);
+		value &= 0x0fff;
+		aSrceSizeInBytes -= 2;
+
+		while (count >= 0)
+			{
+			*destPtr++ = value;
+			count--;
+			}
+		}
+	__ASSERT_DEBUG(aSrceSizeInBytes == 0 && destPtr == destPtrLimit,Panic(EFbsBitmapDecompressionError));
+	}
+
+/** The function decodes 24-bit compressed buffer to the 16-bit stream with unused top bytes by using RLE compression algorithm*/
+void CBitwiseBitmap::DoDecompressSixteenBitData(TUint8* aDestBuffer,TInt aDestSize,TUint8* aSrceBuffer,TInt aSrceSize)
+	{
+	__ASSERT_DEBUG((reinterpret_cast<TUint32>(aDestBuffer) & 0x2)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is half-word aligned
+	__ASSERT_DEBUG((aDestSize & 0x2)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is half-word aligned
+
+	TUint8* srcePtr8 = aSrceBuffer; // pointer to compressed source Byte(8-bit) stream 
+	TUint16* destPtr16 = reinterpret_cast<TUint16*>(aDestBuffer); //pointer to uncompressed destination HalfWord(16-bit) pixel stream
+	TUint8* srcePtrLimit8 = aSrceBuffer + aSrceSize; //maximum number of compressed source bytes
+	TUint16* destPtrLimit16 = reinterpret_cast<TUint16*>(aDestBuffer + aDestSize); //maximum number of uncompressed destination pixel stream
+	const TInt KPixelSize = 2; //number of bytes of the source stream that is to be considered as one Pixel
+	
+	while (srcePtr8 < srcePtrLimit8 && destPtr16 < destPtrLimit16)
+		{
+		TInt8 count = *srcePtr8++; //number of pixels to be retrieved from the source stream
+
+		if (count >= 0) //repeating number of pixels
+			{
+			const TInt numPixels = 1 + Min(count, (destPtrLimit16 - destPtr16));
+			const TUint8 lowByte = *srcePtr8++;
+			const TUint8 highByte = *srcePtr8++;
+			const TUint16 pixel = highByte<<8 | lowByte; //Pixel buffer which needs to be stored in destPtr16
+
+			BitmapFill16(destPtr16, numPixels, pixel);
+			destPtr16 += numPixels;
+			}
+		else
+			{
+			const TInt numPixels = Min(-count, destPtrLimit16 - destPtr16); //number of pixels to be copied
+			const TInt numBytes = numPixels * KPixelSize; //number of bytes needs to be retrieved from the srcePtr
+			Mem::Copy(destPtr16, srcePtr8, numBytes); // copy bytes
+			srcePtr8 += numBytes; //incrementing the srcePtr by number of bytes
+			destPtr16 += numPixels; //incrementing the destPtr16 by number of pixels
+			}
+		}
+	__ASSERT_DEBUG(srcePtr8 == srcePtrLimit8 && destPtr16 == destPtrLimit16, Panic(EFbsBitmapDecompressionError));
+	}
+
+/** The alternative decoding function which decompresses 24-bit buffer to the 16-bit stream with unused top bytes 
+ 	by using RLE compression algorithm. The function is used under low memory conditions. */
+void CBitwiseBitmap::DoDecompressSixteenBitDataAltL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase)
+	{
+	__ASSERT_DEBUG((reinterpret_cast<TUint32>(aBase) & 0x2)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is half-word aligned
+
+	TInt destSizeInPixels = (iHeader.iSizeInPixels.iHeight * iByteWidth); //size of destination Byte pixel buffers
+	destSizeInPixels >>= 1; //dividing by two, to get size of destination interms of Halfword pixel buffers
+	TUint16* destPtr16 = reinterpret_cast<TUint16*>(aBase); //pointer to uncompressed destination HalfWord(16-bit) pixel stream
+	TUint16* destPtrLimit16 = destPtr16 + destSizeInPixels; //maximum number of compressed source bytes
+	const TInt KPixelSize = 2; //number of bytes of the source stream that is to be considered as one Pixel
+
+	while(aSrceSizeInBytes > 0 && destPtr16 < destPtrLimit16)
+		{
+		TInt8 count = aStream.ReadInt8L(); //number of pixels to be retrieved from the source stream
+		aSrceSizeInBytes--; //One byte from source stream read, hence reduce size by one Byte
+
+		if (count >= 0)
+			{
+			const TInt numPixels = 1 + Min(count, (destPtrLimit16 - destPtr16));
+			const TUint16 pixel = aStream.ReadUint16L(); //Pixel buffer which needs to be stored in destPtr16
+			aSrceSizeInBytes -= KPixelSize; //Two bytes (Halfword pixel) read, reduce size by two Bytes
+			
+			BitmapFill16(destPtr16, numPixels, pixel);
+			destPtr16 += numPixels;
+			}
+		else
+			{
+			const TInt numPixels = Min(-count, destPtrLimit16 - destPtr16); //number of pixels to be stored into destPtr16
+			const TInt numBytes = numPixels * KPixelSize; //number of bytes needs to be retrieved from the srcePtr
+			aStream.ReadL(destPtr16, numPixels); //read TUint16's
+			aSrceSizeInBytes -= numBytes; //two-byte (halfword) pixel buffers read, reduce by number of bytes
+			destPtr16 += numPixels; //incrementing the destPtr16 by number of pixels
+			}
+		}
+	__ASSERT_DEBUG(aSrceSizeInBytes == 0 && destPtr16 == destPtrLimit16, Panic(EFbsBitmapDecompressionError));
+	}
+
+void CBitwiseBitmap::DoDecompressTwentyFourBitData(TUint8* aDestBuffer,TInt aDestSize,TUint8* aSrceBuffer,TInt aSrceSize)
+	{
+	TUint8* srcePtr = aSrceBuffer;
+	TUint8* destPtr = aDestBuffer;
+	TUint8* srcePtrLimit = aSrceBuffer + aSrceSize;
+	TUint8* destPtrLimit = aDestBuffer + aDestSize;
+
+	while (srcePtr < srcePtrLimit && destPtr < destPtrLimit)
+		{
+		TInt8 count = *srcePtr++;
+
+		if (count >= 0)
+			{
+			count = Min(count, (destPtrLimit - destPtr) / 3);
+			TUint8 component1 = *srcePtr++;
+			TUint8 component2 = *srcePtr++;
+			TUint8 component3 = *srcePtr++;
+
+			while (count >= 0)
+				{
+				*destPtr++ = component1;
+				*destPtr++ = component2;
+				*destPtr++ = component3;
+				count--;
+				}
+			}
+		else
+			{
+			const TInt numBytes = Min(count * -3, destPtrLimit - destPtr);
+			Mem::Copy(destPtr,srcePtr,numBytes);
+			srcePtr += numBytes;
+			destPtr += numBytes;
+			}
+		}
+	__ASSERT_DEBUG(srcePtr == srcePtrLimit && destPtr == destPtrLimit,Panic(EFbsBitmapDecompressionError));
+	}
+
+void CBitwiseBitmap::DoDecompressTwentyFourBitDataAltL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase)
+	{
+	TInt destSizeInBytes = iHeader.iSizeInPixels.iHeight * iByteWidth;
+	TUint8* destPtr = (TUint8*)aBase;
+	TUint8* destPtrLimit = destPtr + destSizeInBytes;
+
+	while(aSrceSizeInBytes > 0 && destPtr < destPtrLimit)
+		{
+		TInt8 count = aStream.ReadInt8L();
+		aSrceSizeInBytes--;
+
+		if (count >= 0)
+			{
+			count = Min(count, (destPtrLimit - destPtr) / 3);
+			TUint8 component1 = aStream.ReadUint8L();
+			TUint8 component2 = aStream.ReadUint8L();
+			TUint8 component3 = aStream.ReadUint8L();
+			aSrceSizeInBytes -= 3;
+
+			while (count >= 0)
+				{
+				*destPtr++ = component1;
+				*destPtr++ = component2;
+				*destPtr++ = component3;
+				count--;
+				}
+			}
+		else
+			{
+			const TInt numBytes = Min(count * -3, destPtrLimit - destPtr);
+			aStream.ReadL(destPtr, numBytes);
+			aSrceSizeInBytes -= numBytes;
+			destPtr += numBytes;
+			}
+		}
+	__ASSERT_DEBUG(aSrceSizeInBytes == 0 && destPtr == destPtrLimit,Panic(EFbsBitmapDecompressionError));
+	}
+
+/** The function decodes 24-bit compressed buffer to the 32-bit stream with unused top bytes by using RLE compression algorithm*/
+void CBitwiseBitmap::DoDecompressThirtyTwoUBitData(TUint8* aDestBuffer,TInt aDestSize,TUint8* aSrceBuffer,TInt aSrceSize)
+	{
+	
+	__ASSERT_DEBUG((reinterpret_cast<TUint32>(aDestBuffer) & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is word aligned
+	__ASSERT_DEBUG((aDestSize & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the size is whole no of pixels
+	
+	TUint8* srcePtr8 = aSrceBuffer;
+	TUint8* srcePtrLimit8 = aSrceBuffer + aSrceSize;
+
+	TUint32* destPtr32 = reinterpret_cast<TUint32*>(aDestBuffer);
+	TUint32* destPtrLimit32 = reinterpret_cast<TUint32*>(aDestBuffer + aDestSize);
+
+	while (srcePtr8 < srcePtrLimit8 && destPtr32 < destPtrLimit32)
+		{
+		
+		TInt8 count = *srcePtr8++; // important to read into a byte variable
+
+		if (count >= 0) //repeating pixel buffer
+			{
+			count  = Min(count, (destPtrLimit32 - destPtr32));
+			const TUint8 component1 = *srcePtr8++;
+			const TUint8 component2 = *srcePtr8++;
+			const TUint8 component3 = *srcePtr8++;
+
+			const TUint32 pixel = 0xff000000 | (component3<<16) | (component2<<8) | component1;
+
+			// for performance loop is unrolled, using "Duff's Device" pattern
+			TInt blocksOf16 = (count >> 4);	// number of blocks of 16 full words to write
+			// the first iteration writes 1 to 15 words
+			switch (count & 0x0f)
+				{ // note that case statements intentionally cascade
+			case 15:
+				do {	// second and subsequent iterations always write 16 words
+				*destPtr32++ = pixel;
+			case 14:
+				*destPtr32++ = pixel;
+			case 13:
+				*destPtr32++ = pixel;
+			case 12:
+				*destPtr32++ = pixel;
+			case 11:
+				*destPtr32++ = pixel;
+			case 10:
+				*destPtr32++ = pixel;
+			case 9:
+				*destPtr32++ = pixel;
+			case 8:
+				*destPtr32++ = pixel;
+			case 7:
+				*destPtr32++ = pixel;
+			case 6:
+				*destPtr32++ = pixel;
+			case 5:
+				*destPtr32++ = pixel;
+			case 4:
+				*destPtr32++ = pixel;
+			case 3:
+				*destPtr32++ = pixel;
+			case 2:
+				*destPtr32++ = pixel;
+			case 1:
+				*destPtr32++ = pixel;
+			case 0:
+				*destPtr32++ = pixel;
+ 
+				} while(0 <= --blocksOf16);
+				}
+			}
+		else // negative value corresponds non repeating pixel buffer
+			{
+			const TInt numPixel = Min(-count, destPtrLimit32 - destPtr32) ;
+			for(TInt ii = 0; ii < numPixel; ii++)
+				{
+				TUint8 component1 = *srcePtr8++;
+				TUint8 component2 = *srcePtr8++;
+				TUint8 component3 = *srcePtr8++;
+
+				*destPtr32++ =  0xff000000 | (component3<<16) | (component2<<8) | component1;
+				}
+			}
+		}
+
+	__ASSERT_DEBUG(srcePtr8 == srcePtrLimit8 && destPtr32 == destPtrLimit32,Panic(EFbsBitmapDecompressionError));
+	}
+
+/** The alternative decoding function which decompresses 24-bit buffer to the 32-bit stream with unused top bytes 
+	by using RLE compression algorithm. The function is using in case of memory shortage. */
+void CBitwiseBitmap::DoDecompressThirtyTwoUBitDataAltL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase)
+	{
+	const TInt destSizeInDwords = iHeader.iSizeInPixels.iHeight * (iByteWidth>>2);
+	TUint32* destPtr32 = aBase;
+	TUint32* destPtrLimit32 = destPtr32 + destSizeInDwords;
+	
+	const TInt KMaxRLENonRepeatingPixelBufferSize = 128 * 3;
+	TUint8 dataBuffer[KMaxRLENonRepeatingPixelBufferSize];
+
+	while(aSrceSizeInBytes > 0 && destPtr32 < destPtrLimit32)
+		{
+		TInt8 count = aStream.ReadInt8L();
+		aSrceSizeInBytes--;
+
+		if (count >= 0) //repeating pixel buffer
+			{
+			count = Min(count, (destPtrLimit32 - destPtr32));
+			const TUint8 component1 = aStream.ReadUint8L();
+			const TUint8 component2 = aStream.ReadUint8L();
+			const TUint8 component3 = aStream.ReadUint8L();
+			aSrceSizeInBytes -= 3;
+
+			const TUint32 pixel = 0xff000000 | (component3<<16) | (component2<<8) | component1; 
+			
+			TInt blocksOf16 = (count >> 4);	// number of blocks of 16 full words to write
+			// the first iteration writes 1 to 15 words
+			switch (count & 0x0f)
+				{ // note that case statements intentionally cascade
+			case 15:
+				do {	// second and subsequent iterations always write 16 words
+				*destPtr32++ = pixel;
+			case 14:
+				*destPtr32++ = pixel;
+			case 13:
+				*destPtr32++ = pixel;
+			case 12:
+				*destPtr32++ = pixel;
+			case 11:
+				*destPtr32++ = pixel;
+			case 10:
+				*destPtr32++ = pixel;
+			case 9:
+				*destPtr32++ = pixel;
+			case 8:
+				*destPtr32++ = pixel;
+			case 7:
+				*destPtr32++ = pixel;
+			case 6:
+				*destPtr32++ = pixel;
+			case 5:
+				*destPtr32++ = pixel;
+			case 4:
+				*destPtr32++ = pixel;
+			case 3:
+				*destPtr32++ = pixel;
+			case 2:
+				*destPtr32++ = pixel;
+			case 1:
+				*destPtr32++ = pixel;
+			case 0:
+ 				*destPtr32++ = pixel;
+
+				} while(0 <= --blocksOf16);
+				}
+			}
+		else // negative value corresponds non repeating pixel buffer
+			{
+			const TInt numDestDwords = Min(-count, destPtrLimit32 - destPtr32);
+			const TInt numSrcBytes = numDestDwords * 3;
+			aStream.ReadL(&dataBuffer[0], numSrcBytes);
+			aSrceSizeInBytes -= numSrcBytes;
+			TUint8* srcPtr = dataBuffer;
+			const TInt& numPixel = numDestDwords;
+			for(TInt ii = 0; ii < numPixel; ii++)
+				{
+				const TUint8 component1 = *srcPtr++;
+				const TUint8 component2 = *srcPtr++;
+				const TUint8 component3 = *srcPtr++;
+
+				*destPtr32++ = 0xff000000 | (component3<<16) | (component2<<8) | component1; 
+				}
+			}
+		}
+
+	__ASSERT_DEBUG(aSrceSizeInBytes == 0 && destPtr32 == destPtrLimit32,Panic(EFbsBitmapDecompressionError));
+	}
+
+/** The function decodes 32-bit compressed buffer (where top bytes are used as alpha channel) to the 32-bit stream by using RLE compression algorithm*/
+void CBitwiseBitmap::DoDecompressThirtyTwoABitData(TUint8* aDestBuffer,TInt aDestSize,TUint8* aSrceBuffer,TInt aSrceSize)
+	{
+	TUint8* srcePtr = aSrceBuffer;
+	TUint8* srcePtrLimit = aSrceBuffer + aSrceSize;
+
+	TUint32* destPtr32 = reinterpret_cast<TUint32*>(aDestBuffer);
+	TUint32* destPtrLimit32 = reinterpret_cast<TUint32*>(aDestBuffer + aDestSize);
+
+	while (srcePtr < srcePtrLimit && destPtr32 < destPtrLimit32)
+		{
+		TInt8 count = *srcePtr++;
+
+		if (count >= 0) //repeating pixel buffer
+			{
+			count = Min(count, (destPtrLimit32 - destPtr32));
+			TUint8 component1 = *srcePtr++;
+			TUint8 component2 = *srcePtr++;
+			TUint8 component3 = *srcePtr++;
+			TUint8 component4 = *srcePtr++;
+			const TUint32 pixel = (component4<<24) | (component3<<16) | (component2<<8) | component1;
+
+			// for performance loop is unrolled, using "Duff's Device" pattern
+			TInt blocksOf16 = (count >> 4);	// number of blocks of 16 full words to write
+			// the first iteration writes 1 to 15 words
+			switch (count & 0x0f)
+				{ // note that case statements intentionally cascade
+			case 15:
+				do {	// second and subsequent iterations always write 16 words
+				*destPtr32++ = pixel;
+			case 14:
+				*destPtr32++ = pixel;
+			case 13:
+				*destPtr32++ = pixel;
+			case 12:
+				*destPtr32++ = pixel;
+			case 11:
+				*destPtr32++ = pixel;
+			case 10:
+				*destPtr32++ = pixel;
+			case 9:
+				*destPtr32++ = pixel;
+			case 8:
+				*destPtr32++ = pixel;
+			case 7:
+				*destPtr32++ = pixel;
+			case 6:
+				*destPtr32++ = pixel;
+			case 5:
+				*destPtr32++ = pixel;
+			case 4:
+				*destPtr32++ = pixel;
+			case 3:
+				*destPtr32++ = pixel;
+			case 2:
+				*destPtr32++ = pixel;
+			case 1:
+				*destPtr32++ = pixel;
+			case 0:
+ 				*destPtr32++ = pixel;
+
+				} while(0 <= --blocksOf16);
+				}
+			}
+		else // negative value corresponds non repeating pixel buffer
+			{
+			const TInt numPixel = Min(-count, destPtrLimit32 - destPtr32);
+
+			Mem::Copy(destPtr32, srcePtr, numPixel*4); 
+			destPtr32 += numPixel;
+			srcePtr += numPixel*4;
+
+			}
+		}
+
+	__ASSERT_DEBUG(srcePtr == srcePtrLimit && destPtr32 == destPtrLimit32,Panic(EFbsBitmapDecompressionError));
+	}
+
+/** The alternative decoding function which decompresses 32-bit buffer (where top bytes are used as alpha channel)
+	to the 32-bit stream by using RLE compression algorithm. The function is using in case of memory shortage. */
+void CBitwiseBitmap::DoDecompressThirtyTwoABitDataAltL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase)
+	{
+	const TInt destSizeInDwords = iHeader.iSizeInPixels.iHeight * (iByteWidth>>2);
+	TUint32* destPtr32 = aBase;
+	TUint32* destPtrLimit32 = destPtr32 + destSizeInDwords;
+
+	while(aSrceSizeInBytes > 0 && destPtr32 < destPtrLimit32)
+		{
+		TInt8 count = aStream.ReadInt8L();
+		aSrceSizeInBytes--;
+
+		if (count >= 0) //repeating pixel buffer
+			{
+			count = Min(count, (destPtrLimit32 - destPtr32));
+			const TUint32 pixel = aStream.ReadUint32L();
+			aSrceSizeInBytes -= 4;
+
+			// for performance loop is unrolled, using "Duff's Device" pattern
+			TInt blocksOf16 = (count >> 4);	// number of blocks of 16 full words to write
+			// the first iteration writes 1 to 15 words
+			switch (count & 0x0f)
+				{ // note that case statements intentionally cascade
+			case 15:
+				do {	// second and subsequent iterations always write 16 words
+				*destPtr32++ = pixel;
+			case 14:
+				*destPtr32++ = pixel;
+			case 13:
+				*destPtr32++ = pixel;
+			case 12:
+				*destPtr32++ = pixel;
+			case 11:
+				*destPtr32++ = pixel;
+			case 10:
+				*destPtr32++ = pixel;
+			case 9:
+				*destPtr32++ = pixel;
+			case 8:
+				*destPtr32++ = pixel;
+			case 7:
+				*destPtr32++ = pixel;
+			case 6:
+				*destPtr32++ = pixel;
+			case 5:
+				*destPtr32++ = pixel;
+			case 4:
+				*destPtr32++ = pixel;
+			case 3:
+				*destPtr32++ = pixel;
+			case 2:
+				*destPtr32++ = pixel;
+			case 1:
+				*destPtr32++ = pixel;
+			case 0:
+ 				*destPtr32++ = pixel;
+
+				} while(0 <= --blocksOf16);
+				}
+			}
+		else // negative value corresponds non repeating pixel buffer
+			{
+			const TInt numPixels = Min(-count, destPtrLimit32 - destPtr32);
+			aStream.ReadL((TUint16*)destPtr32, numPixels * 2); // read TUint16's
+			aSrceSizeInBytes -= numPixels * 4;
+			destPtr32 += numPixels;
+			}
+		}
+
+	__ASSERT_DEBUG(aSrceSizeInBytes == 0 && destPtr32 == destPtrLimit32,Panic(EFbsBitmapDecompressionError));
+	}
+
+void CBitwiseBitmap::DoExternalizeDataCompressedL(RWriteStream& aStream,TUint8* aData,TInt aSizeInBytes) const
+	{
+	switch (iHeader.iBitsPerPixel)
+		{
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+		DoExternalizeByteDataCompressedL(aStream,aData,aSizeInBytes);
+		break;
+	case 12:
+		DoExternalizeTwelveBitDataCompressedL(aStream,aData,aSizeInBytes);
+		break;
+	case 16:
+		DoExternalizeSixteenBitDataCompressedL(aStream,aData,aSizeInBytes);
+		break;
+	case 24:
+		DoExternalizeTwentyFourBitDataCompressedL(aStream,aData,aSizeInBytes);
+		break;
+	case 32:
+		__ASSERT_DEBUG(iHeader.iColor == SEpocBitmapHeader::EColor||
+						iHeader.iColor == SEpocBitmapHeader::EColorAlpha||
+						iHeader.iColor == SEpocBitmapHeader::EColorAlphaPM,
+						Panic(EFbsBitmapInvalidCompression));
+		if(iHeader.iColor == SEpocBitmapHeader::EColor)
+			{
+			DoExternalizeThirtyTwoUBitDataCompressedL(aStream,aData,aSizeInBytes);
+			}
+		else
+			{
+			DoExternalizeThirtyTwoABitDataCompressedL(aStream,aData,aSizeInBytes);
+			}
+		break;
+	default:
+		break;
+		}
+	}
+
+void CBitwiseBitmap::DoExternalizeByteDataCompressedL(RWriteStream& aStream,TUint8* aData,TInt aSizeInBytes) const
+	{
+	TUint8* dataLimit=aData+aSizeInBytes-2;
+	TUint8 runPair[2];
+	while(aData<dataLimit)
+		{
+		TUint8 value=*aData;
+		TUint8* runStartPtr = aData;
+
+		if (*(aData+1)==value && *(aData+2)==value)
+			{
+			aData+=3;
+			while(aData<dataLimit && *aData==value)
+				aData++;
+			TInt runLength=aData-runStartPtr;
+			runPair[0]=127;
+			runPair[1]=value;
+			while(runLength>128)
+				{
+				aStream.WriteL(&runPair[0],2);
+				runLength-=128;
+				}
+			runPair[0]=TUint8(runLength-1);
+			aStream.WriteL(&runPair[0],2);
+			}
+		else
+			{
+			while(aData<dataLimit && (*(aData+1)!=value || *(aData+2)!=value))
+				{
+				aData++;
+				value=*aData;
+				}
+			TInt runLength = aData - runStartPtr;
+			while (runLength > 128)
+				{
+				aStream.WriteInt8L(-128);
+				aStream.WriteL(runStartPtr,128);
+				runLength-=128;
+				runStartPtr+=128;
+				}
+			aStream.WriteInt8L(-runLength);
+			aStream.WriteL(runStartPtr,runLength);
+			}
+		}
+	dataLimit+=2;
+	if (aData<dataLimit)
+		{
+		TInt runLength=dataLimit-aData;
+		aStream.WriteInt8L(-runLength);
+		aStream.WriteL(aData,runLength);
+		}
+	}
+
+void CBitwiseBitmap::DoExternalizeTwelveBitDataCompressedL(RWriteStream& aStream,TUint8* aData,TInt aSizeInBytes) const
+	{
+	TUint16* srcePtr = (TUint16*)aData;
+	TUint16* srcePtrLimit = srcePtr + (aSizeInBytes / 2);
+
+	while (srcePtr < srcePtrLimit)
+		{
+		TUint16* runStartPtr = srcePtr;
+		TUint16 value = TUint16(*srcePtr & 0x0fff);
+		do
+			{
+			srcePtr++;
+			}
+		while (srcePtr < srcePtrLimit && *srcePtr == value);
+
+		TInt pixelLength = srcePtr - runStartPtr;
+		TUint16 maxLengthData = TUint16(value | 0xf000);
+
+		while (pixelLength > 16)
+			{
+			aStream.WriteUint16L(maxLengthData);
+			pixelLength -= 16;
+			}
+
+		if (pixelLength > 0)
+			aStream.WriteUint16L(value | TUint16((pixelLength - 1) << 12));
+		}
+	}
+
+void CBitwiseBitmap::DoExternalizeSixteenBitDataCompressedL(RWriteStream& aStream,TUint8* aData,TInt aSizeInBytes) const
+	{
+	TUint16* srcePtr = (TUint16*)aData;
+	TUint16* srceLimitPtr = srcePtr + (aSizeInBytes / 2);
+	TUint16* srceLimitPtrMinusOne = srceLimitPtr - 1;
+
+	while (srcePtr < srceLimitPtrMinusOne)
+		{
+		TUint16 value = *srcePtr;
+		TUint16* runStartPtr = srcePtr++;
+
+		if(*srcePtr == value)
+			{
+			do
+				{
+				srcePtr++;
+				}
+			while(srcePtr < srceLimitPtr && *srcePtr == value);
+
+			TInt pixelLength = srcePtr-runStartPtr;
+			while (pixelLength > 128)
+				{
+				aStream.WriteInt8L(127);
+				aStream.WriteUint16L(value);
+				pixelLength -= 128;
+				}
+
+			aStream.WriteUint8L(pixelLength - 1);
+			aStream.WriteUint16L(value);
+			}
+		else
+			{
+			value = *srcePtr;
+			while (srcePtr < srceLimitPtrMinusOne && *(srcePtr + 1) != value)
+				{
+				srcePtr++;
+				value = *srcePtr;
+				}
+
+			TInt pixelLength = srcePtr - runStartPtr;
+			while (pixelLength > 128)
+				{
+				aStream.WriteInt8L(-128);
+				aStream.WriteL(runStartPtr,128);
+				runStartPtr += 128;
+				pixelLength -= 128;
+				}
+
+			aStream.WriteInt8L(-pixelLength);
+			aStream.WriteL(runStartPtr,pixelLength);
+			}
+		}
+
+	TInt remainingPixels = srceLimitPtr - srcePtr;
+	if (remainingPixels > 0)
+		{
+		aStream.WriteInt8L(-remainingPixels);
+		aStream.WriteL(srcePtr,remainingPixels);
+		}
+	}
+
+void CBitwiseBitmap::DoExternalizeTwentyFourBitDataCompressedL(RWriteStream& aStream,TUint8* aData,TInt aSizeInBytes) const
+	{
+	TUint8* srceLimitPtr = aData + aSizeInBytes;
+	TUint8* srceLimitPtrMinusThree = srceLimitPtr - 3; // three bytes == one pixel
+
+	while (aData < srceLimitPtrMinusThree)
+		{
+		TUint8* runStartPtr = aData;
+		TUint8 component1 = *aData++;
+		TUint8 component2 = *aData++;
+		TUint8 component3 = *aData++;
+
+		if (TrueColorPointerCompare(aData,component1,component2,component3))
+			{
+			do
+				{
+				aData += 3;
+				}
+			while (aData < srceLimitPtr && TrueColorPointerCompare(aData,component1,component2,component3));
+
+			TInt pixelLength = (aData - runStartPtr) / 3;
+			while (pixelLength > 128)
+				{
+				aStream.WriteInt8L(127);
+				aStream.WriteUint8L(component1);
+				aStream.WriteUint8L(component2);
+				aStream.WriteUint8L(component3);
+				pixelLength -= 128;
+				}
+
+			aStream.WriteInt8L(pixelLength - 1);
+			aStream.WriteUint8L(component1);
+			aStream.WriteUint8L(component2);
+			aStream.WriteUint8L(component3);
+			}
+		else
+			{
+			TBool more  = ETrue;
+			TBool eqRun = EFalse;
+			do
+				{
+				component1 = *aData++;
+				component2 = *aData++;
+				component3 = *aData++;
+				more = (aData < srceLimitPtr);
+				eqRun = more && TrueColorPointerCompare(aData,component1,component2,component3);
+				}
+			while (more && !eqRun);
+			if (eqRun)
+				aData -= 3;
+			TInt pixelLength = (aData - runStartPtr) / 3;
+			while (pixelLength > 128)
+				{
+				aStream.WriteInt8L(-128);
+				aStream.WriteL(runStartPtr,384);
+				runStartPtr += 384;
+				pixelLength -= 128;
+				}
+
+			aStream.WriteInt8L(-pixelLength);
+			aStream.WriteL(runStartPtr,pixelLength * 3);
+			}
+		}
+
+	TInt remainingPixels = srceLimitPtr - aData;
+	if (remainingPixels > 0)
+		{
+		TInt pixelLength = remainingPixels / 3;
+		aStream.WriteInt8L(-pixelLength);
+		aStream.WriteL(aData,remainingPixels);
+		}
+	}
+	
+/** The function externalizes 32-bit buffer with unused top bytes to the 24-bit compressed stream by using RLE compression algorithm*/
+void CBitwiseBitmap::DoExternalizeThirtyTwoUBitDataCompressedL(RWriteStream& aStream,TUint8* aData8,TInt aSizeInBytes) const
+	{
+
+	__ASSERT_DEBUG((reinterpret_cast<TUint32>(aData8) & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is word aligned
+	__ASSERT_DEBUG((aSizeInBytes & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the size is whole no of pixels
+
+	TUint32* ptr = reinterpret_cast<TUint32*>(aData8);
+	TUint32* srceLimitPtr = reinterpret_cast<TUint32*>(aData8 + aSizeInBytes);
+	TUint32* srceLimitPtr2ndLast = srceLimitPtr - 1; 
+
+	while (ptr < srceLimitPtr2ndLast)
+		{
+		TUint32* runStartPtr = ptr;
+		TUint32 pixel = *ptr++ & 0x00ffffff;
+
+		if ( (((*ptr)&0x00ffffff)==pixel) )
+			{
+			do
+				{
+				ptr++;
+				}
+			while (ptr< srceLimitPtr && (((*ptr)&0x00ffffff)==pixel) );
+
+			TInt pixelLength = (ptr - runStartPtr);
+			while (pixelLength > 128)
+				{
+				aStream.WriteInt8L(127);
+				aStream.WriteUint8L(pixel&0x000000ff);
+				aStream.WriteUint8L((pixel>>8)&0x000000ff);
+				aStream.WriteUint8L((pixel>>16)&0x000000ff);
+				pixelLength -= 128;
+				}
+
+			aStream.WriteInt8L(pixelLength - 1);
+			aStream.WriteUint8L(pixel&0x000000ff);
+			aStream.WriteUint8L((pixel>>8)&0x000000ff);
+			aStream.WriteUint8L((pixel>>16)&0x000000ff);
+			}
+		else
+			{
+			TBool more  = ETrue;
+			TBool eqRun = EFalse;
+			do
+				{
+				pixel = *ptr++ & 0x00ffffff;
+				more = (ptr < srceLimitPtr);
+				eqRun = more && (((*ptr)&0x00ffffff)==pixel);
+				} while (more && !eqRun);
+			if (eqRun)
+				ptr--;
+			TInt pixelLength = (ptr - runStartPtr);
+			while (pixelLength > 128)
+				{
+				aStream.WriteInt8L(-128);
+				for(TInt ii = 0; ii < 128; ii++)
+					{
+					aStream.WriteL(reinterpret_cast<TUint8*>(runStartPtr), 3);
+					runStartPtr++;
+					}
+				pixelLength -= 128;
+				}
+
+			aStream.WriteInt8L(-pixelLength);
+			for(TInt kk = 0; kk < pixelLength; kk++)
+				{
+				aStream.WriteL(reinterpret_cast<TUint8*>(runStartPtr), 3);
+				runStartPtr++;
+				}
+			}
+		}
+
+	const TInt remainingPixels = srceLimitPtr - ptr;
+	if (remainingPixels > 0)
+		{
+		__ASSERT_DEBUG(remainingPixels == 1, Panic(EFbsBitmapDecompressionError));
+
+		aStream.WriteInt8L(-remainingPixels);
+		for(TInt ii = 0; ii < remainingPixels; ii++)
+			{
+			aStream.WriteL(reinterpret_cast<TUint8*>(ptr), 3);
+			ptr++;
+			}
+		}
+	}
+
+/** The function externalizes 32-bit buffer with alpha channel in top byte to the 32-bit compressed stream by using RLE compression algorithm*/
+void CBitwiseBitmap::DoExternalizeThirtyTwoABitDataCompressedL(RWriteStream& aStream,TUint8* aData8,TInt aSizeInBytes) const
+	{
+
+	__ASSERT_DEBUG((reinterpret_cast<TUint32>(aData8) & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is word aligned
+	__ASSERT_DEBUG((aSizeInBytes & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the size is whole no of pixels
+
+	TUint32* ptr = reinterpret_cast<TUint32*>(aData8);
+	TUint32* srceLimitPtr = reinterpret_cast<TUint32*>(aData8 + aSizeInBytes);
+	TUint32* srceLimitPtr2ndLast = srceLimitPtr - 1; 
+
+	while (ptr < srceLimitPtr2ndLast)
+		{
+		TUint32* runStartPtr = ptr;
+		TUint32 pixel = *ptr++;
+
+		if (*ptr==pixel)
+			{
+			do
+				{
+				ptr++;
+				}
+			while (ptr < srceLimitPtr && *ptr==pixel);
+
+			TInt pixelLength = (ptr - runStartPtr);
+			while (pixelLength > 128)
+				{
+				aStream.WriteInt8L(127);
+				aStream.WriteUint32L(pixel);
+				pixelLength -= 128;
+				}
+
+			aStream.WriteInt8L(pixelLength - 1);
+			aStream.WriteUint32L(pixel);
+			}
+		else
+			{
+			TBool more  = ETrue;
+			TBool eqRun = EFalse;
+			do
+				{
+				pixel = *ptr++;
+				more = (ptr < srceLimitPtr);
+				eqRun = more && *ptr==pixel;
+				} while (more && !eqRun);
+			
+			if (eqRun)
+				ptr--;
+			
+			TInt pixelLength = (ptr - runStartPtr);
+			while (pixelLength > 128)
+				{
+				aStream.WriteInt8L(-128);
+				aStream.WriteL(reinterpret_cast<TUint8*>(runStartPtr), 128*4);
+				runStartPtr += 128;
+				pixelLength -= 128;
+				}
+
+			aStream.WriteInt8L(-pixelLength);
+			aStream.WriteL(reinterpret_cast<TUint8*>(runStartPtr), pixelLength*4);
+			}
+		}
+
+	const TInt remainingPixels = srceLimitPtr - ptr;
+	if (remainingPixels > 0)
+		{
+		__ASSERT_DEBUG(remainingPixels == 1, Panic(EFbsBitmapDecompressionError));
+
+		aStream.WriteInt8L(-remainingPixels);
+		aStream.WriteL(reinterpret_cast<TUint8*>(ptr), remainingPixels*4);
+		}
+	}
+
+TInt CBitwiseBitmap::SizeOfDataCompressed(TUint8* aData,TInt aSizeInBytes) const
+	{
+	if(aSizeInBytes<=0)
+		return 0;
+
+	switch (iHeader.iBitsPerPixel)
+		{
+	case 1:
+	case 2:
+	case 4:
+	case 8:
+		return SizeOfByteDataCompressed(aData,aSizeInBytes);
+	case 12:
+		return SizeOfTwelveBitDataCompressed(aData,aSizeInBytes);
+	case 16:
+		return SizeOfSixteenBitDataCompressed(aData,aSizeInBytes);
+	case 24:
+		return SizeOfTwentyFourBitDataCompressed(aData,aSizeInBytes);
+	case 32:
+		__ASSERT_DEBUG(iHeader.iColor == SEpocBitmapHeader::EColor||
+						iHeader.iColor == SEpocBitmapHeader::EColorAlpha||
+						iHeader.iColor == SEpocBitmapHeader::EColorAlphaPM,
+						Panic(EFbsBitmapInvalidCompression));
+		if(iHeader.iColor == SEpocBitmapHeader::EColor)
+			{
+			return SizeOfThirtyTwoUBitDataCompressed(aData,aSizeInBytes);
+			}
+		else
+			{
+			return SizeOfThirtyTwoABitDataCompressed(aData,aSizeInBytes);
+			}
+	default:
+		break;
+		}
+
+	return 0;
+	}
+
+TInt CBitwiseBitmap::SizeOfByteDataCompressed(TUint8* aData,TInt aSizeInBytes) const
+	{
+	if(aSizeInBytes<=0)
+		return 0;
+
+	TInt compressedSize=0;
+	TUint8* dataLimit=aData+aSizeInBytes-2;
+	
+	while(aData<dataLimit)
+		{
+		TUint8 value=*aData;
+		if (*(aData+1)==value && *(aData+2)==value)
+			{
+			TUint8* runStartPtr=aData;
+			aData+=3;
+			while(aData<dataLimit && *aData==value)
+				aData++;
+			TInt runLength=aData-runStartPtr;
+
+			compressedSize+= 2*(((runLength-1)>>7) + 1) ;
+			}
+		else
+			{
+			TUint8* runStartPtr=aData;
+			while(aData<dataLimit && (*(aData+1)!=value || *(aData+2)!=value))
+				{
+				aData++;
+				value=*aData;
+				}
+			TInt runLength=aData-runStartPtr;
+			
+			compressedSize+= runLength + ((runLength-1)>>7) + 1;
+			}
+		}
+	dataLimit+=2;
+	if (aData<dataLimit)
+		compressedSize+=dataLimit-aData+1;
+	return(compressedSize);
+	}
+
+TInt CBitwiseBitmap::SizeOfTwelveBitDataCompressed(TUint8* aData,TInt aSizeInBytes) const
+	{
+	if(aSizeInBytes<=0)
+		return 0;
+
+	TInt compressedSize = 0;
+	TUint16* srcePtr = (TUint16*)aData;
+	TUint16* srcePtrLimit = srcePtr + (aSizeInBytes / 2);
+
+	while (srcePtr < srcePtrLimit)
+		{
+		TUint16* runStartPtr = srcePtr;
+		TUint16 value = TUint16(*srcePtr & 0x0fff);
+		do
+			{
+			srcePtr++;
+			}
+		while (srcePtr < srcePtrLimit && *srcePtr == value);
+
+		TInt pixelLength = srcePtr - runStartPtr;
+
+		compressedSize += 2*( ((pixelLength-1)>>4) + 1);
+		}
+	return compressedSize;
+	}
+
+TInt CBitwiseBitmap::SizeOfSixteenBitDataCompressed(TUint8* aData,TInt aSizeInBytes) const
+	{
+	if(aSizeInBytes<=0)
+		return 0;
+
+	TInt compressedSize = 0;
+	TUint16* srcePtr = (TUint16*)aData;
+	TUint16* srceLimitPtr = srcePtr + (aSizeInBytes / 2);
+	TUint16* srceLimitPtrMinusOne = srceLimitPtr - 1;
+
+	while (srcePtr < srceLimitPtrMinusOne)
+		{
+		TUint16 value = *srcePtr;
+		TUint16* runStartPtr = srcePtr++;
+
+		if(*srcePtr == value)
+			{
+			do
+				{
+				srcePtr++;
+				}
+			while(srcePtr < srceLimitPtr && *srcePtr == value);
+
+			TInt pixelLength = srcePtr-runStartPtr;
+
+			compressedSize += 3*( ((pixelLength-1)>>7) + 1);
+			}
+		else
+			{
+			value = *srcePtr;
+			while (srcePtr < srceLimitPtrMinusOne && *(srcePtr + 1) != value)
+				{
+				srcePtr++;
+				value = *srcePtr;
+				}
+
+			TInt pixelLength = srcePtr-runStartPtr;
+
+			compressedSize += (pixelLength * 2) + ((pixelLength-1)>>7) + 1;
+			}
+		}
+	if (srcePtr < srceLimitPtr)
+		compressedSize += ((srceLimitPtr - srcePtr) * 2) + 1;
+	return compressedSize;
+	}
+
+TInt CBitwiseBitmap::SizeOfTwentyFourBitDataCompressed(TUint8* aData,TInt aSizeInBytes) const
+	{
+	if(aSizeInBytes<=0)
+		return 0;
+
+	TInt compressedSize = 0;
+	TUint8* srceLimitPtr = aData + aSizeInBytes;
+	TUint8* srceLimitPtrMinusThree = srceLimitPtr - 3; // three bytes == one pixel
+
+	while (aData < srceLimitPtrMinusThree)
+		{
+		TUint8* runStartPtr = aData;
+		TUint8 component1 = *aData++;
+		TUint8 component2 = *aData++;
+		TUint8 component3 = *aData++;
+
+		if (TrueColorPointerCompare(aData,component1,component2,component3))
+			{
+			do
+				{
+				aData += 3;
+				}
+			while (aData < srceLimitPtr && TrueColorPointerCompare(aData,component1,component2,component3));
+
+			TInt pixelLength = (aData - runStartPtr) / 3;
+			
+			compressedSize += 4*( ((pixelLength-1)>>7) + 1); 
+			}
+		else
+			{
+			TBool more  = ETrue;
+			TBool eqRun = EFalse;
+			do
+				{
+				component1 = *aData++;
+				component2 = *aData++;
+				component3 = *aData++;
+				more = (aData < srceLimitPtr);
+				eqRun = more && TrueColorPointerCompare(aData,component1,component2,component3);
+				}
+			while (more && !eqRun);
+			if (eqRun)
+				aData -= 3;
+			TInt pixelLength = (aData - runStartPtr) / 3;
+
+			compressedSize += (pixelLength * 3) + ((pixelLength-1)>>7) + 1;
+			}
+		}
+	
+	if (aData < srceLimitPtr)
+		compressedSize += srceLimitPtr - aData + 1;
+
+	return compressedSize;
+	}
+
+/** The function calculates the size of 24-bit RLE compression stream which could be obtain from given 32-bit buffer, 
+	where the top bytes are unused*/
+TInt CBitwiseBitmap::SizeOfThirtyTwoUBitDataCompressed(TUint8* aData8,TInt aSizeInBytes) const
+	{
+	if(aSizeInBytes<=0)
+		return 0;
+
+	__ASSERT_DEBUG((reinterpret_cast<TUint32>(aData8) & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is word aligned
+	__ASSERT_DEBUG((aSizeInBytes & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the size is whole no of pixels
+
+
+	TInt compressedSize = 0;
+	
+	
+	TUint32* ptr = reinterpret_cast<TUint32*>(aData8);
+	TUint32* srceLimitPtr = reinterpret_cast<TUint32*>(aData8 + aSizeInBytes);
+	TUint32* srceLimitPtr2ndLast = srceLimitPtr - 1; 
+	while (ptr < srceLimitPtr2ndLast)
+		{
+		TUint32* runStartPtr = ptr;
+		TUint32 pixel = *ptr++ & 0x00ffffff;
+
+		if ((((*ptr)&0x00ffffff)==pixel))
+			{
+			do
+				{
+				ptr++;
+				}
+			while (ptr < srceLimitPtr && (((*ptr)&0x00ffffff)==pixel));
+
+			TInt pixelLength = (ptr - runStartPtr);
+			compressedSize += 4*( ((pixelLength-1)>>7) + 1); 
+			}	
+		else
+			{
+			TBool more  = ETrue;
+			TBool eqRun = EFalse;
+			do
+				{
+				pixel = *ptr++ & 0x00ffffff;
+				more = (ptr < srceLimitPtr);
+				eqRun = more && (((*ptr)&0x00ffffff)==pixel);
+				} while (more && !eqRun);
+
+			if (eqRun)
+				ptr--;
+
+			TInt pixelLength = (ptr - runStartPtr) ;
+			compressedSize += 3*pixelLength + ((pixelLength-1)>>7) + 1; 
+			}
+		}
+
+	if (ptr < srceLimitPtr)
+		compressedSize += (srceLimitPtr - ptr)*3 + 1;
+
+	return compressedSize;
+	}
+
+
+TBool CBitwiseBitmap::TrueColorPointerCompare(TUint8* aColorPointer,TUint8 aComponent1,TUint8 aComponent2,TUint8 aComponent3) const
+	{
+	return (*aColorPointer == aComponent1 && *(aColorPointer + 1) == aComponent2 && *(aColorPointer + 2) == aComponent3);
+	}
+
+/** This function calculates the size of 32-bit RLE compression stream which is obtained from a given 32-bit buffer, 
+	where the top 8 bits are used to represent the alpha channel*/
+TInt CBitwiseBitmap::SizeOfThirtyTwoABitDataCompressed(TUint8* aData8,TInt aSizeInBytes) const
+	{
+	if(aSizeInBytes<=0)
+		return 0;
+
+	__ASSERT_DEBUG((reinterpret_cast<TUint32>(aData8) & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is word aligned
+	__ASSERT_DEBUG((aSizeInBytes & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the size is whole no of pixels
+
+
+	TInt compressedSize = 0;
+	
+	
+	TUint32* ptr = reinterpret_cast<TUint32*>(aData8);
+	TUint32* srceLimitPtr = reinterpret_cast<TUint32*>(aData8 + aSizeInBytes);
+	TUint32* srceLimitPtr2ndLast = srceLimitPtr - 1; 
+	while (ptr < srceLimitPtr2ndLast)
+		{
+		TUint32* runStartPtr = ptr;
+		TUint32 pixel = *ptr++;
+
+		if (*ptr==pixel)
+			{
+			do
+				{
+				ptr++;
+				}
+			while (ptr < srceLimitPtr && *ptr==pixel);
+
+			TInt pixelLength = (ptr - runStartPtr);
+			compressedSize += 5*( ((pixelLength-1)>>7) + 1); 
+			}	
+		else
+			{
+			TBool more  = ETrue;
+			TBool eqRun = EFalse;
+			do
+				{
+				pixel = *ptr++;
+				more = (ptr < srceLimitPtr);
+				eqRun = more && *ptr==pixel;
+				} while (more && !eqRun);
+
+			if (eqRun)
+				ptr--;
+
+			TInt pixelLength = (ptr - runStartPtr) ;
+			compressedSize += 4*pixelLength + ((pixelLength-1)>>7) + 1; 
+			}
+		}
+
+	if (ptr < srceLimitPtr)
+		compressedSize += (srceLimitPtr - ptr)*4 + 1;
+
+	return compressedSize;
+	}
+
+
+/*	Here's a BNF description of the RLE encoding in use for all but the 12-bit compression:
+
+	encoding := run*
+	run := equal-run | unequal-run
+	equal-run := <runlength - 1> pixel-value
+	unequal-run := <-runlength> pixel-value+    (i.e. pixel-value repeated <runlength> times)
+	runlength := uint8 in 1..128
+	pixelvalue := byte-pixel | 16bit-pixel | 24bit-pixel | 32bit-u-pixel | 32bit-a-pixel
+	byte-pixel := octet
+	16bit-pixel := octet octet
+	24bit-pixel := rr gg bb
+	32bit-u-pixel := rr gg bb
+	32bit-a-pixel := rr gg bb aa
+	rr := octet  (red component)
+	gg := octet  (green component)
+	bb := octet  (blue component)
+	aa := octet  (alpha channel)
+
+	This scheme models runs of 2-128 equal pixels or of upto 127 unequal pixels.
+	Obviously a run of 0 is meaningless.  A run of 1 is considered to be an 'unequal' run containing
+	a single pixel.
+
+	For 12-bit compression a different encoding scheme is used. Only equal-runs are written, and the
+	run	length is encoded into the top 4 bits of a 16 bit word.  Here's a BNF for 12-bit compression:
+	
+	12-bit-encoding := run*
+	run := equal-run
+	equal-run := high-octet low-octet
+	high-octet := [<runlength - 1> rr]
+	low-octet := [gg bb]
+	runlength := 1..16
+	rr := quartet  (red component)
+	gg := quartet  (green component)
+	bb := quartet  (blue component)
+
+*/
+
+//Palette compression additions
+
+/**
+Attempts to compress a bitmap by reducing it to a palette + data.
+If the compression fails, for any of the reasons detailed below, RLE compression will be attempted instead.
+Prerequisites:
+- Bitmap must not already be compressed.
+- Bitmap must contain no more than 255 colors - If bitmap contains >255 colors then palette compression is unlikely to be effective.
+- Bitmap must be 16, 24 or 32 (non alpha) bpp.  Other modes could be implemented, but smaller bit depths will yield less compression
+Small bitmaps (under 1000 pixels) will be unlikely to compress well if at all
+Structure of compressed bitmap will be as follows;
+size of palette[4 bytes] | palette[size * 4 bytes per entry] | data[pixels * upto 1 byte per pixel]
+Bitmap data is packed into memory as efficiently as possible, according to the number of bits required.
+Each line of the compressed bitmap will start on a byte boundary, but not necessarily on a word boundary.
+*/
+TInt CBitwiseBitmap::PaletteCompress()
+	{
+	//Compression algorithm
+	//1.Iterate bitmap data, building hash of unique colours found
+	//2.Iterate the hash, and build linear array of the unique colours (this is the palette)
+	//3.Iterate the array, and set the array index of each colour back into the hash
+	//4.Iterate the bitmap data again, for each pixel replace with palette index found from hash
+	
+	//Bitmap must be uncompressed
+	if (iHeader.iCompression != ENoBitmapCompression)
+		return KErrNone;
+	
+	//There must be some data in the bitmap
+	TUint8* base = REINTERPRET_CAST(TUint8*, DataAddress());
+	if (!base)
+		return KErrNone;
+	
+	//Get the bytes per pixel, and make sure it is a supported configuration
+	TUint sourceBytesPerPixel = PaletteBytesPerPixel(iHeader.iBitsPerPixel);
+	if (sourceBytesPerPixel == 0)
+		return KErrNotSupported;
+	
+	//Create a hash table and give it a decent amount of RAM to start with
+	RHashMap<TInt,TInt> colors;
+	if (colors.Reserve(256) != KErrNone)
+		return KErrNoMemory;
+
+	//Loop the data area of the bitmap, one pixel (sourceBytesPerPixel bytes) at a time
+	TInt numPixels = (iHeader.iSizeInPixels.iWidth * iHeader.iSizeInPixels.iHeight);
+	//we need some pixels!
+	if (numPixels == 0)
+		{
+		colors.Close();
+		return KErrNone;
+		}
+	
+	TUint8* top = base + (iHeader.iSizeInPixels.iHeight * iByteWidth) ; //address of lastmost byte
+	TInt32 lineLengthInBytes = iHeader.iSizeInPixels.iWidth * sourceBytesPerPixel;  //The actual useful data on each line
+	TInt32 lineLengthInBytesPadded = iByteWidth ; //the actual (aligned) length of each line
+	TUint8* pixelAddress;
+	TUint8* lineAddress;
+	//Loop each line of the bitmap data.  Note that each line ends on a 32bit align in the source MBM data.
+	TUint8* lineEnd=0;
+
+	//Separate looping for 16 & 24+ bpp.  Adds a chunk of duplicated code but saves checking bpp for  every pixel
+	if (iHeader.iBitsPerPixel < 24)
+		{
+		for (lineAddress=base;lineAddress<top;lineAddress+=iByteWidth)
+			{
+			//Loop each pixel within the line
+			lineEnd = lineAddress + lineLengthInBytes;
+			for (pixelAddress = lineAddress; pixelAddress < lineEnd; pixelAddress += sourceBytesPerPixel)
+				{
+				//Extract colour value
+				TUint color = *pixelAddress;
+				color |= (*(pixelAddress+1)) << 8;
+				//Insert colour value into hash
+				//Quicker to use Find() to eliminate duplicates Insert()
+				if (colors.Find(color) == NULL)
+					{
+					if (colors.Insert(color,0) != KErrNone)
+						{
+						colors.Close();
+						return KErrNoMemory;
+						}
+					}
+				}
+			//Test each line whether it's worth continuing to the end	
+			//We aren't interested if there's more than 256 colours (RLE compression will probably do a better job in this case)
+			if (colors.Count() > 256)
+				{
+				colors.Close();
+				return KErrNotSupported ;
+				}
+			}
+		}
+	else //>=24 bpp
+		{
+		for (lineAddress = base; lineAddress<top; lineAddress += iByteWidth)
+			{
+			//Loop each pixel within the line
+			lineEnd = lineAddress + lineLengthInBytes;
+			for (pixelAddress = lineAddress; pixelAddress < lineEnd; pixelAddress += sourceBytesPerPixel)
+				{
+				//Extract colour value
+				TUint color = *pixelAddress;
+				color |= (*(pixelAddress+1)) << 8;
+				color |= (*(pixelAddress+2)) << 16;
+				//Insert colour value into hash
+				//Quicker to use Find() to eliminate duplicates Insert()
+
+				if (colors.Find(color) == NULL)
+					{
+					if (colors.Insert(color,0) != KErrNone)
+						{
+						colors.Close();
+						return KErrNoMemory;
+						}
+					}
+				}
+			//Test each line whether it's worth continuing to the end
+			//We aren't interested if there's more than 256 colours (RLE compression will probably do a better job in this case)
+			if (colors.Count() > 256)
+				{
+				colors.Close();
+				return KErrNotSupported;
+				}
+			} //for
+		}//end if
+	
+	
+	//Now we have enough data to build the palette by iterating all the entries in the colors hash
+	RArray<TUint> palette(colors.Count());
+	THashMapIter<TInt,TInt> colorIterator(colors);
+	const TInt* color = colorIterator.NextKey();
+	while (color)
+		{
+		if (palette.Append(*color) != KErrNone)
+			{
+			palette.Close();
+			colors.Close();
+			return KErrNoMemory;
+			}
+		//set the index of each entry back into the color hash for lookup later
+		//const cast needed as CurrentValue returns a const pointer; for no good reason?
+		TInt* index = CONST_CAST(TInt*, colorIterator.CurrentValue());
+		*index = palette.Count() - 1;
+		color = colorIterator.NextKey();
+		}
+		
+	//Set up some new memory for the palettised bitmap
+	//size is (4 bytes for palette size) + (4 bytes per palette entry) + (upto 1 byte per pixel)
+	//pixels are packed according to number of colors
+	TUint compressedBitsPerPixel = PaletteBitsPerPixel(colors.Count());
+	TUint compressedPixelsPerByte = 8 / compressedBitsPerPixel;
+	TUint compressedLineLengthInBytesPadded = (iHeader.iSizeInPixels.iWidth + compressedPixelsPerByte - 1)/ compressedPixelsPerByte;
+	TInt compressedDataBytes = 4 + 4 * colors.Count() + compressedLineLengthInBytesPadded * iHeader.iSizeInPixels.iHeight;
+
+	//add two extra ints for storing function pointers (8 bytes )
+	compressedDataBytes += 8 ;
+	
+	TUint8* compressedBase = NULL;
+	compressedBase = iPile->Alloc(compressedDataBytes);
+	if (!compressedBase)
+		{
+		palette.Close();
+		colors.Close();
+		return KErrNoMemory;
+		}
+	iDataOffset = compressedBase - iPile->ChunkBase();
+
+	iHeader.iBitmapSize = sizeof(SEpocBitmapHeader) + compressedDataBytes;
+	iHeader.iCompression = EGenericPaletteCompression;
+	
+	//copy the palette length into the data area...
+	*(REINTERPRET_CAST(TInt*, compressedBase)) = palette.Count(); //let's hope we're 4 byte aligned...
+	compressedBase+=4;
+	//...then the palette itself...
+	for (TUint loop = 0; loop < palette.Count(); loop++)
+		{
+		*(REINTERPRET_CAST(TInt*, compressedBase)) = palette[loop];
+		compressedBase +=4;
+		}
+		
+	//Work out, then store, the decoding functions required for packing density and colour depth.
+	//This saves having to do it for every scanline during decompression.
+
+	TDecodeFunction decodeFunction = NULL;
+	switch (compressedPixelsPerByte)
+		{
+		case 1:
+			decodeFunction=CBitwiseBitmap::PaletteDecode1PixelPerByte;
+			break;			
+		case 2:
+			decodeFunction=CBitwiseBitmap::PaletteDecode2PixelPerByte;
+			break;			
+		case 4:
+			decodeFunction=CBitwiseBitmap::PaletteDecode4PixelPerByte;
+			break;
+		case 8:
+			decodeFunction=CBitwiseBitmap::PaletteDecode8PixelPerByte;
+			break;			
+		default:
+			::Panic(EFbsNotSupportedForCompression);
+		}
+	*(REINTERPRET_CAST(TDecodeFunction*, compressedBase))  = decodeFunction ;
+	compressedBase += 4 ;
+
+	//Select the appropriate assignment function based on the bits-per-pixel of the target
+	TAssignFunction assignFunction = NULL;
+	switch (iHeader.iBitsPerPixel)
+		{
+		case 16:
+			assignFunction=CBitwiseBitmap::PaletteAssign16BitColor;
+			break;
+		case 24:
+			assignFunction=CBitwiseBitmap::PaletteAssign24BitColor;
+			break;
+		case 32:
+			assignFunction=CBitwiseBitmap::PaletteAssign32BitColor;
+			break;
+		default:
+			::Panic(EFbsNotSupportedForCompression);
+		}
+	*(REINTERPRET_CAST(TAssignFunction*, compressedBase)) = assignFunction ;
+	compressedBase += 4 ;
+		
+ 	//...and finally the data
+	pixelAddress = base;
+
+	//separate loops for 16 & 24+ bpp again
+
+	if ( iHeader.iBitsPerPixel < 24 )
+		{
+		for (lineAddress = base; lineAddress < top; lineAddress += lineLengthInBytesPadded)
+			{
+			//Loop each pixel within the line
+			pixelAddress = lineAddress;
+			while (pixelAddress < lineAddress + lineLengthInBytes)
+				{
+				TUint8 pack = 0;
+				//loop for each pixel to pack into the byte.  If we run out of pixels in the line, we write out the pack byte and continue on the next line
+				for (TInt ii = 0; ii < compressedPixelsPerByte && pixelAddress < lineAddress + lineLengthInBytes; ii++)
+					{
+					pack <<= compressedBitsPerPixel;
+					//extract the color
+					TUint color = *pixelAddress;
+					color |= (*(pixelAddress+1)) << 8;
+					
+					//lookup the palette index for the color
+					TInt* paletteIndex = colors.Find(color);
+					//pack the palette index into the target byte
+					pack |= *paletteIndex;
+					//next pixel
+					pixelAddress += sourceBytesPerPixel;
+					}
+				//store the packed pixel data into the new compressed data area
+				*compressedBase = pack;
+				compressedBase++;				
+				}
+			}
+		}
+	else //>= 24bpp
+		{
+		for (lineAddress = base; lineAddress < top; lineAddress += lineLengthInBytesPadded)
+			{
+			//Loop each pixel within the line
+			pixelAddress = lineAddress;
+			while (pixelAddress < lineAddress + lineLengthInBytes)
+				{
+				TUint8 pack = 0;
+				//loop for each pixel to pack into the byte.  If we run out of pixels in the line, we write out the pack byte and continue on the next line
+				for (TInt ii = 0; ii < compressedPixelsPerByte && pixelAddress < lineAddress + lineLengthInBytes; ii++)
+					{
+					pack <<= compressedBitsPerPixel;
+					//extract the color
+				TUint color = *pixelAddress;
+					color |= (*(pixelAddress+1)) << 8;
+					color |= (*(pixelAddress+2)) << 16;
+					//if 32 bit, just ignore the 4th byte as it is unused for color data
+
+					//lookup the palette index for the color
+					TInt* paletteIndex = colors.Find(color);
+					//pack the palette index into the target byte
+					pack |= *paletteIndex;
+					//next pixel
+					pixelAddress += sourceBytesPerPixel;
+					}
+				//store the packed pixel data into the new compressed data area
+				*compressedBase = pack;
+				compressedBase++;				
+				}
+			}
+		}//if
+
+
+	//Set the RAM compression flag
+	iIsCompressedInRAM = ETrue;
+
+	//Free the old data.
+	iPile->Free(base);
+	//Clean up	
+	palette.Close();
+	colors.Close();
+	return KErrNone;
+	}
+	
+/**
+Create a scan line from a palette compressed bitmap.
+Starting from aPixel in the bitmap pointed to be aBase, populate aDestBuffer with aLength pixels looked up in the palette.
+Note this function assumes 16, 24 or 32 non alpha bit uncompressed bitmaps, compressed into 8 bit palettes (ie <256 colors)
+Structure of bitmap is (4 bytes for palette size) + (4 bytes per palette entry) + (1 byte per pixel)
+@param aDestBuffer Points to the destination buffer. After the call it will be filled
+with the decompressed data.
+@param aPixel The decompression starts from this pixel
+@param aLength Length of requested decompressed data - in pixels
+@param aBase Points to the beginning of compressed bitmap data
+@param aLineScannngPosition Saved information about the last used position in the compressed data
+*/
+void CBitwiseBitmap::GenerateLineFromPaletteCompressedData(
+									 TUint8* aDestBuffer, 
+									 const TPoint& aPixel,
+									 TInt aLength, 
+									 TUint32* aBase, 
+									 TLineScanningPosition& /*aLineScanningPosition*/) const
+	{
+	//At entry, aBase will point to the start of the compressed data, ie the palette size
+	//Each line in the bitmap will start at a byte boundary in the compressed data.
+	
+	TUint32* srcPalette = aBase + 1; //Address of the palette in the source data
+	TUint srcNumPaletteEntries = *aBase;	//Number of entries in the palette (will be <=255)
+	TUint compressedBitsPerPixel = PaletteBitsPerPixel(srcNumPaletteEntries);
+	__ASSERT_DEBUG(compressedBitsPerPixel <= 8, Panic( EFbsBitmapDecompressionError )) ;
+	const TUint8 lookup[] = {0, 8, 4, 0, 2, 0, 0, 0, 1};
+	//TUint compressedPixelsPerByte = 8 / compressedBitsPerPixel;
+	TUint compressedPixelsPerByte = lookup[compressedBitsPerPixel];
+	__ASSERT_DEBUG(compressedPixelsPerByte>0, ::Panic(EFbsNotSupportedForCompression));	
+
+	TUint8* srcData = REINTERPRET_CAST(TUint8*, srcPalette + srcNumPaletteEntries);	//Address of the pixel data in the source data
+
+	//Extract the function pointers for decoding functions. Set up decode & assign functions.
+	TDecodeFunction decodeFunction = NULL ;
+	decodeFunction = reinterpret_cast<TDecodeFunction>(*((TUint32*)srcData )) ;
+	srcData += 4 ;
+	TAssignFunction assignFunction = NULL;
+	assignFunction = reinterpret_cast<TAssignFunction>(*((TUint32*)srcData )) ;
+	srcData += 4 ;
+
+	//Note: The following lines have been optimised to avoid divisions.
+	//By way of explanation the original lines have been left as comments
+
+	//TUint srcBytesPerLinePadded = (iHeader.iSizeInPixels.iWidth + compressedPixelsPerByte - 1) / compressedPixelsPerByte;	//number of bytes occupied by each line in the compressed bitmap.
+	TUint srcBytesPerLinePadded = ((iHeader.iSizeInPixels.iWidth + compressedPixelsPerByte - 1)  * compressedBitsPerPixel) >> 3;	//number of bytes occupied by each line in the compressed bitmap.
+	//TUint srcStartBytesFromBase = aPixel.iY * srcBytesPerLinePadded + aPixel.iX / compressedPixelsPerByte;	//Starting bytes from the start of the bitmap
+	TUint srcStartBytesFromBase = aPixel.iY * srcBytesPerLinePadded + ((aPixel.iX * compressedBitsPerPixel) >> 3);	//Starting bytes from the start of the bitmap
+	//TUint srcStartPixelInByte = aPixel.iX  % compressedPixelsPerByte;		//starting pixel position in byte (lines start on byte boundary)
+	TUint srcStartPixelInByte = aPixel.iX & ((compressedPixelsPerByte)- 1);		//starting pixel position in byte (lines start on byte boundary)
+	//TUint srcEndBytesFromBase = srcStartBytesFromBase + (aLength + compressedPixelsPerByte - 1) / compressedPixelsPerByte;		//Ending bytes from the start of the bitmap
+	TUint srcEndBytesFromBase = srcStartBytesFromBase + (((aLength + compressedPixelsPerByte - 1) * compressedBitsPerPixel) >> 3);		//Ending bytes from the start of the bitmap
+	//TUint srcEndPixelInByte = (aPixel.iX + aLength) % compressedPixelsPerByte;		//Ending pixel position in byte
+	TUint srcEndPixelInByte = (aPixel.iX + aLength) & ((compressedPixelsPerByte)-1);		//Ending pixel position in byte
+	TUint8* srcStartData = srcData + srcStartBytesFromBase;	//Address of the first byte of packed pixels in the source
+	TUint8* srcEndData = srcData + srcEndBytesFromBase;	//Address of the last+1 byte of packed pixels in the source
+	TUint8* destStartData = aDestBuffer + ((aPixel.iX*iHeader.iBitsPerPixel) >> 3); //Address of the first pixel in the destination
+	
+	//3 stages to the decompression:
+	//1. Decompress any pixels which are a subset of the first byte
+	//2. Loop whole bytes extracting all pixels at once
+	//3. Decompress any pixels which are a subset of the last byte
+
+	TUint8* srcDataPtr = srcStartData;
+	
+	//Stage 1: Decompress any pixels which are a subset of the first byte
+	if (srcStartPixelInByte > 0)
+		PaletteDecodeAndAssignGeneric(srcDataPtr++, srcPalette, destStartData, srcStartPixelInByte, compressedPixelsPerByte-1, compressedPixelsPerByte, compressedBitsPerPixel);
+
+	//If the last byte is only partly packed with pixels from this line, stop one byte short in the main loop
+	if (srcEndPixelInByte > 0)
+		srcEndData--;
+	
+	//Stage 2: Loop all the required pixels and call the appropriate functions		
+	while (srcDataPtr < srcEndData)
+		{
+		__ASSERT_DEBUG(srcDataPtr <= srcEndData, ::Panic(EFbsNotSupportedForCompression));	
+		__ASSERT_DEBUG(destStartData <= aDestBuffer + ((aPixel.iX*iHeader.iBitsPerPixel) >> 3) + aLength * PaletteBytesPerPixel(iHeader.iBitsPerPixel), ::Panic(EFbsNotSupportedForCompression));	
+		(*decodeFunction)(srcDataPtr++, srcPalette, destStartData, assignFunction);
+		}
+	
+	//Stage 3: Decompress any pixels which are a subset of the last byte
+	if (srcEndPixelInByte > 0)
+		PaletteDecodeAndAssignGeneric(srcDataPtr++, srcPalette, destStartData, 0, srcEndPixelInByte-1, compressedPixelsPerByte, compressedBitsPerPixel);
+	}
+
+/** 
+This function deals with all different bit depths & color counts dynamically - smaller but slower
+@param aDataPtr Address in compressed data to read from
+@param aPalettePtr Address of the start of the palette in the compressed data
+@param aDestPtr Address to write uncompressed data to.  Will be incremented on return from function.
+@param aStartPixel Zero based position within the compressed byte of the first pixel to decompress
+@param aEndPixel Zero based position within the compressed byte of the last pixel to decompress
+@param aCompressedPixelsPerByte Number of pixels packed into each byte of the compressed data
+@param aCompressedBitsPerPixel Number of bits used to express each pixel in the compressed data.  Nothing to do with the color depth of the image.  
+*/
+void CBitwiseBitmap::PaletteDecodeAndAssignGeneric(	TUint8* aDataPtr, 
+												TUint32* aPalettePtr, 
+												TUint8*& aDestPtr,
+												TUint aStartPixel, 
+												TUint aEndPixel, 
+												TUint aCompressedPixelsPerByte,
+												TUint aCompressedBitsPerPixel) const
+	{
+	__ASSERT_DEBUG(aStartPixel<aCompressedPixelsPerByte, ::Panic(EFbsNotSupportedForCompression));
+	__ASSERT_DEBUG(aEndPixel<aCompressedPixelsPerByte, ::Panic(EFbsNotSupportedForCompression));
+
+	//create a mask for the appropriate number of bits
+	TUint8 mask = 0xFF;
+	mask <<= 8 - aCompressedBitsPerPixel;
+
+	//Adjust the mask in case we've been asked to start at an intermediate pixel
+	mask >>= aStartPixel * aCompressedBitsPerPixel;
+	
+	TUint8 pack = *aDataPtr; //max of 8 bits for palette entry
+	
+	//Loop the pixel data from the requested start to the requested end
+	for (TInt ii = aStartPixel;  ii <= aEndPixel;  ii++)
+		{	
+		//extract the bits corresponding to the required color index from the pack using the mask
+		TUint8 index = pack&mask;
+		//shift the index to the right to get true value
+		index >>= (aCompressedPixelsPerByte- ii - 1) * aCompressedBitsPerPixel;
+		//get the address of the required color value from the palette
+		TUint32 color = *(aPalettePtr + index);
+		//and copy the actual color value into the scanline buffer
+		*aDestPtr ++= color;
+		*aDestPtr ++= color >> 8;
+		if (iHeader.iBitsPerPixel >= 24)
+			*aDestPtr ++= color >> 16;
+		if (iHeader.iBitsPerPixel == 32)
+			*aDestPtr ++= 0xFF;  //use 0xFF rather than 0x00 as it is more alpha friendly
+		
+		//shift the mask to get the next required bits
+		mask >>= aCompressedBitsPerPixel;
+		}
+	}
+
+/** 
+Specialised function for decoding pixels from a palette compressed bitmap with 1 pixel packed in each byte.
+Implemented for speed, not size
+@param aDataPtr Address in compressed data to read from
+@param aPalettePtr Address of the start of the palette in the compressed data
+@param aDestPtr Address to write uncompressed data to.  Will be incremented on return from function.
+@param aAssignFunction Function pointer to assigment function to use to write actual pixel data to uncompressed scanline
+*/
+void CBitwiseBitmap::PaletteDecode1PixelPerByte(TUint8* aDataPtr, TUint32* aPalettePtr, TUint8*& aDestPtr, TAssignFunction aAssignFunction)
+	{
+	(*aAssignFunction)(aDestPtr, *(aPalettePtr + *aDataPtr));
+	}
+	
+/** 
+Specialised function for decoding pixels from a palette compressed bitmap with 2 pixels packed in each byte.
+Implemented for speed, not size
+@param aDataPtr Address in compressed data to read from
+@param aPalettePtr Address of the start of the palette in the compressed data
+@param aDestPtr Address to write uncompressed data to.  Will be incremented on return from function.
+@param aAssignFunction Function pointer to assigment function to use to write actual pixel data to uncompressed scanline
+*/
+void CBitwiseBitmap::PaletteDecode2PixelPerByte(TUint8* aDataPtr, TUint32* aPalettePtr, TUint8*& aDestPtr, TAssignFunction aAssignFunction)
+	{
+	TUint8 mask = 0xF0; //binary 11110000
+	TUint8 pack = *aDataPtr;
+	//Pixel 1
+	TUint8 index = pack&mask;
+	index >>= 4;
+	TUint32 color = *(aPalettePtr + index);
+	(*aAssignFunction)(aDestPtr, color);
+	mask >>= 4;
+ 	//Pixel 2
+ 	index = pack&mask;
+ 	color = *(aPalettePtr + index);
+	(*aAssignFunction)(aDestPtr, color); 			
+	}
+
+/** 
+Specialised function for decoding pixels from a palette compressed bitmap with 4 pixels packed in each byte.
+Implemented for speed, not size
+@param aDataPtr Address in compressed data to read from
+@param aPalettePtr Address of the start of the palette in the compressed data
+@param aDestPtr Address to write uncompressed data to.  Will be incremented on return from function.
+@param aAssignFunction Function pointer to assigment function to use to write actual pixel data to uncompressed scanline
+*/
+void CBitwiseBitmap::PaletteDecode4PixelPerByte(TUint8* aDataPtr, TUint32* aPalettePtr, TUint8*& aDestPtr, TAssignFunction aAssignFunction)
+	{
+	TUint8 mask = 0xC0; //binary 11000000
+	TUint8 pack = *aDataPtr;
+	//Pixel 1
+	TUint8 index = pack&mask;
+	index >>= 6;
+	TUint32 color = *(aPalettePtr + index);
+	(*aAssignFunction)(aDestPtr, color);
+	mask >>= 2;
+ 	//Pixel 2
+ 	index = pack&mask;
+	index >>= 4;
+ 	color = *(aPalettePtr + index);
+	(*aAssignFunction)(aDestPtr, color); 			
+	mask >>= 2;
+ 	//Pixel 3
+ 	index = pack&mask;
+	index >>= 2;
+ 	color = *(aPalettePtr + index);
+	(*aAssignFunction)(aDestPtr, color); 			
+	mask >>= 2;
+ 	//Pixel 4
+ 	index = pack&mask;
+ 	color = *(aPalettePtr + index);
+	(*aAssignFunction)(aDestPtr, color); 			
+	}
+
+/** 
+Specialised function for decoding pixels from a palette compressed bitmap with 8 pixels packed in each byte.
+Implemented for speed, not size
+@param aDataPtr Address in compressed data to read from
+@param aPalettePtr Address of the start of the palette in the compressed data
+@param aDestPtr Address to write uncompressed data to.  Will be incremented on return from function.
+@param aAssignFunction Function pointer to assigment function to use to write actual pixel data to uncompressed scanline
+*/
+void CBitwiseBitmap::PaletteDecode8PixelPerByte(TUint8* aDataPtr, TUint32* aPalettePtr, TUint8*& aDestPtr, TAssignFunction aAssignFunction)
+	{
+	TUint8 mask = 0x80; //binary 10000000
+	TUint8 pack = *aDataPtr;
+	//Pixel 1
+	TUint8 index = pack&mask;
+	index >>= 7;
+	TUint32 color = *(aPalettePtr + index);
+	(*aAssignFunction)(aDestPtr, color);
+	mask >>= 1;
+ 	//Pixel 2
+ 	index = pack&mask;
+	index >>= 6;
+ 	color = *(aPalettePtr + index);
+	(*aAssignFunction)(aDestPtr, color); 			
+	mask>>=1;
+ 	//Pixel 3
+ 	index = pack&mask;
+	index >>= 5;
+ 	color = *(aPalettePtr + index);
+	(*aAssignFunction)(aDestPtr, color); 			
+	mask >>= 1;
+  	//Pixel 4
+ 	index = pack&mask;
+	index >>= 4;
+ 	color = *(aPalettePtr + index);
+	(*aAssignFunction)(aDestPtr, color); 			
+	mask >>= 1;
+  	//Pixel 5
+ 	index = pack&mask;
+	index >>= 3;
+ 	color = *(aPalettePtr + index);
+	(*aAssignFunction)(aDestPtr, color); 			
+	mask >>= 1;
+  	//Pixel 6
+ 	index = pack&mask;
+	index >>= 2;
+ 	color = *(aPalettePtr + index);
+	(*aAssignFunction)(aDestPtr, color); 			
+	mask >>= 1;
+  	//Pixel 7
+ 	index = pack&mask;
+	index >>= 1;
+ 	color = *(aPalettePtr + index);
+	(*aAssignFunction)(aDestPtr, color); 			
+	mask >>= 1;
+ 	//Pixel 8
+ 	index = pack&mask;
+ 	color = *(aPalettePtr + index);
+	(*aAssignFunction)(aDestPtr, color); 			
+	}
+
+/** 
+Specialised function for assigning pixels into an uncompressed scanline of 16 bit color depth.
+Implemented for speed, not size
+@param aDestPtr Address to write uncompressed data to.  Will be incremented on return from function.
+@param aColor Color info to write.
+*/
+void CBitwiseBitmap::PaletteAssign16BitColor(TUint8*& aDestPtr, TUint32 aColor)
+	{
+	*aDestPtr ++= aColor;
+	*aDestPtr ++= aColor >> 8;
+	}
+
+/** 
+Specialised function for assigning pixels into an uncompressed scanline of 24 bit color depth.
+Implemented for speed, not size
+@param aDestPtr Address to write uncompressed data to.  Will be incremented on return from function.
+@param aColor Color info to write.
+*/
+void CBitwiseBitmap::PaletteAssign24BitColor(TUint8*& aDestPtr, TUint32 aColor)
+	{
+	*aDestPtr ++= aColor;
+	*aDestPtr ++= aColor >> 8;
+	*aDestPtr ++= aColor >> 16;
+	}
+
+/** 
+Specialised function for assigning pixels into an uncompressed scanline of 32 bit color depth.
+Implemented for speed, not size
+@param aDestPtr Address to write uncompressed data to.  Will be incremented on return from function.
+@param aColor Color info to write.
+*/
+void CBitwiseBitmap::PaletteAssign32BitColor(TUint8*& aDestPtr, TUint32 aColor)
+	{
+	*aDestPtr ++= aColor;
+	*aDestPtr ++= aColor >> 8;
+	*aDestPtr ++= aColor >> 16;
+	*aDestPtr ++= 0xFF;  //use 0xFF rather than 0x00 as it is more alpha friendly
+	}
+
+/**
+Get the bits used per pixel when packing multiple pixels in palette compression.
+The value returned is a power of 2, not always the most efficient pack, for alignment reasons, Eg
+ 65537 -> KMaxTInt : 32 bpp
+ 257 -> 65536 colors : 16 bpp
+ 17 -> 256 colors : 8 bpp
+ 5  -> 16  colors : 4 bpp
+ 3  -> 4   colors : 2 bpp
+ 0  -> 2   colors : 1 bpp
+@param aNumColors The number of colors in the bitmap.  This governs the size of the palette and thus
+the number of bits needed to represent an index into it.
+*/
+TUint CBitwiseBitmap::PaletteBitsPerPixel(TInt aNumColors) const
+	{
+	if (aNumColors <= 2)
+		return 1;
+	else if (aNumColors <= 4)
+		return 2;
+	else if (aNumColors <= 16)
+		return 4;
+	else if (aNumColors <= 256)
+		return 8;
+	else if (aNumColors <= 65536)
+		return 16;
+	else
+		return 32;
+	}
+	
+/**
+Gets the bytes used per pixel according to the bits per pixel of a bitmap.
+Also used to find which bit per pixel values are supported by palette compression, hence this is not
+a case of simple division by 8.
+If return value is zero, the supplied bit per pixel value is not supported by palette compression.
+@param aBitsPerPixel The bits per pixel value to transform into bytes
+*/
+TUint CBitwiseBitmap::PaletteBytesPerPixel(TInt aBitsPerPixel) const
+	{
+	if (aBitsPerPixel == 16)
+		return 2;  //16 bit
+	else if (aBitsPerPixel == 24)
+		return 3;   //24 bit
+	else if (aBitsPerPixel == 32 && iHeader.iColor == SEpocBitmapHeader::EColor)
+		return 4;	//32 bit with no alpha
+	else 
+		return 0;
+	}
+