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