--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mmplugins/imagingplugins/codecs/BMPCodec/BMPCodec.cpp Tue Feb 02 01:56:55 2010 +0200
@@ -0,0 +1,917 @@
+// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <fbs.h>
+#include "ImageUtils.h"
+
+#include "BMPCodec.h"
+
+/**
+@file
+@internalComponent
+*/
+
+// CBmpReadCodec
+CBmpReadCodec::CBmpReadCodec(const TSize& aBmpSize, const TRgb* aPalette):
+ iOriginalSize(aBmpSize),
+ iPalette(aPalette)
+ {}
+
+CBmpReadCodec::~CBmpReadCodec()
+ {
+ }
+
+
+
+TFrameState CBmpReadCodec::ProcessFrameL(TBufPtr8& aSrc)
+ {
+ const TUint8* srcStart = aSrc.Ptr();
+ iDataPtr = srcStart;
+ iDataPtrLimit = srcStart + aSrc.Length();
+
+ DoProcessL();
+
+ TInt bytesUsed = iDataPtr - srcStart;
+ aSrc.Shift(bytesUsed);
+ iBytesProcessed += bytesUsed;
+ if (iBytesProcessed >= iBytesExpected)
+ {
+ ImageProcessor()->FlushPixels();
+ return EFrameComplete;
+ }
+
+ return EFrameIncomplete;
+ }
+
+void CBmpReadCodec::InitFrameL(TFrameInfo& aFrameInfo, CFrameImageData& /*aFrameImageData*/, TBool aDisableErrorDiffusion, CFbsBitmap& aDestination, CFbsBitmap* /*aDestinationMask*/)
+ {
+ iFrameSize = aFrameInfo.iFrameCoordsInPixels.Size();
+ Pos().iY = iOriginalSize.iHeight - 1;
+
+ const TSize destinationSize(aDestination.SizeInPixels());
+ TInt reductionFactor = ReductionFactor(iOriginalSize, destinationSize);
+
+ CImageProcessor* imageProc = ImageProcessorUtility::NewImageProcessorL(aDestination, reductionFactor, ERgb, aDisableErrorDiffusion);
+
+ SetImageProcessor(imageProc);
+
+ imageProc->PrepareL(aDestination, iOriginalSize);
+ imageProc->SetPos(TPoint(0,iOriginalSize.iHeight - 1));
+ imageProc->SetYPosIncrement(-1);
+ iBytesProcessed = 0;
+ DoNewFrameL();
+
+ ClearBitmapL(aDestination, KRgbWhite);
+ // clear full bitmap, in case of streaming partial decode
+ }
+
+void CBmpReadCodec::InitFrameHeader(TFrameInfo& aFrameInfo, CFrameImageData& /*aFrameData*/)
+ {
+ ASSERT(aFrameInfo.CurrentFrameState() == TFrameInfo::EFrameInfoUninitialised);
+ iFrameInfo = &aFrameInfo;
+ aFrameInfo.SetCurrentFrameState(TFrameInfo::EFrameInfoProcessingFrameHeader);
+ }
+
+TFrameState CBmpReadCodec::ProcessFrameHeaderL(TBufPtr8&/* aData*/)
+ {
+ ASSERT(iFrameInfo);
+ iFrameInfo->SetCurrentFrameState(TFrameInfo::EFrameInfoProcessingComplete);
+ return EFrameComplete;
+ }
+
+void CBmpReadCodec::DoNewFrameL()
+ {}
+
+
+// CBmp1BppReadCodec
+CBmp1BppReadCodec::CBmp1BppReadCodec(const TSize& aBmpSize, const TRgb* aPalette):
+ CBmpReadCodec(aBmpSize, aPalette)
+ {
+ ASSERT(iPalette);
+ }
+
+
+CBmp1BppReadCodec* CBmp1BppReadCodec::NewL(const TSize& aBmpSize, const TRgb* aPalette)
+{
+ CBmp1BppReadCodec* self = new(ELeave) CBmp1BppReadCodec(aBmpSize, aPalette);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self); // self
+ return self;
+}
+
+void CBmp1BppReadCodec::DoProcessL()
+ {
+ CImageProcessor *const imageProc = ImageProcessor();
+ while (iDataPtr < iDataPtrLimit)
+ {
+ TUint8 value = *iDataPtr++;
+
+ for(TUint8 pixelMask = 0x80; pixelMask!=0 ;pixelMask >>= 1)
+ imageProc->SetPixel((value & pixelMask) ? iEntry1 : iEntry0);
+ }
+ }
+
+void CBmp1BppReadCodec::DoNewFrameL()
+ {
+ iEntry0 = iPalette[0];
+ iEntry1 = iPalette[1];
+
+ TInt actualWidth = (iOriginalSize.iWidth + 31) & ~31;
+ ImageProcessor()->SetPixelPadding(actualWidth - iOriginalSize.iWidth);
+ iBytesExpected = (actualWidth >> 3) * iOriginalSize.iHeight;
+ }
+
+
+// CBmpNoComp4BppReadCodec
+CBmpNoComp4BppReadCodec* CBmpNoComp4BppReadCodec::NewL(const TSize& aBmpSize, const TRgb* aPalette)
+{
+ CBmpNoComp4BppReadCodec* self = new(ELeave) CBmpNoComp4BppReadCodec(aBmpSize, aPalette);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+CBmpNoComp4BppReadCodec::CBmpNoComp4BppReadCodec(const TSize& aBmpSize, const TRgb* aPalette):
+ CBmpReadCodec(aBmpSize, aPalette)
+ {
+ ASSERT(iPalette);
+ }
+
+void CBmpNoComp4BppReadCodec::DoNewFrameL()
+ {
+ TInt actualWidth = (iOriginalSize.iWidth + 7) & ~7;
+ ImageProcessor()->SetPixelPadding(actualWidth - iOriginalSize.iWidth);
+ iBytesExpected = (actualWidth >> 1) * iOriginalSize.iHeight;
+ }
+
+void CBmpNoComp4BppReadCodec::DoProcessL()
+ {
+ CImageProcessor *const imageProc = ImageProcessor();
+ while (iDataPtr < iDataPtrLimit)
+ {
+ TUint8 value = *iDataPtr++;
+ imageProc->SetPixel(iPalette[value >> 4]);
+ imageProc->SetPixel(iPalette[value & 0x0f]);
+ }
+ }
+
+
+// CBmpRLE4ReadCodec
+CBmpRLE4ReadCodec* CBmpRLE4ReadCodec::NewL(const TSize& aBmpSize, const TRgb* aPalette)
+{
+ CBmpRLE4ReadCodec* self = new(ELeave) CBmpRLE4ReadCodec(aBmpSize, aPalette);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+CBmpRLE4ReadCodec::CBmpRLE4ReadCodec(const TSize& aBmpSize, const TRgb* aPalette):
+ CBmpReadCodec(aBmpSize, aPalette)
+ {
+ ASSERT(iPalette);
+ }
+
+void CBmpRLE4ReadCodec::DoNewFrameL()
+ {
+ iBytesExpected = KMaxTInt;
+ }
+
+void CBmpRLE4ReadCodec::DoProcessL()
+ {
+ const TUint8* srcSafeLimit = iDataPtrLimit - 1;
+
+ TPoint& pos = Pos();
+ CImageProcessor*const imageProc = ImageProcessor();
+
+ while (iDataPtr < srcSafeLimit || pos.iY < 0)
+ {
+ TUint8 index = *iDataPtr++;
+ if (index > 0) // Encoded mode
+ WriteRun(*iDataPtr++,index);
+ else
+ {
+ index = *iDataPtr++;
+ if (index > 2) // Absolute mode
+ {
+ TInt byteCount = (index + ((index & 1) ? 1 : 0)) >> 1;
+ TInt padding = (byteCount & 1) ? 1 : 0;
+ if ((iDataPtr + (byteCount + padding)) > iDataPtrLimit)
+ {
+ iDataPtr -= 2;
+ break;
+ }
+ WriteData(index);
+ if (padding)
+ iDataPtr++;
+ }
+ else if (index == 0) // End of line
+ {
+ pos.iX = 0;
+ pos.iY--;
+ if (!imageProc->SetPos(pos))
+ {
+ iBytesExpected = 0;
+ break;
+ }
+ }
+ else if (index == 1) // End of bitmap
+ {
+ iBytesExpected = 0;
+ Pos().iY = -1;
+ break;
+ }
+ else // Delta
+ {
+ if ((iDataPtr + 2) > iDataPtrLimit)
+ {
+ iDataPtr -= 2;
+ break;
+ }
+ imageProc->FlushPixels();
+ pos.iX += *iDataPtr++;
+ pos.iY -= *iDataPtr++;
+ if (!imageProc->SetPos(pos))
+ break;
+ }
+ }
+ }
+ if (pos.iY < 0)
+ {
+ // that may mean a dodgy image, so flag decoding immediately complete
+ iBytesExpected = 0;
+ }
+ }
+
+void CBmpRLE4ReadCodec::WriteRun(TUint8 aValue, TInt aNumPixels)
+ {
+ CImageProcessor*const imageProc = ImageProcessor();
+ Pos().iX += aNumPixels;
+ TRgb highValue = iPalette[aValue >> 4];
+ TRgb lowValue = iPalette[aValue & 0x0f];
+ TInt numPixels;
+ for (numPixels = aNumPixels; numPixels > 1; numPixels -= 2)
+ {
+ imageProc->SetPixel(highValue);
+ imageProc->SetPixel(lowValue);
+ }
+ if (numPixels & 1)
+ imageProc->SetPixel(highValue);
+ }
+
+void CBmpRLE4ReadCodec::WriteData(TInt aNumPixels)
+ {
+ CImageProcessor*const imageProc = ImageProcessor();
+ const TUint8* dataPtrLimit = iDataPtr + (aNumPixels >> 1);
+ while (iDataPtr < dataPtrLimit)
+ {
+ TUint8 value = *iDataPtr++;
+ imageProc->SetPixel(iPalette[value >> 4]);
+ imageProc->SetPixel(iPalette[value & 0x0f]);
+ }
+ if (aNumPixels & 1)
+ {
+ TUint8 value = *iDataPtr++;
+ imageProc->SetPixel(iPalette[value >> 4]);
+ }
+ Pos().iX += aNumPixels;
+ }
+
+
+// CBmpNoComp8BppReadCodec
+CBmpNoComp8BppReadCodec* CBmpNoComp8BppReadCodec::NewL(const TSize& aBmpSize, const TRgb* aPalette)
+{
+ CBmpNoComp8BppReadCodec* self = new(ELeave) CBmpNoComp8BppReadCodec(aBmpSize, aPalette);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+CBmpNoComp8BppReadCodec::CBmpNoComp8BppReadCodec(const TSize& aBmpSize, const TRgb* aPalette):
+ CBmpReadCodec(aBmpSize, aPalette)
+ {
+ ASSERT(iPalette);
+ }
+
+void CBmpNoComp8BppReadCodec::DoNewFrameL()
+ {
+ TInt actualWidth = (iOriginalSize.iWidth + 3) & ~3;
+ ImageProcessor()->SetPixelPadding(actualWidth - iOriginalSize.iWidth);
+ iBytesExpected = actualWidth * iOriginalSize.iHeight;
+ }
+
+void CBmpNoComp8BppReadCodec::DoProcessL()
+ {
+ CImageProcessor*const imageProc = ImageProcessor();
+ while (iDataPtr < iDataPtrLimit)
+ imageProc->SetPixel(iPalette[*iDataPtr++]);
+ }
+
+
+// CBmpRLE8ReadCodec
+CBmpRLE8ReadCodec* CBmpRLE8ReadCodec::NewL(const TSize& aBmpSize, const TRgb* aPalette)
+{
+ CBmpRLE8ReadCodec* self = new(ELeave) CBmpRLE8ReadCodec(aBmpSize, aPalette);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+CBmpRLE8ReadCodec::CBmpRLE8ReadCodec(const TSize& aBmpSize, const TRgb* aPalette):
+ CBmpReadCodec(aBmpSize, aPalette)
+ {
+ ASSERT(iPalette);
+ }
+
+void CBmpRLE8ReadCodec::DoNewFrameL()
+ {
+ iBytesExpected = KMaxTInt;
+ }
+
+void CBmpRLE8ReadCodec::DoProcessL()
+ {
+ const TUint8* srcSafeLimit = iDataPtrLimit - 1;
+
+ TPoint& pos = Pos();
+ CImageProcessor*const imageProc = ImageProcessor();
+
+ while (iDataPtr < srcSafeLimit || pos.iY < 0)
+ {
+ TUint8 index = *iDataPtr++;
+ if (index > 0) // Encoded mode
+ WriteRun(*iDataPtr++,index);
+ else
+ {
+ index = *iDataPtr++;
+ if (index > 2) // Absolute mode
+ {
+ TInt padding = (index & 1) ? 1 : 0;
+ if ((iDataPtr + (index + padding)) > iDataPtrLimit)
+ {
+ iDataPtr -= 2;
+ break;
+ }
+ WriteData(index);
+ if (padding)
+ iDataPtr++;
+ }
+ else if (index == 0) // End of line
+ {
+ pos.iX = 0;
+ pos.iY--;
+ if (!imageProc->SetPos(pos))
+ {
+ iBytesExpected = 0;
+ break;
+ }
+ }
+ else if (index == 1) // End of bitmap
+ {
+ iBytesExpected = 0;
+ Pos().iY = -1;
+ break;
+ }
+ else // Delta
+ {
+ if ((iDataPtr + 2) > iDataPtrLimit)
+ {
+ iDataPtr -= 2;
+ break;
+ }
+ imageProc->FlushPixels();
+ pos.iX += *iDataPtr++;
+ pos.iY -= *iDataPtr++;
+ if (!imageProc->SetPos(pos))
+ break;
+ }
+ }
+ }
+
+ if (pos.iY < 0)
+ {
+ // that may indicate a dodgy image, so flag decoding complete
+ iBytesExpected = 0;
+ }
+ }
+
+void CBmpRLE8ReadCodec::WriteRun(TUint8 aValue, TInt aNumPixels)
+ {
+ CImageProcessor*const imageProc = ImageProcessor();
+ Pos().iX += aNumPixels;
+ TRgb value = iPalette[aValue];
+ for (; aNumPixels > 0; aNumPixels--)
+ imageProc->SetPixel(value);
+ }
+
+void CBmpRLE8ReadCodec::WriteData(TInt aNumPixels)
+ {
+ CImageProcessor*const imageProc = ImageProcessor();
+ Pos().iX += aNumPixels;
+ const TUint8* dataPtrLimit = iDataPtr + aNumPixels;
+ while (iDataPtr < dataPtrLimit)
+ imageProc->SetPixel(iPalette[*iDataPtr++]);
+ }
+
+/*static*/
+CBmpBiRgbReadCodec* CBmpBiRgbReadCodec::NewL(const TSize& aBmpSize, TInt aPixelSize, const TRgb* aPalette)
+ {
+ CBmpBiRgbReadCodec* self = new(ELeave) CBmpBiRgbReadCodec(aBmpSize, aPixelSize, aPalette);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CBmpBiRgbReadCodec::CBmpBiRgbReadCodec(const TSize& aBmpSize, TInt aPixelSize, const TRgb* aPalette):
+ CBmpReadCodec(aBmpSize, aPalette),
+ iPixelSize(aPixelSize)
+ {
+ }
+/**
+ calculate:
+ 1. mask used to extract channel value
+ 2. right shift value used to place channel value into "low" byte
+ 3. left shift value used to scale up channel if it has got less than 8 bits
+*/
+void CBmpBiRgbReadCodec::ConstructL()
+ {
+ // 16 Bpp 5-5-5 bitmaps do not have masks defined
+ // as they are "standard", so use predefined ones
+ static const TUint32 KDefault555Masks[]=
+ {
+ 0x7C00u, //red
+ 0x03E0u, //green
+ 0x001Fu //blue
+ };
+
+ CBmpReadCodec::ConstructL();
+
+ const TRgb* const masks= iPalette ? iPalette : reinterpret_cast<const TRgb*>(KDefault555Masks);
+
+ for (TInt comp=0; comp<=KBlueCompIdx; comp++)
+ {
+ iCompInfo[comp].iMask = 0x00FFFFFF & masks[comp].Internal(); // ignore the alpha channel
+ TInt shiftVal=0;
+ const TUint maskValue=iCompInfo[comp].iMask;
+ while (shiftVal < sizeof(TUint32) * 8 && ((maskValue >> shiftVal) &1 )==0)
+ {
+ ++shiftVal;
+ }
+ iCompInfo[comp].iRightShiftValue = shiftVal;
+ while (shiftVal < sizeof(TUint32) * 8 && ((maskValue >> shiftVal) &1) !=0 )
+ {
+ ++shiftVal;
+ }
+ iCompInfo[comp].iLeftShiftValue = 8 - (shiftVal - iCompInfo[comp].iRightShiftValue);
+ if (iCompInfo[comp].iLeftShiftValue < 0)
+ {
+ // We've got image with bad mask
+ User::Leave(KErrCorrupt);
+ }
+ }
+ }
+
+void CBmpBiRgbReadCodec::DoProcessL()
+ {
+ TInt bytesRemaining = iDataPtrLimit - iDataPtr;
+ CImageProcessor* const imageProc = ImageProcessor();
+ while (bytesRemaining >= iPixelSize)
+ {
+ TInt bytesToWrite = iPixelByteWidth - iBytePos;
+ if (bytesToWrite > 0)
+ {
+ TInt pixelsToWrite = Min(bytesRemaining, bytesToWrite) / iPixelSize;
+ const TInt bytesWritten = pixelsToWrite * iPixelSize;
+ const TUint8* const tempDataPtrLimit = iDataPtr + bytesWritten;
+ bytesRemaining -= bytesWritten;
+ iBytePos += bytesWritten;
+ while (iDataPtr < tempDataPtrLimit)
+ {
+ TUint pixelValue;
+ switch (iPixelSize)
+ {
+ case sizeof(TUint16):
+ pixelValue=PtrReadUtil::ReadUint16(iDataPtr);
+ break;
+
+ case sizeof(TUint16) + sizeof(TUint8):
+ pixelValue=PtrReadUtil::ReadUint16(iDataPtr) | (iDataPtr[2] << 16);
+ break;
+
+ case sizeof(TUint32):
+ pixelValue=PtrReadUtil::ReadUint32(iDataPtr);
+ break;
+
+ default:
+ ASSERT(EFalse);
+ pixelValue = 0;
+ }
+ TInt red=((pixelValue & iCompInfo[KRedCompIdx].iMask) >> iCompInfo[KRedCompIdx].iRightShiftValue) << iCompInfo[KRedCompIdx].iLeftShiftValue;
+ red |=red >> (8 - iCompInfo[KRedCompIdx].iLeftShiftValue);
+
+ TInt green = ((pixelValue & iCompInfo[KGreenCompIdx].iMask) >> iCompInfo[KGreenCompIdx].iRightShiftValue) << iCompInfo[KGreenCompIdx].iLeftShiftValue;
+ green |= green >> (8 - iCompInfo[KGreenCompIdx].iLeftShiftValue);
+
+ TInt blue = ((pixelValue & iCompInfo[KBlueCompIdx].iMask) >> iCompInfo[KBlueCompIdx].iRightShiftValue) << iCompInfo[KBlueCompIdx].iLeftShiftValue;
+ blue |= blue >> (8 - iCompInfo[KBlueCompIdx].iLeftShiftValue);
+
+ imageProc->SetPixel( TRgb(red, green, blue) );
+ iDataPtr += iPixelSize;
+ }
+ }
+
+ if (iBytePos >= iPixelByteWidth)
+ {
+ const TInt KBytesToSkip = Min(bytesRemaining, iTotalByteWidth - iBytePos);
+ bytesRemaining -= KBytesToSkip;
+ iBytePos += KBytesToSkip;
+ iDataPtr += KBytesToSkip;
+ }
+
+ if (iBytePos >= iTotalByteWidth)
+ {
+ iBytePos = 0;
+ }
+ }
+ }
+
+void CBmpBiRgbReadCodec::DoNewFrameL()
+ {
+ if (iPixelSize < 4)
+ {
+ iTotalByteWidth = ((iOriginalSize.iWidth * iPixelSize) + iPixelSize) & ~iPixelSize;
+ }
+ else
+ {
+ iTotalByteWidth = (iOriginalSize.iWidth * iPixelSize);
+ }
+
+ iPixelByteWidth = (iOriginalSize.iWidth * iPixelSize);
+ iPaddingByteWidth = iTotalByteWidth - iPixelByteWidth;
+ iBytePos = 0;
+ iBytesExpected = iTotalByteWidth * iOriginalSize.iHeight;
+ }
+
+// CBmp24BppReadCodec
+CBmp24BppReadCodec* CBmp24BppReadCodec::NewL(const TSize& aBmpSize)
+{
+ CBmp24BppReadCodec* self = new(ELeave) CBmp24BppReadCodec(aBmpSize);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+CBmp24BppReadCodec::CBmp24BppReadCodec(const TSize& aBmpSize)
+ : CBmpReadCodec(aBmpSize, NULL)
+ {}
+
+void CBmp24BppReadCodec::DoProcessL()
+ {
+ TInt bytesRemaining = iDataPtrLimit - iDataPtr;
+ CImageProcessor*const imageProc = ImageProcessor();
+ while (bytesRemaining > 2)
+ {
+ TInt bytesToWrite = iPixelByteWidth - iBytePos;
+ if (bytesToWrite > 0)
+ {
+ TInt pixelsToWrite = Min(bytesRemaining, bytesToWrite) / 3;
+ TInt bytesWritten = pixelsToWrite * 3;
+ const TUint8* tempDataPtrLimit = iDataPtr + bytesWritten;
+ bytesRemaining -= bytesWritten;
+ iBytePos += bytesWritten;
+ while (iDataPtr < tempDataPtrLimit)
+ {
+ imageProc->SetPixel(TRgb(iDataPtr[2], iDataPtr[1], iDataPtr[0]));
+ iDataPtr += 3;
+ }
+ }
+
+ if (iBytePos >= iPixelByteWidth)
+ {
+ TInt bytesToSkip = Min(bytesRemaining, iTotalByteWidth - iBytePos);
+ bytesRemaining -= bytesToSkip;
+ iBytePos += bytesToSkip;
+ iDataPtr += bytesToSkip;
+ }
+
+ if (iBytePos >= iTotalByteWidth)
+ iBytePos = 0;
+ }
+ }
+
+void CBmp24BppReadCodec::DoNewFrameL()
+ {
+ iTotalByteWidth = ((iOriginalSize.iWidth * 3) + 3) & ~3;
+ iPixelByteWidth = (iOriginalSize.iWidth * 3);
+ iPaddingByteWidth = iTotalByteWidth - iPixelByteWidth;
+ iBytePos = 0;
+ iBytesExpected = iTotalByteWidth * iOriginalSize.iHeight;
+ }
+
+// CBmp32BppReadCodec
+CBmp32BppReadCodec* CBmp32BppReadCodec::NewL(const TSize& aBmpSize)
+{
+ CBmp32BppReadCodec* self = new(ELeave) CBmp32BppReadCodec(aBmpSize);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+CBmp32BppReadCodec::CBmp32BppReadCodec(const TSize& aBmpSize)
+ : CBmpReadCodec(aBmpSize, NULL)
+ {}
+
+void CBmp32BppReadCodec::DoProcessL()
+ {
+ TInt bytesRemaining = iDataPtrLimit - iDataPtr;
+ CImageProcessor*const imageProc = ImageProcessor();
+ while (bytesRemaining > 3)
+ {
+ TInt bytesToWrite = iPixelByteWidth - iBytePos;
+ if (bytesToWrite > 0)
+ {
+ TInt pixelsToWrite = Min(bytesRemaining, bytesToWrite) / 4;
+ TInt bytesWritten = pixelsToWrite * 4;
+ const TUint8* tempDataPtrLimit = iDataPtr + bytesWritten;
+ bytesRemaining -= bytesWritten;
+ iBytePos += bytesWritten;
+ while (iDataPtr < tempDataPtrLimit)
+ {
+ imageProc->SetPixel(TRgb(iDataPtr[2], iDataPtr[1], iDataPtr[0]));
+ iDataPtr += 4;
+ }
+ }
+
+ if (iBytePos >= iPixelByteWidth)
+ {
+ TInt bytesToSkip = Min(bytesRemaining, iTotalByteWidth - iBytePos);
+ bytesRemaining -= bytesToSkip;
+ iBytePos += bytesToSkip;
+ iDataPtr += bytesToSkip;
+ }
+
+ if (iBytePos >= iTotalByteWidth)
+ iBytePos = 0;
+ }
+ }
+
+void CBmp32BppReadCodec::DoNewFrameL()
+ {
+ iTotalByteWidth = iOriginalSize.iWidth * 4;
+ iPixelByteWidth = iTotalByteWidth;
+ iPaddingByteWidth = iTotalByteWidth - iPixelByteWidth;
+ iBytePos = 0;
+ iBytesExpected = iTotalByteWidth * iOriginalSize.iHeight;
+ }
+
+// CBmpWriteCodec
+void CBmpWriteCodec::InitFrameL(TBufPtr8& aDst, const CFbsBitmap& aSource)
+ {
+ SetSource(&aSource);
+ iSourceRect = TRect(aSource.SizeInPixels());
+ iPos.SetXY(0,0);
+ iPos.iY = iSourceRect.iBr.iY - 1;
+ iPaddingBytes = PaddingBytes();
+ iBytesToWrite = 0;
+ aDst.SetLength(0); //No frame header
+ }
+
+TFrameState CBmpWriteCodec::ProcessFrameL(TBufPtr8& aDst)
+ {
+ //Setup buffer to use all available space
+ TUint8* destStartPtr = CONST_CAST(TUint8*,aDst.Ptr());
+ iDestPtr = destStartPtr;
+ iDestPtrLimit = iDestPtr + aDst.MaxLength();
+
+ DoProcessL(*Source());
+
+ aDst.SetLength(iDestPtr - destStartPtr);
+
+ // If processed all pixels
+ if (iPos.iY < iSourceRect.iTl.iY)
+ return EFrameComplete;
+
+ return EFrameIncomplete;
+ }
+
+
+// CBmp1BppWriteCodec
+CBmp1BppWriteCodec* CBmp1BppWriteCodec::NewL(void)
+{
+ CBmp1BppWriteCodec* self = new(ELeave) CBmp1BppWriteCodec();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+TInt CBmp1BppWriteCodec::PaddingBytes()
+ {
+ TInt byteWidth = (iSourceRect.Size().iWidth + 7) / 8;
+ return ((byteWidth + 3) & ~3) - byteWidth;
+ }
+
+void CBmp1BppWriteCodec::DoProcessL(const CFbsBitmap& aFrame)
+ {
+ while (iDestPtr < iDestPtrLimit)
+ {
+ for ( ; (iBytesToWrite > 0) && (iDestPtr < iDestPtrLimit) ; iBytesToWrite--)
+ *iDestPtr++ = 0;
+
+ if (iPos.iY < 0)
+ break;
+
+ TInt scanLength = Min(iSourceRect.iBr.iX - iPos.iX, (iDestPtrLimit - iDestPtr) * 8);
+ TInt dstLength = (scanLength + 7) / 8;
+ TPtr8 dstBuf(iDestPtr,dstLength,dstLength);
+
+ aFrame.GetScanLine(dstBuf, iPos, scanLength, EGray2);
+
+ iPos.iX += scanLength;
+ TUint8* tempDestPtrLimit = iDestPtr + dstLength;
+ while (iDestPtr < tempDestPtrLimit)
+ {
+ TUint8 tempVal = iDestPtr[0];
+ TUint reverseVal = 0;
+ TUint origValCopy = tempVal;
+ for(TInt countBit = 0; countBit<8; countBit++)
+ {
+ reverseVal<<=1;
+ reverseVal |= origValCopy & 1;
+ origValCopy>>=1;
+ }
+ iDestPtr[0] = TUint8(reverseVal);
+ iDestPtr++;
+ }
+
+ if (iPos.iX == iSourceRect.iBr.iX)
+ {
+ iPos.iX = iSourceRect.iTl.iX;
+ iPos.iY--;
+ iBytesToWrite = iPaddingBytes;
+ }
+ }
+ }
+
+
+// CBmp4BppWriteCodec
+CBmp4BppWriteCodec* CBmp4BppWriteCodec::NewL(void)
+{
+ CBmp4BppWriteCodec* self = new(ELeave) CBmp4BppWriteCodec();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+TInt CBmp4BppWriteCodec::PaddingBytes()
+ {
+ TInt byteWidth = (iSourceRect.Size().iWidth + 1) / 2;
+ return ((byteWidth + 3) & ~3) - byteWidth;
+ }
+
+void CBmp4BppWriteCodec::DoProcessL(const CFbsBitmap& aFrame)
+ {
+ while (iDestPtr < iDestPtrLimit)
+ {
+ for ( ; (iBytesToWrite > 0) && (iDestPtr < iDestPtrLimit) ; iBytesToWrite--)
+ *iDestPtr++ = 0;
+
+ if (iPos.iY < 0)
+ break;
+
+ TInt scanLength = Min(iSourceRect.iBr.iX - iPos.iX, (iDestPtrLimit - iDestPtr) * 2);
+ TInt dstLength = (scanLength + 1) / 2;
+ TPtr8 dstBuf(iDestPtr,dstLength,dstLength);
+
+ aFrame.GetScanLine(dstBuf, iPos, scanLength, EColor16);
+
+ iPos.iX += scanLength;
+ TUint8* tempDestPtrLimit = iDestPtr + dstLength;
+ while (iDestPtr < tempDestPtrLimit)
+ {
+ TInt tempVal = iDestPtr[0];
+ TInt lowNibble = tempVal << 4;
+ TInt highNibble = tempVal >> 4;
+ iDestPtr[0] = TUint8(lowNibble | highNibble);
+ iDestPtr++;
+ }
+
+ if (iPos.iX == iSourceRect.iBr.iX)
+ {
+ iPos.iX = iSourceRect.iTl.iX;
+ iPos.iY--;
+ iBytesToWrite = iPaddingBytes;
+ }
+ }
+ }
+
+
+// CBmp8BppWriteCodec
+CBmp8BppWriteCodec* CBmp8BppWriteCodec::NewL(void)
+{
+ CBmp8BppWriteCodec* self = new(ELeave) CBmp8BppWriteCodec();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+TInt CBmp8BppWriteCodec::PaddingBytes()
+ {
+ TInt byteWidth = iSourceRect.Size().iWidth;
+ return ((byteWidth + 3) & ~3) - byteWidth;
+ }
+
+void CBmp8BppWriteCodec::DoProcessL(const CFbsBitmap& aFrame)
+ {
+ while (iDestPtr < iDestPtrLimit)
+ {
+ for ( ; (iBytesToWrite > 0) && (iDestPtr < iDestPtrLimit) ; iBytesToWrite--)
+ *iDestPtr++ = 0;
+
+ if (iPos.iY < 0)
+ break;
+
+ TInt scanLength = Min(iSourceRect.iBr.iX - iPos.iX, iDestPtrLimit - iDestPtr);
+ TPtr8 dstBuf(iDestPtr, scanLength, scanLength);
+
+ aFrame.GetScanLine(dstBuf, iPos, scanLength, EColor256);
+
+ iPos.iX += scanLength;
+ iDestPtr += scanLength;
+
+ if (iPos.iX == iSourceRect.iBr.iX)
+ {
+ iPos.iX = iSourceRect.iTl.iX;
+ iPos.iY--;
+ iBytesToWrite = iPaddingBytes;
+ }
+ }
+ }
+
+
+// CBmp24BppWriteCodec
+CBmp24BppWriteCodec* CBmp24BppWriteCodec::NewL(void)
+{
+ CBmp24BppWriteCodec* self = new(ELeave) CBmp24BppWriteCodec();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+}
+
+TInt CBmp24BppWriteCodec::PaddingBytes()
+ {
+ TInt byteWidth = iSourceRect.Size().iWidth * 3;
+ return ((byteWidth + 3) & ~3) - byteWidth;
+ }
+
+void CBmp24BppWriteCodec::DoProcessL(const CFbsBitmap& aFrame)
+ {
+ TUint8* safeDestPtrLimit = iDestPtrLimit - 2;
+
+ while (iDestPtr < safeDestPtrLimit)
+ {
+ for ( ; (iBytesToWrite > 0) && (iDestPtr < iDestPtrLimit) ; iBytesToWrite--)
+ *iDestPtr++ = 0;
+
+ if (iPos.iY < 0)
+ break;
+
+ TInt scanLength = Min(iSourceRect.iBr.iX - iPos.iX, (iDestPtrLimit - iDestPtr) / 3);
+ TInt dstLength = scanLength * 3;
+ TPtr8 dstBuf(iDestPtr, dstLength, dstLength);
+
+ aFrame.GetScanLine(dstBuf, iPos, scanLength, EColor16M);
+
+ iPos.iX += scanLength;
+ iDestPtr += dstLength;
+
+ if (iPos.iX == iSourceRect.iBr.iX)
+ {
+ iPos.iX = iSourceRect.iTl.iX;
+ iPos.iY--;
+ iBytesToWrite = iPaddingBytes;
+ }
+ }
+ }
+