mmplugins/imagingplugins/codecs/PNGCodec/PngScanlineDecoder.cpp
branchRCL_3
changeset 50 948c7f65f6d4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmplugins/imagingplugins/codecs/PNGCodec/PngScanlineDecoder.cpp	Wed Sep 01 12:38:50 2010 +0100
@@ -0,0 +1,1722 @@
+// Copyright (c) 1997-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 "PNGCodec.h"
+#include "ImageUtils.h"
+
+const TInt KPngScanlineFilterTypeLength = 1;
+
+const TInt KColStart[KPngNumInterlacedPasses] = { 0, 4, 0, 2, 0, 1, 0, 0 };
+const TInt KRowStart[KPngNumInterlacedPasses] = { 0, 0, 4, 0, 2, 0, 1, 0 };
+const TInt KColIncrement[KPngNumInterlacedPasses] = { 8, 8, 4, 4, 2, 2, 1, 0 };
+const TInt KRowIncrement[KPngNumInterlacedPasses] = { 8, 8, 8, 4, 4, 2, 2, 0 };
+const TInt KBlockWidth[KPngNumInterlacedPasses] = { 8, 4, 4, 2, 2, 1, 1, 0 };
+const TInt KBlockHeight[KPngNumInterlacedPasses] = { 8, 8, 4, 4, 2, 2, 1, 0 };
+
+const TInt KPngDepth1BytesPerPixel = 1;
+const TInt KPngDepth3BytesPerPixel = 3;
+const TInt KPngDepth4BytesPerPixel = 4;
+
+// CFastProcessor16MAto16MA
+/**This class is a specific implementation of CFastProcessor.
+It provides a conversion of 24bpp + 8bpp alpha to EColor16MA display mode.
+*/
+class CFastProcessor16MAto16MA: public CFastProcessor
+    {
+public:
+	CFastProcessor16MAto16MA(CFbsBitmap* aDestination, TBool aRgbaMode);
+    void SetPixels(const TUint8* aDataPtr, const TUint8* aDataPtrLimit, TRgb* aLineCache, TPoint& aPos);
+    };
+   
+// CFastProcessor16MAto16MAP
+/**This class is a specific implementation of CFastProcessor.
+It provides a conversion of 24bpp + 8bpp alpha to EColor16MAP display mode.
+*/
+class CFastProcessor16MAto16MAP: public CFastProcessor
+    {
+public:
+	CFastProcessor16MAto16MAP(CFbsBitmap* aDestination, TBool aRgbaMode);
+    void SetPixels(const TUint8* aDataPtr, const TUint8* aDataPtrLimit, TRgb* aLineCache, TPoint& aPos);
+    };
+   
+// CFastProcessor16MtoM
+/**This class is a specific implementation of CFastProcessor.
+It provides a conversion of 24bpp to EColor16M display mode. 
+*/
+class CFastProcessor16Mto16M: public CFastProcessor
+    {
+public:
+	CFastProcessor16Mto16M(CFbsBitmap* aDestination, TBool aRgbaMode);
+    void SetPixels(const TUint8* aDataPtr, const TUint8* aDataPtrLimit, TRgb* aLineCache, TPoint& aPos);
+    };
+
+// CFastProcessor16MtoMA
+/**This class is a specific implementation of CFastProcessor.
+It provides a conversion of 24bpp to EColor16MU, EColor16MA or EColor16MAP display mode. 
+*/
+class CFastProcessor16Mto16MA: public CFastProcessor
+    {
+public:
+	CFastProcessor16Mto16MA(CFbsBitmap* aDestination, TBool aRgbaMode);
+    void SetPixels(const TUint8* aDataPtr, const TUint8* aDataPtrLimit, TRgb* aLineCache, TPoint& aPos);
+    };
+
+// CFastProcessor16MAto16MU
+/**This class is a specific implementation of CFastProcessor.
+It provides a conversion of a 24bpp + 8bpp alpha source to a EColor16MU (setting alpha as 0xFF).
+*/
+class CFastProcessor16MAto16MU: public CFastProcessor
+    {
+public:
+	CFastProcessor16MAto16MU(CFbsBitmap* aDestination, TBool aRgbaMode);
+    void SetPixels(const TUint8* aDataPtr, const TUint8* aDataPtrLimit, TRgb* aLineCache, TPoint& aPos);
+    };
+
+// CFastProcessor32bitTo32bitAndMask
+/**This class is a specific implementation of CFastProcessor.
+It provides a conversion of a 24bpp + 8bpp alpha source to an opaque 32 bit destination bitmap (i.e.
+setting the alpha channel to 0xFF) and EGray256 mask (which contains the alpha channel of the source).
+*/
+class CFastProcessor32bitTo32bitAndMask: public CFastProcessor
+    {
+public:
+	CFastProcessor32bitTo32bitAndMask(CFbsBitmap* aDestination, CFbsBitmap* aMask, TBool aRgbaMode);
+    void SetPixels(const TUint8* aDataPtr, const TUint8* aDataPtrLimit, TRgb* aLineCache, TPoint& aPos);
+    };
+
+/**
+Constructs a new FastProcessor based on the conversion type.
+
+@param  aImageInfo
+        A reference to TPngImageInformation for the FastProcessor to use.
+@param  aDestination
+        A reference to the destination bitmap.
+@param  aRgbaMode
+        This flag indicates that MNG frames are being processed.
+*/
+CFastProcessor* CFastProcessor::NewL(const TPngImageInformation& aImageInfo, CFbsBitmap* aDestination, CFbsBitmap* aMask, TBool aRgbaMode)
+    {
+	CFastProcessor* self = NULL;
+
+	if (aRgbaMode) //if MNG
+		{
+		if (aImageInfo.iColorType == TPngImageInformation::EDirectColor)
+			{
+			self = new (ELeave) CFastProcessor16Mto16MA(aDestination, aRgbaMode);	
+			}
+		else if(aImageInfo.iColorType == TPngImageInformation::EAlphaDirectColor)
+			{
+			self = new (ELeave) CFastProcessor16MAto16MA(aDestination, aRgbaMode);	
+			}
+		else
+			{
+			User::Leave(KErrNotSupported);	
+			}
+		}
+	else
+		{
+		TDisplayMode mode = aDestination->DisplayMode();
+		
+		switch (aImageInfo.iColorType)
+			{
+			case TPngImageInformation::EDirectColor:
+				if(EColor16M == mode)
+					{
+					self = new (ELeave) CFastProcessor16Mto16M(aDestination, aRgbaMode);	
+					}
+				else if(EColor16MAP == mode || EColor16MA == mode || EColor16MU == mode)
+					{
+					self = new (ELeave) CFastProcessor16Mto16MA(aDestination, aRgbaMode);	
+					}
+				break;
+
+			case TPngImageInformation::EAlphaDirectColor:
+				if(aMask && (EColor16MA == mode || EColor16MU == mode || EColor16MAP == mode))
+					{
+					self = new (ELeave) CFastProcessor32bitTo32bitAndMask(aDestination, aMask, aRgbaMode);
+					}
+				else if(EColor16MA == mode)
+					{
+					self = new (ELeave) CFastProcessor16MAto16MA(aDestination, aRgbaMode);	
+					}
+				else if(EColor16MAP == mode)
+					{
+					self = new (ELeave) CFastProcessor16MAto16MAP(aDestination, aRgbaMode);	
+					}
+				else if(EColor16MU == mode)
+					{
+					self = new (ELeave) CFastProcessor16MAto16MU(aDestination, aRgbaMode);
+					}
+				else
+					{
+					User::Leave(KErrNotSupported);	
+					}
+				break;
+		
+			default:
+				User::Leave(KErrNotSupported);
+				break;				
+			}		
+		}
+	
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self); 
+	return self;	   
+    }
+
+/**
+Destructor for this class.
+Releases the lock for the current bitmap.
+*/
+CFastProcessor::~CFastProcessor()
+    {
+    }
+
+/**
+Second phase constructor.
+Requests a lock for the current bitmap.
+*/    
+void CFastProcessor::ConstructL()
+	{
+	// NO-OP - reserved for changes at a later stage.
+	}
+
+/**
+Default constructor 
+*/
+CFastProcessor::CFastProcessor(CFbsBitmap* aDestination, CFbsBitmap* aMask, TBool aRgbaMode)
+    {
+    iRgbaMode = aRgbaMode;
+    
+    if (!aRgbaMode)
+	    {
+	    iBitmap = aDestination;
+	    iBitmapSize = iBitmap->SizeInPixels();	
+		if (aMask)
+			{
+			ASSERT(aMask->SizeInPixels() == iBitmapSize);
+			iMask = aMask;
+			}
+		}    	
+	}
+
+/**
+Requests a lock for the current bitmap from the font & bitmap server and
+sets the current position in the bitmap to the first pixel.
+*/
+void CFastProcessor::Begin()
+	{
+	if (!iRgbaMode)
+		{
+		if (iBitmapBuffer==NULL)
+			{
+			iBitmapBuffer = reinterpret_cast<TUint8*>( iBitmap->DataAddress() );
+     		if (iMask)
+     			{
+     			iMaskBuffer = reinterpret_cast<TUint8*>( iMask->DataAddress() );
+     			}
+			}
+		}
+	}
+
+/**
+Releases a lock previously acquired using CFastProcessor::Begin().
+*/
+void CFastProcessor::End()
+	{
+	if (!iRgbaMode)
+		{    
+		if (iBitmapBuffer)
+			{
+			iBitmapBuffer = NULL;
+			}
+		if (iMaskBuffer)
+			{
+			iMaskBuffer = NULL;
+			}
+		}
+	}
+
+/**
+Default constructor for this class.
+*/
+CFastProcessor16Mto16M::CFastProcessor16Mto16M(CFbsBitmap* aDestination, TBool aRgbaMode):
+	CFastProcessor(aDestination, NULL, aRgbaMode)
+    {}
+
+/**
+Sets an array of pixel values, starting at the current bitmap position using the
+values supplied in aDataPtr.
+
+@param  aDataPtr
+        A pointer to the first element in the array.
+@param  aDataPtrLimit
+        A pointer to the last element in the array.
+*/
+void CFastProcessor16Mto16M::SetPixels(const TUint8* aDataPtr, const TUint8* aDataPtrLimit, TRgb* /*aLineCache*/, TPoint& /*aPos*/)
+    {       
+    TUint8* scanLinePtr = (iBitmapBuffer + KPngDepth3BytesPerPixel * ( iPos.iX +  iPos.iY * (( (iBitmapSize.iWidth + 3)>>2)<<2))); //aligns the specified value onto a 4-byte boundary.
+       
+    iPos.iX += TUint(aDataPtrLimit - aDataPtr) / KPngDepth3BytesPerPixel;
+
+    while (aDataPtr < aDataPtrLimit)
+        {
+        scanLinePtr[0] = aDataPtr[2];
+        scanLinePtr[1] = aDataPtr[1];
+        scanLinePtr[2] = aDataPtr[0];
+      	
+ 		scanLinePtr += KPngDepth3BytesPerPixel;
+        aDataPtr += KPngDepth3BytesPerPixel;
+        }
+
+    while (iPos.iX >= iBitmapSize.iWidth)
+        {
+        iPos.iY++;
+        iPos.iX -= iBitmapSize.iWidth;
+        }
+    }
+
+/**
+Default constructor for this class.
+*/
+CFastProcessor16Mto16MA::CFastProcessor16Mto16MA(CFbsBitmap* aDestination, TBool aRgbaMode):
+	CFastProcessor(aDestination, NULL, aRgbaMode)
+    {}
+
+/**
+Sets an array of pixel values, starting at the current bitmap position using the
+values supplied in aDataPtr.
+
+@param  aDataPtr
+        A pointer to the first element in the array.
+@param  aDataPtrLimit
+        A pointer to the last element in the array.
+//used only if RgbaMode i.e MNG processing        
+@param  aLineCache
+        A pointer to current scanline buffer.
+@param  aPos
+        Current pixel position.
+*/
+void CFastProcessor16Mto16MA::SetPixels(const TUint8* aDataPtr, const TUint8* aDataPtrLimit, TRgb* aLineCache, TPoint& aPos)
+    {
+    TUint32* scanLinePtr;
+ 
+    if (!iRgbaMode)
+	    {
+		scanLinePtr = (TUint32*)(iBitmapBuffer + (KPngDepth3BytesPerPixel + 1) * ( iPos.iX +  iPos.iY * iBitmapSize.iWidth));
+		iPos.iX += TUint(aDataPtrLimit - aDataPtr) / KPngDepth3BytesPerPixel;
+	    }
+	else
+		{
+		scanLinePtr = reinterpret_cast<TUint32*>(aLineCache);
+		aPos.iX = TUint(aDataPtrLimit - aDataPtr) / KPngDepth3BytesPerPixel;
+		}
+    
+    while (aDataPtr < aDataPtrLimit)
+        {
+        *scanLinePtr++ = ((TUint32)0xFF << 24) | ((TUint32)aDataPtr[0] << 16) | ((TUint32)aDataPtr[1] << 8) | aDataPtr[2]; 
+
+        aDataPtr += KPngDepth3BytesPerPixel;
+        }
+        	
+	if (!iRgbaMode)
+		{
+	    while (iPos.iX >= iBitmapSize.iWidth)
+	        {
+	        iPos.iY++;
+	        iPos.iX -= iBitmapSize.iWidth;
+	        }              
+		}
+    }
+
+/**
+Default constructor for this class.
+*/
+CFastProcessor16MAto16MA::CFastProcessor16MAto16MA(CFbsBitmap* aDestination, TBool aRgbaMode):
+	CFastProcessor(aDestination, NULL, aRgbaMode)
+    {}
+
+/**
+Sets an array of pixel values, starting at the current bitmap position using the
+values supplied in aDataPtr.
+
+@param  aDataPtr
+        A pointer to the first element in the array.
+@param  aDataPtrLimit
+        A pointer to the last element in the array.
+//used only if RgbaMode i.e MNG processing        
+@param  aLineCache
+        A pointer to current scanline buffer.
+@param  aPos
+        Current pixel position.
+*/
+void CFastProcessor16MAto16MA::SetPixels(const TUint8* aDataPtr, const TUint8* aDataPtrLimit, TRgb* aLineCache, TPoint& aPos)
+    {
+    TUint32* scanLinePtr;
+
+    if (!iRgbaMode)
+	    {
+    	scanLinePtr = (TUint32*)(iBitmapBuffer + KPngDepth4BytesPerPixel * ( iPos.iX + iPos.iY * iBitmapSize.iWidth));
+    	iPos.iX += TUint(aDataPtrLimit - aDataPtr) / KPngDepth4BytesPerPixel;	    	
+	    }
+    else
+	    {
+		scanLinePtr = reinterpret_cast<TUint32*>(aLineCache);
+		aPos.iX = TUint(aDataPtrLimit - aDataPtr) / KPngDepth4BytesPerPixel;	    	
+	    }
+
+    while (aDataPtr + sizeof(TUint32) < aDataPtrLimit)
+        {       
+        TUint32 pixel1 = *(TUint32*) aDataPtr;
+        aDataPtr += KPngDepth4BytesPerPixel;
+        TUint32 pixel2 = *(TUint32*) aDataPtr;
+        aDataPtr += KPngDepth4BytesPerPixel;
+
+        pixel1 = (pixel1 & 0xFF00FF00) | ((pixel1 & 0xFF)<<16) | ((pixel1>>16) & 0xFF);
+        pixel2 = (pixel2 & 0xFF00FF00) | ((pixel2 & 0xFF)<<16) | ((pixel2>>16) & 0xFF);
+
+        *scanLinePtr++ = pixel1;
+        *scanLinePtr++ = pixel2;
+        }
+        
+    if (aDataPtr + sizeof(TUint32) == aDataPtrLimit)
+    	{
+    	TUint32 pixel1 = *(TUint32*) aDataPtr;
+    	
+    	*scanLinePtr = (pixel1 & 0xFF00FF00) | ((pixel1 & 0xFF)<<16) | ((pixel1>>16) & 0xFF);
+    	}        
+
+	if (!iRgbaMode)
+		{
+	    while (iPos.iX >= iBitmapSize.iWidth)
+	        {
+	        iPos.iY++;
+	        iPos.iX -= iBitmapSize.iWidth;
+	        }		
+		}
+    }
+
+/**
+Default constructor for this class.
+*/
+CFastProcessor16MAto16MAP::CFastProcessor16MAto16MAP(CFbsBitmap* aDestination, TBool aRgbaMode):
+	CFastProcessor(aDestination, NULL, aRgbaMode)
+    {}
+
+/**
+Sets an array of pixel values, starting at the current bitmap position using the
+values supplied in aDataPtr.
+
+@param  aDataPtr
+        A pointer to the first element in the array.
+@param  aDataPtrLimit
+        A pointer to the last element in the array.
+//used only if RgbaMode i.e MNG processing        
+@param  aLineCache
+        A pointer to current scanline buffer.
+@param  aPos
+        Current pixel position.
+*/
+
+// function to convert PNG pixel to 16MAP pixel
+
+static TUint32 PngTo16Map(TUint32 aPngPixel)
+	{
+	TUint8 const alpha = TUint8( aPngPixel >> 24 );
+
+	if (alpha == 0)
+		{
+		aPngPixel = 0;
+		}
+	else
+		{
+		// PNG bytes position in TUint32 are ABGR and must be coverted to ARGB in our case
+
+		if (alpha == 0xff)
+			{
+			aPngPixel = (aPngPixel & 0xFF00FF00) | ((aPngPixel & 0xFF) << 16) | ((aPngPixel >> 16) & 0xFF);
+			}
+		else
+			{   
+			// Use a bias value of 128 rather than 255, but also add 1/256 of the numerator 
+			// before dividing the sum by 256.
+
+			TUint32 scaledRB = (aPngPixel & KRBMask) * alpha + KRBBias;
+			scaledRB = (scaledRB + ( (scaledRB >> 8) & KRBMask) ) >> 8;
+			// swap now the R & B channels
+			scaledRB = (scaledRB << 16) | (scaledRB >> 16);
+
+			TUint32 scaledG = (aPngPixel & KGMask) * alpha + KGBias;
+			scaledG = (scaledG + (scaledG >> 8)) >> 8;
+
+			// compose the new pixel swapping R with B as we premultiplied alpha on a PNG pixel 
+
+			aPngPixel = (aPngPixel & KAMask) | (scaledRB & KRBMask) | (scaledG & KGMask); 
+			}
+		}
+
+	return aPngPixel;
+	}
+
+void CFastProcessor16MAto16MAP::SetPixels(const TUint8* aDataPtr, const TUint8* aDataPtrLimit, TRgb* aLineCache, TPoint& aPos)
+    {
+    TUint32* scanLinePtr;
+
+	if (!iRgbaMode)
+		{
+		scanLinePtr = (TUint32*)(iBitmapBuffer + KPngDepth4BytesPerPixel * ( iPos.iX +  iPos.iY * iBitmapSize.iWidth));
+		iPos.iX += TUint(aDataPtrLimit - aDataPtr) / KPngDepth4BytesPerPixel;      
+		}
+	else
+		{
+		scanLinePtr = reinterpret_cast<TUint32*>(aLineCache);
+		aPos.iX = TUint(aDataPtrLimit - aDataPtr) / KPngDepth4BytesPerPixel;      
+		}
+
+	// perform a direct conversion PNG -> Pixel 16MAP
+
+    while (aDataPtr + sizeof(TUint32) < aDataPtrLimit)
+		{
+		TUint32 pixel1 = *(TUint32*) aDataPtr;
+		aDataPtr += KPngDepth4BytesPerPixel;
+		TUint32 pixel2 = *(TUint32*) aDataPtr;
+		aDataPtr += KPngDepth4BytesPerPixel;
+
+		pixel1 = PngTo16Map(pixel1);
+		pixel2 = PngTo16Map(pixel2);
+
+		*scanLinePtr++ = pixel1;
+		*scanLinePtr++ = pixel2;
+		}
+
+    if (aDataPtr + sizeof(TUint32) == aDataPtrLimit)
+		{
+		*scanLinePtr = PngTo16Map(*(TUint32*) aDataPtr);
+		}
+
+ 	if (!iRgbaMode)
+  		{
+		while (iPos.iX >= iBitmapSize.iWidth)
+			{
+			iPos.iY++;
+			iPos.iX -= iBitmapSize.iWidth;
+			}  
+		}
+    }
+
+/**
+Default constructor for this class.
+*/
+CFastProcessor32bitTo32bitAndMask::CFastProcessor32bitTo32bitAndMask(CFbsBitmap* aDestination, CFbsBitmap* aMask, TBool aRgbaMode)
+: CFastProcessor(aDestination, aMask, aRgbaMode)
+	{}
+
+/**
+Sets an array of pixel values, starting at the current bitmap position using the
+values supplied in aDataPtr.
+
+@param  aDataPtr
+        A pointer to the first element in the array.
+@param  aDataPtrLimit
+        A pointer to the last element in the array.
+//used only if RgbaMode i.e MNG processing        
+@param  aLineCache
+        A pointer to current scanline buffer.
+@param  aPos
+        Current pixel position.
+*/
+void CFastProcessor32bitTo32bitAndMask::SetPixels(const TUint8* aDataPtr, const TUint8* aDataPtrLimit, TRgb* /*aLineCache*/, TPoint& /*aPos*/)
+	{
+	ASSERT(!iRgbaMode); // Not configured for MNG use
+	
+	TUint32* scanLinePtr;  // alpha channel set to fully opaque
+	TUint8* maskScanLinePtr;  // set alpha channel in mask
+
+	scanLinePtr = (TUint32*)(iBitmapBuffer + KPngDepth4BytesPerPixel * ( iPos.iX +  iPos.iY * iBitmapSize.iWidth));
+	maskScanLinePtr = (TUint8*)(iMaskBuffer + KPngDepth1BytesPerPixel * ( iPos.iX +  iPos.iY * iBitmapSize.iWidth));
+	iPos.iX += TUint(aDataPtrLimit - aDataPtr) / KPngDepth4BytesPerPixel;
+	
+	if (iBitmap->DisplayMode() == EColor16MAP)
+		{
+	    while (aDataPtr + sizeof(TUint32) < aDataPtrLimit)
+			{
+			TUint32 pixel1 = *(TUint32*) aDataPtr;
+			aDataPtr += KPngDepth4BytesPerPixel;
+			TUint32 pixel2 = *(TUint32*) aDataPtr;
+			aDataPtr += KPngDepth4BytesPerPixel;
+
+			pixel1 = PngTo16Map(pixel1);
+			pixel2 = PngTo16Map(pixel2);
+			
+			*scanLinePtr++ = 0xFF000000 | pixel1;
+			*maskScanLinePtr++ = (pixel1 & 0xFF000000) >> 24;
+			
+			*scanLinePtr++ = 0xFF000000 | pixel2;
+			*maskScanLinePtr++ = (pixel2 & 0xFF000000) >> 24;
+			}
+		
+		if (aDataPtr + sizeof(TUint32) == aDataPtrLimit)
+			{
+			TUint32 oddPixel = *(TUint32*) aDataPtr;
+			
+			oddPixel = PngTo16Map(oddPixel);
+			
+			*scanLinePtr++ = 0xFF000000 | oddPixel;
+			*maskScanLinePtr++ = (oddPixel & 0xFF000000) >> 24;
+			}
+		}
+	else
+		{
+		while (aDataPtr < aDataPtrLimit)
+			{
+			*scanLinePtr++ = 0xFF000000 | (aDataPtr[0] << 16) | (aDataPtr[1] << 8) | aDataPtr[2];
+			*maskScanLinePtr++ = (aDataPtr[3]);
+
+			aDataPtr += KPngDepth4BytesPerPixel;
+			}
+		}
+	
+	while (iPos.iX >= iBitmapSize.iWidth)
+		{
+		iPos.iY++;
+		iPos.iX -= iBitmapSize.iWidth;
+		}
+	}
+
+/**
+Default constructor for this class.
+*/
+CFastProcessor16MAto16MU::CFastProcessor16MAto16MU(CFbsBitmap* aDestination, TBool aRgbaMode)
+: CFastProcessor(aDestination, NULL, aRgbaMode)
+	{}
+
+/**
+Sets an array of pixel values, starting at the current bitmap position using the
+values supplied in aDataPtr.
+
+@param  aDataPtr
+        A pointer to the first element in the array.
+@param  aDataPtrLimit
+        A pointer to the last element in the array.
+//used only if RgbaMode i.e MNG processing        
+@param  aLineCache
+        A pointer to current scanline buffer.
+@param  aPos
+        Current pixel position.
+*/
+void CFastProcessor16MAto16MU::SetPixels(const TUint8* aDataPtr, const TUint8* aDataPtrLimit, TRgb* aLineCache, TPoint& aPos)
+    {
+    TUint32* scanLinePtr;
+
+    if (!iRgbaMode)
+	    {
+    	scanLinePtr = (TUint32*)(iBitmapBuffer + KPngDepth4BytesPerPixel * ( iPos.iX + iPos.iY * iBitmapSize.iWidth));
+    	iPos.iX += TUint(aDataPtrLimit - aDataPtr) / KPngDepth4BytesPerPixel;	    	
+	    }
+    else
+	    {
+		scanLinePtr = reinterpret_cast<TUint32*>(aLineCache);
+		aPos.iX = TUint(aDataPtrLimit - aDataPtr) / KPngDepth4BytesPerPixel;	    	
+	    }
+
+    while (aDataPtr < aDataPtrLimit)
+        {
+        *scanLinePtr++ = 0xFF000000 | (aDataPtr[0] << 16) | (aDataPtr[1] << 8) | aDataPtr[2]; 
+
+        aDataPtr += KPngDepth4BytesPerPixel;
+        }       
+
+	if (!iRgbaMode)
+		{
+	    while (iPos.iX >= iBitmapSize.iWidth)
+	        {
+	        iPos.iY++;
+	        iPos.iX -= iBitmapSize.iWidth;
+	        }		
+		}
+    }
+
+class CBitDepth1Decoder : public CPngReadSubCodec
+	{
+private:
+	virtual void DoConstructL();
+	virtual TInt ScanlineBufferSize(TInt aPixelLength);
+	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
+	};
+
+class CBitDepth2Decoder : public CPngReadSubCodec
+	{
+private:
+	virtual void DoConstructL();
+	virtual TInt ScanlineBufferSize(TInt aPixelLength);
+	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
+	};
+
+class CBitDepth4Decoder : public CPngReadSubCodec
+	{
+private:
+	virtual void DoConstructL();
+	virtual TInt ScanlineBufferSize(TInt aPixelLength);
+	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
+	};
+
+class CBitDepth8Decoder : public CPngReadSubCodec
+	{
+private:
+	virtual void DoConstructL();
+	virtual TInt ScanlineBufferSize(TInt aPixelLength);
+	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
+	};
+
+class CBitDepth8ColorType2Decoder : public CPngReadSubCodec
+	{
+private:
+	virtual void DoConstructL();
+	virtual TInt ScanlineBufferSize(TInt aPixelLength);
+	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
+	};
+
+class CBitDepth8ColorType4Decoder : public CPngReadSubCodec
+	{
+private:
+	virtual void DoConstructL();
+	virtual TInt ScanlineBufferSize(TInt aPixelLength);
+	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
+	};
+
+class CBitDepth8ColorType6Decoder : public CPngReadSubCodec
+	{
+private:
+	virtual void DoConstructL();
+	virtual TInt ScanlineBufferSize(TInt aPixelLength);
+	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
+	};
+
+class CBitDepth16ColorType0Decoder : public CPngReadSubCodec
+	{
+private:
+	virtual void DoConstructL();
+	virtual TInt ScanlineBufferSize(TInt aPixelLength);
+	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
+	};
+
+class CBitDepth16ColorType2Decoder : public CPngReadSubCodec
+	{
+private:
+	virtual void DoConstructL();
+	virtual TInt ScanlineBufferSize(TInt aPixelLength);
+	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
+	};
+
+class CBitDepth16ColorType4Decoder : public CPngReadSubCodec
+	{
+private:
+	virtual void DoConstructL();
+	virtual TInt ScanlineBufferSize(TInt aPixelLength);
+	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
+	};
+
+class CBitDepth16ColorType6Decoder : public CPngReadSubCodec
+	{
+private:
+	virtual void DoConstructL();
+	virtual TInt ScanlineBufferSize(TInt aPixelLength);
+	virtual void DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit);
+	};
+
+// CPngReadSubCodec
+CPngReadSubCodec* CPngReadSubCodec::NewL(CImageProcessor* aImageProc,CImageProcessor* aMaskProc,const TPngImageInformation& aInfo, CFastProcessor* aFastProc, TBool aFastProcessorMode)
+	{
+	CPngReadSubCodec* self = NULL;
+
+	switch (aInfo.iBitDepth)
+		{
+	case 1:
+		self = new(ELeave) CBitDepth1Decoder;
+		break;
+	case 2:
+		self = new(ELeave) CBitDepth2Decoder;
+		break;
+	case 4:
+		self = new(ELeave) CBitDepth4Decoder;
+		break;
+	case 8:
+		switch (aInfo.iColorType)
+			{
+		case TPngImageInformation::EGrayscale:
+		case TPngImageInformation::EIndexedColor:
+			self = new(ELeave) CBitDepth8Decoder;
+			break;
+		case TPngImageInformation::EDirectColor:
+			self = new(ELeave) CBitDepth8ColorType2Decoder;
+			break;
+		case TPngImageInformation::EAlphaGrayscale:
+			self = new(ELeave) CBitDepth8ColorType4Decoder;
+			break;
+		case TPngImageInformation::EAlphaDirectColor:
+			self = new(ELeave) CBitDepth8ColorType6Decoder;
+			break;
+		default:
+			User::Leave(KErrNotSupported);
+			break;
+			}
+		break;
+	case 16:
+		switch (aInfo.iColorType)
+			{
+		case TPngImageInformation::EGrayscale:
+			self = new(ELeave) CBitDepth16ColorType0Decoder;
+			break;
+		case TPngImageInformation::EDirectColor:
+			self = new(ELeave) CBitDepth16ColorType2Decoder;
+			break;
+		case TPngImageInformation::EAlphaGrayscale:
+			self = new(ELeave) CBitDepth16ColorType4Decoder;
+			break;
+		case TPngImageInformation::EAlphaDirectColor:
+			self = new(ELeave) CBitDepth16ColorType6Decoder;
+			break;
+		case TPngImageInformation::EIndexedColor:
+		default:
+			User::Leave(KErrNotSupported);
+			break;
+			}
+		break;
+	default:
+		User::Leave(KErrNotSupported);
+		break;
+		}
+
+	CleanupStack::PushL(self);
+	self->ConstructL(aImageProc,aMaskProc,aInfo, aFastProc, aFastProcessorMode);
+	CleanupStack::Pop(self); 
+	return self;
+	}
+
+CPngReadSubCodec::CPngReadSubCodec():
+	iScanlineDes1(NULL,0),
+	iScanlineDes2(NULL,0)
+	{}
+
+CPngReadSubCodec::~CPngReadSubCodec()
+	{
+	delete iScanlineBuffer1;
+	delete iScanlineBuffer2;
+	delete [] iLineCache;
+	}
+
+void CPngReadSubCodec::ConstructL(CImageProcessor* aImageProc,CImageProcessor* aMaskProc,const TPngImageInformation& aInfo, CFastProcessor* aFastProc, TBool aFastProcessorMode)
+	{
+	iImageProc = aImageProc;
+	iMaskProc = aMaskProc;
+	iFastProc = aFastProc;
+	
+	iInfo = aInfo;
+	
+	SetFastProcessorMode(aFastProcessorMode);				
+
+	iScanlineBufferSize = ScanlineBufferSize(iInfo.iSize.iWidth);
+
+	DoConstructL();
+	if (iInfo.iInterlaceMethod != TPngImageInformation::EAdam7Interlace)
+		{
+		iLineCache = new (ELeave) TRgb [iInfo.iSize.iWidth + 8]; // +8 to be sure we won't exceed buffer for padded images (up to 8 pixels padding)
+		}
+
+	iScanlineBuffer1 = HBufC8::NewMaxL(iScanlineBufferSize + 7);
+	iScanlineBuffer2 = HBufC8::NewMaxL(iScanlineBufferSize + 7);
+
+	if (iInfo.iInterlaceMethod == TPngImageInformation::EAdam7Interlace)
+		{
+		iInterlacedScanlineBufferSize[0] = ScanlineBufferSize((iInfo.iSize.iWidth + 7) >> 3);
+		iInterlacedScanlineBufferSize[1] = ScanlineBufferSize((iInfo.iSize.iWidth + 3) >> 3);
+		iInterlacedScanlineBufferSize[2] = ScanlineBufferSize((iInfo.iSize.iWidth + 3) >> 2);
+		iInterlacedScanlineBufferSize[3] = ScanlineBufferSize((iInfo.iSize.iWidth + 1) >> 2);
+		iInterlacedScanlineBufferSize[4] = ScanlineBufferSize((iInfo.iSize.iWidth + 1) >> 1);
+		iInterlacedScanlineBufferSize[5] = ScanlineBufferSize(iInfo.iSize.iWidth >> 1);
+		iInterlacedScanlineBufferSize[6] = iScanlineBufferSize;
+		iInterlacedScanlineBufferSize[7] = 0;
+		iPass = 0;
+
+		iScanlineDes1.Set(&(iScanlineBuffer1->Des())[0],iInterlacedScanlineBufferSize[0],iInterlacedScanlineBufferSize[0]);
+		iScanlineDes2.Set(&(iScanlineBuffer2->Des())[0],iInterlacedScanlineBufferSize[0],iInterlacedScanlineBufferSize[0]);
+		
+		if(iImageProc)
+			{
+			const TInt lineRepeat = ClampValue(KBlockHeight[iPass]-1,0,iInfo.iSize.iHeight-iPos.iY-2);
+			iImageProc->SetLineRepeat(lineRepeat);	
+			}
+		}
+	else
+		{
+		// to align actual data per word boudary
+		iScanlineDes1.Set(&(iScanlineBuffer1->Des())[3],iScanlineBufferSize,iScanlineBufferSize);
+		iScanlineDes2.Set(&(iScanlineBuffer2->Des())[3],iScanlineBufferSize,iScanlineBufferSize);
+		}
+	}
+
+void CPngReadCodec::SetImageProcessor(CImageProcessor* aImageProc, TBool aOwnsProcessor)
+	{
+	if (iOwnsImageProcessor)
+		delete iImageProc;
+	iImageProc = aImageProc;
+	iOwnsImageProcessor = aOwnsProcessor;
+	}
+
+void CPngReadCodec::SetMaskProcessor(CImageProcessor* aMaskProc, TBool aOwnsProcessor)
+	{
+	if (iOwnsMaskProcessor)
+		delete iMaskProc;
+	iMaskProc = aMaskProc;
+	iOwnsMaskProcessor = aOwnsProcessor;
+	}
+
+void CPngReadCodec::SetFastProcessor(CFastProcessor* aFastProc, TBool aOwnsProcessor)
+	{
+	if (iOwnsFastProcessor)
+		delete iFastProc;
+	iFastProc = aFastProc;
+	iOwnsFastProcessor = aOwnsProcessor;		
+	}
+
+void CPngReadSubCodec::SetFastProcessorMode(TBool aMode)
+	{
+	iFastProcessorMode = aMode;
+	}
+
+void CPngReadSubCodec::ResetL()
+	{
+	iPos.SetXY(0,0);
+	iPass = 0;
+	if (iInfo.iInterlaceMethod == TPngImageInformation::EAdam7Interlace)
+		{
+		iScanlineDes1.Set(&(iScanlineBuffer1->Des())[0],iInterlacedScanlineBufferSize[0],iInterlacedScanlineBufferSize[0]);
+		iScanlineDes2.Set(&(iScanlineBuffer2->Des())[0],iInterlacedScanlineBufferSize[0],iInterlacedScanlineBufferSize[0]);
+	
+		if(iImageProc)
+			{
+			const TInt lineRepeat = ClampValue(KBlockHeight[iPass]-1,0,iInfo.iSize.iHeight-iPos.iY-2);
+			iImageProc->SetLineRepeat(lineRepeat);
+			}
+		}
+	}
+
+TDes8& CPngReadSubCodec::FirstBuffer()
+	{
+	iScanlineDes1.FillZ();
+	iCurrentScanlineBuffer = 2;
+	return iScanlineDes2;
+	}
+
+TDes8& CPngReadSubCodec::DecodeL()
+	{
+	TUint8* dataPtr = (iCurrentScanlineBuffer == 1) ? &iScanlineDes1[1] : &iScanlineDes2[1];
+	const TUint8* dataPtrLimit = dataPtr + iScanlineDes1.Length() - 1;
+
+	FilterScanlineDataL(dataPtr,dataPtrLimit);
+	
+	if (iFastProcessorMode)
+		{
+		iFastProc->Begin();	
+		}
+	
+	DoDecode(dataPtr,dataPtrLimit);
+
+	if (iFastProcessorMode)
+		{
+		iFastProc->End();	
+		}
+	
+	UpdatePos();
+	
+	if (iCurrentScanlineBuffer == 1)
+		{
+		iCurrentScanlineBuffer = 2;
+		return iScanlineDes2;
+		}
+	else
+		{
+		iCurrentScanlineBuffer = 1;
+		return iScanlineDes1;
+		}
+	}
+
+void CPngReadSubCodec::FilterScanlineDataL(TUint8* aDataPtr,const TUint8* aDataPtrLimit)
+	{
+	TInt filterType = (iCurrentScanlineBuffer == 1) ? iScanlineDes1[0] : iScanlineDes2[0];
+
+	switch (filterType)
+		{
+	case 0: // None
+		break;
+	case 1: // Sub
+		{
+		aDataPtr += iBytesPerPixel;
+
+		while (aDataPtr < aDataPtrLimit)
+			{
+			aDataPtr[0] = TUint8(aDataPtr[0] + aDataPtr[-iBytesPerPixel]);
+			aDataPtr++;
+			}
+		}
+		break;
+	case 2: // Up
+		{
+		TUint8* altDataPtr = (iCurrentScanlineBuffer == 1) ? &iScanlineDes2[1] : &iScanlineDes1[1];
+
+		while (aDataPtr < aDataPtrLimit)
+			{
+			*aDataPtr = TUint8(*aDataPtr + *altDataPtr);
+			aDataPtr++;
+			altDataPtr++;
+			}
+		}
+		break;
+	case 3: // Average
+		{
+		const TUint8* tempDataPtrLimit = Min<const TUint8*>(aDataPtr + iBytesPerPixel,aDataPtrLimit);
+		TUint8* altDataPtr = (iCurrentScanlineBuffer == 1) ? &iScanlineDes2[1] : &iScanlineDes1[1];
+
+		while (aDataPtr < tempDataPtrLimit)
+			{
+			aDataPtr[0] = TUint8(aDataPtr[0] + (altDataPtr[0] / 2));
+			aDataPtr++;
+			altDataPtr++;
+			}
+
+		while (aDataPtr < aDataPtrLimit)
+			{
+			aDataPtr[0] = TUint8(aDataPtr[0] + ((altDataPtr[0] + aDataPtr[-iBytesPerPixel]) / 2));
+			aDataPtr++;
+			altDataPtr++;
+			}
+		}
+		break;
+	case 4: // Paeth
+		{
+		const TUint8* tempDataPtrLimit = Min<const TUint8*>(aDataPtr + iBytesPerPixel,aDataPtrLimit);
+		TUint8* altDataPtr = (iCurrentScanlineBuffer == 1) ? &iScanlineDes2[1] : &iScanlineDes1[1];
+
+		while (aDataPtr < tempDataPtrLimit)
+			{
+			aDataPtr[0] = TUint8(aDataPtr[0] + altDataPtr[0]);
+			aDataPtr++;
+			altDataPtr++;
+			}
+
+		while (aDataPtr < aDataPtrLimit)
+			{
+			aDataPtr[0] = TUint8(aDataPtr[0] + PaethPredictor(aDataPtr[-iBytesPerPixel],altDataPtr[0],altDataPtr[-iBytesPerPixel]));
+			aDataPtr++;
+			altDataPtr++;
+			}
+		}
+		break;
+
+	case 64: // support for additional MNG-defined filter (Adaptive filtering with five basic types and intrapixel differencing)
+		{
+		const TInt plusAlpha=(0 != (iInfo.iColorType & TPngImageInformation::EAlphaChannelUsed));
+		if ( iInfo.iBitDepth == 16)
+			{
+			const TUint KBytesPerPixel=2*(3+plusAlpha);
+			aDataPtrLimit-=KBytesPerPixel;
+			while(aDataPtr < aDataPtrLimit)
+				{
+				const TUint32 s0   = (aDataPtr[0] << 8) | aDataPtr[1];
+				const TUint32 s1   = 0x10000u + (aDataPtr[2] << 8) | aDataPtr[3];
+				const TUint32 s2   = (aDataPtr[4] << 8) | aDataPtr[5];
+				const TUint32 red  = ((s0+s1) & 0xffffu);
+				const TUint32 blue = ((s2+s1) & 0xffffu);
+				aDataPtr[0] = TUint8((red >> 8) & 0xff);
+				aDataPtr[1] = TUint8(red & 0xff);
+				aDataPtr[4] = TUint8((blue >> 8) & 0xff);
+				aDataPtr[5] = TUint8(blue & 0xff);
+				aDataPtr+=KBytesPerPixel;
+				}
+			}
+		else if (iInfo.iBitDepth == 8)
+			{
+			const TUint KBytesPerPixel=3+plusAlpha;
+			aDataPtrLimit-=KBytesPerPixel;
+			while(aDataPtr < aDataPtrLimit)
+				{
+				aDataPtr[0] = TUint8((0x100u + aDataPtr[0] + aDataPtr[1])&0xffu);
+				aDataPtr[1] = TUint8((0x100u + aDataPtr[2] + aDataPtr[1])&0xffu);
+				aDataPtr +=KBytesPerPixel;
+				}
+			}
+		}
+		break;
+
+	default: // Error
+		User::Leave(KErrCorrupt);
+		break;
+		}
+	}
+
+TInt CPngReadSubCodec::PaethPredictor(TInt aLeft,TInt aAbove,TInt aAboveLeft)
+	{
+	TInt p = aLeft + aAbove - aAboveLeft;
+	TInt pa = Abs(p - aLeft);
+	TInt pb = Abs(p - aAbove);
+	TInt pc = Abs(p - aAboveLeft);
+
+	if (pa <= pb && pa <= pc)
+		return aLeft;
+	else if (pb <= pc)
+		return aAbove;
+	else
+		return aAboveLeft;
+	}
+
+void CPngReadSubCodec::WritePixel(TRgb aPixelColor)
+	{
+	if (iInfo.iInterlaceMethod == TPngImageInformation::EAdam7Interlace)
+		{
+		const TInt width = ClampValue(KBlockWidth[iPass],0,iInfo.iSize.iWidth - iPos.iX);
+		TPoint pos(iPos);
+		iImageProc->SetPos(pos);
+		iImageProc->SetPixelRun(aPixelColor,width);
+		iPos.iX += KColIncrement[iPass];
+		}
+	else
+		{
+		if (iRgbaMode)
+			{
+			iLineCache[iPos.iX++]=aPixelColor;
+			}
+		else
+			{
+			iImageProc->SetPixel(aPixelColor);
+			}
+		}
+	}
+
+void CPngReadSubCodec::WritePixel(TRgb aPixelColor,TUint8 aAlphaValue)
+	{
+	if(iAlphaMode || iRgbaMode)
+		{
+		TRgb RgbaColour( aPixelColor.Internal()&0xFFFFFF, (TUint32(aAlphaValue)) );
+		
+		if (iInfo.iInterlaceMethod == TPngImageInformation::EAdam7Interlace)
+			{
+			iImageProc->SetPos(iPos);
+			iImageProc->SetPixel(RgbaColour);
+			iPos.iX += KColIncrement[iPass];
+			}
+		else
+			{
+			iRgbaMode ? iLineCache[iPos.iX++]=RgbaColour : iImageProc->SetPixel(RgbaColour);
+			}
+		}
+	else
+		{
+		ASSERT(iMaskProc);
+			{
+			TRgb maskColor(TRgb::Gray256(aAlphaValue));
+		
+			if (iInfo.iInterlaceMethod == TPngImageInformation::EAdam7Interlace)
+				{
+				iImageProc->SetPos(iPos);
+				iMaskProc->SetPos(iPos);
+				iImageProc->SetPixel(aPixelColor);
+				iMaskProc->SetPixel(maskColor);
+
+				iPos.iX += KColIncrement[iPass];
+				}
+			else
+				{
+				iImageProc->SetPixel(aPixelColor);
+				iMaskProc->SetPixel(maskColor);
+				}	
+			}
+		}
+	}
+
+void CPngReadSubCodec::UpdatePos()
+	{
+	if (iInfo.iInterlaceMethod == TPngImageInformation::EAdam7Interlace)
+		{
+		ASSERT(iPass <= 7);
+
+		iPos.iX = KColStart[iPass];
+		iPos.iY += KRowIncrement[iPass];
+
+		while (iPos.iX >= iInfo.iSize.iWidth || iPos.iY >= iInfo.iSize.iHeight)
+			{
+			iPass++;
+			
+			/* Coverity may flag this up as an overrun of KColStart and KRowStart.  This is a false
+			positive because both arrays have a 'safety entry' at index [7], which is 0.  Thus,
+			iPos.iX and iPos.iY will be be 0, and so never equal to the image width/height as we
+			won't decode images with these dimensions.  Therefore, this loop will never be entered.*/
+			
+			iPos.iX = KColStart[iPass];
+			iPos.iY = KRowStart[iPass];
+			iScanlineDes1.Set(&(iScanlineBuffer1->Des())[0],iInterlacedScanlineBufferSize[iPass],iInterlacedScanlineBufferSize[iPass]);
+			iScanlineDes2.Set(&(iScanlineBuffer2->Des())[0],iInterlacedScanlineBufferSize[iPass],iInterlacedScanlineBufferSize[iPass]);
+			iScanlineDes1.FillZ();
+			iScanlineDes2.FillZ();
+			}
+
+		if(iImageProc)
+			{
+			const TInt lineRepeat = ClampValue(KBlockHeight[iPass]-1,0,iInfo.iSize.iHeight-iPos.iY-2);
+			iImageProc->SetLineRepeat(lineRepeat);
+			}
+		}
+	else
+		{
+		if (iRgbaMode)
+			{
+			iImageProc->SetPixels(iLineCache, iPos.iX);
+			}
+		iPos.iX=0;
+		}
+	}
+
+
+// CBitDepth1Decoder
+void CBitDepth1Decoder::DoConstructL()
+	{
+	if (!(iInfo.iColorType & TPngImageInformation::EPaletteUsed))
+		{ // Set up palette to be grayscale values
+		iInfo.iPalette[0] = KRgbBlack;
+		iInfo.iPalette[1] = KRgbWhite;
+
+
+		if (iInfo.iTransparencyPresent)
+			{
+			if (iInfo.iTransparentGray <= 1)
+				iInfo.iTransparencyValue[iInfo.iTransparentGray] = 0;
+			}
+		}
+
+	// Replicate values to avoid shifts when decoding
+	iInfo.iPalette[2] = iInfo.iPalette[1];
+	iInfo.iPalette[4] = iInfo.iPalette[1];
+	iInfo.iPalette[8] = iInfo.iPalette[1];
+	iInfo.iPalette[16] = iInfo.iPalette[1];
+	iInfo.iPalette[32] = iInfo.iPalette[1];
+	iInfo.iPalette[64] = iInfo.iPalette[1];
+	iInfo.iPalette[128] = iInfo.iPalette[1];
+
+	if (iInfo.iTransparencyPresent && iInfo.iTransparencyValue[1] != 255)
+		{
+		iInfo.iTransparencyValue[2] = iInfo.iTransparencyValue[1];
+		iInfo.iTransparencyValue[4] = iInfo.iTransparencyValue[1];
+		iInfo.iTransparencyValue[8] = iInfo.iTransparencyValue[1];
+		iInfo.iTransparencyValue[16] = iInfo.iTransparencyValue[1];
+		iInfo.iTransparencyValue[32] = iInfo.iTransparencyValue[1];
+		iInfo.iTransparencyValue[64] = iInfo.iTransparencyValue[1];
+		iInfo.iTransparencyValue[128] = iInfo.iTransparencyValue[1];
+		}
+
+	iBytesPerPixel = 1;
+	if (iInfo.iInterlaceMethod == TPngImageInformation::ENoInterlace)
+		{
+		TInt pixelPadding = ((iInfo.iSize.iWidth + 7) & ~7) - iInfo.iSize.iWidth;
+		if(iImageProc)
+			{
+			iImageProc->SetPixelPadding(pixelPadding);	
+			}
+		if (iMaskProc)
+			{
+			iMaskProc->SetPixelPadding(pixelPadding);	
+			}
+		}
+	}
+
+TInt CBitDepth1Decoder::ScanlineBufferSize(TInt aPixelLength)
+	{
+	return ((aPixelLength + 7) / 8) + KPngScanlineFilterTypeLength;
+	}
+
+void CBitDepth1Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit)
+	{
+	if (iInfo.iTransparencyPresent && (iMaskProc || iAlphaMode) )
+		{
+		while (aDataPtr < aDataPtrLimit)
+			{
+			TInt dataValue = *aDataPtr++;
+
+			for (TUint mask=0x80; mask!=0; mask>>=1) // iterate with 0x80, 0x40 .. 0x01
+				WritePixel(iInfo.iPalette[dataValue & mask],iInfo.iTransparencyValue[dataValue & mask]);
+			}
+		}
+	else
+		{
+		while (aDataPtr < aDataPtrLimit)
+			{
+			TInt dataValue = *aDataPtr++;
+
+			for (TUint mask=0x80; mask!=0; mask>>=1) // iterate with 0x80, 0x40 .. 0x01
+				WritePixel(iInfo.iPalette[dataValue & mask]);
+			}
+		}
+	}
+
+
+// CBitDepth2Decoder
+void CBitDepth2Decoder::DoConstructL()
+	{
+	if (!(iInfo.iColorType & TPngImageInformation::EPaletteUsed))
+		{ // Set up palette to be grayscale values
+		iInfo.iPalette[0] = KRgbBlack;
+		iInfo.iPalette[1] = KRgbDarkGray;
+		iInfo.iPalette[2] = KRgbGray;
+		iInfo.iPalette[3] = KRgbWhite;
+
+		if (iInfo.iTransparencyPresent)
+			{
+			if (iInfo.iTransparentGray <= 3)
+				iInfo.iTransparencyValue[iInfo.iTransparentGray] = 0;
+			}
+		}
+
+	// Replicate values to avoid shifts when decoding
+	iInfo.iPalette[4] = iInfo.iPalette[1];
+	iInfo.iPalette[8] = iInfo.iPalette[2];
+	iInfo.iPalette[12] = iInfo.iPalette[3];
+
+	iInfo.iPalette[16] = iInfo.iPalette[1];
+	iInfo.iPalette[32] = iInfo.iPalette[2];
+	iInfo.iPalette[48] = iInfo.iPalette[3];
+
+	iInfo.iPalette[64] = iInfo.iPalette[1];
+	iInfo.iPalette[128] = iInfo.iPalette[2];
+	iInfo.iPalette[192] = iInfo.iPalette[3];
+
+	if (iInfo.iTransparencyPresent)
+		{
+		iInfo.iTransparencyValue[4] = iInfo.iTransparencyValue[1];
+		iInfo.iTransparencyValue[8] = iInfo.iTransparencyValue[2];
+		iInfo.iTransparencyValue[12] = iInfo.iTransparencyValue[3];
+
+		iInfo.iTransparencyValue[16] = iInfo.iTransparencyValue[1];
+		iInfo.iTransparencyValue[32] = iInfo.iTransparencyValue[2];
+		iInfo.iTransparencyValue[48] = iInfo.iTransparencyValue[3];
+
+		iInfo.iTransparencyValue[64] = iInfo.iTransparencyValue[1];
+		iInfo.iTransparencyValue[128] = iInfo.iTransparencyValue[2];
+		iInfo.iTransparencyValue[192] = iInfo.iTransparencyValue[3];
+		}
+
+	iBytesPerPixel = 1;
+	if (iInfo.iInterlaceMethod == TPngImageInformation::ENoInterlace)
+		{
+		TInt pixelPadding = ((iInfo.iSize.iWidth + 3) & ~3) - iInfo.iSize.iWidth;
+		if(iImageProc)
+			{
+			iImageProc->SetPixelPadding(pixelPadding);	
+			}
+		if (iMaskProc)
+			{
+			iMaskProc->SetPixelPadding(pixelPadding);	
+			}
+		}
+	}
+
+TInt CBitDepth2Decoder::ScanlineBufferSize(TInt aPixelLength)
+	{
+	return ((aPixelLength + 3) / 4) + KPngScanlineFilterTypeLength;
+	}
+
+void CBitDepth2Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit)
+	{
+	if (iInfo.iTransparencyPresent && (iMaskProc || iAlphaMode) )
+		{
+		while (aDataPtr < aDataPtrLimit)
+			{
+			TInt dataValue = *aDataPtr++;
+
+			for (TInt mask=0xc0; mask!=0; mask>>=2) // iterate through 0xc0, 0x30, 0x0c and 0x03
+				WritePixel(iInfo.iPalette[dataValue & mask],iInfo.iTransparencyValue[dataValue & mask]);
+			}
+		}
+	else
+		{
+		while (aDataPtr < aDataPtrLimit)
+			{
+			TInt dataValue = *aDataPtr++;
+
+			for (TInt mask=0xc0; mask!=0; mask>>=2) // iterate through 0xc0, 0x30, 0x0c and 0x03
+				WritePixel(iInfo.iPalette[dataValue & mask]);
+			}
+		}
+	}
+
+
+// CBitDepth4Decoder
+void CBitDepth4Decoder::DoConstructL()
+	{
+	if (!(iInfo.iColorType & TPngImageInformation::EPaletteUsed))
+		{ // Set up palette to be grayscale values
+		for (TInt index = 0; index < 16; index++)
+			iInfo.iPalette[index] = TRgb::Gray16(index);
+
+		if (iInfo.iTransparencyPresent)
+			{
+			if (iInfo.iTransparentGray <= 15)
+				iInfo.iTransparencyValue[iInfo.iTransparentGray] = 0;
+			}
+		}
+
+	iBytesPerPixel = 1;
+	if (iInfo.iInterlaceMethod == TPngImageInformation::ENoInterlace)
+		{
+		TInt pixelPadding = ((iInfo.iSize.iWidth + 1) & ~1) - iInfo.iSize.iWidth;
+		if(iImageProc)
+			{
+			iImageProc->SetPixelPadding(pixelPadding);
+			}			
+		if (iMaskProc)
+			{
+			iMaskProc->SetPixelPadding(pixelPadding);
+			}			
+		}
+	}
+
+TInt CBitDepth4Decoder::ScanlineBufferSize(TInt aPixelLength)
+	{
+	return ((aPixelLength + 1) / 2) + KPngScanlineFilterTypeLength;
+	}
+
+void CBitDepth4Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit)
+	{
+	if (iInfo.iTransparencyPresent && (iMaskProc || iAlphaMode) )
+		{
+		while (aDataPtr < aDataPtrLimit)
+			{
+			TInt dataValue = *aDataPtr++;
+
+			WritePixel(iInfo.iPalette[dataValue >> 4],iInfo.iTransparencyValue[dataValue >> 4]);
+			WritePixel(iInfo.iPalette[dataValue & 0x0f],iInfo.iTransparencyValue[dataValue & 0x0f]);
+			}
+		}
+	else
+		{
+		while (aDataPtr < aDataPtrLimit)
+			{
+			TInt dataValue = *aDataPtr++;
+
+			WritePixel(iInfo.iPalette[dataValue >> 4]);
+			WritePixel(iInfo.iPalette[dataValue & 0x0f]);
+			}
+		}
+	}
+
+
+// CBitDepth8Decoder
+void CBitDepth8Decoder::DoConstructL()
+	{
+	if (!(iInfo.iColorType & TPngImageInformation::EPaletteUsed))
+		{ // Set up palette to be grayscale values
+		for (TInt index = 0; index < 256; index++)
+			iInfo.iPalette[index] = TRgb::Gray256(index);
+
+		if (iInfo.iTransparencyPresent)
+			{
+			if (iInfo.iTransparentGray <= 255)
+				iInfo.iTransparencyValue[iInfo.iTransparentGray] = 0;
+			}
+		}
+
+	iBytesPerPixel = 1;
+	}
+
+TInt CBitDepth8Decoder::ScanlineBufferSize(TInt aPixelLength)
+	{
+	return aPixelLength + KPngScanlineFilterTypeLength;
+	}
+
+void CBitDepth8Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit)
+	{
+	if (iInfo.iTransparencyPresent && (iMaskProc || iAlphaMode) )
+		{
+		while (aDataPtr < aDataPtrLimit)
+			{
+			WritePixel(iInfo.iPalette[aDataPtr[0]],iInfo.iTransparencyValue[aDataPtr[0]]);
+			aDataPtr++;
+			}
+		}
+	else
+		{
+		while (aDataPtr < aDataPtrLimit)
+			WritePixel(iInfo.iPalette[*aDataPtr++]);
+		}
+	}
+
+
+// CBitDepth8ColorType2Decoder
+void CBitDepth8ColorType2Decoder::DoConstructL()
+	{
+	iBytesPerPixel = 3;
+	}
+
+TInt CBitDepth8ColorType2Decoder::ScanlineBufferSize(TInt aPixelLength)
+	{
+	return (aPixelLength * 3) + KPngScanlineFilterTypeLength;
+	}
+
+void CBitDepth8ColorType2Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit)
+	{
+	if (!iFastProcessorMode)
+		{
+		if (iInfo.iTransparencyPresent && (iMaskProc || iAlphaMode) )
+			{
+			while (aDataPtr < aDataPtrLimit)
+				{
+				TInt red = aDataPtr[0];
+				TInt green = aDataPtr[1];
+				TInt blue = aDataPtr[2];
+				TRgb pixelColor(red,green,blue);
+				if (red == iInfo.iTransparentRed && green == iInfo.iTransparentGreen && blue == iInfo.iTransparentBlue)
+					{
+					WritePixel(pixelColor,0);	
+					}
+				else
+					{
+					WritePixel(pixelColor,255);	
+					}
+				aDataPtr += 3;
+				}
+			}
+		else
+			{
+			while (aDataPtr < aDataPtrLimit)
+				{
+				WritePixel(TRgb(aDataPtr[0],aDataPtr[1],aDataPtr[2]));
+				aDataPtr += 3;
+				}
+			}
+		}
+	else
+		{
+		iFastProc->SetPixels(aDataPtr, aDataPtrLimit, iLineCache, iPos);
+		}
+	}
+
+
+// CBitDepth8ColorType4Decoder
+void CBitDepth8ColorType4Decoder::DoConstructL()
+	{
+	iBytesPerPixel = 2;
+	}
+
+TInt CBitDepth8ColorType4Decoder::ScanlineBufferSize(TInt aPixelLength)
+	{
+	return (aPixelLength * 2) + KPngScanlineFilterTypeLength;
+	}
+
+void CBitDepth8ColorType4Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit)
+	{
+	if (iMaskProc || iAlphaMode)
+		{
+		while (aDataPtr < aDataPtrLimit)
+			{
+			WritePixel(TRgb::Gray256(aDataPtr[0]),aDataPtr[1]);
+			aDataPtr += 2;
+			}
+		}
+	else
+		{
+		while (aDataPtr < aDataPtrLimit)
+			{
+			WritePixel(TRgb::Gray256(aDataPtr[0]));
+			aDataPtr += 2;
+			}
+		}
+	}
+
+
+// CBitDepth8ColorType6Decoder
+void CBitDepth8ColorType6Decoder::DoConstructL()
+	{
+	iBytesPerPixel = 4;
+	}
+
+TInt CBitDepth8ColorType6Decoder::ScanlineBufferSize(TInt aPixelLength)
+	{
+	return (aPixelLength * 4) + KPngScanlineFilterTypeLength;
+	}
+
+void CBitDepth8ColorType6Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit)
+	{
+	if (!iFastProcessorMode)
+		{
+		if (iMaskProc || iAlphaMode)
+			{
+			while (aDataPtr < aDataPtrLimit)
+				{
+				WritePixel(TRgb(aDataPtr[0],aDataPtr[1],aDataPtr[2]),aDataPtr[3]);
+				aDataPtr += 4;
+				}
+			}
+		else
+			{
+			while (aDataPtr < aDataPtrLimit)
+				{
+				WritePixel(TRgb(aDataPtr[0],aDataPtr[1],aDataPtr[2]));
+				aDataPtr += 4;
+				}
+			}
+		}
+	else
+		{
+		iFastProc->SetPixels(aDataPtr, aDataPtrLimit, iLineCache, iPos);						
+		}
+	}
+
+
+// CBitDepth16ColorType0Decoder
+void CBitDepth16ColorType0Decoder::DoConstructL()
+	{
+	iBytesPerPixel = 2;
+	}
+
+TInt CBitDepth16ColorType0Decoder::ScanlineBufferSize(TInt aPixelLength)
+	{
+	return (aPixelLength * 2) + KPngScanlineFilterTypeLength;
+	}
+
+void CBitDepth16ColorType0Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit)
+	{
+	if (iInfo.iTransparencyPresent && (iMaskProc || iAlphaMode) )
+		{
+		while (aDataPtr < aDataPtrLimit)
+			{
+			TInt gray = (aDataPtr[0] << 8) | aDataPtr[1];
+			TRgb pixelColor(TRgb::Gray256(aDataPtr[0]));
+			if (gray == iInfo.iTransparentGray)
+				WritePixel(pixelColor,0);
+			else
+				WritePixel(pixelColor,255);
+			aDataPtr += 2;
+			}
+		}
+	else
+		{
+		while (aDataPtr < aDataPtrLimit)
+			{
+			WritePixel(TRgb::Gray256(aDataPtr[0]));
+			aDataPtr += 2;
+			}
+		}
+	}
+
+
+// CBitDepth16ColorType2Decoder
+void CBitDepth16ColorType2Decoder::DoConstructL()
+	{
+	iBytesPerPixel = 6;
+	}
+
+TInt CBitDepth16ColorType2Decoder::ScanlineBufferSize(TInt aPixelLength)
+	{
+	return (aPixelLength * 6) + KPngScanlineFilterTypeLength;
+	}
+
+void CBitDepth16ColorType2Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit)
+	{
+	if (iInfo.iTransparencyPresent && (iMaskProc || iAlphaMode) )
+		{
+		while (aDataPtr < aDataPtrLimit)
+			{
+			TInt red = (aDataPtr[0] << 8) | aDataPtr[1];
+			TInt green = (aDataPtr[2] << 8) | aDataPtr[3];
+			TInt blue = (aDataPtr[4] << 8) | aDataPtr[5];
+			TRgb pixelColor(aDataPtr[0],aDataPtr[2],aDataPtr[4]);
+			if (red == iInfo.iTransparentRed && green == iInfo.iTransparentGreen && blue == iInfo.iTransparentBlue)
+				WritePixel(pixelColor,0);
+			else
+				WritePixel(pixelColor,255);
+			aDataPtr += 6;
+			}
+		}
+	else
+		{
+		while (aDataPtr < aDataPtrLimit)
+			{
+			WritePixel(TRgb(aDataPtr[0],aDataPtr[2],aDataPtr[4]));
+			aDataPtr += 6;
+			}
+		}
+	}
+
+
+// CBitDepth16ColorType4Decoder
+void CBitDepth16ColorType4Decoder::DoConstructL()
+	{
+	iBytesPerPixel = 4;
+	}
+
+TInt CBitDepth16ColorType4Decoder::ScanlineBufferSize(TInt aPixelLength)
+	{
+	return (aPixelLength * 4) + KPngScanlineFilterTypeLength;
+	}
+
+void CBitDepth16ColorType4Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit)
+	{
+	if (iMaskProc || iAlphaMode)
+		{
+		while (aDataPtr < aDataPtrLimit)
+			{
+			WritePixel(TRgb::Gray256(aDataPtr[0]),aDataPtr[2]);
+			aDataPtr += 4;
+			}
+		}
+	else
+		{
+		while (aDataPtr < aDataPtrLimit)
+			{
+			WritePixel(TRgb::Gray256(aDataPtr[0]));
+			aDataPtr += 4;
+			}
+		}
+	}
+
+
+// CBitDepth16ColorType6Decoder
+void CBitDepth16ColorType6Decoder::DoConstructL()
+	{
+	iBytesPerPixel = 8;
+	}
+
+TInt CBitDepth16ColorType6Decoder::ScanlineBufferSize(TInt aPixelLength)
+	{
+	return (aPixelLength * 8) + KPngScanlineFilterTypeLength;
+	}
+
+void CBitDepth16ColorType6Decoder::DoDecode(TUint8* aDataPtr,const TUint8* aDataPtrLimit)
+	{
+	if (iMaskProc || iAlphaMode)
+		{
+		while (aDataPtr < aDataPtrLimit)
+			{
+			WritePixel(TRgb(aDataPtr[0],aDataPtr[2],aDataPtr[4]),aDataPtr[6]);
+			aDataPtr += 8;
+			}
+		}
+	else
+		{
+		while (aDataPtr < aDataPtrLimit)
+			{
+			WritePixel(TRgb(aDataPtr[0],aDataPtr[2],aDataPtr[4]));
+			aDataPtr += 8;
+			}
+		}
+	}