Update contrib.
1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
21 #include <e32hashtab.h>
23 GLREF_C void Panic(TFbsPanic aPanic);
25 void CBitwiseBitmap::DoInternalizeCompressedDataL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase,TBitmapfileCompression aCompression)
27 TInt destSizeInBytes = iHeader.iSizeInPixels.iHeight * iByteWidth;
28 TUint8* destPtr = (TUint8*)aBase;
30 // try to allocate memory for the compressed bitmap
31 TUint8* decompressionBuffer = (TUint8*)User::Alloc(aSrceSizeInBytes);
33 if (decompressionBuffer)
35 // read the compressed bitmap, then decompress
36 CleanupStack::PushL(decompressionBuffer);
37 aStream.ReadL(decompressionBuffer,aSrceSizeInBytes);
40 case EByteRLECompression:
41 DoDecompressByteData(destPtr,destSizeInBytes,decompressionBuffer,aSrceSizeInBytes);
43 case ETwelveBitRLECompression:
44 DoDecompressTwelveBitData(destPtr,destSizeInBytes,decompressionBuffer,aSrceSizeInBytes);
46 case ESixteenBitRLECompression:
47 DoDecompressSixteenBitData(destPtr,destSizeInBytes,decompressionBuffer,aSrceSizeInBytes);
49 case ETwentyFourBitRLECompression:
50 DoDecompressTwentyFourBitData(destPtr,destSizeInBytes,decompressionBuffer,aSrceSizeInBytes);
52 case EThirtyTwoUBitRLECompression:
53 DoDecompressThirtyTwoUBitData(destPtr,destSizeInBytes,decompressionBuffer,aSrceSizeInBytes);
55 case EThirtyTwoABitRLECompression:
56 DoDecompressThirtyTwoABitData(destPtr,destSizeInBytes,decompressionBuffer,aSrceSizeInBytes);
61 CleanupStack::PopAndDestroy(); // decompressionBuffer
65 // not enough heap to pre-load the source bitmap
68 case EByteRLECompression:
69 DoDecompressByteDataAltL(aStream,aSrceSizeInBytes,aBase);
71 case ETwelveBitRLECompression:
72 DoDecompressTwelveBitDataAltL(aStream,aSrceSizeInBytes,aBase);
74 case ESixteenBitRLECompression:
75 DoDecompressSixteenBitDataAltL(aStream,aSrceSizeInBytes,aBase);
77 case ETwentyFourBitRLECompression:
78 DoDecompressTwentyFourBitDataAltL(aStream,aSrceSizeInBytes,aBase);
80 case EThirtyTwoUBitRLECompression:
81 DoDecompressThirtyTwoUBitDataAltL(aStream,aSrceSizeInBytes,aBase);
83 case EThirtyTwoABitRLECompression:
84 DoDecompressThirtyTwoABitDataAltL(aStream,aSrceSizeInBytes,aBase);
91 void CBitwiseBitmap::DoDecompressByteData(TUint8* aDestBuffer,TInt aDestSize,TUint8* aSrceBuffer,TInt aSrceSize)
93 TUint8* srcePtr = aSrceBuffer;
94 TUint8* destPtr = aDestBuffer;
95 TUint8* srcePtrLimit = aSrceBuffer + aSrceSize;
96 TUint8* destPtrLimit = aDestBuffer + aDestSize;
98 while (srcePtr < srcePtrLimit && destPtr < destPtrLimit)
100 TInt8 count = *srcePtr++;
104 const TInt numBytes = Min(count + 1, destPtrLimit - destPtr);
105 Mem::Fill(destPtr,numBytes,*srcePtr++);
110 const TInt numBytes = Min(-count, destPtrLimit - destPtr);
111 Mem::Copy(destPtr,srcePtr,numBytes);
116 __ASSERT_DEBUG(srcePtr == srcePtrLimit && destPtr == destPtrLimit,Panic(EFbsBitmapDecompressionError));
119 void CBitwiseBitmap::DoDecompressByteDataAltL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase)
121 TInt destSizeInBytes = iHeader.iSizeInPixels.iHeight * iByteWidth;
122 TUint8* destPtr = (TUint8*)aBase;
123 TUint8* destPtrLimit = destPtr + destSizeInBytes;
125 while(aSrceSizeInBytes > 0 && destPtr < destPtrLimit)
127 TInt8 count = aStream.ReadInt8L();
132 const TInt numBytes = Min(count + 1, destPtrLimit - destPtr);
133 TUint8 value = aStream.ReadUint8L();
135 Mem::Fill(destPtr,numBytes,value);
140 const TInt numBytes = Min(-count, destPtrLimit - destPtr);
141 aStream.ReadL(destPtr,numBytes);
142 aSrceSizeInBytes -= numBytes;
146 __ASSERT_DEBUG(aSrceSizeInBytes == 0 && destPtr == destPtrLimit,Panic(EFbsBitmapDecompressionError));
149 /** Fills the 32bit pixels into the destination pointer
150 This method uses the concept of Duff's Device
151 @param aDestPtr32 pointer to 32bit destination buffer.
152 @param aCount Number of 32bit pixels to be copied.
153 @param aValue32 32bit pixel data. */
154 void CBitwiseBitmap::BitmapFill32(TUint32* aDestPtr32, TInt aCount, TUint32 aValue32)
156 __ASSERT_DEBUG(aCount > 0, Panic(EFbsBitmapDecompressionError));
158 { // for performance loop is unrolled, using "Duff's Device" pattern
159 TInt blocksOf16 = aCount / 16; // number of blocks of 16 full words to write
160 // the first iteration writes 1 to 15 words
162 switch (aCount & 0x0f)
163 { // note that case statements intentionally cascade
165 write16dblPixels: // second and subsequent iterations always write 16 words
167 *aDestPtr32++ = aValue32;
168 //coverity [fallthrough]
170 *aDestPtr32++ = aValue32;
171 //coverity [fallthrough]
173 *aDestPtr32++ = aValue32;
174 //coverity [fallthrough]
176 *aDestPtr32++ = aValue32;
177 //coverity [fallthrough]
179 *aDestPtr32++ = aValue32;
180 //coverity [fallthrough]
182 *aDestPtr32++ = aValue32;
183 //coverity [fallthrough]
185 *aDestPtr32++ = aValue32;
186 //coverity [fallthrough]
188 *aDestPtr32++ = aValue32;
189 //coverity [fallthrough]
191 *aDestPtr32++ = aValue32;
192 //coverity [fallthrough]
194 *aDestPtr32++ = aValue32;
195 //coverity [fallthrough]
197 *aDestPtr32++ = aValue32;
198 //coverity [fallthrough]
200 *aDestPtr32++ = aValue32;
201 //coverity [fallthrough]
203 *aDestPtr32++ = aValue32;
204 //coverity [fallthrough]
206 *aDestPtr32++ = aValue32;
207 //coverity [fallthrough]
209 *aDestPtr32++ = aValue32;
210 //coverity [fallthrough]
212 *aDestPtr32++ = aValue32;
217 goto write16dblPixels;
222 /** Fills the 16bit pixels into the destination pointer
223 This method uses the concept of Duff's Device
224 @param aDestPtr16 pointer to 16bit destination buffer.
225 @param aCount Number of 16bit pixels to be copied.
226 @param aValue16 16bit pixel data. */
227 inline void CBitwiseBitmap::BitmapFill16(TUint16* aDestPtr16, TInt aCount, TUint16 aValue16)
229 // Call the 32-bit fill method if there at least 8 pixels to fill
232 // first pixel is on half word address?
233 if (reinterpret_cast<TUint32>(aDestPtr16) & 2)
235 *aDestPtr16++ = aValue16;
239 // destPtr16 is now full Word aligned
240 const TInt countDoublePixels = aCount / 2;
241 TUint32* destPtr32 = (TUint32*) aDestPtr16;
242 BitmapFill32(destPtr32, countDoublePixels, (aValue16 << 16) | aValue16);
244 aCount -= countDoublePixels * 2;
246 { // last pixel is on a half-word
247 aDestPtr16 += countDoublePixels * 2;
248 *aDestPtr16++ = aValue16;
252 { // less than 8 pixels to fill
254 { // note that case statements intentionally cascade
256 *aDestPtr16++ = aValue16;
258 *aDestPtr16++ = aValue16;
260 *aDestPtr16++ = aValue16;
262 *aDestPtr16++ = aValue16;
264 *aDestPtr16++ = aValue16;
266 *aDestPtr16++ = aValue16;
268 *aDestPtr16++ = aValue16;
269 case 0: // nothing to do
275 void CBitwiseBitmap::DoDecompressTwelveBitData(TUint8* aDestBuffer,TInt aDestSize,TUint8* aSrceBuffer,TInt aSrceSize)
277 TUint16* srcePtr = (TUint16*)aSrceBuffer;
278 TUint16* destPtr = (TUint16*)aDestBuffer;
279 TUint16* srcePtrLimit = srcePtr + (aSrceSize / 2);
280 TUint16* destPtrLimit = destPtr + (aDestSize / 2);
282 while (srcePtr < srcePtrLimit && destPtr < destPtrLimit)
284 TUint16 value = *srcePtr++;
285 TInt count = Min(value >> 12, destPtrLimit - destPtr);
295 __ASSERT_DEBUG(srcePtr == srcePtrLimit && destPtr == destPtrLimit,Panic(EFbsBitmapDecompressionError));
298 void CBitwiseBitmap::DoDecompressTwelveBitDataAltL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase)
300 TInt destSizeInBytes = iHeader.iSizeInPixels.iHeight * iByteWidth;
301 TUint16* destPtr = (TUint16*)aBase;
302 TUint16* destPtrLimit = destPtr + (destSizeInBytes / 2);
304 while(aSrceSizeInBytes > 0 && destPtr < destPtrLimit)
306 TUint16 value = aStream.ReadUint16L();
307 TInt count = Min(value >> 12, destPtrLimit - destPtr);
309 aSrceSizeInBytes -= 2;
317 __ASSERT_DEBUG(aSrceSizeInBytes == 0 && destPtr == destPtrLimit,Panic(EFbsBitmapDecompressionError));
320 /** The function decodes 24-bit compressed buffer to the 16-bit stream with unused top bytes by using RLE compression algorithm*/
321 void CBitwiseBitmap::DoDecompressSixteenBitData(TUint8* aDestBuffer,TInt aDestSize,TUint8* aSrceBuffer,TInt aSrceSize)
323 __ASSERT_DEBUG((reinterpret_cast<TUint32>(aDestBuffer) & 0x2)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is half-word aligned
324 __ASSERT_DEBUG((aDestSize & 0x2)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is half-word aligned
326 TUint8* srcePtr8 = aSrceBuffer; // pointer to compressed source Byte(8-bit) stream
327 TUint16* destPtr16 = reinterpret_cast<TUint16*>(aDestBuffer); //pointer to uncompressed destination HalfWord(16-bit) pixel stream
328 TUint8* srcePtrLimit8 = aSrceBuffer + aSrceSize; //maximum number of compressed source bytes
329 TUint16* destPtrLimit16 = reinterpret_cast<TUint16*>(aDestBuffer + aDestSize); //maximum number of uncompressed destination pixel stream
330 const TInt KPixelSize = 2; //number of bytes of the source stream that is to be considered as one Pixel
332 while (srcePtr8 < srcePtrLimit8 && destPtr16 < destPtrLimit16)
334 TInt8 count = *srcePtr8++; //number of pixels to be retrieved from the source stream
336 if (count >= 0) //repeating number of pixels
338 const TInt numPixels = 1 + Min(count, (destPtrLimit16 - destPtr16));
339 const TUint8 lowByte = *srcePtr8++;
340 const TUint8 highByte = *srcePtr8++;
341 const TUint16 pixel = highByte<<8 | lowByte; //Pixel buffer which needs to be stored in destPtr16
343 BitmapFill16(destPtr16, numPixels, pixel);
344 destPtr16 += numPixels;
348 const TInt numPixels = Min(-count, destPtrLimit16 - destPtr16); //number of pixels to be copied
349 const TInt numBytes = numPixels * KPixelSize; //number of bytes needs to be retrieved from the srcePtr
350 Mem::Copy(destPtr16, srcePtr8, numBytes); // copy bytes
351 srcePtr8 += numBytes; //incrementing the srcePtr by number of bytes
352 destPtr16 += numPixels; //incrementing the destPtr16 by number of pixels
355 __ASSERT_DEBUG(srcePtr8 == srcePtrLimit8 && destPtr16 == destPtrLimit16, Panic(EFbsBitmapDecompressionError));
358 /** The alternative decoding function which decompresses 24-bit buffer to the 16-bit stream with unused top bytes
359 by using RLE compression algorithm. The function is used under low memory conditions. */
360 void CBitwiseBitmap::DoDecompressSixteenBitDataAltL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase)
362 __ASSERT_DEBUG((reinterpret_cast<TUint32>(aBase) & 0x2)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is half-word aligned
364 TInt destSizeInPixels = (iHeader.iSizeInPixels.iHeight * iByteWidth); //size of destination Byte pixel buffers
365 destSizeInPixels >>= 1; //dividing by two, to get size of destination interms of Halfword pixel buffers
366 TUint16* destPtr16 = reinterpret_cast<TUint16*>(aBase); //pointer to uncompressed destination HalfWord(16-bit) pixel stream
367 TUint16* destPtrLimit16 = destPtr16 + destSizeInPixels; //maximum number of compressed source bytes
368 const TInt KPixelSize = 2; //number of bytes of the source stream that is to be considered as one Pixel
370 while(aSrceSizeInBytes > 0 && destPtr16 < destPtrLimit16)
372 TInt8 count = aStream.ReadInt8L(); //number of pixels to be retrieved from the source stream
373 aSrceSizeInBytes--; //One byte from source stream read, hence reduce size by one Byte
377 const TInt numPixels = 1 + Min(count, (destPtrLimit16 - destPtr16));
378 const TUint16 pixel = aStream.ReadUint16L(); //Pixel buffer which needs to be stored in destPtr16
379 aSrceSizeInBytes -= KPixelSize; //Two bytes (Halfword pixel) read, reduce size by two Bytes
381 BitmapFill16(destPtr16, numPixels, pixel);
382 destPtr16 += numPixels;
386 const TInt numPixels = Min(-count, destPtrLimit16 - destPtr16); //number of pixels to be stored into destPtr16
387 const TInt numBytes = numPixels * KPixelSize; //number of bytes needs to be retrieved from the srcePtr
388 aStream.ReadL(destPtr16, numPixels); //read TUint16's
389 aSrceSizeInBytes -= numBytes; //two-byte (halfword) pixel buffers read, reduce by number of bytes
390 destPtr16 += numPixels; //incrementing the destPtr16 by number of pixels
393 __ASSERT_DEBUG(aSrceSizeInBytes == 0 && destPtr16 == destPtrLimit16, Panic(EFbsBitmapDecompressionError));
396 void CBitwiseBitmap::DoDecompressTwentyFourBitData(TUint8* aDestBuffer,TInt aDestSize,TUint8* aSrceBuffer,TInt aSrceSize)
398 TUint8* srcePtr = aSrceBuffer;
399 TUint8* destPtr = aDestBuffer;
400 TUint8* srcePtrLimit = aSrceBuffer + aSrceSize;
401 TUint8* destPtrLimit = aDestBuffer + aDestSize;
403 while (srcePtr < srcePtrLimit && destPtr < destPtrLimit)
405 TInt8 count = *srcePtr++;
409 count = Min(count, (destPtrLimit - destPtr) / 3);
410 TUint8 component1 = *srcePtr++;
411 TUint8 component2 = *srcePtr++;
412 TUint8 component3 = *srcePtr++;
416 *destPtr++ = component1;
417 *destPtr++ = component2;
418 *destPtr++ = component3;
424 const TInt numBytes = Min(count * -3, destPtrLimit - destPtr);
425 Mem::Copy(destPtr,srcePtr,numBytes);
430 __ASSERT_DEBUG(srcePtr == srcePtrLimit && destPtr == destPtrLimit,Panic(EFbsBitmapDecompressionError));
433 void CBitwiseBitmap::DoDecompressTwentyFourBitDataAltL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase)
435 TInt destSizeInBytes = iHeader.iSizeInPixels.iHeight * iByteWidth;
436 TUint8* destPtr = (TUint8*)aBase;
437 TUint8* destPtrLimit = destPtr + destSizeInBytes;
439 while(aSrceSizeInBytes > 0 && destPtr < destPtrLimit)
441 TInt8 count = aStream.ReadInt8L();
446 count = Min(count, (destPtrLimit - destPtr) / 3);
447 TUint8 component1 = aStream.ReadUint8L();
448 TUint8 component2 = aStream.ReadUint8L();
449 TUint8 component3 = aStream.ReadUint8L();
450 aSrceSizeInBytes -= 3;
454 *destPtr++ = component1;
455 *destPtr++ = component2;
456 *destPtr++ = component3;
462 const TInt numBytes = Min(count * -3, destPtrLimit - destPtr);
463 aStream.ReadL(destPtr, numBytes);
464 aSrceSizeInBytes -= numBytes;
468 __ASSERT_DEBUG(aSrceSizeInBytes == 0 && destPtr == destPtrLimit,Panic(EFbsBitmapDecompressionError));
471 /** The function decodes 24-bit compressed buffer to the 32-bit stream with unused top bytes by using RLE compression algorithm*/
472 void CBitwiseBitmap::DoDecompressThirtyTwoUBitData(TUint8* aDestBuffer,TInt aDestSize,TUint8* aSrceBuffer,TInt aSrceSize)
475 __ASSERT_DEBUG((reinterpret_cast<TUint32>(aDestBuffer) & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is word aligned
476 __ASSERT_DEBUG((aDestSize & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the size is whole no of pixels
478 TUint8* srcePtr8 = aSrceBuffer;
479 TUint8* srcePtrLimit8 = aSrceBuffer + aSrceSize;
481 TUint32* destPtr32 = reinterpret_cast<TUint32*>(aDestBuffer);
482 TUint32* destPtrLimit32 = reinterpret_cast<TUint32*>(aDestBuffer + aDestSize);
484 while (srcePtr8 < srcePtrLimit8 && destPtr32 < destPtrLimit32)
487 TInt8 count = *srcePtr8++; // important to read into a byte variable
489 if (count >= 0) //repeating pixel buffer
491 count = Min(count, (destPtrLimit32 - destPtr32));
492 const TUint8 component1 = *srcePtr8++;
493 const TUint8 component2 = *srcePtr8++;
494 const TUint8 component3 = *srcePtr8++;
496 const TUint32 pixel = 0xff000000 | (component3<<16) | (component2<<8) | component1;
498 // for performance loop is unrolled, using "Duff's Device" pattern
499 TInt blocksOf16 = (count >> 4); // number of blocks of 16 full words to write
500 // the first iteration writes 1 to 15 words
501 switch (count & 0x0f)
502 { // note that case statements intentionally cascade
504 do { // second and subsequent iterations always write 16 words
505 *destPtr32++ = pixel;
507 *destPtr32++ = pixel;
509 *destPtr32++ = pixel;
511 *destPtr32++ = pixel;
513 *destPtr32++ = pixel;
515 *destPtr32++ = pixel;
517 *destPtr32++ = pixel;
519 *destPtr32++ = pixel;
521 *destPtr32++ = pixel;
523 *destPtr32++ = pixel;
525 *destPtr32++ = pixel;
527 *destPtr32++ = pixel;
529 *destPtr32++ = pixel;
531 *destPtr32++ = pixel;
533 *destPtr32++ = pixel;
535 *destPtr32++ = pixel;
537 } while(0 <= --blocksOf16);
540 else // negative value corresponds non repeating pixel buffer
542 const TInt numPixel = Min(-count, destPtrLimit32 - destPtr32) ;
543 for(TInt ii = 0; ii < numPixel; ii++)
545 TUint8 component1 = *srcePtr8++;
546 TUint8 component2 = *srcePtr8++;
547 TUint8 component3 = *srcePtr8++;
549 *destPtr32++ = 0xff000000 | (component3<<16) | (component2<<8) | component1;
554 __ASSERT_DEBUG(srcePtr8 == srcePtrLimit8 && destPtr32 == destPtrLimit32,Panic(EFbsBitmapDecompressionError));
557 /** The alternative decoding function which decompresses 24-bit buffer to the 32-bit stream with unused top bytes
558 by using RLE compression algorithm. The function is using in case of memory shortage. */
559 void CBitwiseBitmap::DoDecompressThirtyTwoUBitDataAltL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase)
561 const TInt destSizeInDwords = iHeader.iSizeInPixels.iHeight * (iByteWidth>>2);
562 TUint32* destPtr32 = aBase;
563 TUint32* destPtrLimit32 = destPtr32 + destSizeInDwords;
565 const TInt KMaxRLENonRepeatingPixelBufferSize = 128 * 3;
566 TUint8 dataBuffer[KMaxRLENonRepeatingPixelBufferSize];
568 while(aSrceSizeInBytes > 0 && destPtr32 < destPtrLimit32)
570 TInt8 count = aStream.ReadInt8L();
573 if (count >= 0) //repeating pixel buffer
575 count = Min(count, (destPtrLimit32 - destPtr32));
576 const TUint8 component1 = aStream.ReadUint8L();
577 const TUint8 component2 = aStream.ReadUint8L();
578 const TUint8 component3 = aStream.ReadUint8L();
579 aSrceSizeInBytes -= 3;
581 const TUint32 pixel = 0xff000000 | (component3<<16) | (component2<<8) | component1;
583 TInt blocksOf16 = (count >> 4); // number of blocks of 16 full words to write
584 // the first iteration writes 1 to 15 words
585 switch (count & 0x0f)
586 { // note that case statements intentionally cascade
588 do { // second and subsequent iterations always write 16 words
589 *destPtr32++ = pixel;
591 *destPtr32++ = pixel;
593 *destPtr32++ = pixel;
595 *destPtr32++ = pixel;
597 *destPtr32++ = pixel;
599 *destPtr32++ = pixel;
601 *destPtr32++ = pixel;
603 *destPtr32++ = pixel;
605 *destPtr32++ = pixel;
607 *destPtr32++ = pixel;
609 *destPtr32++ = pixel;
611 *destPtr32++ = pixel;
613 *destPtr32++ = pixel;
615 *destPtr32++ = pixel;
617 *destPtr32++ = pixel;
619 *destPtr32++ = pixel;
621 } while(0 <= --blocksOf16);
624 else // negative value corresponds non repeating pixel buffer
626 const TInt numDestDwords = Min(-count, destPtrLimit32 - destPtr32);
627 const TInt numSrcBytes = numDestDwords * 3;
628 aStream.ReadL(&dataBuffer[0], numSrcBytes);
629 aSrceSizeInBytes -= numSrcBytes;
630 TUint8* srcPtr = dataBuffer;
631 const TInt& numPixel = numDestDwords;
632 for(TInt ii = 0; ii < numPixel; ii++)
634 const TUint8 component1 = *srcPtr++;
635 const TUint8 component2 = *srcPtr++;
636 const TUint8 component3 = *srcPtr++;
638 *destPtr32++ = 0xff000000 | (component3<<16) | (component2<<8) | component1;
643 __ASSERT_DEBUG(aSrceSizeInBytes == 0 && destPtr32 == destPtrLimit32,Panic(EFbsBitmapDecompressionError));
646 /** The function decodes 32-bit compressed buffer (where top bytes are used as alpha channel) to the 32-bit stream by using RLE compression algorithm*/
647 void CBitwiseBitmap::DoDecompressThirtyTwoABitData(TUint8* aDestBuffer,TInt aDestSize,TUint8* aSrceBuffer,TInt aSrceSize)
649 TUint8* srcePtr = aSrceBuffer;
650 TUint8* srcePtrLimit = aSrceBuffer + aSrceSize;
652 TUint32* destPtr32 = reinterpret_cast<TUint32*>(aDestBuffer);
653 TUint32* destPtrLimit32 = reinterpret_cast<TUint32*>(aDestBuffer + aDestSize);
655 while (srcePtr < srcePtrLimit && destPtr32 < destPtrLimit32)
657 TInt8 count = *srcePtr++;
659 if (count >= 0) //repeating pixel buffer
661 count = Min(count, (destPtrLimit32 - destPtr32));
662 TUint8 component1 = *srcePtr++;
663 TUint8 component2 = *srcePtr++;
664 TUint8 component3 = *srcePtr++;
665 TUint8 component4 = *srcePtr++;
666 const TUint32 pixel = (component4<<24) | (component3<<16) | (component2<<8) | component1;
668 // for performance loop is unrolled, using "Duff's Device" pattern
669 TInt blocksOf16 = (count >> 4); // number of blocks of 16 full words to write
670 // the first iteration writes 1 to 15 words
671 switch (count & 0x0f)
672 { // note that case statements intentionally cascade
674 do { // second and subsequent iterations always write 16 words
675 *destPtr32++ = pixel;
677 *destPtr32++ = pixel;
679 *destPtr32++ = pixel;
681 *destPtr32++ = pixel;
683 *destPtr32++ = pixel;
685 *destPtr32++ = pixel;
687 *destPtr32++ = pixel;
689 *destPtr32++ = pixel;
691 *destPtr32++ = pixel;
693 *destPtr32++ = pixel;
695 *destPtr32++ = pixel;
697 *destPtr32++ = pixel;
699 *destPtr32++ = pixel;
701 *destPtr32++ = pixel;
703 *destPtr32++ = pixel;
705 *destPtr32++ = pixel;
707 } while(0 <= --blocksOf16);
710 else // negative value corresponds non repeating pixel buffer
712 const TInt numPixel = Min(-count, destPtrLimit32 - destPtr32);
714 Mem::Copy(destPtr32, srcePtr, numPixel*4);
715 destPtr32 += numPixel;
716 srcePtr += numPixel*4;
721 __ASSERT_DEBUG(srcePtr == srcePtrLimit && destPtr32 == destPtrLimit32,Panic(EFbsBitmapDecompressionError));
724 /** The alternative decoding function which decompresses 32-bit buffer (where top bytes are used as alpha channel)
725 to the 32-bit stream by using RLE compression algorithm. The function is using in case of memory shortage. */
726 void CBitwiseBitmap::DoDecompressThirtyTwoABitDataAltL(RReadStream& aStream,TInt aSrceSizeInBytes,TUint32* aBase)
728 const TInt destSizeInDwords = iHeader.iSizeInPixels.iHeight * (iByteWidth>>2);
729 TUint32* destPtr32 = aBase;
730 TUint32* destPtrLimit32 = destPtr32 + destSizeInDwords;
732 while(aSrceSizeInBytes > 0 && destPtr32 < destPtrLimit32)
734 TInt8 count = aStream.ReadInt8L();
737 if (count >= 0) //repeating pixel buffer
739 count = Min(count, (destPtrLimit32 - destPtr32));
740 const TUint32 pixel = aStream.ReadUint32L();
741 aSrceSizeInBytes -= 4;
743 // for performance loop is unrolled, using "Duff's Device" pattern
744 TInt blocksOf16 = (count >> 4); // number of blocks of 16 full words to write
745 // the first iteration writes 1 to 15 words
746 switch (count & 0x0f)
747 { // note that case statements intentionally cascade
749 do { // second and subsequent iterations always write 16 words
750 *destPtr32++ = pixel;
752 *destPtr32++ = pixel;
754 *destPtr32++ = pixel;
756 *destPtr32++ = pixel;
758 *destPtr32++ = pixel;
760 *destPtr32++ = pixel;
762 *destPtr32++ = pixel;
764 *destPtr32++ = pixel;
766 *destPtr32++ = pixel;
768 *destPtr32++ = pixel;
770 *destPtr32++ = pixel;
772 *destPtr32++ = pixel;
774 *destPtr32++ = pixel;
776 *destPtr32++ = pixel;
778 *destPtr32++ = pixel;
780 *destPtr32++ = pixel;
782 } while(0 <= --blocksOf16);
785 else // negative value corresponds non repeating pixel buffer
787 const TInt numPixels = Min(-count, destPtrLimit32 - destPtr32);
788 aStream.ReadL((TUint16*)destPtr32, numPixels * 2); // read TUint16's
789 aSrceSizeInBytes -= numPixels * 4;
790 destPtr32 += numPixels;
794 __ASSERT_DEBUG(aSrceSizeInBytes == 0 && destPtr32 == destPtrLimit32,Panic(EFbsBitmapDecompressionError));
797 void CBitwiseBitmap::DoExternalizeDataCompressedL(RWriteStream& aStream,TUint8* aData,TInt aSizeInBytes) const
799 switch (iHeader.iBitsPerPixel)
805 DoExternalizeByteDataCompressedL(aStream,aData,aSizeInBytes);
808 DoExternalizeTwelveBitDataCompressedL(aStream,aData,aSizeInBytes);
811 DoExternalizeSixteenBitDataCompressedL(aStream,aData,aSizeInBytes);
814 DoExternalizeTwentyFourBitDataCompressedL(aStream,aData,aSizeInBytes);
817 __ASSERT_DEBUG(iHeader.iColor == SEpocBitmapHeader::EColor||
818 iHeader.iColor == SEpocBitmapHeader::EColorAlpha||
819 iHeader.iColor == SEpocBitmapHeader::EColorAlphaPM,
820 Panic(EFbsBitmapInvalidCompression));
821 if(iHeader.iColor == SEpocBitmapHeader::EColor)
823 DoExternalizeThirtyTwoUBitDataCompressedL(aStream,aData,aSizeInBytes);
827 DoExternalizeThirtyTwoABitDataCompressedL(aStream,aData,aSizeInBytes);
835 void CBitwiseBitmap::DoExternalizeByteDataCompressedL(RWriteStream& aStream,TUint8* aData,TInt aSizeInBytes) const
837 TUint8* dataLimit=aData+aSizeInBytes-2;
839 while(aData<dataLimit)
842 TUint8* runStartPtr = aData;
844 if (*(aData+1)==value && *(aData+2)==value)
847 while(aData<dataLimit && *aData==value)
849 TInt runLength=aData-runStartPtr;
854 aStream.WriteL(&runPair[0],2);
857 runPair[0]=TUint8(runLength-1);
858 aStream.WriteL(&runPair[0],2);
862 while(aData<dataLimit && (*(aData+1)!=value || *(aData+2)!=value))
867 TInt runLength = aData - runStartPtr;
868 while (runLength > 128)
870 aStream.WriteInt8L(-128);
871 aStream.WriteL(runStartPtr,128);
875 aStream.WriteInt8L(-runLength);
876 aStream.WriteL(runStartPtr,runLength);
882 TInt runLength=dataLimit-aData;
883 aStream.WriteInt8L(-runLength);
884 aStream.WriteL(aData,runLength);
888 void CBitwiseBitmap::DoExternalizeTwelveBitDataCompressedL(RWriteStream& aStream,TUint8* aData,TInt aSizeInBytes) const
890 TUint16* srcePtr = (TUint16*)aData;
891 TUint16* srcePtrLimit = srcePtr + (aSizeInBytes / 2);
893 while (srcePtr < srcePtrLimit)
895 TUint16* runStartPtr = srcePtr;
896 TUint16 value = TUint16(*srcePtr & 0x0fff);
901 while (srcePtr < srcePtrLimit && *srcePtr == value);
903 TInt pixelLength = srcePtr - runStartPtr;
904 TUint16 maxLengthData = TUint16(value | 0xf000);
906 while (pixelLength > 16)
908 aStream.WriteUint16L(maxLengthData);
913 aStream.WriteUint16L(value | TUint16((pixelLength - 1) << 12));
917 void CBitwiseBitmap::DoExternalizeSixteenBitDataCompressedL(RWriteStream& aStream,TUint8* aData,TInt aSizeInBytes) const
919 TUint16* srcePtr = (TUint16*)aData;
920 TUint16* srceLimitPtr = srcePtr + (aSizeInBytes / 2);
921 TUint16* srceLimitPtrMinusOne = srceLimitPtr - 1;
923 while (srcePtr < srceLimitPtrMinusOne)
925 TUint16 value = *srcePtr;
926 TUint16* runStartPtr = srcePtr++;
928 if(*srcePtr == value)
934 while(srcePtr < srceLimitPtr && *srcePtr == value);
936 TInt pixelLength = srcePtr-runStartPtr;
937 while (pixelLength > 128)
939 aStream.WriteInt8L(127);
940 aStream.WriteUint16L(value);
944 aStream.WriteUint8L(pixelLength - 1);
945 aStream.WriteUint16L(value);
950 while (srcePtr < srceLimitPtrMinusOne && *(srcePtr + 1) != value)
956 TInt pixelLength = srcePtr - runStartPtr;
957 while (pixelLength > 128)
959 aStream.WriteInt8L(-128);
960 aStream.WriteL(runStartPtr,128);
965 aStream.WriteInt8L(-pixelLength);
966 aStream.WriteL(runStartPtr,pixelLength);
970 TInt remainingPixels = srceLimitPtr - srcePtr;
971 if (remainingPixels > 0)
973 aStream.WriteInt8L(-remainingPixels);
974 aStream.WriteL(srcePtr,remainingPixels);
978 void CBitwiseBitmap::DoExternalizeTwentyFourBitDataCompressedL(RWriteStream& aStream,TUint8* aData,TInt aSizeInBytes) const
980 TUint8* srceLimitPtr = aData + aSizeInBytes;
981 TUint8* srceLimitPtrMinusThree = srceLimitPtr - 3; // three bytes == one pixel
983 while (aData < srceLimitPtrMinusThree)
985 TUint8* runStartPtr = aData;
986 TUint8 component1 = *aData++;
987 TUint8 component2 = *aData++;
988 TUint8 component3 = *aData++;
990 if (TrueColorPointerCompare(aData,component1,component2,component3))
996 while (aData < srceLimitPtr && TrueColorPointerCompare(aData,component1,component2,component3));
998 TInt pixelLength = (aData - runStartPtr) / 3;
999 while (pixelLength > 128)
1001 aStream.WriteInt8L(127);
1002 aStream.WriteUint8L(component1);
1003 aStream.WriteUint8L(component2);
1004 aStream.WriteUint8L(component3);
1008 aStream.WriteInt8L(pixelLength - 1);
1009 aStream.WriteUint8L(component1);
1010 aStream.WriteUint8L(component2);
1011 aStream.WriteUint8L(component3);
1016 TBool eqRun = EFalse;
1019 component1 = *aData++;
1020 component2 = *aData++;
1021 component3 = *aData++;
1022 more = (aData < srceLimitPtr);
1023 eqRun = more && TrueColorPointerCompare(aData,component1,component2,component3);
1025 while (more && !eqRun);
1028 TInt pixelLength = (aData - runStartPtr) / 3;
1029 while (pixelLength > 128)
1031 aStream.WriteInt8L(-128);
1032 aStream.WriteL(runStartPtr,384);
1037 aStream.WriteInt8L(-pixelLength);
1038 aStream.WriteL(runStartPtr,pixelLength * 3);
1042 TInt remainingPixels = srceLimitPtr - aData;
1043 if (remainingPixels > 0)
1045 TInt pixelLength = remainingPixels / 3;
1046 aStream.WriteInt8L(-pixelLength);
1047 aStream.WriteL(aData,remainingPixels);
1051 /** The function externalizes 32-bit buffer with unused top bytes to the 24-bit compressed stream by using RLE compression algorithm*/
1052 void CBitwiseBitmap::DoExternalizeThirtyTwoUBitDataCompressedL(RWriteStream& aStream,TUint8* aData8,TInt aSizeInBytes) const
1055 __ASSERT_DEBUG((reinterpret_cast<TUint32>(aData8) & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is word aligned
1056 __ASSERT_DEBUG((aSizeInBytes & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the size is whole no of pixels
1058 TUint32* ptr = reinterpret_cast<TUint32*>(aData8);
1059 TUint32* srceLimitPtr = reinterpret_cast<TUint32*>(aData8 + aSizeInBytes);
1060 TUint32* srceLimitPtr2ndLast = srceLimitPtr - 1;
1062 while (ptr < srceLimitPtr2ndLast)
1064 TUint32* runStartPtr = ptr;
1065 TUint32 pixel = *ptr++ & 0x00ffffff;
1067 if ( (((*ptr)&0x00ffffff)==pixel) )
1073 while (ptr< srceLimitPtr && (((*ptr)&0x00ffffff)==pixel) );
1075 TInt pixelLength = (ptr - runStartPtr);
1076 while (pixelLength > 128)
1078 aStream.WriteInt8L(127);
1079 aStream.WriteUint8L(pixel&0x000000ff);
1080 aStream.WriteUint8L((pixel>>8)&0x000000ff);
1081 aStream.WriteUint8L((pixel>>16)&0x000000ff);
1085 aStream.WriteInt8L(pixelLength - 1);
1086 aStream.WriteUint8L(pixel&0x000000ff);
1087 aStream.WriteUint8L((pixel>>8)&0x000000ff);
1088 aStream.WriteUint8L((pixel>>16)&0x000000ff);
1093 TBool eqRun = EFalse;
1096 pixel = *ptr++ & 0x00ffffff;
1097 more = (ptr < srceLimitPtr);
1098 eqRun = more && (((*ptr)&0x00ffffff)==pixel);
1099 } while (more && !eqRun);
1102 TInt pixelLength = (ptr - runStartPtr);
1103 while (pixelLength > 128)
1105 aStream.WriteInt8L(-128);
1106 for(TInt ii = 0; ii < 128; ii++)
1108 aStream.WriteL(reinterpret_cast<TUint8*>(runStartPtr), 3);
1114 aStream.WriteInt8L(-pixelLength);
1115 for(TInt kk = 0; kk < pixelLength; kk++)
1117 aStream.WriteL(reinterpret_cast<TUint8*>(runStartPtr), 3);
1123 const TInt remainingPixels = srceLimitPtr - ptr;
1124 if (remainingPixels > 0)
1126 __ASSERT_DEBUG(remainingPixels == 1, Panic(EFbsBitmapDecompressionError));
1128 aStream.WriteInt8L(-remainingPixels);
1129 for(TInt ii = 0; ii < remainingPixels; ii++)
1131 aStream.WriteL(reinterpret_cast<TUint8*>(ptr), 3);
1137 /** The function externalizes 32-bit buffer with alpha channel in top byte to the 32-bit compressed stream by using RLE compression algorithm*/
1138 void CBitwiseBitmap::DoExternalizeThirtyTwoABitDataCompressedL(RWriteStream& aStream,TUint8* aData8,TInt aSizeInBytes) const
1141 __ASSERT_DEBUG((reinterpret_cast<TUint32>(aData8) & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is word aligned
1142 __ASSERT_DEBUG((aSizeInBytes & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the size is whole no of pixels
1144 TUint32* ptr = reinterpret_cast<TUint32*>(aData8);
1145 TUint32* srceLimitPtr = reinterpret_cast<TUint32*>(aData8 + aSizeInBytes);
1146 TUint32* srceLimitPtr2ndLast = srceLimitPtr - 1;
1148 while (ptr < srceLimitPtr2ndLast)
1150 TUint32* runStartPtr = ptr;
1151 TUint32 pixel = *ptr++;
1159 while (ptr < srceLimitPtr && *ptr==pixel);
1161 TInt pixelLength = (ptr - runStartPtr);
1162 while (pixelLength > 128)
1164 aStream.WriteInt8L(127);
1165 aStream.WriteUint32L(pixel);
1169 aStream.WriteInt8L(pixelLength - 1);
1170 aStream.WriteUint32L(pixel);
1175 TBool eqRun = EFalse;
1179 more = (ptr < srceLimitPtr);
1180 eqRun = more && *ptr==pixel;
1181 } while (more && !eqRun);
1186 TInt pixelLength = (ptr - runStartPtr);
1187 while (pixelLength > 128)
1189 aStream.WriteInt8L(-128);
1190 aStream.WriteL(reinterpret_cast<TUint8*>(runStartPtr), 128*4);
1195 aStream.WriteInt8L(-pixelLength);
1196 aStream.WriteL(reinterpret_cast<TUint8*>(runStartPtr), pixelLength*4);
1200 const TInt remainingPixels = srceLimitPtr - ptr;
1201 if (remainingPixels > 0)
1203 __ASSERT_DEBUG(remainingPixels == 1, Panic(EFbsBitmapDecompressionError));
1205 aStream.WriteInt8L(-remainingPixels);
1206 aStream.WriteL(reinterpret_cast<TUint8*>(ptr), remainingPixels*4);
1210 TInt CBitwiseBitmap::SizeOfDataCompressed(TUint8* aData,TInt aSizeInBytes) const
1215 switch (iHeader.iBitsPerPixel)
1221 return SizeOfByteDataCompressed(aData,aSizeInBytes);
1223 return SizeOfTwelveBitDataCompressed(aData,aSizeInBytes);
1225 return SizeOfSixteenBitDataCompressed(aData,aSizeInBytes);
1227 return SizeOfTwentyFourBitDataCompressed(aData,aSizeInBytes);
1229 __ASSERT_DEBUG(iHeader.iColor == SEpocBitmapHeader::EColor||
1230 iHeader.iColor == SEpocBitmapHeader::EColorAlpha||
1231 iHeader.iColor == SEpocBitmapHeader::EColorAlphaPM,
1232 Panic(EFbsBitmapInvalidCompression));
1233 if(iHeader.iColor == SEpocBitmapHeader::EColor)
1235 return SizeOfThirtyTwoUBitDataCompressed(aData,aSizeInBytes);
1239 return SizeOfThirtyTwoABitDataCompressed(aData,aSizeInBytes);
1248 TInt CBitwiseBitmap::SizeOfByteDataCompressed(TUint8* aData,TInt aSizeInBytes) const
1253 TInt compressedSize=0;
1254 TUint8* dataLimit=aData+aSizeInBytes-2;
1256 while(aData<dataLimit)
1258 TUint8 value=*aData;
1259 if (*(aData+1)==value && *(aData+2)==value)
1261 TUint8* runStartPtr=aData;
1263 while(aData<dataLimit && *aData==value)
1265 TInt runLength=aData-runStartPtr;
1267 compressedSize+= 2*(((runLength-1)>>7) + 1) ;
1271 TUint8* runStartPtr=aData;
1272 while(aData<dataLimit && (*(aData+1)!=value || *(aData+2)!=value))
1277 TInt runLength=aData-runStartPtr;
1279 compressedSize+= runLength + ((runLength-1)>>7) + 1;
1283 if (aData<dataLimit)
1284 compressedSize+=dataLimit-aData+1;
1285 return(compressedSize);
1288 TInt CBitwiseBitmap::SizeOfTwelveBitDataCompressed(TUint8* aData,TInt aSizeInBytes) const
1293 TInt compressedSize = 0;
1294 TUint16* srcePtr = (TUint16*)aData;
1295 TUint16* srcePtrLimit = srcePtr + (aSizeInBytes / 2);
1297 while (srcePtr < srcePtrLimit)
1299 TUint16* runStartPtr = srcePtr;
1300 TUint16 value = TUint16(*srcePtr & 0x0fff);
1305 while (srcePtr < srcePtrLimit && *srcePtr == value);
1307 TInt pixelLength = srcePtr - runStartPtr;
1309 compressedSize += 2*( ((pixelLength-1)>>4) + 1);
1311 return compressedSize;
1314 TInt CBitwiseBitmap::SizeOfSixteenBitDataCompressed(TUint8* aData,TInt aSizeInBytes) const
1319 TInt compressedSize = 0;
1320 TUint16* srcePtr = (TUint16*)aData;
1321 TUint16* srceLimitPtr = srcePtr + (aSizeInBytes / 2);
1322 TUint16* srceLimitPtrMinusOne = srceLimitPtr - 1;
1324 while (srcePtr < srceLimitPtrMinusOne)
1326 TUint16 value = *srcePtr;
1327 TUint16* runStartPtr = srcePtr++;
1329 if(*srcePtr == value)
1335 while(srcePtr < srceLimitPtr && *srcePtr == value);
1337 TInt pixelLength = srcePtr-runStartPtr;
1339 compressedSize += 3*( ((pixelLength-1)>>7) + 1);
1344 while (srcePtr < srceLimitPtrMinusOne && *(srcePtr + 1) != value)
1350 TInt pixelLength = srcePtr-runStartPtr;
1352 compressedSize += (pixelLength * 2) + ((pixelLength-1)>>7) + 1;
1355 if (srcePtr < srceLimitPtr)
1356 compressedSize += ((srceLimitPtr - srcePtr) * 2) + 1;
1357 return compressedSize;
1360 TInt CBitwiseBitmap::SizeOfTwentyFourBitDataCompressed(TUint8* aData,TInt aSizeInBytes) const
1365 TInt compressedSize = 0;
1366 TUint8* srceLimitPtr = aData + aSizeInBytes;
1367 TUint8* srceLimitPtrMinusThree = srceLimitPtr - 3; // three bytes == one pixel
1369 while (aData < srceLimitPtrMinusThree)
1371 TUint8* runStartPtr = aData;
1372 TUint8 component1 = *aData++;
1373 TUint8 component2 = *aData++;
1374 TUint8 component3 = *aData++;
1376 if (TrueColorPointerCompare(aData,component1,component2,component3))
1382 while (aData < srceLimitPtr && TrueColorPointerCompare(aData,component1,component2,component3));
1384 TInt pixelLength = (aData - runStartPtr) / 3;
1386 compressedSize += 4*( ((pixelLength-1)>>7) + 1);
1391 TBool eqRun = EFalse;
1394 component1 = *aData++;
1395 component2 = *aData++;
1396 component3 = *aData++;
1397 more = (aData < srceLimitPtr);
1398 eqRun = more && TrueColorPointerCompare(aData,component1,component2,component3);
1400 while (more && !eqRun);
1403 TInt pixelLength = (aData - runStartPtr) / 3;
1405 compressedSize += (pixelLength * 3) + ((pixelLength-1)>>7) + 1;
1409 if (aData < srceLimitPtr)
1410 compressedSize += srceLimitPtr - aData + 1;
1412 return compressedSize;
1415 /** The function calculates the size of 24-bit RLE compression stream which could be obtain from given 32-bit buffer,
1416 where the top bytes are unused*/
1417 TInt CBitwiseBitmap::SizeOfThirtyTwoUBitDataCompressed(TUint8* aData8,TInt aSizeInBytes) const
1422 __ASSERT_DEBUG((reinterpret_cast<TUint32>(aData8) & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is word aligned
1423 __ASSERT_DEBUG((aSizeInBytes & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the size is whole no of pixels
1426 TInt compressedSize = 0;
1429 TUint32* ptr = reinterpret_cast<TUint32*>(aData8);
1430 TUint32* srceLimitPtr = reinterpret_cast<TUint32*>(aData8 + aSizeInBytes);
1431 TUint32* srceLimitPtr2ndLast = srceLimitPtr - 1;
1432 while (ptr < srceLimitPtr2ndLast)
1434 TUint32* runStartPtr = ptr;
1435 TUint32 pixel = *ptr++ & 0x00ffffff;
1437 if ((((*ptr)&0x00ffffff)==pixel))
1443 while (ptr < srceLimitPtr && (((*ptr)&0x00ffffff)==pixel));
1445 TInt pixelLength = (ptr - runStartPtr);
1446 compressedSize += 4*( ((pixelLength-1)>>7) + 1);
1451 TBool eqRun = EFalse;
1454 pixel = *ptr++ & 0x00ffffff;
1455 more = (ptr < srceLimitPtr);
1456 eqRun = more && (((*ptr)&0x00ffffff)==pixel);
1457 } while (more && !eqRun);
1462 TInt pixelLength = (ptr - runStartPtr) ;
1463 compressedSize += 3*pixelLength + ((pixelLength-1)>>7) + 1;
1467 if (ptr < srceLimitPtr)
1468 compressedSize += (srceLimitPtr - ptr)*3 + 1;
1470 return compressedSize;
1474 TBool CBitwiseBitmap::TrueColorPointerCompare(TUint8* aColorPointer,TUint8 aComponent1,TUint8 aComponent2,TUint8 aComponent3) const
1476 return (*aColorPointer == aComponent1 && *(aColorPointer + 1) == aComponent2 && *(aColorPointer + 2) == aComponent3);
1479 /** This function calculates the size of 32-bit RLE compression stream which is obtained from a given 32-bit buffer,
1480 where the top 8 bits are used to represent the alpha channel*/
1481 TInt CBitwiseBitmap::SizeOfThirtyTwoABitDataCompressed(TUint8* aData8,TInt aSizeInBytes) const
1486 __ASSERT_DEBUG((reinterpret_cast<TUint32>(aData8) & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the start address is word aligned
1487 __ASSERT_DEBUG((aSizeInBytes & 0x3)==0,Panic(EFbsBitmapDecompressionError)); // make sure the size is whole no of pixels
1490 TInt compressedSize = 0;
1493 TUint32* ptr = reinterpret_cast<TUint32*>(aData8);
1494 TUint32* srceLimitPtr = reinterpret_cast<TUint32*>(aData8 + aSizeInBytes);
1495 TUint32* srceLimitPtr2ndLast = srceLimitPtr - 1;
1496 while (ptr < srceLimitPtr2ndLast)
1498 TUint32* runStartPtr = ptr;
1499 TUint32 pixel = *ptr++;
1507 while (ptr < srceLimitPtr && *ptr==pixel);
1509 TInt pixelLength = (ptr - runStartPtr);
1510 compressedSize += 5*( ((pixelLength-1)>>7) + 1);
1515 TBool eqRun = EFalse;
1519 more = (ptr < srceLimitPtr);
1520 eqRun = more && *ptr==pixel;
1521 } while (more && !eqRun);
1526 TInt pixelLength = (ptr - runStartPtr) ;
1527 compressedSize += 4*pixelLength + ((pixelLength-1)>>7) + 1;
1531 if (ptr < srceLimitPtr)
1532 compressedSize += (srceLimitPtr - ptr)*4 + 1;
1534 return compressedSize;
1538 /* Here's a BNF description of the RLE encoding in use for all but the 12-bit compression:
1541 run := equal-run | unequal-run
1542 equal-run := <runlength - 1> pixel-value
1543 unequal-run := <-runlength> pixel-value+ (i.e. pixel-value repeated <runlength> times)
1544 runlength := uint8 in 1..128
1545 pixelvalue := byte-pixel | 16bit-pixel | 24bit-pixel | 32bit-u-pixel | 32bit-a-pixel
1547 16bit-pixel := octet octet
1548 24bit-pixel := rr gg bb
1549 32bit-u-pixel := rr gg bb
1550 32bit-a-pixel := rr gg bb aa
1551 rr := octet (red component)
1552 gg := octet (green component)
1553 bb := octet (blue component)
1554 aa := octet (alpha channel)
1556 This scheme models runs of 2-128 equal pixels or of upto 127 unequal pixels.
1557 Obviously a run of 0 is meaningless. A run of 1 is considered to be an 'unequal' run containing
1560 For 12-bit compression a different encoding scheme is used. Only equal-runs are written, and the
1561 run length is encoded into the top 4 bits of a 16 bit word. Here's a BNF for 12-bit compression:
1563 12-bit-encoding := run*
1565 equal-run := high-octet low-octet
1566 high-octet := [<runlength - 1> rr]
1567 low-octet := [gg bb]
1569 rr := quartet (red component)
1570 gg := quartet (green component)
1571 bb := quartet (blue component)
1575 //Palette compression additions
1578 Attempts to compress a bitmap by reducing it to a palette + data.
1579 If the compression fails, for any of the reasons detailed below, RLE compression will be attempted instead.
1581 - Bitmap must not already be compressed.
1582 - Bitmap must contain no more than 255 colors - If bitmap contains >255 colors then palette compression is unlikely to be effective.
1583 - Bitmap must be 16, 24 or 32 (non alpha) bpp. Other modes could be implemented, but smaller bit depths will yield less compression
1584 Small bitmaps (under 1000 pixels) will be unlikely to compress well if at all
1585 Structure of compressed bitmap will be as follows;
1586 size of palette[4 bytes] | palette[size * 4 bytes per entry] | data[pixels * upto 1 byte per pixel]
1587 Bitmap data is packed into memory as efficiently as possible, according to the number of bits required.
1588 Each line of the compressed bitmap will start on a byte boundary, but not necessarily on a word boundary.
1590 TInt CBitwiseBitmap::PaletteCompress()
1592 //Compression algorithm
1593 //1.Iterate bitmap data, building hash of unique colours found
1594 //2.Iterate the hash, and build linear array of the unique colours (this is the palette)
1595 //3.Iterate the array, and set the array index of each colour back into the hash
1596 //4.Iterate the bitmap data again, for each pixel replace with palette index found from hash
1598 //Bitmap must be uncompressed
1599 if (iHeader.iCompression != ENoBitmapCompression)
1602 //There must be some data in the bitmap
1603 TUint8* base = REINTERPRET_CAST(TUint8*, DataAddress());
1607 //Get the bytes per pixel, and make sure it is a supported configuration
1608 TUint sourceBytesPerPixel = PaletteBytesPerPixel(iHeader.iBitsPerPixel);
1609 if (sourceBytesPerPixel == 0)
1610 return KErrNotSupported;
1612 //Create a hash table and give it a decent amount of RAM to start with
1613 RHashMap<TInt,TInt> colors;
1614 if (colors.Reserve(256) != KErrNone)
1615 return KErrNoMemory;
1617 //Loop the data area of the bitmap, one pixel (sourceBytesPerPixel bytes) at a time
1618 TInt numPixels = (iHeader.iSizeInPixels.iWidth * iHeader.iSizeInPixels.iHeight);
1619 //we need some pixels!
1626 TUint8* top = base + (iHeader.iSizeInPixels.iHeight * iByteWidth) ; //address of lastmost byte
1627 TInt32 lineLengthInBytes = iHeader.iSizeInPixels.iWidth * sourceBytesPerPixel; //The actual useful data on each line
1628 TInt32 lineLengthInBytesPadded = iByteWidth ; //the actual (aligned) length of each line
1629 TUint8* pixelAddress;
1630 TUint8* lineAddress;
1631 //Loop each line of the bitmap data. Note that each line ends on a 32bit align in the source MBM data.
1634 //Separate looping for 16 & 24+ bpp. Adds a chunk of duplicated code but saves checking bpp for every pixel
1635 if (iHeader.iBitsPerPixel < 24)
1637 for (lineAddress=base;lineAddress<top;lineAddress+=iByteWidth)
1639 //Loop each pixel within the line
1640 lineEnd = lineAddress + lineLengthInBytes;
1641 for (pixelAddress = lineAddress; pixelAddress < lineEnd; pixelAddress += sourceBytesPerPixel)
1643 //Extract colour value
1644 TUint color = *pixelAddress;
1645 color |= (*(pixelAddress+1)) << 8;
1646 //Insert colour value into hash
1647 //Quicker to use Find() to eliminate duplicates Insert()
1648 if (colors.Find(color) == NULL)
1650 if (colors.Insert(color,0) != KErrNone)
1653 return KErrNoMemory;
1657 //Test each line whether it's worth continuing to the end
1658 //We aren't interested if there's more than 256 colours (RLE compression will probably do a better job in this case)
1659 if (colors.Count() > 256)
1662 return KErrNotSupported ;
1668 for (lineAddress = base; lineAddress<top; lineAddress += iByteWidth)
1670 //Loop each pixel within the line
1671 lineEnd = lineAddress + lineLengthInBytes;
1672 for (pixelAddress = lineAddress; pixelAddress < lineEnd; pixelAddress += sourceBytesPerPixel)
1674 //Extract colour value
1675 TUint color = *pixelAddress;
1676 color |= (*(pixelAddress+1)) << 8;
1677 color |= (*(pixelAddress+2)) << 16;
1678 //Insert colour value into hash
1679 //Quicker to use Find() to eliminate duplicates Insert()
1681 if (colors.Find(color) == NULL)
1683 if (colors.Insert(color,0) != KErrNone)
1686 return KErrNoMemory;
1690 //Test each line whether it's worth continuing to the end
1691 //We aren't interested if there's more than 256 colours (RLE compression will probably do a better job in this case)
1692 if (colors.Count() > 256)
1695 return KErrNotSupported;
1701 //Now we have enough data to build the palette by iterating all the entries in the colors hash
1702 RArray<TUint> palette(colors.Count());
1703 THashMapIter<TInt,TInt> colorIterator(colors);
1704 const TInt* color = colorIterator.NextKey();
1707 if (palette.Append(*color) != KErrNone)
1711 return KErrNoMemory;
1713 //set the index of each entry back into the color hash for lookup later
1714 //const cast needed as CurrentValue returns a const pointer; for no good reason?
1715 TInt* index = CONST_CAST(TInt*, colorIterator.CurrentValue());
1716 *index = palette.Count() - 1;
1717 color = colorIterator.NextKey();
1720 //Set up some new memory for the palettised bitmap
1721 //size is (4 bytes for palette size) + (4 bytes per palette entry) + (upto 1 byte per pixel)
1722 //pixels are packed according to number of colors
1723 TUint compressedBitsPerPixel = PaletteBitsPerPixel(colors.Count());
1724 TUint compressedPixelsPerByte = 8 / compressedBitsPerPixel;
1725 TUint compressedLineLengthInBytesPadded = (iHeader.iSizeInPixels.iWidth + compressedPixelsPerByte - 1)/ compressedPixelsPerByte;
1726 TInt compressedDataBytes = 4 + 4 * colors.Count() + compressedLineLengthInBytesPadded * iHeader.iSizeInPixels.iHeight;
1728 //add two extra ints for storing function pointers (8 bytes )
1729 compressedDataBytes += 8 ;
1731 TUint8* compressedBase = NULL;
1732 compressedBase = iPile->Alloc(compressedDataBytes);
1733 if (!compressedBase)
1737 return KErrNoMemory;
1739 iDataOffset = compressedBase - iPile->ChunkBase();
1741 iHeader.iBitmapSize = sizeof(SEpocBitmapHeader) + compressedDataBytes;
1742 iHeader.iCompression = EGenericPaletteCompression;
1744 //copy the palette length into the data area...
1745 *(REINTERPRET_CAST(TInt*, compressedBase)) = palette.Count(); //let's hope we're 4 byte aligned...
1747 //...then the palette itself...
1748 for (TUint loop = 0; loop < palette.Count(); loop++)
1750 *(REINTERPRET_CAST(TInt*, compressedBase)) = palette[loop];
1754 //Work out, then store, the decoding functions required for packing density and colour depth.
1755 //This saves having to do it for every scanline during decompression.
1757 TDecodeFunction decodeFunction = NULL;
1758 switch (compressedPixelsPerByte)
1761 decodeFunction=CBitwiseBitmap::PaletteDecode1PixelPerByte;
1764 decodeFunction=CBitwiseBitmap::PaletteDecode2PixelPerByte;
1767 decodeFunction=CBitwiseBitmap::PaletteDecode4PixelPerByte;
1770 decodeFunction=CBitwiseBitmap::PaletteDecode8PixelPerByte;
1773 ::Panic(EFbsNotSupportedForCompression);
1775 *(REINTERPRET_CAST(TDecodeFunction*, compressedBase)) = decodeFunction ;
1776 compressedBase += 4 ;
1778 //Select the appropriate assignment function based on the bits-per-pixel of the target
1779 TAssignFunction assignFunction = NULL;
1780 switch (iHeader.iBitsPerPixel)
1783 assignFunction=CBitwiseBitmap::PaletteAssign16BitColor;
1786 assignFunction=CBitwiseBitmap::PaletteAssign24BitColor;
1789 assignFunction=CBitwiseBitmap::PaletteAssign32BitColor;
1792 ::Panic(EFbsNotSupportedForCompression);
1794 *(REINTERPRET_CAST(TAssignFunction*, compressedBase)) = assignFunction ;
1795 compressedBase += 4 ;
1797 //...and finally the data
1798 pixelAddress = base;
1800 //separate loops for 16 & 24+ bpp again
1802 if ( iHeader.iBitsPerPixel < 24 )
1804 for (lineAddress = base; lineAddress < top; lineAddress += lineLengthInBytesPadded)
1806 //Loop each pixel within the line
1807 pixelAddress = lineAddress;
1808 while (pixelAddress < lineAddress + lineLengthInBytes)
1811 //loop for each pixel to pack into the byte. If we run out of pixels in the line, we write out the pack byte and continue on the next line
1812 for (TInt ii = 0; ii < compressedPixelsPerByte && pixelAddress < lineAddress + lineLengthInBytes; ii++)
1814 pack <<= compressedBitsPerPixel;
1816 TUint color = *pixelAddress;
1817 color |= (*(pixelAddress+1)) << 8;
1819 //lookup the palette index for the color
1820 TInt* paletteIndex = colors.Find(color);
1821 //pack the palette index into the target byte
1822 pack |= *paletteIndex;
1824 pixelAddress += sourceBytesPerPixel;
1826 //store the packed pixel data into the new compressed data area
1827 *compressedBase = pack;
1834 for (lineAddress = base; lineAddress < top; lineAddress += lineLengthInBytesPadded)
1836 //Loop each pixel within the line
1837 pixelAddress = lineAddress;
1838 while (pixelAddress < lineAddress + lineLengthInBytes)
1841 //loop for each pixel to pack into the byte. If we run out of pixels in the line, we write out the pack byte and continue on the next line
1842 for (TInt ii = 0; ii < compressedPixelsPerByte && pixelAddress < lineAddress + lineLengthInBytes; ii++)
1844 pack <<= compressedBitsPerPixel;
1846 TUint color = *pixelAddress;
1847 color |= (*(pixelAddress+1)) << 8;
1848 color |= (*(pixelAddress+2)) << 16;
1849 //if 32 bit, just ignore the 4th byte as it is unused for color data
1851 //lookup the palette index for the color
1852 TInt* paletteIndex = colors.Find(color);
1853 //pack the palette index into the target byte
1854 pack |= *paletteIndex;
1856 pixelAddress += sourceBytesPerPixel;
1858 //store the packed pixel data into the new compressed data area
1859 *compressedBase = pack;
1866 //Set the RAM compression flag
1867 iIsCompressedInRAM = ETrue;
1869 //Free the old data.
1878 Create a scan line from a palette compressed bitmap.
1879 Starting from aPixel in the bitmap pointed to be aBase, populate aDestBuffer with aLength pixels looked up in the palette.
1880 Note this function assumes 16, 24 or 32 non alpha bit uncompressed bitmaps, compressed into 8 bit palettes (ie <256 colors)
1881 Structure of bitmap is (4 bytes for palette size) + (4 bytes per palette entry) + (1 byte per pixel)
1882 @param aDestBuffer Points to the destination buffer. After the call it will be filled
1883 with the decompressed data.
1884 @param aPixel The decompression starts from this pixel
1885 @param aLength Length of requested decompressed data - in pixels
1886 @param aBase Points to the beginning of compressed bitmap data
1887 @param aLineScannngPosition Saved information about the last used position in the compressed data
1889 void CBitwiseBitmap::GenerateLineFromPaletteCompressedData(
1890 TUint8* aDestBuffer,
1891 const TPoint& aPixel,
1894 TLineScanningPosition& /*aLineScanningPosition*/) const
1896 //At entry, aBase will point to the start of the compressed data, ie the palette size
1897 //Each line in the bitmap will start at a byte boundary in the compressed data.
1899 TUint32* srcPalette = aBase + 1; //Address of the palette in the source data
1900 TUint srcNumPaletteEntries = *aBase; //Number of entries in the palette (will be <=255)
1901 TUint compressedBitsPerPixel = PaletteBitsPerPixel(srcNumPaletteEntries);
1902 __ASSERT_DEBUG(compressedBitsPerPixel <= 8, Panic( EFbsBitmapDecompressionError )) ;
1903 const TUint8 lookup[] = {0, 8, 4, 0, 2, 0, 0, 0, 1};
1904 //TUint compressedPixelsPerByte = 8 / compressedBitsPerPixel;
1905 TUint compressedPixelsPerByte = lookup[compressedBitsPerPixel];
1906 __ASSERT_DEBUG(compressedPixelsPerByte>0, ::Panic(EFbsNotSupportedForCompression));
1908 TUint8* srcData = REINTERPRET_CAST(TUint8*, srcPalette + srcNumPaletteEntries); //Address of the pixel data in the source data
1910 //Extract the function pointers for decoding functions. Set up decode & assign functions.
1911 TDecodeFunction decodeFunction = NULL ;
1912 decodeFunction = reinterpret_cast<TDecodeFunction>(*((TUint32*)srcData )) ;
1914 TAssignFunction assignFunction = NULL;
1915 assignFunction = reinterpret_cast<TAssignFunction>(*((TUint32*)srcData )) ;
1918 //Note: The following lines have been optimised to avoid divisions.
1919 //By way of explanation the original lines have been left as comments
1921 //TUint srcBytesPerLinePadded = (iHeader.iSizeInPixels.iWidth + compressedPixelsPerByte - 1) / compressedPixelsPerByte; //number of bytes occupied by each line in the compressed bitmap.
1922 TUint srcBytesPerLinePadded = ((iHeader.iSizeInPixels.iWidth + compressedPixelsPerByte - 1) * compressedBitsPerPixel) >> 3; //number of bytes occupied by each line in the compressed bitmap.
1923 //TUint srcStartBytesFromBase = aPixel.iY * srcBytesPerLinePadded + aPixel.iX / compressedPixelsPerByte; //Starting bytes from the start of the bitmap
1924 TUint srcStartBytesFromBase = aPixel.iY * srcBytesPerLinePadded + ((aPixel.iX * compressedBitsPerPixel) >> 3); //Starting bytes from the start of the bitmap
1925 //TUint srcStartPixelInByte = aPixel.iX % compressedPixelsPerByte; //starting pixel position in byte (lines start on byte boundary)
1926 TUint srcStartPixelInByte = aPixel.iX & ((compressedPixelsPerByte)- 1); //starting pixel position in byte (lines start on byte boundary)
1927 //TUint srcEndBytesFromBase = srcStartBytesFromBase + (aLength + compressedPixelsPerByte - 1) / compressedPixelsPerByte; //Ending bytes from the start of the bitmap
1928 TUint srcEndBytesFromBase = srcStartBytesFromBase + (((aLength + compressedPixelsPerByte - 1) * compressedBitsPerPixel) >> 3); //Ending bytes from the start of the bitmap
1929 //TUint srcEndPixelInByte = (aPixel.iX + aLength) % compressedPixelsPerByte; //Ending pixel position in byte
1930 TUint srcEndPixelInByte = (aPixel.iX + aLength) & ((compressedPixelsPerByte)-1); //Ending pixel position in byte
1931 TUint8* srcStartData = srcData + srcStartBytesFromBase; //Address of the first byte of packed pixels in the source
1932 TUint8* srcEndData = srcData + srcEndBytesFromBase; //Address of the last+1 byte of packed pixels in the source
1933 TUint8* destStartData = aDestBuffer + ((aPixel.iX*iHeader.iBitsPerPixel) >> 3); //Address of the first pixel in the destination
1935 //3 stages to the decompression:
1936 //1. Decompress any pixels which are a subset of the first byte
1937 //2. Loop whole bytes extracting all pixels at once
1938 //3. Decompress any pixels which are a subset of the last byte
1940 TUint8* srcDataPtr = srcStartData;
1942 //Stage 1: Decompress any pixels which are a subset of the first byte
1943 if (srcStartPixelInByte > 0)
1944 PaletteDecodeAndAssignGeneric(srcDataPtr++, srcPalette, destStartData, srcStartPixelInByte, compressedPixelsPerByte-1, compressedPixelsPerByte, compressedBitsPerPixel);
1946 //If the last byte is only partly packed with pixels from this line, stop one byte short in the main loop
1947 if (srcEndPixelInByte > 0)
1950 //Stage 2: Loop all the required pixels and call the appropriate functions
1951 while (srcDataPtr < srcEndData)
1953 __ASSERT_DEBUG(srcDataPtr <= srcEndData, ::Panic(EFbsNotSupportedForCompression));
1954 __ASSERT_DEBUG(destStartData <= aDestBuffer + ((aPixel.iX*iHeader.iBitsPerPixel) >> 3) + aLength * PaletteBytesPerPixel(iHeader.iBitsPerPixel), ::Panic(EFbsNotSupportedForCompression));
1955 (*decodeFunction)(srcDataPtr++, srcPalette, destStartData, assignFunction);
1958 //Stage 3: Decompress any pixels which are a subset of the last byte
1959 if (srcEndPixelInByte > 0)
1960 PaletteDecodeAndAssignGeneric(srcDataPtr++, srcPalette, destStartData, 0, srcEndPixelInByte-1, compressedPixelsPerByte, compressedBitsPerPixel);
1964 This function deals with all different bit depths & color counts dynamically - smaller but slower
1965 @param aDataPtr Address in compressed data to read from
1966 @param aPalettePtr Address of the start of the palette in the compressed data
1967 @param aDestPtr Address to write uncompressed data to. Will be incremented on return from function.
1968 @param aStartPixel Zero based position within the compressed byte of the first pixel to decompress
1969 @param aEndPixel Zero based position within the compressed byte of the last pixel to decompress
1970 @param aCompressedPixelsPerByte Number of pixels packed into each byte of the compressed data
1971 @param aCompressedBitsPerPixel Number of bits used to express each pixel in the compressed data. Nothing to do with the color depth of the image.
1973 void CBitwiseBitmap::PaletteDecodeAndAssignGeneric( TUint8* aDataPtr,
1974 TUint32* aPalettePtr,
1978 TUint aCompressedPixelsPerByte,
1979 TUint aCompressedBitsPerPixel) const
1981 __ASSERT_DEBUG(aStartPixel<aCompressedPixelsPerByte, ::Panic(EFbsNotSupportedForCompression));
1982 __ASSERT_DEBUG(aEndPixel<aCompressedPixelsPerByte, ::Panic(EFbsNotSupportedForCompression));
1984 //create a mask for the appropriate number of bits
1986 mask <<= 8 - aCompressedBitsPerPixel;
1988 //Adjust the mask in case we've been asked to start at an intermediate pixel
1989 mask >>= aStartPixel * aCompressedBitsPerPixel;
1991 TUint8 pack = *aDataPtr; //max of 8 bits for palette entry
1993 //Loop the pixel data from the requested start to the requested end
1994 for (TInt ii = aStartPixel; ii <= aEndPixel; ii++)
1996 //extract the bits corresponding to the required color index from the pack using the mask
1997 TUint8 index = pack&mask;
1998 //shift the index to the right to get true value
1999 index >>= (aCompressedPixelsPerByte- ii - 1) * aCompressedBitsPerPixel;
2000 //get the address of the required color value from the palette
2001 TUint32 color = *(aPalettePtr + index);
2002 //and copy the actual color value into the scanline buffer
2003 *aDestPtr ++= color;
2004 *aDestPtr ++= color >> 8;
2005 if (iHeader.iBitsPerPixel >= 24)
2006 *aDestPtr ++= color >> 16;
2007 if (iHeader.iBitsPerPixel == 32)
2008 *aDestPtr ++= 0xFF; //use 0xFF rather than 0x00 as it is more alpha friendly
2010 //shift the mask to get the next required bits
2011 mask >>= aCompressedBitsPerPixel;
2016 Specialised function for decoding pixels from a palette compressed bitmap with 1 pixel packed in each byte.
2017 Implemented for speed, not size
2018 @param aDataPtr Address in compressed data to read from
2019 @param aPalettePtr Address of the start of the palette in the compressed data
2020 @param aDestPtr Address to write uncompressed data to. Will be incremented on return from function.
2021 @param aAssignFunction Function pointer to assigment function to use to write actual pixel data to uncompressed scanline
2023 void CBitwiseBitmap::PaletteDecode1PixelPerByte(TUint8* aDataPtr, TUint32* aPalettePtr, TUint8*& aDestPtr, TAssignFunction aAssignFunction)
2025 (*aAssignFunction)(aDestPtr, *(aPalettePtr + *aDataPtr));
2029 Specialised function for decoding pixels from a palette compressed bitmap with 2 pixels packed in each byte.
2030 Implemented for speed, not size
2031 @param aDataPtr Address in compressed data to read from
2032 @param aPalettePtr Address of the start of the palette in the compressed data
2033 @param aDestPtr Address to write uncompressed data to. Will be incremented on return from function.
2034 @param aAssignFunction Function pointer to assigment function to use to write actual pixel data to uncompressed scanline
2036 void CBitwiseBitmap::PaletteDecode2PixelPerByte(TUint8* aDataPtr, TUint32* aPalettePtr, TUint8*& aDestPtr, TAssignFunction aAssignFunction)
2038 TUint8 mask = 0xF0; //binary 11110000
2039 TUint8 pack = *aDataPtr;
2041 TUint8 index = pack&mask;
2043 TUint32 color = *(aPalettePtr + index);
2044 (*aAssignFunction)(aDestPtr, color);
2048 color = *(aPalettePtr + index);
2049 (*aAssignFunction)(aDestPtr, color);
2053 Specialised function for decoding pixels from a palette compressed bitmap with 4 pixels packed in each byte.
2054 Implemented for speed, not size
2055 @param aDataPtr Address in compressed data to read from
2056 @param aPalettePtr Address of the start of the palette in the compressed data
2057 @param aDestPtr Address to write uncompressed data to. Will be incremented on return from function.
2058 @param aAssignFunction Function pointer to assigment function to use to write actual pixel data to uncompressed scanline
2060 void CBitwiseBitmap::PaletteDecode4PixelPerByte(TUint8* aDataPtr, TUint32* aPalettePtr, TUint8*& aDestPtr, TAssignFunction aAssignFunction)
2062 TUint8 mask = 0xC0; //binary 11000000
2063 TUint8 pack = *aDataPtr;
2065 TUint8 index = pack&mask;
2067 TUint32 color = *(aPalettePtr + index);
2068 (*aAssignFunction)(aDestPtr, color);
2073 color = *(aPalettePtr + index);
2074 (*aAssignFunction)(aDestPtr, color);
2079 color = *(aPalettePtr + index);
2080 (*aAssignFunction)(aDestPtr, color);
2084 color = *(aPalettePtr + index);
2085 (*aAssignFunction)(aDestPtr, color);
2089 Specialised function for decoding pixels from a palette compressed bitmap with 8 pixels packed in each byte.
2090 Implemented for speed, not size
2091 @param aDataPtr Address in compressed data to read from
2092 @param aPalettePtr Address of the start of the palette in the compressed data
2093 @param aDestPtr Address to write uncompressed data to. Will be incremented on return from function.
2094 @param aAssignFunction Function pointer to assigment function to use to write actual pixel data to uncompressed scanline
2096 void CBitwiseBitmap::PaletteDecode8PixelPerByte(TUint8* aDataPtr, TUint32* aPalettePtr, TUint8*& aDestPtr, TAssignFunction aAssignFunction)
2098 TUint8 mask = 0x80; //binary 10000000
2099 TUint8 pack = *aDataPtr;
2101 TUint8 index = pack&mask;
2103 TUint32 color = *(aPalettePtr + index);
2104 (*aAssignFunction)(aDestPtr, color);
2109 color = *(aPalettePtr + index);
2110 (*aAssignFunction)(aDestPtr, color);
2115 color = *(aPalettePtr + index);
2116 (*aAssignFunction)(aDestPtr, color);
2121 color = *(aPalettePtr + index);
2122 (*aAssignFunction)(aDestPtr, color);
2127 color = *(aPalettePtr + index);
2128 (*aAssignFunction)(aDestPtr, color);
2133 color = *(aPalettePtr + index);
2134 (*aAssignFunction)(aDestPtr, color);
2139 color = *(aPalettePtr + index);
2140 (*aAssignFunction)(aDestPtr, color);
2144 color = *(aPalettePtr + index);
2145 (*aAssignFunction)(aDestPtr, color);
2149 Specialised function for assigning pixels into an uncompressed scanline of 16 bit color depth.
2150 Implemented for speed, not size
2151 @param aDestPtr Address to write uncompressed data to. Will be incremented on return from function.
2152 @param aColor Color info to write.
2154 void CBitwiseBitmap::PaletteAssign16BitColor(TUint8*& aDestPtr, TUint32 aColor)
2156 *aDestPtr ++= aColor;
2157 *aDestPtr ++= aColor >> 8;
2161 Specialised function for assigning pixels into an uncompressed scanline of 24 bit color depth.
2162 Implemented for speed, not size
2163 @param aDestPtr Address to write uncompressed data to. Will be incremented on return from function.
2164 @param aColor Color info to write.
2166 void CBitwiseBitmap::PaletteAssign24BitColor(TUint8*& aDestPtr, TUint32 aColor)
2168 *aDestPtr ++= aColor;
2169 *aDestPtr ++= aColor >> 8;
2170 *aDestPtr ++= aColor >> 16;
2174 Specialised function for assigning pixels into an uncompressed scanline of 32 bit color depth.
2175 Implemented for speed, not size
2176 @param aDestPtr Address to write uncompressed data to. Will be incremented on return from function.
2177 @param aColor Color info to write.
2179 void CBitwiseBitmap::PaletteAssign32BitColor(TUint8*& aDestPtr, TUint32 aColor)
2181 *aDestPtr ++= aColor;
2182 *aDestPtr ++= aColor >> 8;
2183 *aDestPtr ++= aColor >> 16;
2184 *aDestPtr ++= 0xFF; //use 0xFF rather than 0x00 as it is more alpha friendly
2188 Get the bits used per pixel when packing multiple pixels in palette compression.
2189 The value returned is a power of 2, not always the most efficient pack, for alignment reasons, Eg
2190 65537 -> KMaxTInt : 32 bpp
2191 257 -> 65536 colors : 16 bpp
2192 17 -> 256 colors : 8 bpp
2193 5 -> 16 colors : 4 bpp
2194 3 -> 4 colors : 2 bpp
2195 0 -> 2 colors : 1 bpp
2196 @param aNumColors The number of colors in the bitmap. This governs the size of the palette and thus
2197 the number of bits needed to represent an index into it.
2199 TUint CBitwiseBitmap::PaletteBitsPerPixel(TInt aNumColors) const
2201 if (aNumColors <= 2)
2203 else if (aNumColors <= 4)
2205 else if (aNumColors <= 16)
2207 else if (aNumColors <= 256)
2209 else if (aNumColors <= 65536)
2216 Gets the bytes used per pixel according to the bits per pixel of a bitmap.
2217 Also used to find which bit per pixel values are supported by palette compression, hence this is not
2218 a case of simple division by 8.
2219 If return value is zero, the supplied bit per pixel value is not supported by palette compression.
2220 @param aBitsPerPixel The bits per pixel value to transform into bytes
2222 TUint CBitwiseBitmap::PaletteBytesPerPixel(TInt aBitsPerPixel) const
2224 if (aBitsPerPixel == 16)
2226 else if (aBitsPerPixel == 24)
2228 else if (aBitsPerPixel == 32 && iHeader.iColor == SEpocBitmapHeader::EColor)
2229 return 4; //32 bit with no alpha