os/graphics/fbs/fontandbitmapserver/sfbs/BITCOMP.CPP
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 1995-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 <f32file.h>
    17 #include <s32file.h>
    18 #include <fbs.h>
    19 #include <bitmap.h>
    20 #include "UTILS.H"
    21 #include <e32hashtab.h>
    22 
    23 GLREF_C void Panic(TFbsPanic aPanic);
    24 
    25 void CBitwiseBitmap::DoInternalizeCompressedDataL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase,TBitmapfileCompression aCompression)
    26 	{
    27 	TInt destSizeInBytes = iHeader.iSizeInPixels.iHeight * iByteWidth;
    28 	TUint8* destPtr = (TUint8*)aBase;
    29 
    30 	// try to allocate memory for the compressed bitmap
    31 	TUint8* decompressionBuffer = (TUint8*)User::Alloc(aSrceSizeInBytes);
    32 
    33 	if (decompressionBuffer)
    34 		{
    35 		// read the compressed bitmap, then decompress
    36 		CleanupStack::PushL(decompressionBuffer);
    37 		aStream.ReadL(decompressionBuffer,aSrceSizeInBytes);
    38 		switch (aCompression)
    39 			{
    40 		case EByteRLECompression:
    41 			DoDecompressByteData(destPtr,destSizeInBytes,decompressionBuffer,aSrceSizeInBytes);
    42 			break;
    43 		case ETwelveBitRLECompression:
    44 			DoDecompressTwelveBitData(destPtr,destSizeInBytes,decompressionBuffer,aSrceSizeInBytes);
    45 			break;
    46 		case ESixteenBitRLECompression:
    47 			DoDecompressSixteenBitData(destPtr,destSizeInBytes,decompressionBuffer,aSrceSizeInBytes);
    48 			break;
    49 		case ETwentyFourBitRLECompression:
    50 			DoDecompressTwentyFourBitData(destPtr,destSizeInBytes,decompressionBuffer,aSrceSizeInBytes);
    51 			break;
    52 		case EThirtyTwoUBitRLECompression:
    53 			DoDecompressThirtyTwoUBitData(destPtr,destSizeInBytes,decompressionBuffer,aSrceSizeInBytes);
    54 			break;
    55 		case EThirtyTwoABitRLECompression:
    56 			DoDecompressThirtyTwoABitData(destPtr,destSizeInBytes,decompressionBuffer,aSrceSizeInBytes);
    57 			break;
    58 		default:
    59 			break;
    60 			}
    61 		CleanupStack::PopAndDestroy(); // decompressionBuffer
    62 		return;
    63 		}
    64 
    65 	// not enough heap to pre-load the source bitmap
    66 	switch (aCompression)
    67 		{
    68 	case EByteRLECompression:
    69 		DoDecompressByteDataAltL(aStream,aSrceSizeInBytes,aBase);
    70 		break;
    71 	case ETwelveBitRLECompression:
    72 		DoDecompressTwelveBitDataAltL(aStream,aSrceSizeInBytes,aBase);
    73 		break;
    74 	case ESixteenBitRLECompression:
    75 		DoDecompressSixteenBitDataAltL(aStream,aSrceSizeInBytes,aBase);
    76 		break;
    77 	case ETwentyFourBitRLECompression:
    78 		DoDecompressTwentyFourBitDataAltL(aStream,aSrceSizeInBytes,aBase);
    79 		break;
    80 	case EThirtyTwoUBitRLECompression:
    81 		DoDecompressThirtyTwoUBitDataAltL(aStream,aSrceSizeInBytes,aBase);
    82 		break;
    83 	case EThirtyTwoABitRLECompression:
    84 		DoDecompressThirtyTwoABitDataAltL(aStream,aSrceSizeInBytes,aBase);
    85 		break;
    86 	default:
    87 		break;
    88 		}
    89 	}
    90 
    91 void CBitwiseBitmap::DoDecompressByteData(TUint8* aDestBuffer,TInt aDestSize,TUint8* aSrceBuffer,TInt aSrceSize)
    92 	{
    93 	TUint8* srcePtr = aSrceBuffer;
    94 	TUint8* destPtr = aDestBuffer;
    95 	TUint8* srcePtrLimit = aSrceBuffer + aSrceSize;
    96 	TUint8* destPtrLimit = aDestBuffer + aDestSize;
    97 
    98 	while (srcePtr < srcePtrLimit && destPtr < destPtrLimit)
    99 		{
   100 		TInt8 count = *srcePtr++;
   101 
   102 		if (count >= 0)
   103 			{
   104 			const TInt numBytes = Min(count + 1, destPtrLimit - destPtr);
   105 			Mem::Fill(destPtr,numBytes,*srcePtr++);
   106 			destPtr += numBytes;
   107 			}
   108 		else
   109 			{
   110 			const TInt numBytes = Min(-count, destPtrLimit - destPtr);
   111 			Mem::Copy(destPtr,srcePtr,numBytes);
   112 			srcePtr += numBytes;
   113 			destPtr += numBytes;
   114 			}
   115 		}
   116 	__ASSERT_DEBUG(srcePtr == srcePtrLimit && destPtr == destPtrLimit,Panic(EFbsBitmapDecompressionError));
   117 	}
   118 
   119 void CBitwiseBitmap::DoDecompressByteDataAltL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase)
   120 	{
   121 	TInt destSizeInBytes = iHeader.iSizeInPixels.iHeight * iByteWidth;
   122 	TUint8* destPtr = (TUint8*)aBase;
   123 	TUint8* destPtrLimit = destPtr + destSizeInBytes;
   124 
   125 	while(aSrceSizeInBytes > 0 && destPtr < destPtrLimit)
   126 		{
   127 		TInt8 count = aStream.ReadInt8L();
   128 		aSrceSizeInBytes--;
   129 
   130 		if (count >= 0)
   131 			{
   132 			const TInt numBytes = Min(count + 1, destPtrLimit - destPtr);
   133 			TUint8 value = aStream.ReadUint8L();
   134 			aSrceSizeInBytes--;
   135 			Mem::Fill(destPtr,numBytes,value);
   136 			destPtr += numBytes;
   137 			}
   138 		else
   139 			{
   140 			const TInt numBytes = Min(-count, destPtrLimit - destPtr);
   141 			aStream.ReadL(destPtr,numBytes);
   142 			aSrceSizeInBytes -= numBytes;
   143 			destPtr += numBytes;
   144 			}
   145 		}
   146 	__ASSERT_DEBUG(aSrceSizeInBytes == 0 && destPtr == destPtrLimit,Panic(EFbsBitmapDecompressionError));
   147 	}
   148 
   149 /** Fills the 32bit pixels into the destination pointer
   150 This method uses the concept of Duff's Device 
   151 @param aDestPtr32 pointer to 32bit destination buffer.
   152 @param aCount Number of 32bit pixels to be copied.
   153 @param aValue32 32bit pixel data. */
   154 void CBitwiseBitmap::BitmapFill32(TUint32* aDestPtr32, TInt aCount, TUint32 aValue32)
   155 	{
   156 	__ASSERT_DEBUG(aCount > 0, Panic(EFbsBitmapDecompressionError));
   157 	if (aCount > 0)
   158 		{ // for performance loop is unrolled, using "Duff's Device" pattern
   159 		TInt blocksOf16 = aCount / 16;	// number of blocks of 16 full words to write
   160 		// the first iteration writes 1 to 15 words
   161 
   162 		switch (aCount & 0x0f)
   163 			{ // note that case statements intentionally cascade
   164 		case 0:
   165 write16dblPixels:	// second and subsequent iterations always write 16 words
   166 			--blocksOf16;
   167 			*aDestPtr32++ = aValue32;
   168 			//coverity [fallthrough]
   169 		case 15:
   170 			*aDestPtr32++ = aValue32;
   171 			//coverity [fallthrough]
   172 		case 14:
   173 			*aDestPtr32++ = aValue32;
   174 			//coverity [fallthrough]
   175 		case 13:
   176 			*aDestPtr32++ = aValue32;
   177 			//coverity [fallthrough]
   178 		case 12:
   179 			*aDestPtr32++ = aValue32;
   180 			//coverity [fallthrough]
   181 		case 11:
   182 			*aDestPtr32++ = aValue32;
   183 			//coverity [fallthrough]
   184 		case 10:
   185 			*aDestPtr32++ = aValue32;
   186 			//coverity [fallthrough]
   187 		case 9:
   188 			*aDestPtr32++ = aValue32;
   189 			//coverity [fallthrough]
   190 		case 8:
   191 			*aDestPtr32++ = aValue32;
   192 			//coverity [fallthrough]
   193 		case 7:
   194 			*aDestPtr32++ = aValue32;
   195 			//coverity [fallthrough]
   196 		case 6:
   197 			*aDestPtr32++ = aValue32;
   198 			//coverity [fallthrough]
   199 		case 5:
   200 			*aDestPtr32++ = aValue32;
   201 			//coverity [fallthrough]
   202 		case 4:
   203 			*aDestPtr32++ = aValue32;
   204 			//coverity [fallthrough]
   205 		case 3:
   206 			*aDestPtr32++ = aValue32;
   207 			//coverity [fallthrough]
   208 		case 2:
   209 			*aDestPtr32++ = aValue32;
   210 			//coverity [fallthrough]
   211 		case 1:
   212 			*aDestPtr32++ = aValue32;
   213 			}
   214 
   215 		if (blocksOf16 > 0)
   216 			{
   217 			goto write16dblPixels;
   218 			}
   219 		}
   220 	}
   221 
   222 /** Fills the 16bit pixels into the destination pointer
   223 This method uses the concept of Duff's Device 
   224 @param aDestPtr16 pointer to 16bit destination buffer.
   225 @param aCount Number of 16bit pixels to be copied.
   226 @param aValue16 16bit pixel data. */
   227 inline void CBitwiseBitmap::BitmapFill16(TUint16* aDestPtr16, TInt aCount, TUint16 aValue16)
   228 	{
   229 	// Call the 32-bit fill method if there at least 8 pixels to fill
   230 	if (aCount >= 8)
   231 		{
   232 		// first pixel is on half word address?
   233 		if (reinterpret_cast<TUint32>(aDestPtr16) & 2) 
   234 			{
   235 			*aDestPtr16++ = aValue16; 
   236 			--aCount; 
   237 			} 
   238 
   239 		// destPtr16 is now full Word aligned
   240 		const TInt countDoublePixels = aCount / 2;
   241 		TUint32* destPtr32 = (TUint32*) aDestPtr16;
   242 		BitmapFill32(destPtr32, countDoublePixels, (aValue16 << 16) | aValue16);
   243 
   244 		aCount -= countDoublePixels * 2;
   245 		if (aCount == 1)
   246 			{ // last pixel is on a half-word
   247 			aDestPtr16 += countDoublePixels * 2;
   248 			*aDestPtr16++ = aValue16; 
   249 			}
   250 		}
   251 	else
   252 		{ // less than 8 pixels to fill
   253 		switch (aCount)
   254 			{ // note that case statements intentionally cascade
   255 		case 7:
   256 			*aDestPtr16++ = aValue16; 
   257 		case 6:
   258 			*aDestPtr16++ = aValue16; 
   259 		case 5:
   260 			*aDestPtr16++ = aValue16; 
   261 		case 4:
   262 			*aDestPtr16++ = aValue16; 
   263 		case 3:
   264 			*aDestPtr16++ = aValue16; 
   265 		case 2:
   266 			*aDestPtr16++ = aValue16; 
   267 		case 1:
   268 			*aDestPtr16++ = aValue16; 
   269 		case 0: // nothing to do
   270 			;
   271 			}
   272 		}
   273 	}
   274 
   275 void CBitwiseBitmap::DoDecompressTwelveBitData(TUint8* aDestBuffer,TInt aDestSize,TUint8* aSrceBuffer,TInt aSrceSize)
   276 	{
   277 	TUint16* srcePtr = (TUint16*)aSrceBuffer;
   278 	TUint16* destPtr = (TUint16*)aDestBuffer;
   279 	TUint16* srcePtrLimit = srcePtr + (aSrceSize / 2);
   280 	TUint16* destPtrLimit = destPtr + (aDestSize / 2);
   281 
   282 	while (srcePtr < srcePtrLimit && destPtr < destPtrLimit)
   283 		{
   284 		TUint16 value = *srcePtr++;
   285 		TInt count = Min(value >> 12, destPtrLimit - destPtr);
   286 		value &= 0x0fff;
   287 
   288 		while (count >= 0)
   289 			{
   290 			*destPtr++ = value;
   291 			count--;
   292 			}
   293 		}
   294 
   295 	__ASSERT_DEBUG(srcePtr == srcePtrLimit && destPtr == destPtrLimit,Panic(EFbsBitmapDecompressionError));
   296 	}
   297 
   298 void CBitwiseBitmap::DoDecompressTwelveBitDataAltL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase)
   299 	{
   300 	TInt destSizeInBytes = iHeader.iSizeInPixels.iHeight * iByteWidth;
   301 	TUint16* destPtr = (TUint16*)aBase;
   302 	TUint16* destPtrLimit = destPtr + (destSizeInBytes / 2);
   303 
   304 	while(aSrceSizeInBytes > 0 && destPtr < destPtrLimit)
   305 		{
   306 		TUint16 value = aStream.ReadUint16L();
   307 		TInt count = Min(value >> 12, destPtrLimit - destPtr);
   308 		value &= 0x0fff;
   309 		aSrceSizeInBytes -= 2;
   310 
   311 		while (count >= 0)
   312 			{
   313 			*destPtr++ = value;
   314 			count--;
   315 			}
   316 		}
   317 	__ASSERT_DEBUG(aSrceSizeInBytes == 0 && destPtr == destPtrLimit,Panic(EFbsBitmapDecompressionError));
   318 	}
   319 
   320 /** The function decodes 24-bit compressed buffer to the 16-bit stream with unused top bytes by using RLE compression algorithm*/
   321 void CBitwiseBitmap::DoDecompressSixteenBitData(TUint8* aDestBuffer,TInt aDestSize,TUint8* aSrceBuffer,TInt aSrceSize)
   322 	{
   323 	__ASSERT_DEBUG((reinterpret_cast<TUint32>(aDestBuffer) & 0x2)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is half-word aligned
   324 	__ASSERT_DEBUG((aDestSize & 0x2)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is half-word aligned
   325 
   326 	TUint8* srcePtr8 = aSrceBuffer; // pointer to compressed source Byte(8-bit) stream 
   327 	TUint16* destPtr16 = reinterpret_cast<TUint16*>(aDestBuffer); //pointer to uncompressed destination HalfWord(16-bit) pixel stream
   328 	TUint8* srcePtrLimit8 = aSrceBuffer + aSrceSize; //maximum number of compressed source bytes
   329 	TUint16* destPtrLimit16 = reinterpret_cast<TUint16*>(aDestBuffer + aDestSize); //maximum number of uncompressed destination pixel stream
   330 	const TInt KPixelSize = 2; //number of bytes of the source stream that is to be considered as one Pixel
   331 	
   332 	while (srcePtr8 < srcePtrLimit8 && destPtr16 < destPtrLimit16)
   333 		{
   334 		TInt8 count = *srcePtr8++; //number of pixels to be retrieved from the source stream
   335 
   336 		if (count >= 0) //repeating number of pixels
   337 			{
   338 			const TInt numPixels = 1 + Min(count, (destPtrLimit16 - destPtr16));
   339 			const TUint8 lowByte = *srcePtr8++;
   340 			const TUint8 highByte = *srcePtr8++;
   341 			const TUint16 pixel = highByte<<8 | lowByte; //Pixel buffer which needs to be stored in destPtr16
   342 
   343 			BitmapFill16(destPtr16, numPixels, pixel);
   344 			destPtr16 += numPixels;
   345 			}
   346 		else
   347 			{
   348 			const TInt numPixels = Min(-count, destPtrLimit16 - destPtr16); //number of pixels to be copied
   349 			const TInt numBytes = numPixels * KPixelSize; //number of bytes needs to be retrieved from the srcePtr
   350 			Mem::Copy(destPtr16, srcePtr8, numBytes); // copy bytes
   351 			srcePtr8 += numBytes; //incrementing the srcePtr by number of bytes
   352 			destPtr16 += numPixels; //incrementing the destPtr16 by number of pixels
   353 			}
   354 		}
   355 	__ASSERT_DEBUG(srcePtr8 == srcePtrLimit8 && destPtr16 == destPtrLimit16, Panic(EFbsBitmapDecompressionError));
   356 	}
   357 
   358 /** The alternative decoding function which decompresses 24-bit buffer to the 16-bit stream with unused top bytes 
   359  	by using RLE compression algorithm. The function is used under low memory conditions. */
   360 void CBitwiseBitmap::DoDecompressSixteenBitDataAltL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase)
   361 	{
   362 	__ASSERT_DEBUG((reinterpret_cast<TUint32>(aBase) & 0x2)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is half-word aligned
   363 
   364 	TInt destSizeInPixels = (iHeader.iSizeInPixels.iHeight * iByteWidth); //size of destination Byte pixel buffers
   365 	destSizeInPixels >>= 1; //dividing by two, to get size of destination interms of Halfword pixel buffers
   366 	TUint16* destPtr16 = reinterpret_cast<TUint16*>(aBase); //pointer to uncompressed destination HalfWord(16-bit) pixel stream
   367 	TUint16* destPtrLimit16 = destPtr16 + destSizeInPixels; //maximum number of compressed source bytes
   368 	const TInt KPixelSize = 2; //number of bytes of the source stream that is to be considered as one Pixel
   369 
   370 	while(aSrceSizeInBytes > 0 && destPtr16 < destPtrLimit16)
   371 		{
   372 		TInt8 count = aStream.ReadInt8L(); //number of pixels to be retrieved from the source stream
   373 		aSrceSizeInBytes--; //One byte from source stream read, hence reduce size by one Byte
   374 
   375 		if (count >= 0)
   376 			{
   377 			const TInt numPixels = 1 + Min(count, (destPtrLimit16 - destPtr16));
   378 			const TUint16 pixel = aStream.ReadUint16L(); //Pixel buffer which needs to be stored in destPtr16
   379 			aSrceSizeInBytes -= KPixelSize; //Two bytes (Halfword pixel) read, reduce size by two Bytes
   380 			
   381 			BitmapFill16(destPtr16, numPixels, pixel);
   382 			destPtr16 += numPixels;
   383 			}
   384 		else
   385 			{
   386 			const TInt numPixels = Min(-count, destPtrLimit16 - destPtr16); //number of pixels to be stored into destPtr16
   387 			const TInt numBytes = numPixels * KPixelSize; //number of bytes needs to be retrieved from the srcePtr
   388 			aStream.ReadL(destPtr16, numPixels); //read TUint16's
   389 			aSrceSizeInBytes -= numBytes; //two-byte (halfword) pixel buffers read, reduce by number of bytes
   390 			destPtr16 += numPixels; //incrementing the destPtr16 by number of pixels
   391 			}
   392 		}
   393 	__ASSERT_DEBUG(aSrceSizeInBytes == 0 && destPtr16 == destPtrLimit16, Panic(EFbsBitmapDecompressionError));
   394 	}
   395 
   396 void CBitwiseBitmap::DoDecompressTwentyFourBitData(TUint8* aDestBuffer,TInt aDestSize,TUint8* aSrceBuffer,TInt aSrceSize)
   397 	{
   398 	TUint8* srcePtr = aSrceBuffer;
   399 	TUint8* destPtr = aDestBuffer;
   400 	TUint8* srcePtrLimit = aSrceBuffer + aSrceSize;
   401 	TUint8* destPtrLimit = aDestBuffer + aDestSize;
   402 
   403 	while (srcePtr < srcePtrLimit && destPtr < destPtrLimit)
   404 		{
   405 		TInt8 count = *srcePtr++;
   406 
   407 		if (count >= 0)
   408 			{
   409 			count = Min(count, (destPtrLimit - destPtr) / 3);
   410 			TUint8 component1 = *srcePtr++;
   411 			TUint8 component2 = *srcePtr++;
   412 			TUint8 component3 = *srcePtr++;
   413 
   414 			while (count >= 0)
   415 				{
   416 				*destPtr++ = component1;
   417 				*destPtr++ = component2;
   418 				*destPtr++ = component3;
   419 				count--;
   420 				}
   421 			}
   422 		else
   423 			{
   424 			const TInt numBytes = Min(count * -3, destPtrLimit - destPtr);
   425 			Mem::Copy(destPtr,srcePtr,numBytes);
   426 			srcePtr += numBytes;
   427 			destPtr += numBytes;
   428 			}
   429 		}
   430 	__ASSERT_DEBUG(srcePtr == srcePtrLimit && destPtr == destPtrLimit,Panic(EFbsBitmapDecompressionError));
   431 	}
   432 
   433 void CBitwiseBitmap::DoDecompressTwentyFourBitDataAltL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase)
   434 	{
   435 	TInt destSizeInBytes = iHeader.iSizeInPixels.iHeight * iByteWidth;
   436 	TUint8* destPtr = (TUint8*)aBase;
   437 	TUint8* destPtrLimit = destPtr + destSizeInBytes;
   438 
   439 	while(aSrceSizeInBytes > 0 && destPtr < destPtrLimit)
   440 		{
   441 		TInt8 count = aStream.ReadInt8L();
   442 		aSrceSizeInBytes--;
   443 
   444 		if (count >= 0)
   445 			{
   446 			count = Min(count, (destPtrLimit - destPtr) / 3);
   447 			TUint8 component1 = aStream.ReadUint8L();
   448 			TUint8 component2 = aStream.ReadUint8L();
   449 			TUint8 component3 = aStream.ReadUint8L();
   450 			aSrceSizeInBytes -= 3;
   451 
   452 			while (count >= 0)
   453 				{
   454 				*destPtr++ = component1;
   455 				*destPtr++ = component2;
   456 				*destPtr++ = component3;
   457 				count--;
   458 				}
   459 			}
   460 		else
   461 			{
   462 			const TInt numBytes = Min(count * -3, destPtrLimit - destPtr);
   463 			aStream.ReadL(destPtr, numBytes);
   464 			aSrceSizeInBytes -= numBytes;
   465 			destPtr += numBytes;
   466 			}
   467 		}
   468 	__ASSERT_DEBUG(aSrceSizeInBytes == 0 && destPtr == destPtrLimit,Panic(EFbsBitmapDecompressionError));
   469 	}
   470 
   471 /** The function decodes 24-bit compressed buffer to the 32-bit stream with unused top bytes by using RLE compression algorithm*/
   472 void CBitwiseBitmap::DoDecompressThirtyTwoUBitData(TUint8* aDestBuffer,TInt aDestSize,TUint8* aSrceBuffer,TInt aSrceSize)
   473 	{
   474 	
   475 	__ASSERT_DEBUG((reinterpret_cast<TUint32>(aDestBuffer) & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is word aligned
   476 	__ASSERT_DEBUG((aDestSize & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the size is whole no of pixels
   477 	
   478 	TUint8* srcePtr8 = aSrceBuffer;
   479 	TUint8* srcePtrLimit8 = aSrceBuffer + aSrceSize;
   480 
   481 	TUint32* destPtr32 = reinterpret_cast<TUint32*>(aDestBuffer);
   482 	TUint32* destPtrLimit32 = reinterpret_cast<TUint32*>(aDestBuffer + aDestSize);
   483 
   484 	while (srcePtr8 < srcePtrLimit8 && destPtr32 < destPtrLimit32)
   485 		{
   486 		
   487 		TInt8 count = *srcePtr8++; // important to read into a byte variable
   488 
   489 		if (count >= 0) //repeating pixel buffer
   490 			{
   491 			count  = Min(count, (destPtrLimit32 - destPtr32));
   492 			const TUint8 component1 = *srcePtr8++;
   493 			const TUint8 component2 = *srcePtr8++;
   494 			const TUint8 component3 = *srcePtr8++;
   495 
   496 			const TUint32 pixel = 0xff000000 | (component3<<16) | (component2<<8) | component1;
   497 
   498 			// for performance loop is unrolled, using "Duff's Device" pattern
   499 			TInt blocksOf16 = (count >> 4);	// number of blocks of 16 full words to write
   500 			// the first iteration writes 1 to 15 words
   501 			switch (count & 0x0f)
   502 				{ // note that case statements intentionally cascade
   503 			case 15:
   504 				do {	// second and subsequent iterations always write 16 words
   505 				*destPtr32++ = pixel;
   506 			case 14:
   507 				*destPtr32++ = pixel;
   508 			case 13:
   509 				*destPtr32++ = pixel;
   510 			case 12:
   511 				*destPtr32++ = pixel;
   512 			case 11:
   513 				*destPtr32++ = pixel;
   514 			case 10:
   515 				*destPtr32++ = pixel;
   516 			case 9:
   517 				*destPtr32++ = pixel;
   518 			case 8:
   519 				*destPtr32++ = pixel;
   520 			case 7:
   521 				*destPtr32++ = pixel;
   522 			case 6:
   523 				*destPtr32++ = pixel;
   524 			case 5:
   525 				*destPtr32++ = pixel;
   526 			case 4:
   527 				*destPtr32++ = pixel;
   528 			case 3:
   529 				*destPtr32++ = pixel;
   530 			case 2:
   531 				*destPtr32++ = pixel;
   532 			case 1:
   533 				*destPtr32++ = pixel;
   534 			case 0:
   535 				*destPtr32++ = pixel;
   536  
   537 				} while(0 <= --blocksOf16);
   538 				}
   539 			}
   540 		else // negative value corresponds non repeating pixel buffer
   541 			{
   542 			const TInt numPixel = Min(-count, destPtrLimit32 - destPtr32) ;
   543 			for(TInt ii = 0; ii < numPixel; ii++)
   544 				{
   545 				TUint8 component1 = *srcePtr8++;
   546 				TUint8 component2 = *srcePtr8++;
   547 				TUint8 component3 = *srcePtr8++;
   548 
   549 				*destPtr32++ =  0xff000000 | (component3<<16) | (component2<<8) | component1;
   550 				}
   551 			}
   552 		}
   553 
   554 	__ASSERT_DEBUG(srcePtr8 == srcePtrLimit8 && destPtr32 == destPtrLimit32,Panic(EFbsBitmapDecompressionError));
   555 	}
   556 
   557 /** The alternative decoding function which decompresses 24-bit buffer to the 32-bit stream with unused top bytes 
   558 	by using RLE compression algorithm. The function is using in case of memory shortage. */
   559 void CBitwiseBitmap::DoDecompressThirtyTwoUBitDataAltL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase)
   560 	{
   561 	const TInt destSizeInDwords = iHeader.iSizeInPixels.iHeight * (iByteWidth>>2);
   562 	TUint32* destPtr32 = aBase;
   563 	TUint32* destPtrLimit32 = destPtr32 + destSizeInDwords;
   564 	
   565 	const TInt KMaxRLENonRepeatingPixelBufferSize = 128 * 3;
   566 	TUint8 dataBuffer[KMaxRLENonRepeatingPixelBufferSize];
   567 
   568 	while(aSrceSizeInBytes > 0 && destPtr32 < destPtrLimit32)
   569 		{
   570 		TInt8 count = aStream.ReadInt8L();
   571 		aSrceSizeInBytes--;
   572 
   573 		if (count >= 0) //repeating pixel buffer
   574 			{
   575 			count = Min(count, (destPtrLimit32 - destPtr32));
   576 			const TUint8 component1 = aStream.ReadUint8L();
   577 			const TUint8 component2 = aStream.ReadUint8L();
   578 			const TUint8 component3 = aStream.ReadUint8L();
   579 			aSrceSizeInBytes -= 3;
   580 
   581 			const TUint32 pixel = 0xff000000 | (component3<<16) | (component2<<8) | component1; 
   582 			
   583 			TInt blocksOf16 = (count >> 4);	// number of blocks of 16 full words to write
   584 			// the first iteration writes 1 to 15 words
   585 			switch (count & 0x0f)
   586 				{ // note that case statements intentionally cascade
   587 			case 15:
   588 				do {	// second and subsequent iterations always write 16 words
   589 				*destPtr32++ = pixel;
   590 			case 14:
   591 				*destPtr32++ = pixel;
   592 			case 13:
   593 				*destPtr32++ = pixel;
   594 			case 12:
   595 				*destPtr32++ = pixel;
   596 			case 11:
   597 				*destPtr32++ = pixel;
   598 			case 10:
   599 				*destPtr32++ = pixel;
   600 			case 9:
   601 				*destPtr32++ = pixel;
   602 			case 8:
   603 				*destPtr32++ = pixel;
   604 			case 7:
   605 				*destPtr32++ = pixel;
   606 			case 6:
   607 				*destPtr32++ = pixel;
   608 			case 5:
   609 				*destPtr32++ = pixel;
   610 			case 4:
   611 				*destPtr32++ = pixel;
   612 			case 3:
   613 				*destPtr32++ = pixel;
   614 			case 2:
   615 				*destPtr32++ = pixel;
   616 			case 1:
   617 				*destPtr32++ = pixel;
   618 			case 0:
   619  				*destPtr32++ = pixel;
   620 
   621 				} while(0 <= --blocksOf16);
   622 				}
   623 			}
   624 		else // negative value corresponds non repeating pixel buffer
   625 			{
   626 			const TInt numDestDwords = Min(-count, destPtrLimit32 - destPtr32);
   627 			const TInt numSrcBytes = numDestDwords * 3;
   628 			aStream.ReadL(&dataBuffer[0], numSrcBytes);
   629 			aSrceSizeInBytes -= numSrcBytes;
   630 			TUint8* srcPtr = dataBuffer;
   631 			const TInt& numPixel = numDestDwords;
   632 			for(TInt ii = 0; ii < numPixel; ii++)
   633 				{
   634 				const TUint8 component1 = *srcPtr++;
   635 				const TUint8 component2 = *srcPtr++;
   636 				const TUint8 component3 = *srcPtr++;
   637 
   638 				*destPtr32++ = 0xff000000 | (component3<<16) | (component2<<8) | component1; 
   639 				}
   640 			}
   641 		}
   642 
   643 	__ASSERT_DEBUG(aSrceSizeInBytes == 0 && destPtr32 == destPtrLimit32,Panic(EFbsBitmapDecompressionError));
   644 	}
   645 
   646 /** 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*/
   647 void CBitwiseBitmap::DoDecompressThirtyTwoABitData(TUint8* aDestBuffer,TInt aDestSize,TUint8* aSrceBuffer,TInt aSrceSize)
   648 	{
   649 	TUint8* srcePtr = aSrceBuffer;
   650 	TUint8* srcePtrLimit = aSrceBuffer + aSrceSize;
   651 
   652 	TUint32* destPtr32 = reinterpret_cast<TUint32*>(aDestBuffer);
   653 	TUint32* destPtrLimit32 = reinterpret_cast<TUint32*>(aDestBuffer + aDestSize);
   654 
   655 	while (srcePtr < srcePtrLimit && destPtr32 < destPtrLimit32)
   656 		{
   657 		TInt8 count = *srcePtr++;
   658 
   659 		if (count >= 0) //repeating pixel buffer
   660 			{
   661 			count = Min(count, (destPtrLimit32 - destPtr32));
   662 			TUint8 component1 = *srcePtr++;
   663 			TUint8 component2 = *srcePtr++;
   664 			TUint8 component3 = *srcePtr++;
   665 			TUint8 component4 = *srcePtr++;
   666 			const TUint32 pixel = (component4<<24) | (component3<<16) | (component2<<8) | component1;
   667 
   668 			// for performance loop is unrolled, using "Duff's Device" pattern
   669 			TInt blocksOf16 = (count >> 4);	// number of blocks of 16 full words to write
   670 			// the first iteration writes 1 to 15 words
   671 			switch (count & 0x0f)
   672 				{ // note that case statements intentionally cascade
   673 			case 15:
   674 				do {	// second and subsequent iterations always write 16 words
   675 				*destPtr32++ = pixel;
   676 			case 14:
   677 				*destPtr32++ = pixel;
   678 			case 13:
   679 				*destPtr32++ = pixel;
   680 			case 12:
   681 				*destPtr32++ = pixel;
   682 			case 11:
   683 				*destPtr32++ = pixel;
   684 			case 10:
   685 				*destPtr32++ = pixel;
   686 			case 9:
   687 				*destPtr32++ = pixel;
   688 			case 8:
   689 				*destPtr32++ = pixel;
   690 			case 7:
   691 				*destPtr32++ = pixel;
   692 			case 6:
   693 				*destPtr32++ = pixel;
   694 			case 5:
   695 				*destPtr32++ = pixel;
   696 			case 4:
   697 				*destPtr32++ = pixel;
   698 			case 3:
   699 				*destPtr32++ = pixel;
   700 			case 2:
   701 				*destPtr32++ = pixel;
   702 			case 1:
   703 				*destPtr32++ = pixel;
   704 			case 0:
   705  				*destPtr32++ = pixel;
   706 
   707 				} while(0 <= --blocksOf16);
   708 				}
   709 			}
   710 		else // negative value corresponds non repeating pixel buffer
   711 			{
   712 			const TInt numPixel = Min(-count, destPtrLimit32 - destPtr32);
   713 
   714 			Mem::Copy(destPtr32, srcePtr, numPixel*4); 
   715 			destPtr32 += numPixel;
   716 			srcePtr += numPixel*4;
   717 
   718 			}
   719 		}
   720 
   721 	__ASSERT_DEBUG(srcePtr == srcePtrLimit && destPtr32 == destPtrLimit32,Panic(EFbsBitmapDecompressionError));
   722 	}
   723 
   724 /** The alternative decoding function which decompresses 32-bit buffer (where top bytes are used as alpha channel)
   725 	to the 32-bit stream by using RLE compression algorithm. The function is using in case of memory shortage. */
   726 void CBitwiseBitmap::DoDecompressThirtyTwoABitDataAltL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase)
   727 	{
   728 	const TInt destSizeInDwords = iHeader.iSizeInPixels.iHeight * (iByteWidth>>2);
   729 	TUint32* destPtr32 = aBase;
   730 	TUint32* destPtrLimit32 = destPtr32 + destSizeInDwords;
   731 
   732 	while(aSrceSizeInBytes > 0 && destPtr32 < destPtrLimit32)
   733 		{
   734 		TInt8 count = aStream.ReadInt8L();
   735 		aSrceSizeInBytes--;
   736 
   737 		if (count >= 0) //repeating pixel buffer
   738 			{
   739 			count = Min(count, (destPtrLimit32 - destPtr32));
   740 			const TUint32 pixel = aStream.ReadUint32L();
   741 			aSrceSizeInBytes -= 4;
   742 
   743 			// for performance loop is unrolled, using "Duff's Device" pattern
   744 			TInt blocksOf16 = (count >> 4);	// number of blocks of 16 full words to write
   745 			// the first iteration writes 1 to 15 words
   746 			switch (count & 0x0f)
   747 				{ // note that case statements intentionally cascade
   748 			case 15:
   749 				do {	// second and subsequent iterations always write 16 words
   750 				*destPtr32++ = pixel;
   751 			case 14:
   752 				*destPtr32++ = pixel;
   753 			case 13:
   754 				*destPtr32++ = pixel;
   755 			case 12:
   756 				*destPtr32++ = pixel;
   757 			case 11:
   758 				*destPtr32++ = pixel;
   759 			case 10:
   760 				*destPtr32++ = pixel;
   761 			case 9:
   762 				*destPtr32++ = pixel;
   763 			case 8:
   764 				*destPtr32++ = pixel;
   765 			case 7:
   766 				*destPtr32++ = pixel;
   767 			case 6:
   768 				*destPtr32++ = pixel;
   769 			case 5:
   770 				*destPtr32++ = pixel;
   771 			case 4:
   772 				*destPtr32++ = pixel;
   773 			case 3:
   774 				*destPtr32++ = pixel;
   775 			case 2:
   776 				*destPtr32++ = pixel;
   777 			case 1:
   778 				*destPtr32++ = pixel;
   779 			case 0:
   780  				*destPtr32++ = pixel;
   781 
   782 				} while(0 <= --blocksOf16);
   783 				}
   784 			}
   785 		else // negative value corresponds non repeating pixel buffer
   786 			{
   787 			const TInt numPixels = Min(-count, destPtrLimit32 - destPtr32);
   788 			aStream.ReadL((TUint16*)destPtr32, numPixels * 2); // read TUint16's
   789 			aSrceSizeInBytes -= numPixels * 4;
   790 			destPtr32 += numPixels;
   791 			}
   792 		}
   793 
   794 	__ASSERT_DEBUG(aSrceSizeInBytes == 0 && destPtr32 == destPtrLimit32,Panic(EFbsBitmapDecompressionError));
   795 	}
   796 
   797 void CBitwiseBitmap::DoExternalizeDataCompressedL(RWriteStream& aStream,TUint8* aData,TInt aSizeInBytes) const
   798 	{
   799 	switch (iHeader.iBitsPerPixel)
   800 		{
   801 	case 1:
   802 	case 2:
   803 	case 4:
   804 	case 8:
   805 		DoExternalizeByteDataCompressedL(aStream,aData,aSizeInBytes);
   806 		break;
   807 	case 12:
   808 		DoExternalizeTwelveBitDataCompressedL(aStream,aData,aSizeInBytes);
   809 		break;
   810 	case 16:
   811 		DoExternalizeSixteenBitDataCompressedL(aStream,aData,aSizeInBytes);
   812 		break;
   813 	case 24:
   814 		DoExternalizeTwentyFourBitDataCompressedL(aStream,aData,aSizeInBytes);
   815 		break;
   816 	case 32:
   817 		__ASSERT_DEBUG(iHeader.iColor == SEpocBitmapHeader::EColor||
   818 						iHeader.iColor == SEpocBitmapHeader::EColorAlpha||
   819 						iHeader.iColor == SEpocBitmapHeader::EColorAlphaPM,
   820 						Panic(EFbsBitmapInvalidCompression));
   821 		if(iHeader.iColor == SEpocBitmapHeader::EColor)
   822 			{
   823 			DoExternalizeThirtyTwoUBitDataCompressedL(aStream,aData,aSizeInBytes);
   824 			}
   825 		else
   826 			{
   827 			DoExternalizeThirtyTwoABitDataCompressedL(aStream,aData,aSizeInBytes);
   828 			}
   829 		break;
   830 	default:
   831 		break;
   832 		}
   833 	}
   834 
   835 void CBitwiseBitmap::DoExternalizeByteDataCompressedL(RWriteStream& aStream,TUint8* aData,TInt aSizeInBytes) const
   836 	{
   837 	TUint8* dataLimit=aData+aSizeInBytes-2;
   838 	TUint8 runPair[2];
   839 	while(aData<dataLimit)
   840 		{
   841 		TUint8 value=*aData;
   842 		TUint8* runStartPtr = aData;
   843 
   844 		if (*(aData+1)==value && *(aData+2)==value)
   845 			{
   846 			aData+=3;
   847 			while(aData<dataLimit && *aData==value)
   848 				aData++;
   849 			TInt runLength=aData-runStartPtr;
   850 			runPair[0]=127;
   851 			runPair[1]=value;
   852 			while(runLength>128)
   853 				{
   854 				aStream.WriteL(&runPair[0],2);
   855 				runLength-=128;
   856 				}
   857 			runPair[0]=TUint8(runLength-1);
   858 			aStream.WriteL(&runPair[0],2);
   859 			}
   860 		else
   861 			{
   862 			while(aData<dataLimit && (*(aData+1)!=value || *(aData+2)!=value))
   863 				{
   864 				aData++;
   865 				value=*aData;
   866 				}
   867 			TInt runLength = aData - runStartPtr;
   868 			while (runLength > 128)
   869 				{
   870 				aStream.WriteInt8L(-128);
   871 				aStream.WriteL(runStartPtr,128);
   872 				runLength-=128;
   873 				runStartPtr+=128;
   874 				}
   875 			aStream.WriteInt8L(-runLength);
   876 			aStream.WriteL(runStartPtr,runLength);
   877 			}
   878 		}
   879 	dataLimit+=2;
   880 	if (aData<dataLimit)
   881 		{
   882 		TInt runLength=dataLimit-aData;
   883 		aStream.WriteInt8L(-runLength);
   884 		aStream.WriteL(aData,runLength);
   885 		}
   886 	}
   887 
   888 void CBitwiseBitmap::DoExternalizeTwelveBitDataCompressedL(RWriteStream& aStream,TUint8* aData,TInt aSizeInBytes) const
   889 	{
   890 	TUint16* srcePtr = (TUint16*)aData;
   891 	TUint16* srcePtrLimit = srcePtr + (aSizeInBytes / 2);
   892 
   893 	while (srcePtr < srcePtrLimit)
   894 		{
   895 		TUint16* runStartPtr = srcePtr;
   896 		TUint16 value = TUint16(*srcePtr & 0x0fff);
   897 		do
   898 			{
   899 			srcePtr++;
   900 			}
   901 		while (srcePtr < srcePtrLimit && *srcePtr == value);
   902 
   903 		TInt pixelLength = srcePtr - runStartPtr;
   904 		TUint16 maxLengthData = TUint16(value | 0xf000);
   905 
   906 		while (pixelLength > 16)
   907 			{
   908 			aStream.WriteUint16L(maxLengthData);
   909 			pixelLength -= 16;
   910 			}
   911 
   912 		if (pixelLength > 0)
   913 			aStream.WriteUint16L(value | TUint16((pixelLength - 1) << 12));
   914 		}
   915 	}
   916 
   917 void CBitwiseBitmap::DoExternalizeSixteenBitDataCompressedL(RWriteStream& aStream,TUint8* aData,TInt aSizeInBytes) const
   918 	{
   919 	TUint16* srcePtr = (TUint16*)aData;
   920 	TUint16* srceLimitPtr = srcePtr + (aSizeInBytes / 2);
   921 	TUint16* srceLimitPtrMinusOne = srceLimitPtr - 1;
   922 
   923 	while (srcePtr < srceLimitPtrMinusOne)
   924 		{
   925 		TUint16 value = *srcePtr;
   926 		TUint16* runStartPtr = srcePtr++;
   927 
   928 		if(*srcePtr == value)
   929 			{
   930 			do
   931 				{
   932 				srcePtr++;
   933 				}
   934 			while(srcePtr < srceLimitPtr && *srcePtr == value);
   935 
   936 			TInt pixelLength = srcePtr-runStartPtr;
   937 			while (pixelLength > 128)
   938 				{
   939 				aStream.WriteInt8L(127);
   940 				aStream.WriteUint16L(value);
   941 				pixelLength -= 128;
   942 				}
   943 
   944 			aStream.WriteUint8L(pixelLength - 1);
   945 			aStream.WriteUint16L(value);
   946 			}
   947 		else
   948 			{
   949 			value = *srcePtr;
   950 			while (srcePtr < srceLimitPtrMinusOne && *(srcePtr + 1) != value)
   951 				{
   952 				srcePtr++;
   953 				value = *srcePtr;
   954 				}
   955 
   956 			TInt pixelLength = srcePtr - runStartPtr;
   957 			while (pixelLength > 128)
   958 				{
   959 				aStream.WriteInt8L(-128);
   960 				aStream.WriteL(runStartPtr,128);
   961 				runStartPtr += 128;
   962 				pixelLength -= 128;
   963 				}
   964 
   965 			aStream.WriteInt8L(-pixelLength);
   966 			aStream.WriteL(runStartPtr,pixelLength);
   967 			}
   968 		}
   969 
   970 	TInt remainingPixels = srceLimitPtr - srcePtr;
   971 	if (remainingPixels > 0)
   972 		{
   973 		aStream.WriteInt8L(-remainingPixels);
   974 		aStream.WriteL(srcePtr,remainingPixels);
   975 		}
   976 	}
   977 
   978 void CBitwiseBitmap::DoExternalizeTwentyFourBitDataCompressedL(RWriteStream& aStream,TUint8* aData,TInt aSizeInBytes) const
   979 	{
   980 	TUint8* srceLimitPtr = aData + aSizeInBytes;
   981 	TUint8* srceLimitPtrMinusThree = srceLimitPtr - 3; // three bytes == one pixel
   982 
   983 	while (aData < srceLimitPtrMinusThree)
   984 		{
   985 		TUint8* runStartPtr = aData;
   986 		TUint8 component1 = *aData++;
   987 		TUint8 component2 = *aData++;
   988 		TUint8 component3 = *aData++;
   989 
   990 		if (TrueColorPointerCompare(aData,component1,component2,component3))
   991 			{
   992 			do
   993 				{
   994 				aData += 3;
   995 				}
   996 			while (aData < srceLimitPtr && TrueColorPointerCompare(aData,component1,component2,component3));
   997 
   998 			TInt pixelLength = (aData - runStartPtr) / 3;
   999 			while (pixelLength > 128)
  1000 				{
  1001 				aStream.WriteInt8L(127);
  1002 				aStream.WriteUint8L(component1);
  1003 				aStream.WriteUint8L(component2);
  1004 				aStream.WriteUint8L(component3);
  1005 				pixelLength -= 128;
  1006 				}
  1007 
  1008 			aStream.WriteInt8L(pixelLength - 1);
  1009 			aStream.WriteUint8L(component1);
  1010 			aStream.WriteUint8L(component2);
  1011 			aStream.WriteUint8L(component3);
  1012 			}
  1013 		else
  1014 			{
  1015 			TBool more  = ETrue;
  1016 			TBool eqRun = EFalse;
  1017 			do
  1018 				{
  1019 				component1 = *aData++;
  1020 				component2 = *aData++;
  1021 				component3 = *aData++;
  1022 				more = (aData < srceLimitPtr);
  1023 				eqRun = more && TrueColorPointerCompare(aData,component1,component2,component3);
  1024 				}
  1025 			while (more && !eqRun);
  1026 			if (eqRun)
  1027 				aData -= 3;
  1028 			TInt pixelLength = (aData - runStartPtr) / 3;
  1029 			while (pixelLength > 128)
  1030 				{
  1031 				aStream.WriteInt8L(-128);
  1032 				aStream.WriteL(runStartPtr,384);
  1033 				runStartPtr += 384;
  1034 				pixelLength -= 128;
  1035 				}
  1036 
  1037 			aStream.WriteInt8L(-pixelLength);
  1038 			aStream.WriteL(runStartPtr,pixelLength * 3);
  1039 			}
  1040 		}
  1041 
  1042 	TInt remainingPixels = srceLimitPtr - aData;
  1043 	if (remainingPixels > 0)
  1044 		{
  1045 		TInt pixelLength = remainingPixels / 3;
  1046 		aStream.WriteInt8L(-pixelLength);
  1047 		aStream.WriteL(aData,remainingPixels);
  1048 		}
  1049 	}
  1050 	
  1051 /** The function externalizes 32-bit buffer with unused top bytes to the 24-bit compressed stream by using RLE compression algorithm*/
  1052 void CBitwiseBitmap::DoExternalizeThirtyTwoUBitDataCompressedL(RWriteStream& aStream,TUint8* aData8,TInt aSizeInBytes) const
  1053 	{
  1054 
  1055 	__ASSERT_DEBUG((reinterpret_cast<TUint32>(aData8) & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is word aligned
  1056 	__ASSERT_DEBUG((aSizeInBytes & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the size is whole no of pixels
  1057 
  1058 	TUint32* ptr = reinterpret_cast<TUint32*>(aData8);
  1059 	TUint32* srceLimitPtr = reinterpret_cast<TUint32*>(aData8 + aSizeInBytes);
  1060 	TUint32* srceLimitPtr2ndLast = srceLimitPtr - 1; 
  1061 
  1062 	while (ptr < srceLimitPtr2ndLast)
  1063 		{
  1064 		TUint32* runStartPtr = ptr;
  1065 		TUint32 pixel = *ptr++ & 0x00ffffff;
  1066 
  1067 		if ( (((*ptr)&0x00ffffff)==pixel) )
  1068 			{
  1069 			do
  1070 				{
  1071 				ptr++;
  1072 				}
  1073 			while (ptr< srceLimitPtr && (((*ptr)&0x00ffffff)==pixel) );
  1074 
  1075 			TInt pixelLength = (ptr - runStartPtr);
  1076 			while (pixelLength > 128)
  1077 				{
  1078 				aStream.WriteInt8L(127);
  1079 				aStream.WriteUint8L(pixel&0x000000ff);
  1080 				aStream.WriteUint8L((pixel>>8)&0x000000ff);
  1081 				aStream.WriteUint8L((pixel>>16)&0x000000ff);
  1082 				pixelLength -= 128;
  1083 				}
  1084 
  1085 			aStream.WriteInt8L(pixelLength - 1);
  1086 			aStream.WriteUint8L(pixel&0x000000ff);
  1087 			aStream.WriteUint8L((pixel>>8)&0x000000ff);
  1088 			aStream.WriteUint8L((pixel>>16)&0x000000ff);
  1089 			}
  1090 		else
  1091 			{
  1092 			TBool more  = ETrue;
  1093 			TBool eqRun = EFalse;
  1094 			do
  1095 				{
  1096 				pixel = *ptr++ & 0x00ffffff;
  1097 				more = (ptr < srceLimitPtr);
  1098 				eqRun = more && (((*ptr)&0x00ffffff)==pixel);
  1099 				} while (more && !eqRun);
  1100 			if (eqRun)
  1101 				ptr--;
  1102 			TInt pixelLength = (ptr - runStartPtr);
  1103 			while (pixelLength > 128)
  1104 				{
  1105 				aStream.WriteInt8L(-128);
  1106 				for(TInt ii = 0; ii < 128; ii++)
  1107 					{
  1108 					aStream.WriteL(reinterpret_cast<TUint8*>(runStartPtr), 3);
  1109 					runStartPtr++;
  1110 					}
  1111 				pixelLength -= 128;
  1112 				}
  1113 
  1114 			aStream.WriteInt8L(-pixelLength);
  1115 			for(TInt kk = 0; kk < pixelLength; kk++)
  1116 				{
  1117 				aStream.WriteL(reinterpret_cast<TUint8*>(runStartPtr), 3);
  1118 				runStartPtr++;
  1119 				}
  1120 			}
  1121 		}
  1122 
  1123 	const TInt remainingPixels = srceLimitPtr - ptr;
  1124 	if (remainingPixels > 0)
  1125 		{
  1126 		__ASSERT_DEBUG(remainingPixels == 1, Panic(EFbsBitmapDecompressionError));
  1127 
  1128 		aStream.WriteInt8L(-remainingPixels);
  1129 		for(TInt ii = 0; ii < remainingPixels; ii++)
  1130 			{
  1131 			aStream.WriteL(reinterpret_cast<TUint8*>(ptr), 3);
  1132 			ptr++;
  1133 			}
  1134 		}
  1135 	}
  1136 
  1137 /** The function externalizes 32-bit buffer with alpha channel in top byte to the 32-bit compressed stream by using RLE compression algorithm*/
  1138 void CBitwiseBitmap::DoExternalizeThirtyTwoABitDataCompressedL(RWriteStream& aStream,TUint8* aData8,TInt aSizeInBytes) const
  1139 	{
  1140 
  1141 	__ASSERT_DEBUG((reinterpret_cast<TUint32>(aData8) & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is word aligned
  1142 	__ASSERT_DEBUG((aSizeInBytes & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the size is whole no of pixels
  1143 
  1144 	TUint32* ptr = reinterpret_cast<TUint32*>(aData8);
  1145 	TUint32* srceLimitPtr = reinterpret_cast<TUint32*>(aData8 + aSizeInBytes);
  1146 	TUint32* srceLimitPtr2ndLast = srceLimitPtr - 1; 
  1147 
  1148 	while (ptr < srceLimitPtr2ndLast)
  1149 		{
  1150 		TUint32* runStartPtr = ptr;
  1151 		TUint32 pixel = *ptr++;
  1152 
  1153 		if (*ptr==pixel)
  1154 			{
  1155 			do
  1156 				{
  1157 				ptr++;
  1158 				}
  1159 			while (ptr < srceLimitPtr && *ptr==pixel);
  1160 
  1161 			TInt pixelLength = (ptr - runStartPtr);
  1162 			while (pixelLength > 128)
  1163 				{
  1164 				aStream.WriteInt8L(127);
  1165 				aStream.WriteUint32L(pixel);
  1166 				pixelLength -= 128;
  1167 				}
  1168 
  1169 			aStream.WriteInt8L(pixelLength - 1);
  1170 			aStream.WriteUint32L(pixel);
  1171 			}
  1172 		else
  1173 			{
  1174 			TBool more  = ETrue;
  1175 			TBool eqRun = EFalse;
  1176 			do
  1177 				{
  1178 				pixel = *ptr++;
  1179 				more = (ptr < srceLimitPtr);
  1180 				eqRun = more && *ptr==pixel;
  1181 				} while (more && !eqRun);
  1182 			
  1183 			if (eqRun)
  1184 				ptr--;
  1185 			
  1186 			TInt pixelLength = (ptr - runStartPtr);
  1187 			while (pixelLength > 128)
  1188 				{
  1189 				aStream.WriteInt8L(-128);
  1190 				aStream.WriteL(reinterpret_cast<TUint8*>(runStartPtr), 128*4);
  1191 				runStartPtr += 128;
  1192 				pixelLength -= 128;
  1193 				}
  1194 
  1195 			aStream.WriteInt8L(-pixelLength);
  1196 			aStream.WriteL(reinterpret_cast<TUint8*>(runStartPtr), pixelLength*4);
  1197 			}
  1198 		}
  1199 
  1200 	const TInt remainingPixels = srceLimitPtr - ptr;
  1201 	if (remainingPixels > 0)
  1202 		{
  1203 		__ASSERT_DEBUG(remainingPixels == 1, Panic(EFbsBitmapDecompressionError));
  1204 
  1205 		aStream.WriteInt8L(-remainingPixels);
  1206 		aStream.WriteL(reinterpret_cast<TUint8*>(ptr), remainingPixels*4);
  1207 		}
  1208 	}
  1209 
  1210 TInt CBitwiseBitmap::SizeOfDataCompressed(TUint8* aData,TInt aSizeInBytes) const
  1211 	{
  1212 	if(aSizeInBytes<=0)
  1213 		return 0;
  1214 
  1215 	switch (iHeader.iBitsPerPixel)
  1216 		{
  1217 	case 1:
  1218 	case 2:
  1219 	case 4:
  1220 	case 8:
  1221 		return SizeOfByteDataCompressed(aData,aSizeInBytes);
  1222 	case 12:
  1223 		return SizeOfTwelveBitDataCompressed(aData,aSizeInBytes);
  1224 	case 16:
  1225 		return SizeOfSixteenBitDataCompressed(aData,aSizeInBytes);
  1226 	case 24:
  1227 		return SizeOfTwentyFourBitDataCompressed(aData,aSizeInBytes);
  1228 	case 32:
  1229 		__ASSERT_DEBUG(iHeader.iColor == SEpocBitmapHeader::EColor||
  1230 						iHeader.iColor == SEpocBitmapHeader::EColorAlpha||
  1231 						iHeader.iColor == SEpocBitmapHeader::EColorAlphaPM,
  1232 						Panic(EFbsBitmapInvalidCompression));
  1233 		if(iHeader.iColor == SEpocBitmapHeader::EColor)
  1234 			{
  1235 			return SizeOfThirtyTwoUBitDataCompressed(aData,aSizeInBytes);
  1236 			}
  1237 		else
  1238 			{
  1239 			return SizeOfThirtyTwoABitDataCompressed(aData,aSizeInBytes);
  1240 			}
  1241 	default:
  1242 		break;
  1243 		}
  1244 
  1245 	return 0;
  1246 	}
  1247 
  1248 TInt CBitwiseBitmap::SizeOfByteDataCompressed(TUint8* aData,TInt aSizeInBytes) const
  1249 	{
  1250 	if(aSizeInBytes<=0)
  1251 		return 0;
  1252 
  1253 	TInt compressedSize=0;
  1254 	TUint8* dataLimit=aData+aSizeInBytes-2;
  1255 	
  1256 	while(aData<dataLimit)
  1257 		{
  1258 		TUint8 value=*aData;
  1259 		if (*(aData+1)==value && *(aData+2)==value)
  1260 			{
  1261 			TUint8* runStartPtr=aData;
  1262 			aData+=3;
  1263 			while(aData<dataLimit && *aData==value)
  1264 				aData++;
  1265 			TInt runLength=aData-runStartPtr;
  1266 
  1267 			compressedSize+= 2*(((runLength-1)>>7) + 1) ;
  1268 			}
  1269 		else
  1270 			{
  1271 			TUint8* runStartPtr=aData;
  1272 			while(aData<dataLimit && (*(aData+1)!=value || *(aData+2)!=value))
  1273 				{
  1274 				aData++;
  1275 				value=*aData;
  1276 				}
  1277 			TInt runLength=aData-runStartPtr;
  1278 			
  1279 			compressedSize+= runLength + ((runLength-1)>>7) + 1;
  1280 			}
  1281 		}
  1282 	dataLimit+=2;
  1283 	if (aData<dataLimit)
  1284 		compressedSize+=dataLimit-aData+1;
  1285 	return(compressedSize);
  1286 	}
  1287 
  1288 TInt CBitwiseBitmap::SizeOfTwelveBitDataCompressed(TUint8* aData,TInt aSizeInBytes) const
  1289 	{
  1290 	if(aSizeInBytes<=0)
  1291 		return 0;
  1292 
  1293 	TInt compressedSize = 0;
  1294 	TUint16* srcePtr = (TUint16*)aData;
  1295 	TUint16* srcePtrLimit = srcePtr + (aSizeInBytes / 2);
  1296 
  1297 	while (srcePtr < srcePtrLimit)
  1298 		{
  1299 		TUint16* runStartPtr = srcePtr;
  1300 		TUint16 value = TUint16(*srcePtr & 0x0fff);
  1301 		do
  1302 			{
  1303 			srcePtr++;
  1304 			}
  1305 		while (srcePtr < srcePtrLimit && *srcePtr == value);
  1306 
  1307 		TInt pixelLength = srcePtr - runStartPtr;
  1308 
  1309 		compressedSize += 2*( ((pixelLength-1)>>4) + 1);
  1310 		}
  1311 	return compressedSize;
  1312 	}
  1313 
  1314 TInt CBitwiseBitmap::SizeOfSixteenBitDataCompressed(TUint8* aData,TInt aSizeInBytes) const
  1315 	{
  1316 	if(aSizeInBytes<=0)
  1317 		return 0;
  1318 
  1319 	TInt compressedSize = 0;
  1320 	TUint16* srcePtr = (TUint16*)aData;
  1321 	TUint16* srceLimitPtr = srcePtr + (aSizeInBytes / 2);
  1322 	TUint16* srceLimitPtrMinusOne = srceLimitPtr - 1;
  1323 
  1324 	while (srcePtr < srceLimitPtrMinusOne)
  1325 		{
  1326 		TUint16 value = *srcePtr;
  1327 		TUint16* runStartPtr = srcePtr++;
  1328 
  1329 		if(*srcePtr == value)
  1330 			{
  1331 			do
  1332 				{
  1333 				srcePtr++;
  1334 				}
  1335 			while(srcePtr < srceLimitPtr && *srcePtr == value);
  1336 
  1337 			TInt pixelLength = srcePtr-runStartPtr;
  1338 
  1339 			compressedSize += 3*( ((pixelLength-1)>>7) + 1);
  1340 			}
  1341 		else
  1342 			{
  1343 			value = *srcePtr;
  1344 			while (srcePtr < srceLimitPtrMinusOne && *(srcePtr + 1) != value)
  1345 				{
  1346 				srcePtr++;
  1347 				value = *srcePtr;
  1348 				}
  1349 
  1350 			TInt pixelLength = srcePtr-runStartPtr;
  1351 
  1352 			compressedSize += (pixelLength * 2) + ((pixelLength-1)>>7) + 1;
  1353 			}
  1354 		}
  1355 	if (srcePtr < srceLimitPtr)
  1356 		compressedSize += ((srceLimitPtr - srcePtr) * 2) + 1;
  1357 	return compressedSize;
  1358 	}
  1359 
  1360 TInt CBitwiseBitmap::SizeOfTwentyFourBitDataCompressed(TUint8* aData,TInt aSizeInBytes) const
  1361 	{
  1362 	if(aSizeInBytes<=0)
  1363 		return 0;
  1364 
  1365 	TInt compressedSize = 0;
  1366 	TUint8* srceLimitPtr = aData + aSizeInBytes;
  1367 	TUint8* srceLimitPtrMinusThree = srceLimitPtr - 3; // three bytes == one pixel
  1368 
  1369 	while (aData < srceLimitPtrMinusThree)
  1370 		{
  1371 		TUint8* runStartPtr = aData;
  1372 		TUint8 component1 = *aData++;
  1373 		TUint8 component2 = *aData++;
  1374 		TUint8 component3 = *aData++;
  1375 
  1376 		if (TrueColorPointerCompare(aData,component1,component2,component3))
  1377 			{
  1378 			do
  1379 				{
  1380 				aData += 3;
  1381 				}
  1382 			while (aData < srceLimitPtr && TrueColorPointerCompare(aData,component1,component2,component3));
  1383 
  1384 			TInt pixelLength = (aData - runStartPtr) / 3;
  1385 			
  1386 			compressedSize += 4*( ((pixelLength-1)>>7) + 1); 
  1387 			}
  1388 		else
  1389 			{
  1390 			TBool more  = ETrue;
  1391 			TBool eqRun = EFalse;
  1392 			do
  1393 				{
  1394 				component1 = *aData++;
  1395 				component2 = *aData++;
  1396 				component3 = *aData++;
  1397 				more = (aData < srceLimitPtr);
  1398 				eqRun = more && TrueColorPointerCompare(aData,component1,component2,component3);
  1399 				}
  1400 			while (more && !eqRun);
  1401 			if (eqRun)
  1402 				aData -= 3;
  1403 			TInt pixelLength = (aData - runStartPtr) / 3;
  1404 
  1405 			compressedSize += (pixelLength * 3) + ((pixelLength-1)>>7) + 1;
  1406 			}
  1407 		}
  1408 	
  1409 	if (aData < srceLimitPtr)
  1410 		compressedSize += srceLimitPtr - aData + 1;
  1411 
  1412 	return compressedSize;
  1413 	}
  1414 
  1415 /** The function calculates the size of 24-bit RLE compression stream which could be obtain from given 32-bit buffer, 
  1416 	where the top bytes are unused*/
  1417 TInt CBitwiseBitmap::SizeOfThirtyTwoUBitDataCompressed(TUint8* aData8,TInt aSizeInBytes) const
  1418 	{
  1419 	if(aSizeInBytes<=0)
  1420 		return 0;
  1421 
  1422 	__ASSERT_DEBUG((reinterpret_cast<TUint32>(aData8) & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is word aligned
  1423 	__ASSERT_DEBUG((aSizeInBytes & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the size is whole no of pixels
  1424 
  1425 
  1426 	TInt compressedSize = 0;
  1427 	
  1428 	
  1429 	TUint32* ptr = reinterpret_cast<TUint32*>(aData8);
  1430 	TUint32* srceLimitPtr = reinterpret_cast<TUint32*>(aData8 + aSizeInBytes);
  1431 	TUint32* srceLimitPtr2ndLast = srceLimitPtr - 1; 
  1432 	while (ptr < srceLimitPtr2ndLast)
  1433 		{
  1434 		TUint32* runStartPtr = ptr;
  1435 		TUint32 pixel = *ptr++ & 0x00ffffff;
  1436 
  1437 		if ((((*ptr)&0x00ffffff)==pixel))
  1438 			{
  1439 			do
  1440 				{
  1441 				ptr++;
  1442 				}
  1443 			while (ptr < srceLimitPtr && (((*ptr)&0x00ffffff)==pixel));
  1444 
  1445 			TInt pixelLength = (ptr - runStartPtr);
  1446 			compressedSize += 4*( ((pixelLength-1)>>7) + 1); 
  1447 			}	
  1448 		else
  1449 			{
  1450 			TBool more  = ETrue;
  1451 			TBool eqRun = EFalse;
  1452 			do
  1453 				{
  1454 				pixel = *ptr++ & 0x00ffffff;
  1455 				more = (ptr < srceLimitPtr);
  1456 				eqRun = more && (((*ptr)&0x00ffffff)==pixel);
  1457 				} while (more && !eqRun);
  1458 
  1459 			if (eqRun)
  1460 				ptr--;
  1461 
  1462 			TInt pixelLength = (ptr - runStartPtr) ;
  1463 			compressedSize += 3*pixelLength + ((pixelLength-1)>>7) + 1; 
  1464 			}
  1465 		}
  1466 
  1467 	if (ptr < srceLimitPtr)
  1468 		compressedSize += (srceLimitPtr - ptr)*3 + 1;
  1469 
  1470 	return compressedSize;
  1471 	}
  1472 
  1473 
  1474 TBool CBitwiseBitmap::TrueColorPointerCompare(TUint8* aColorPointer,TUint8 aComponent1,TUint8 aComponent2,TUint8 aComponent3) const
  1475 	{
  1476 	return (*aColorPointer == aComponent1 && *(aColorPointer + 1) == aComponent2 && *(aColorPointer + 2) == aComponent3);
  1477 	}
  1478 
  1479 /** This function calculates the size of 32-bit RLE compression stream which is obtained from a given 32-bit buffer, 
  1480 	where the top 8 bits are used to represent the alpha channel*/
  1481 TInt CBitwiseBitmap::SizeOfThirtyTwoABitDataCompressed(TUint8* aData8,TInt aSizeInBytes) const
  1482 	{
  1483 	if(aSizeInBytes<=0)
  1484 		return 0;
  1485 
  1486 	__ASSERT_DEBUG((reinterpret_cast<TUint32>(aData8) & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is word aligned
  1487 	__ASSERT_DEBUG((aSizeInBytes & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the size is whole no of pixels
  1488 
  1489 
  1490 	TInt compressedSize = 0;
  1491 	
  1492 	
  1493 	TUint32* ptr = reinterpret_cast<TUint32*>(aData8);
  1494 	TUint32* srceLimitPtr = reinterpret_cast<TUint32*>(aData8 + aSizeInBytes);
  1495 	TUint32* srceLimitPtr2ndLast = srceLimitPtr - 1; 
  1496 	while (ptr < srceLimitPtr2ndLast)
  1497 		{
  1498 		TUint32* runStartPtr = ptr;
  1499 		TUint32 pixel = *ptr++;
  1500 
  1501 		if (*ptr==pixel)
  1502 			{
  1503 			do
  1504 				{
  1505 				ptr++;
  1506 				}
  1507 			while (ptr < srceLimitPtr && *ptr==pixel);
  1508 
  1509 			TInt pixelLength = (ptr - runStartPtr);
  1510 			compressedSize += 5*( ((pixelLength-1)>>7) + 1); 
  1511 			}	
  1512 		else
  1513 			{
  1514 			TBool more  = ETrue;
  1515 			TBool eqRun = EFalse;
  1516 			do
  1517 				{
  1518 				pixel = *ptr++;
  1519 				more = (ptr < srceLimitPtr);
  1520 				eqRun = more && *ptr==pixel;
  1521 				} while (more && !eqRun);
  1522 
  1523 			if (eqRun)
  1524 				ptr--;
  1525 
  1526 			TInt pixelLength = (ptr - runStartPtr) ;
  1527 			compressedSize += 4*pixelLength + ((pixelLength-1)>>7) + 1; 
  1528 			}
  1529 		}
  1530 
  1531 	if (ptr < srceLimitPtr)
  1532 		compressedSize += (srceLimitPtr - ptr)*4 + 1;
  1533 
  1534 	return compressedSize;
  1535 	}
  1536 
  1537 
  1538 /*	Here's a BNF description of the RLE encoding in use for all but the 12-bit compression:
  1539 
  1540 	encoding := run*
  1541 	run := equal-run | unequal-run
  1542 	equal-run := <runlength - 1> pixel-value
  1543 	unequal-run := <-runlength> pixel-value+    (i.e. pixel-value repeated <runlength> times)
  1544 	runlength := uint8 in 1..128
  1545 	pixelvalue := byte-pixel | 16bit-pixel | 24bit-pixel | 32bit-u-pixel | 32bit-a-pixel
  1546 	byte-pixel := octet
  1547 	16bit-pixel := octet octet
  1548 	24bit-pixel := rr gg bb
  1549 	32bit-u-pixel := rr gg bb
  1550 	32bit-a-pixel := rr gg bb aa
  1551 	rr := octet  (red component)
  1552 	gg := octet  (green component)
  1553 	bb := octet  (blue component)
  1554 	aa := octet  (alpha channel)
  1555 
  1556 	This scheme models runs of 2-128 equal pixels or of upto 127 unequal pixels.
  1557 	Obviously a run of 0 is meaningless.  A run of 1 is considered to be an 'unequal' run containing
  1558 	a single pixel.
  1559 
  1560 	For 12-bit compression a different encoding scheme is used. Only equal-runs are written, and the
  1561 	run	length is encoded into the top 4 bits of a 16 bit word.  Here's a BNF for 12-bit compression:
  1562 	
  1563 	12-bit-encoding := run*
  1564 	run := equal-run
  1565 	equal-run := high-octet low-octet
  1566 	high-octet := [<runlength - 1> rr]
  1567 	low-octet := [gg bb]
  1568 	runlength := 1..16
  1569 	rr := quartet  (red component)
  1570 	gg := quartet  (green component)
  1571 	bb := quartet  (blue component)
  1572 
  1573 */
  1574 
  1575 //Palette compression additions
  1576 
  1577 /**
  1578 Attempts to compress a bitmap by reducing it to a palette + data.
  1579 If the compression fails, for any of the reasons detailed below, RLE compression will be attempted instead.
  1580 Prerequisites:
  1581 - Bitmap must not already be compressed.
  1582 - Bitmap must contain no more than 255 colors - If bitmap contains >255 colors then palette compression is unlikely to be effective.
  1583 - Bitmap must be 16, 24 or 32 (non alpha) bpp.  Other modes could be implemented, but smaller bit depths will yield less compression
  1584 Small bitmaps (under 1000 pixels) will be unlikely to compress well if at all
  1585 Structure of compressed bitmap will be as follows;
  1586 size of palette[4 bytes] | palette[size * 4 bytes per entry] | data[pixels * upto 1 byte per pixel]
  1587 Bitmap data is packed into memory as efficiently as possible, according to the number of bits required.
  1588 Each line of the compressed bitmap will start on a byte boundary, but not necessarily on a word boundary.
  1589 */
  1590 TInt CBitwiseBitmap::PaletteCompress()
  1591 	{
  1592 	//Compression algorithm
  1593 	//1.Iterate bitmap data, building hash of unique colours found
  1594 	//2.Iterate the hash, and build linear array of the unique colours (this is the palette)
  1595 	//3.Iterate the array, and set the array index of each colour back into the hash
  1596 	//4.Iterate the bitmap data again, for each pixel replace with palette index found from hash
  1597 	
  1598 	//Bitmap must be uncompressed
  1599 	if (iHeader.iCompression != ENoBitmapCompression)
  1600 		return KErrNone;
  1601 	
  1602 	//There must be some data in the bitmap
  1603 	TUint8* base = REINTERPRET_CAST(TUint8*, DataAddress());
  1604 	if (!base)
  1605 		return KErrNone;
  1606 	
  1607 	//Get the bytes per pixel, and make sure it is a supported configuration
  1608 	TUint sourceBytesPerPixel = PaletteBytesPerPixel(iHeader.iBitsPerPixel);
  1609 	if (sourceBytesPerPixel == 0)
  1610 		return KErrNotSupported;
  1611 	
  1612 	//Create a hash table and give it a decent amount of RAM to start with
  1613 	RHashMap<TInt,TInt> colors;
  1614 	if (colors.Reserve(256) != KErrNone)
  1615 		return KErrNoMemory;
  1616 
  1617 	//Loop the data area of the bitmap, one pixel (sourceBytesPerPixel bytes) at a time
  1618 	TInt numPixels = (iHeader.iSizeInPixels.iWidth * iHeader.iSizeInPixels.iHeight);
  1619 	//we need some pixels!
  1620 	if (numPixels == 0)
  1621 		{
  1622 		colors.Close();
  1623 		return KErrNone;
  1624 		}
  1625 	
  1626 	TUint8* top = base + (iHeader.iSizeInPixels.iHeight * iByteWidth) ; //address of lastmost byte
  1627 	TInt32 lineLengthInBytes = iHeader.iSizeInPixels.iWidth * sourceBytesPerPixel;  //The actual useful data on each line
  1628 	TInt32 lineLengthInBytesPadded = iByteWidth ; //the actual (aligned) length of each line
  1629 	TUint8* pixelAddress;
  1630 	TUint8* lineAddress;
  1631 	//Loop each line of the bitmap data.  Note that each line ends on a 32bit align in the source MBM data.
  1632 	TUint8* lineEnd=0;
  1633 
  1634 	//Separate looping for 16 & 24+ bpp.  Adds a chunk of duplicated code but saves checking bpp for  every pixel
  1635 	if (iHeader.iBitsPerPixel < 24)
  1636 		{
  1637 		for (lineAddress=base;lineAddress<top;lineAddress+=iByteWidth)
  1638 			{
  1639 			//Loop each pixel within the line
  1640 			lineEnd = lineAddress + lineLengthInBytes;
  1641 			for (pixelAddress = lineAddress; pixelAddress < lineEnd; pixelAddress += sourceBytesPerPixel)
  1642 				{
  1643 				//Extract colour value
  1644 				TUint color = *pixelAddress;
  1645 				color |= (*(pixelAddress+1)) << 8;
  1646 				//Insert colour value into hash
  1647 				//Quicker to use Find() to eliminate duplicates Insert()
  1648 				if (colors.Find(color) == NULL)
  1649 					{
  1650 					if (colors.Insert(color,0) != KErrNone)
  1651 						{
  1652 						colors.Close();
  1653 						return KErrNoMemory;
  1654 						}
  1655 					}
  1656 				}
  1657 			//Test each line whether it's worth continuing to the end	
  1658 			//We aren't interested if there's more than 256 colours (RLE compression will probably do a better job in this case)
  1659 			if (colors.Count() > 256)
  1660 				{
  1661 				colors.Close();
  1662 				return KErrNotSupported ;
  1663 				}
  1664 			}
  1665 		}
  1666 	else //>=24 bpp
  1667 		{
  1668 		for (lineAddress = base; lineAddress<top; lineAddress += iByteWidth)
  1669 			{
  1670 			//Loop each pixel within the line
  1671 			lineEnd = lineAddress + lineLengthInBytes;
  1672 			for (pixelAddress = lineAddress; pixelAddress < lineEnd; pixelAddress += sourceBytesPerPixel)
  1673 				{
  1674 				//Extract colour value
  1675 				TUint color = *pixelAddress;
  1676 				color |= (*(pixelAddress+1)) << 8;
  1677 				color |= (*(pixelAddress+2)) << 16;
  1678 				//Insert colour value into hash
  1679 				//Quicker to use Find() to eliminate duplicates Insert()
  1680 
  1681 				if (colors.Find(color) == NULL)
  1682 					{
  1683 					if (colors.Insert(color,0) != KErrNone)
  1684 						{
  1685 						colors.Close();
  1686 						return KErrNoMemory;
  1687 						}
  1688 					}
  1689 				}
  1690 			//Test each line whether it's worth continuing to the end
  1691 			//We aren't interested if there's more than 256 colours (RLE compression will probably do a better job in this case)
  1692 			if (colors.Count() > 256)
  1693 				{
  1694 				colors.Close();
  1695 				return KErrNotSupported;
  1696 				}
  1697 			} //for
  1698 		}//end if
  1699 	
  1700 	
  1701 	//Now we have enough data to build the palette by iterating all the entries in the colors hash
  1702 	RArray<TUint> palette(colors.Count());
  1703 	THashMapIter<TInt,TInt> colorIterator(colors);
  1704 	const TInt* color = colorIterator.NextKey();
  1705 	while (color)
  1706 		{
  1707 		if (palette.Append(*color) != KErrNone)
  1708 			{
  1709 			palette.Close();
  1710 			colors.Close();
  1711 			return KErrNoMemory;
  1712 			}
  1713 		//set the index of each entry back into the color hash for lookup later
  1714 		//const cast needed as CurrentValue returns a const pointer; for no good reason?
  1715 		TInt* index = CONST_CAST(TInt*, colorIterator.CurrentValue());
  1716 		*index = palette.Count() - 1;
  1717 		color = colorIterator.NextKey();
  1718 		}
  1719 		
  1720 	//Set up some new memory for the palettised bitmap
  1721 	//size is (4 bytes for palette size) + (4 bytes per palette entry) + (upto 1 byte per pixel)
  1722 	//pixels are packed according to number of colors
  1723 	TUint compressedBitsPerPixel = PaletteBitsPerPixel(colors.Count());
  1724 	TUint compressedPixelsPerByte = 8 / compressedBitsPerPixel;
  1725 	TUint compressedLineLengthInBytesPadded = (iHeader.iSizeInPixels.iWidth + compressedPixelsPerByte - 1)/ compressedPixelsPerByte;
  1726 	TInt compressedDataBytes = 4 + 4 * colors.Count() + compressedLineLengthInBytesPadded * iHeader.iSizeInPixels.iHeight;
  1727 
  1728 	//add two extra ints for storing function pointers (8 bytes )
  1729 	compressedDataBytes += 8 ;
  1730 	
  1731 	TUint8* compressedBase = NULL;
  1732 	compressedBase = iPile->Alloc(compressedDataBytes);
  1733 	if (!compressedBase)
  1734 		{
  1735 		palette.Close();
  1736 		colors.Close();
  1737 		return KErrNoMemory;
  1738 		}
  1739 	iDataOffset = compressedBase - iPile->ChunkBase();
  1740 
  1741 	iHeader.iBitmapSize = sizeof(SEpocBitmapHeader) + compressedDataBytes;
  1742 	iHeader.iCompression = EGenericPaletteCompression;
  1743 	
  1744 	//copy the palette length into the data area...
  1745 	*(REINTERPRET_CAST(TInt*, compressedBase)) = palette.Count(); //let's hope we're 4 byte aligned...
  1746 	compressedBase+=4;
  1747 	//...then the palette itself...
  1748 	for (TUint loop = 0; loop < palette.Count(); loop++)
  1749 		{
  1750 		*(REINTERPRET_CAST(TInt*, compressedBase)) = palette[loop];
  1751 		compressedBase +=4;
  1752 		}
  1753 		
  1754 	//Work out, then store, the decoding functions required for packing density and colour depth.
  1755 	//This saves having to do it for every scanline during decompression.
  1756 
  1757 	TDecodeFunction decodeFunction = NULL;
  1758 	switch (compressedPixelsPerByte)
  1759 		{
  1760 		case 1:
  1761 			decodeFunction=CBitwiseBitmap::PaletteDecode1PixelPerByte;
  1762 			break;			
  1763 		case 2:
  1764 			decodeFunction=CBitwiseBitmap::PaletteDecode2PixelPerByte;
  1765 			break;			
  1766 		case 4:
  1767 			decodeFunction=CBitwiseBitmap::PaletteDecode4PixelPerByte;
  1768 			break;
  1769 		case 8:
  1770 			decodeFunction=CBitwiseBitmap::PaletteDecode8PixelPerByte;
  1771 			break;			
  1772 		default:
  1773 			::Panic(EFbsNotSupportedForCompression);
  1774 		}
  1775 	*(REINTERPRET_CAST(TDecodeFunction*, compressedBase))  = decodeFunction ;
  1776 	compressedBase += 4 ;
  1777 
  1778 	//Select the appropriate assignment function based on the bits-per-pixel of the target
  1779 	TAssignFunction assignFunction = NULL;
  1780 	switch (iHeader.iBitsPerPixel)
  1781 		{
  1782 		case 16:
  1783 			assignFunction=CBitwiseBitmap::PaletteAssign16BitColor;
  1784 			break;
  1785 		case 24:
  1786 			assignFunction=CBitwiseBitmap::PaletteAssign24BitColor;
  1787 			break;
  1788 		case 32:
  1789 			assignFunction=CBitwiseBitmap::PaletteAssign32BitColor;
  1790 			break;
  1791 		default:
  1792 			::Panic(EFbsNotSupportedForCompression);
  1793 		}
  1794 	*(REINTERPRET_CAST(TAssignFunction*, compressedBase)) = assignFunction ;
  1795 	compressedBase += 4 ;
  1796 		
  1797  	//...and finally the data
  1798 	pixelAddress = base;
  1799 
  1800 	//separate loops for 16 & 24+ bpp again
  1801 
  1802 	if ( iHeader.iBitsPerPixel < 24 )
  1803 		{
  1804 		for (lineAddress = base; lineAddress < top; lineAddress += lineLengthInBytesPadded)
  1805 			{
  1806 			//Loop each pixel within the line
  1807 			pixelAddress = lineAddress;
  1808 			while (pixelAddress < lineAddress + lineLengthInBytes)
  1809 				{
  1810 				TUint8 pack = 0;
  1811 				//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
  1812 				for (TInt ii = 0; ii < compressedPixelsPerByte && pixelAddress < lineAddress + lineLengthInBytes; ii++)
  1813 					{
  1814 					pack <<= compressedBitsPerPixel;
  1815 					//extract the color
  1816 					TUint color = *pixelAddress;
  1817 					color |= (*(pixelAddress+1)) << 8;
  1818 					
  1819 					//lookup the palette index for the color
  1820 					TInt* paletteIndex = colors.Find(color);
  1821 					//pack the palette index into the target byte
  1822 					pack |= *paletteIndex;
  1823 					//next pixel
  1824 					pixelAddress += sourceBytesPerPixel;
  1825 					}
  1826 				//store the packed pixel data into the new compressed data area
  1827 				*compressedBase = pack;
  1828 				compressedBase++;				
  1829 				}
  1830 			}
  1831 		}
  1832 	else //>= 24bpp
  1833 		{
  1834 		for (lineAddress = base; lineAddress < top; lineAddress += lineLengthInBytesPadded)
  1835 			{
  1836 			//Loop each pixel within the line
  1837 			pixelAddress = lineAddress;
  1838 			while (pixelAddress < lineAddress + lineLengthInBytes)
  1839 				{
  1840 				TUint8 pack = 0;
  1841 				//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
  1842 				for (TInt ii = 0; ii < compressedPixelsPerByte && pixelAddress < lineAddress + lineLengthInBytes; ii++)
  1843 					{
  1844 					pack <<= compressedBitsPerPixel;
  1845 					//extract the color
  1846 				TUint color = *pixelAddress;
  1847 					color |= (*(pixelAddress+1)) << 8;
  1848 					color |= (*(pixelAddress+2)) << 16;
  1849 					//if 32 bit, just ignore the 4th byte as it is unused for color data
  1850 
  1851 					//lookup the palette index for the color
  1852 					TInt* paletteIndex = colors.Find(color);
  1853 					//pack the palette index into the target byte
  1854 					pack |= *paletteIndex;
  1855 					//next pixel
  1856 					pixelAddress += sourceBytesPerPixel;
  1857 					}
  1858 				//store the packed pixel data into the new compressed data area
  1859 				*compressedBase = pack;
  1860 				compressedBase++;				
  1861 				}
  1862 			}
  1863 		}//if
  1864 
  1865 
  1866 	//Set the RAM compression flag
  1867 	iIsCompressedInRAM = ETrue;
  1868 
  1869 	//Free the old data.
  1870 	iPile->Free(base);
  1871 	//Clean up	
  1872 	palette.Close();
  1873 	colors.Close();
  1874 	return KErrNone;
  1875 	}
  1876 	
  1877 /**
  1878 Create a scan line from a palette compressed bitmap.
  1879 Starting from aPixel in the bitmap pointed to be aBase, populate aDestBuffer with aLength pixels looked up in the palette.
  1880 Note this function assumes 16, 24 or 32 non alpha bit uncompressed bitmaps, compressed into 8 bit palettes (ie <256 colors)
  1881 Structure of bitmap is (4 bytes for palette size) + (4 bytes per palette entry) + (1 byte per pixel)
  1882 @param aDestBuffer Points to the destination buffer. After the call it will be filled
  1883 with the decompressed data.
  1884 @param aPixel The decompression starts from this pixel
  1885 @param aLength Length of requested decompressed data - in pixels
  1886 @param aBase Points to the beginning of compressed bitmap data
  1887 @param aLineScannngPosition Saved information about the last used position in the compressed data
  1888 */
  1889 void CBitwiseBitmap::GenerateLineFromPaletteCompressedData(
  1890 									 TUint8* aDestBuffer, 
  1891 									 const TPoint& aPixel,
  1892 									 TInt aLength, 
  1893 									 TUint32* aBase, 
  1894 									 TLineScanningPosition& /*aLineScanningPosition*/) const
  1895 	{
  1896 	//At entry, aBase will point to the start of the compressed data, ie the palette size
  1897 	//Each line in the bitmap will start at a byte boundary in the compressed data.
  1898 	
  1899 	TUint32* srcPalette = aBase + 1; //Address of the palette in the source data
  1900 	TUint srcNumPaletteEntries = *aBase;	//Number of entries in the palette (will be <=255)
  1901 	TUint compressedBitsPerPixel = PaletteBitsPerPixel(srcNumPaletteEntries);
  1902 	__ASSERT_DEBUG(compressedBitsPerPixel <= 8, Panic( EFbsBitmapDecompressionError )) ;
  1903 	const TUint8 lookup[] = {0, 8, 4, 0, 2, 0, 0, 0, 1};
  1904 	//TUint compressedPixelsPerByte = 8 / compressedBitsPerPixel;
  1905 	TUint compressedPixelsPerByte = lookup[compressedBitsPerPixel];
  1906 	__ASSERT_DEBUG(compressedPixelsPerByte>0, ::Panic(EFbsNotSupportedForCompression));	
  1907 
  1908 	TUint8* srcData = REINTERPRET_CAST(TUint8*, srcPalette + srcNumPaletteEntries);	//Address of the pixel data in the source data
  1909 
  1910 	//Extract the function pointers for decoding functions. Set up decode & assign functions.
  1911 	TDecodeFunction decodeFunction = NULL ;
  1912 	decodeFunction = reinterpret_cast<TDecodeFunction>(*((TUint32*)srcData )) ;
  1913 	srcData += 4 ;
  1914 	TAssignFunction assignFunction = NULL;
  1915 	assignFunction = reinterpret_cast<TAssignFunction>(*((TUint32*)srcData )) ;
  1916 	srcData += 4 ;
  1917 
  1918 	//Note: The following lines have been optimised to avoid divisions.
  1919 	//By way of explanation the original lines have been left as comments
  1920 
  1921 	//TUint srcBytesPerLinePadded = (iHeader.iSizeInPixels.iWidth + compressedPixelsPerByte - 1) / compressedPixelsPerByte;	//number of bytes occupied by each line in the compressed bitmap.
  1922 	TUint srcBytesPerLinePadded = ((iHeader.iSizeInPixels.iWidth + compressedPixelsPerByte - 1)  * compressedBitsPerPixel) >> 3;	//number of bytes occupied by each line in the compressed bitmap.
  1923 	//TUint srcStartBytesFromBase = aPixel.iY * srcBytesPerLinePadded + aPixel.iX / compressedPixelsPerByte;	//Starting bytes from the start of the bitmap
  1924 	TUint srcStartBytesFromBase = aPixel.iY * srcBytesPerLinePadded + ((aPixel.iX * compressedBitsPerPixel) >> 3);	//Starting bytes from the start of the bitmap
  1925 	//TUint srcStartPixelInByte = aPixel.iX  % compressedPixelsPerByte;		//starting pixel position in byte (lines start on byte boundary)
  1926 	TUint srcStartPixelInByte = aPixel.iX & ((compressedPixelsPerByte)- 1);		//starting pixel position in byte (lines start on byte boundary)
  1927 	//TUint srcEndBytesFromBase = srcStartBytesFromBase + (aLength + compressedPixelsPerByte - 1) / compressedPixelsPerByte;		//Ending bytes from the start of the bitmap
  1928 	TUint srcEndBytesFromBase = srcStartBytesFromBase + (((aLength + compressedPixelsPerByte - 1) * compressedBitsPerPixel) >> 3);		//Ending bytes from the start of the bitmap
  1929 	//TUint srcEndPixelInByte = (aPixel.iX + aLength) % compressedPixelsPerByte;		//Ending pixel position in byte
  1930 	TUint srcEndPixelInByte = (aPixel.iX + aLength) & ((compressedPixelsPerByte)-1);		//Ending pixel position in byte
  1931 	TUint8* srcStartData = srcData + srcStartBytesFromBase;	//Address of the first byte of packed pixels in the source
  1932 	TUint8* srcEndData = srcData + srcEndBytesFromBase;	//Address of the last+1 byte of packed pixels in the source
  1933 	TUint8* destStartData = aDestBuffer + ((aPixel.iX*iHeader.iBitsPerPixel) >> 3); //Address of the first pixel in the destination
  1934 	
  1935 	//3 stages to the decompression:
  1936 	//1. Decompress any pixels which are a subset of the first byte
  1937 	//2. Loop whole bytes extracting all pixels at once
  1938 	//3. Decompress any pixels which are a subset of the last byte
  1939 
  1940 	TUint8* srcDataPtr = srcStartData;
  1941 	
  1942 	//Stage 1: Decompress any pixels which are a subset of the first byte
  1943 	if (srcStartPixelInByte > 0)
  1944 		PaletteDecodeAndAssignGeneric(srcDataPtr++, srcPalette, destStartData, srcStartPixelInByte, compressedPixelsPerByte-1, compressedPixelsPerByte, compressedBitsPerPixel);
  1945 
  1946 	//If the last byte is only partly packed with pixels from this line, stop one byte short in the main loop
  1947 	if (srcEndPixelInByte > 0)
  1948 		srcEndData--;
  1949 	
  1950 	//Stage 2: Loop all the required pixels and call the appropriate functions		
  1951 	while (srcDataPtr < srcEndData)
  1952 		{
  1953 		__ASSERT_DEBUG(srcDataPtr <= srcEndData, ::Panic(EFbsNotSupportedForCompression));	
  1954 		__ASSERT_DEBUG(destStartData <= aDestBuffer + ((aPixel.iX*iHeader.iBitsPerPixel) >> 3) + aLength * PaletteBytesPerPixel(iHeader.iBitsPerPixel), ::Panic(EFbsNotSupportedForCompression));	
  1955 		(*decodeFunction)(srcDataPtr++, srcPalette, destStartData, assignFunction);
  1956 		}
  1957 	
  1958 	//Stage 3: Decompress any pixels which are a subset of the last byte
  1959 	if (srcEndPixelInByte > 0)
  1960 		PaletteDecodeAndAssignGeneric(srcDataPtr++, srcPalette, destStartData, 0, srcEndPixelInByte-1, compressedPixelsPerByte, compressedBitsPerPixel);
  1961 	}
  1962 
  1963 /** 
  1964 This function deals with all different bit depths & color counts dynamically - smaller but slower
  1965 @param aDataPtr Address in compressed data to read from
  1966 @param aPalettePtr Address of the start of the palette in the compressed data
  1967 @param aDestPtr Address to write uncompressed data to.  Will be incremented on return from function.
  1968 @param aStartPixel Zero based position within the compressed byte of the first pixel to decompress
  1969 @param aEndPixel Zero based position within the compressed byte of the last pixel to decompress
  1970 @param aCompressedPixelsPerByte Number of pixels packed into each byte of the compressed data
  1971 @param aCompressedBitsPerPixel Number of bits used to express each pixel in the compressed data.  Nothing to do with the color depth of the image.  
  1972 */
  1973 void CBitwiseBitmap::PaletteDecodeAndAssignGeneric(	TUint8* aDataPtr, 
  1974 												TUint32* aPalettePtr, 
  1975 												TUint8*& aDestPtr,
  1976 												TUint aStartPixel, 
  1977 												TUint aEndPixel, 
  1978 												TUint aCompressedPixelsPerByte,
  1979 												TUint aCompressedBitsPerPixel) const
  1980 	{
  1981 	__ASSERT_DEBUG(aStartPixel<aCompressedPixelsPerByte, ::Panic(EFbsNotSupportedForCompression));
  1982 	__ASSERT_DEBUG(aEndPixel<aCompressedPixelsPerByte, ::Panic(EFbsNotSupportedForCompression));
  1983 
  1984 	//create a mask for the appropriate number of bits
  1985 	TUint8 mask = 0xFF;
  1986 	mask <<= 8 - aCompressedBitsPerPixel;
  1987 
  1988 	//Adjust the mask in case we've been asked to start at an intermediate pixel
  1989 	mask >>= aStartPixel * aCompressedBitsPerPixel;
  1990 	
  1991 	TUint8 pack = *aDataPtr; //max of 8 bits for palette entry
  1992 	
  1993 	//Loop the pixel data from the requested start to the requested end
  1994 	for (TInt ii = aStartPixel;  ii <= aEndPixel;  ii++)
  1995 		{	
  1996 		//extract the bits corresponding to the required color index from the pack using the mask
  1997 		TUint8 index = pack&mask;
  1998 		//shift the index to the right to get true value
  1999 		index >>= (aCompressedPixelsPerByte- ii - 1) * aCompressedBitsPerPixel;
  2000 		//get the address of the required color value from the palette
  2001 		TUint32 color = *(aPalettePtr + index);
  2002 		//and copy the actual color value into the scanline buffer
  2003 		*aDestPtr ++= color;
  2004 		*aDestPtr ++= color >> 8;
  2005 		if (iHeader.iBitsPerPixel >= 24)
  2006 			*aDestPtr ++= color >> 16;
  2007 		if (iHeader.iBitsPerPixel == 32)
  2008 			*aDestPtr ++= 0xFF;  //use 0xFF rather than 0x00 as it is more alpha friendly
  2009 		
  2010 		//shift the mask to get the next required bits
  2011 		mask >>= aCompressedBitsPerPixel;
  2012 		}
  2013 	}
  2014 
  2015 /** 
  2016 Specialised function for decoding pixels from a palette compressed bitmap with 1 pixel packed in each byte.
  2017 Implemented for speed, not size
  2018 @param aDataPtr Address in compressed data to read from
  2019 @param aPalettePtr Address of the start of the palette in the compressed data
  2020 @param aDestPtr Address to write uncompressed data to.  Will be incremented on return from function.
  2021 @param aAssignFunction Function pointer to assigment function to use to write actual pixel data to uncompressed scanline
  2022 */
  2023 void CBitwiseBitmap::PaletteDecode1PixelPerByte(TUint8* aDataPtr, TUint32* aPalettePtr, TUint8*& aDestPtr, TAssignFunction aAssignFunction)
  2024 	{
  2025 	(*aAssignFunction)(aDestPtr, *(aPalettePtr + *aDataPtr));
  2026 	}
  2027 	
  2028 /** 
  2029 Specialised function for decoding pixels from a palette compressed bitmap with 2 pixels packed in each byte.
  2030 Implemented for speed, not size
  2031 @param aDataPtr Address in compressed data to read from
  2032 @param aPalettePtr Address of the start of the palette in the compressed data
  2033 @param aDestPtr Address to write uncompressed data to.  Will be incremented on return from function.
  2034 @param aAssignFunction Function pointer to assigment function to use to write actual pixel data to uncompressed scanline
  2035 */
  2036 void CBitwiseBitmap::PaletteDecode2PixelPerByte(TUint8* aDataPtr, TUint32* aPalettePtr, TUint8*& aDestPtr, TAssignFunction aAssignFunction)
  2037 	{
  2038 	TUint8 mask = 0xF0; //binary 11110000
  2039 	TUint8 pack = *aDataPtr;
  2040 	//Pixel 1
  2041 	TUint8 index = pack&mask;
  2042 	index >>= 4;
  2043 	TUint32 color = *(aPalettePtr + index);
  2044 	(*aAssignFunction)(aDestPtr, color);
  2045 	mask >>= 4;
  2046  	//Pixel 2
  2047  	index = pack&mask;
  2048  	color = *(aPalettePtr + index);
  2049 	(*aAssignFunction)(aDestPtr, color); 			
  2050 	}
  2051 
  2052 /** 
  2053 Specialised function for decoding pixels from a palette compressed bitmap with 4 pixels packed in each byte.
  2054 Implemented for speed, not size
  2055 @param aDataPtr Address in compressed data to read from
  2056 @param aPalettePtr Address of the start of the palette in the compressed data
  2057 @param aDestPtr Address to write uncompressed data to.  Will be incremented on return from function.
  2058 @param aAssignFunction Function pointer to assigment function to use to write actual pixel data to uncompressed scanline
  2059 */
  2060 void CBitwiseBitmap::PaletteDecode4PixelPerByte(TUint8* aDataPtr, TUint32* aPalettePtr, TUint8*& aDestPtr, TAssignFunction aAssignFunction)
  2061 	{
  2062 	TUint8 mask = 0xC0; //binary 11000000
  2063 	TUint8 pack = *aDataPtr;
  2064 	//Pixel 1
  2065 	TUint8 index = pack&mask;
  2066 	index >>= 6;
  2067 	TUint32 color = *(aPalettePtr + index);
  2068 	(*aAssignFunction)(aDestPtr, color);
  2069 	mask >>= 2;
  2070  	//Pixel 2
  2071  	index = pack&mask;
  2072 	index >>= 4;
  2073  	color = *(aPalettePtr + index);
  2074 	(*aAssignFunction)(aDestPtr, color); 			
  2075 	mask >>= 2;
  2076  	//Pixel 3
  2077  	index = pack&mask;
  2078 	index >>= 2;
  2079  	color = *(aPalettePtr + index);
  2080 	(*aAssignFunction)(aDestPtr, color); 			
  2081 	mask >>= 2;
  2082  	//Pixel 4
  2083  	index = pack&mask;
  2084  	color = *(aPalettePtr + index);
  2085 	(*aAssignFunction)(aDestPtr, color); 			
  2086 	}
  2087 
  2088 /** 
  2089 Specialised function for decoding pixels from a palette compressed bitmap with 8 pixels packed in each byte.
  2090 Implemented for speed, not size
  2091 @param aDataPtr Address in compressed data to read from
  2092 @param aPalettePtr Address of the start of the palette in the compressed data
  2093 @param aDestPtr Address to write uncompressed data to.  Will be incremented on return from function.
  2094 @param aAssignFunction Function pointer to assigment function to use to write actual pixel data to uncompressed scanline
  2095 */
  2096 void CBitwiseBitmap::PaletteDecode8PixelPerByte(TUint8* aDataPtr, TUint32* aPalettePtr, TUint8*& aDestPtr, TAssignFunction aAssignFunction)
  2097 	{
  2098 	TUint8 mask = 0x80; //binary 10000000
  2099 	TUint8 pack = *aDataPtr;
  2100 	//Pixel 1
  2101 	TUint8 index = pack&mask;
  2102 	index >>= 7;
  2103 	TUint32 color = *(aPalettePtr + index);
  2104 	(*aAssignFunction)(aDestPtr, color);
  2105 	mask >>= 1;
  2106  	//Pixel 2
  2107  	index = pack&mask;
  2108 	index >>= 6;
  2109  	color = *(aPalettePtr + index);
  2110 	(*aAssignFunction)(aDestPtr, color); 			
  2111 	mask>>=1;
  2112  	//Pixel 3
  2113  	index = pack&mask;
  2114 	index >>= 5;
  2115  	color = *(aPalettePtr + index);
  2116 	(*aAssignFunction)(aDestPtr, color); 			
  2117 	mask >>= 1;
  2118   	//Pixel 4
  2119  	index = pack&mask;
  2120 	index >>= 4;
  2121  	color = *(aPalettePtr + index);
  2122 	(*aAssignFunction)(aDestPtr, color); 			
  2123 	mask >>= 1;
  2124   	//Pixel 5
  2125  	index = pack&mask;
  2126 	index >>= 3;
  2127  	color = *(aPalettePtr + index);
  2128 	(*aAssignFunction)(aDestPtr, color); 			
  2129 	mask >>= 1;
  2130   	//Pixel 6
  2131  	index = pack&mask;
  2132 	index >>= 2;
  2133  	color = *(aPalettePtr + index);
  2134 	(*aAssignFunction)(aDestPtr, color); 			
  2135 	mask >>= 1;
  2136   	//Pixel 7
  2137  	index = pack&mask;
  2138 	index >>= 1;
  2139  	color = *(aPalettePtr + index);
  2140 	(*aAssignFunction)(aDestPtr, color); 			
  2141 	mask >>= 1;
  2142  	//Pixel 8
  2143  	index = pack&mask;
  2144  	color = *(aPalettePtr + index);
  2145 	(*aAssignFunction)(aDestPtr, color); 			
  2146 	}
  2147 
  2148 /** 
  2149 Specialised function for assigning pixels into an uncompressed scanline of 16 bit color depth.
  2150 Implemented for speed, not size
  2151 @param aDestPtr Address to write uncompressed data to.  Will be incremented on return from function.
  2152 @param aColor Color info to write.
  2153 */
  2154 void CBitwiseBitmap::PaletteAssign16BitColor(TUint8*& aDestPtr, TUint32 aColor)
  2155 	{
  2156 	*aDestPtr ++= aColor;
  2157 	*aDestPtr ++= aColor >> 8;
  2158 	}
  2159 
  2160 /** 
  2161 Specialised function for assigning pixels into an uncompressed scanline of 24 bit color depth.
  2162 Implemented for speed, not size
  2163 @param aDestPtr Address to write uncompressed data to.  Will be incremented on return from function.
  2164 @param aColor Color info to write.
  2165 */
  2166 void CBitwiseBitmap::PaletteAssign24BitColor(TUint8*& aDestPtr, TUint32 aColor)
  2167 	{
  2168 	*aDestPtr ++= aColor;
  2169 	*aDestPtr ++= aColor >> 8;
  2170 	*aDestPtr ++= aColor >> 16;
  2171 	}
  2172 
  2173 /** 
  2174 Specialised function for assigning pixels into an uncompressed scanline of 32 bit color depth.
  2175 Implemented for speed, not size
  2176 @param aDestPtr Address to write uncompressed data to.  Will be incremented on return from function.
  2177 @param aColor Color info to write.
  2178 */
  2179 void CBitwiseBitmap::PaletteAssign32BitColor(TUint8*& aDestPtr, TUint32 aColor)
  2180 	{
  2181 	*aDestPtr ++= aColor;
  2182 	*aDestPtr ++= aColor >> 8;
  2183 	*aDestPtr ++= aColor >> 16;
  2184 	*aDestPtr ++= 0xFF;  //use 0xFF rather than 0x00 as it is more alpha friendly
  2185 	}
  2186 
  2187 /**
  2188 Get the bits used per pixel when packing multiple pixels in palette compression.
  2189 The value returned is a power of 2, not always the most efficient pack, for alignment reasons, Eg
  2190  65537 -> KMaxTInt : 32 bpp
  2191  257 -> 65536 colors : 16 bpp
  2192  17 -> 256 colors : 8 bpp
  2193  5  -> 16  colors : 4 bpp
  2194  3  -> 4   colors : 2 bpp
  2195  0  -> 2   colors : 1 bpp
  2196 @param aNumColors The number of colors in the bitmap.  This governs the size of the palette and thus
  2197 the number of bits needed to represent an index into it.
  2198 */
  2199 TUint CBitwiseBitmap::PaletteBitsPerPixel(TInt aNumColors) const
  2200 	{
  2201 	if (aNumColors <= 2)
  2202 		return 1;
  2203 	else if (aNumColors <= 4)
  2204 		return 2;
  2205 	else if (aNumColors <= 16)
  2206 		return 4;
  2207 	else if (aNumColors <= 256)
  2208 		return 8;
  2209 	else if (aNumColors <= 65536)
  2210 		return 16;
  2211 	else
  2212 		return 32;
  2213 	}
  2214 	
  2215 /**
  2216 Gets the bytes used per pixel according to the bits per pixel of a bitmap.
  2217 Also used to find which bit per pixel values are supported by palette compression, hence this is not
  2218 a case of simple division by 8.
  2219 If return value is zero, the supplied bit per pixel value is not supported by palette compression.
  2220 @param aBitsPerPixel The bits per pixel value to transform into bytes
  2221 */
  2222 TUint CBitwiseBitmap::PaletteBytesPerPixel(TInt aBitsPerPixel) const
  2223 	{
  2224 	if (aBitsPerPixel == 16)
  2225 		return 2;  //16 bit
  2226 	else if (aBitsPerPixel == 24)
  2227 		return 3;   //24 bit
  2228 	else if (aBitsPerPixel == 32 && iHeader.iColor == SEpocBitmapHeader::EColor)
  2229 		return 4;	//32 bit with no alpha
  2230 	else 
  2231 		return 0;
  2232 	}
  2233