imagingmodules/jp2kcodec/Src/JP2KSynthesis.cpp
changeset 0 469c91dae73b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imagingmodules/jp2kcodec/Src/JP2KSynthesis.cpp	Thu Dec 17 09:22:31 2009 +0200
@@ -0,0 +1,2366 @@
+/*
+* Copyright (c) 2003, 2004 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:  CJ2kSynthesis class used to perform inverse quantization and
+*                inverse DWT.
+*
+*/
+
+
+// INCLUDE FILES
+#include "JP2KTileInfo.h"
+#include "JP2KImageInfo.h"
+#include "JP2KImageWriter.h"
+#include "JP2KEntropyDecoder.h"
+#include "JP2KCodeBlock.h"
+#include "JP2KPacket.h"
+#include "JP2KSubband.h"
+#include "JP2KComponentInfo.h"
+#include "JP2KSynthesis.h"
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES  
+
+// CONSTANTS
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+
+// FORWARD DECLARATIONS
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::CJ2kSynthesis
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CJ2kSynthesis::CJ2kSynthesis() 
+    {
+    // Set up the filter taps for irreversible filter
+    iTapsLow[0] = KFixedLow9x70;
+    iTapsLow[1] = KFixedLow9x71;
+    iTapsLow[2] = KFixedLow9x72;
+    iTapsLow[3] = KFixedLow9x73;
+  
+    iTapsHigh[0] = KFixedHigh9x70;
+    iTapsHigh[1] = KFixedHigh9x71;
+    iTapsHigh[2] = KFixedHigh9x72;
+    iTapsHigh[3] = KFixedHigh9x73;
+    iTapsHigh[4] = KFixedHigh9x74;
+    }
+
+// Destructor
+CJ2kSynthesis::~CJ2kSynthesis()
+    {
+    if ( iInputBuffer )
+        {
+        iInputBuffer  -= ( KFilterExtension + 1 );
+        User::Free( iInputBuffer );
+        iInputBuffer = 0;
+        }
+    if ( iOutputBuffer )
+        {
+        iOutputBuffer -= ( KFilterExtension + 1 );
+        User::Free( iOutputBuffer );
+        iOutputBuffer = 0;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::DecodeTileL
+// Decode a single tile
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kSynthesis::DecodeTileL( CJ2kImageWriter& aImageWriter, 
+                                 CJ2kEntropyDecoder& aEntropyDecoder,
+                                 CJ2kImageInfo& aImageInfo,
+                                 CJ2kTileInfo& aTile )
+    {
+    if ( aImageInfo.Crop() )
+        {
+        // If this tile doesn't belong to the crop area, continue
+        if ( !aImageInfo.TileMaskAt( aTile.SotMarker().iIsot ) )
+            {
+            return;
+            }
+        }
+
+    CJ2kComponentInfo* componentInfo = 0;
+    TInt32 maxSize = 0;
+    TUint16 compIndex = 0;
+    TUint16 numOfComponents = aImageInfo.NumOfComponents();
+
+    // Find the largest width or height
+    for ( compIndex = 0; compIndex < numOfComponents; ++compIndex )
+        {
+        componentInfo = CONST_CAST( CJ2kComponentInfo*, &aTile.ComponentAt( compIndex ) );
+        maxSize = Max( maxSize, Max( componentInfo->ComponentCanvas().Height(), 
+                                     componentInfo->ComponentCanvas().Width() ) );
+        }
+
+    maxSize += 2 * ( KFilterExtension + 1 );
+    AllocBufferL( maxSize );
+
+    TSize   subbandSize( 0, 0 );
+    TUint16 bandIndex = 0;
+    TUint16 blockIndex = 0;
+
+    CJ2kSubband*   subband = 0;
+    CJ2kPacket*    packet = 0;
+    CJ2kCodeBlock* codeblock = 0;
+
+    TUint8  quantStyle = 0;
+    TUint8  bitDepth = 0;
+    TUint8  cblkStyle = 0;
+    TUint8  levelIndex = 0;
+    TUint32 packetIndex = 0;
+
+    CJ2kWriterComponentInfo* component = 0;
+    RPointerArray<CJ2kPacket>* packetList;
+
+    aEntropyDecoder.SetNewSizeL( aImageInfo.MaxBlockSize() );
+
+    // For each component in the tile
+    for ( compIndex = 0; compIndex < aImageInfo.NumOfComponents(); ++compIndex )
+        {
+        componentInfo = CONST_CAST( CJ2kComponentInfo*, &aTile.ComponentAt( compIndex ) );
+
+        // Skip the component when height or width is 0
+        if ( componentInfo->ComponentCanvas().Height() == 0 ||
+             componentInfo->ComponentCanvas().Width() == 0  )
+            {
+            continue;   //lint !e960    Continue is OK.
+            }
+
+        // Check for component truncation
+        if ( aImageInfo.ComponentDrop() )
+            {
+            if ( aImageWriter.SingleFileOutput() )
+                {
+                if ( compIndex == ( aImageInfo.ComponentDrop() - 1 ) )
+                    {
+                    numOfComponents = compIndex;
+                    }
+                else
+                    {
+                    continue;   //lint !e960    Continue is OK.
+                    }
+                }
+            else
+                {
+                if ( compIndex != ( aImageInfo.ComponentDrop() - 1 ) )
+                    {
+                    continue;   //lint !e960    Continue is OK.
+                    }
+                }
+            }
+
+        // Get the resolution level for this component
+        iWaveletLevels = (TInt16)( componentInfo->Levels() - aImageInfo.LevelDrop() );
+
+        TInt32 stepSize = 1;
+        if ( iWaveletLevels < 0 )
+            {
+            TInt32 i;
+
+            // Compute the output step size, the stepSize indicates how much more 
+            // resolution has to be dropped if the image didn't have enough wavelet
+            // levels to begin with. One indicates no extra resolution drop (write
+            // each sample) and for each extra drop skip half of the samples, i.e.
+            // stepSize is 2^extraLevels in case extra drop is needed.
+        
+            // Adjust the tile starting points and the stepSize
+            for ( i = 0; i < (-iWaveletLevels); i++ )
+                {
+                // Double the step size for every extra level dropped.
+                stepSize *= 2;
+                }
+        
+            iWaveletLevels = 0;
+            }
+
+        // Get the top subband ( original image )
+        subband = CONST_CAST( CJ2kSubband*, componentInfo->SubbandAt( (TUint8)iWaveletLevels ) );
+
+        if ( subband->SubbandResLevel() != 0 )
+            {
+            subband = subband->Parent();
+            }
+
+        subbandSize = subband->SubbandCanvasSize();
+
+        // Skip the component when subband's height or width is 0
+        if ( subbandSize.iWidth == 0 || subbandSize.iHeight == 0 )
+            {
+            continue;   //lint !e960    Continue is OK.
+            }
+
+        component = CONST_CAST( CJ2kWriterComponentInfo*, &aImageWriter.WriterComponentAt( compIndex ) );
+
+        // Have to allocate memory for each component in the image writer
+        component->AllocDataL( subbandSize );
+
+        bitDepth = aImageInfo.DepthOfComponent( compIndex );
+        
+        // Get the right number of levels and transform type 
+        // reversible == 1 for 5x3 filter and == 0 for 9x7 filter
+        iReversible = componentInfo->IsReversible();
+        iROIShift   = componentInfo->RoiShift();
+
+        quantStyle  = componentInfo->QuantizationStyle();
+        cblkStyle   = componentInfo->CodeBlockStyle();
+
+        // For each resolution level in the component
+        for ( levelIndex = 0; levelIndex <= iWaveletLevels; levelIndex++ )
+            {
+            subband = CONST_CAST( CJ2kSubband*, componentInfo->SubbandAt( levelIndex ) );
+
+            // For each subband in the resolution level
+            do    
+                {
+                bandIndex = ( quantStyle == 1 ) ? (TUint16)0 : subband->SubbandTreeIndex();
+
+                // Get the right magnitude bits for this band
+                iMagnitudeBitsHere = componentInfo->MagnitudeBits( bandIndex );
+        
+                // Compute the Quantization parameters here, so we don't repeat that for every codeblock/precinct
+                ComputeQuantizationParameters( *componentInfo, bandIndex, subband->SubbandGain(), bitDepth );
+
+                // Set the lookup table for entropy decoder
+                aEntropyDecoder.SetCurrentZCLUT( (TUint8)( subband->SubbandType() ) );
+
+                packetList = CONST_CAST( RPointerArray<CJ2kPacket>*, &subband->PacketList() );    //lint !e665 the first parameter cannot be parenthesized here
+
+                // For each packet in the subband
+                for ( packetIndex = 0; packetIndex < componentInfo->NumOfPackets( levelIndex ); ++packetIndex )
+                    {
+                    packet = ( *packetList )[packetIndex];
+
+                    // For each codeblock in the packet
+                    for ( blockIndex = 0; blockIndex < packet->NumOfBlocks(); ++blockIndex )
+                        {
+                        codeblock = CONST_CAST( CJ2kCodeBlock*, &packet->CodeBlockAt( blockIndex ) );
+
+                        // There is coded data in the codeblock
+                        if ( codeblock->DataLength() )
+                            {
+                            // Decode the codeblock
+                            aEntropyDecoder.DecodeCodeblock( *codeblock, cblkStyle, (TUint8)( iMagnitudeBitsHere + iROIShift ) );
+
+                            // Copy data from the decoded codeblock for inverse quantization and ROI shifting
+                            CopyDataToImage( aEntropyDecoder, component->Data(), *subband, *codeblock, quantStyle );
+                            }
+                        } // end of each codeblock
+                    }  // end of each packet
+
+                // Get the sibling subband
+                subband = subband->NextSubbandRaster();
+
+                } while ( subband ); // end of each subband in the resolution level
+
+            }  // end of each resolution level in the component
+    
+        // Point to the LL-band before calling inverse wavelet transform
+        subband = CONST_CAST( CJ2kSubband*, componentInfo->SubbandAt( 0 ) );
+
+        // Perform a full inverse wavelet transformation
+        FullWaveletInverse( component->Data(), subband );
+
+
+        // Check whether extra downsampling is needed
+        if(stepSize > 1)
+            {
+            TInt32 i,j;
+            TInt32 iStep,jStep;
+
+            // If the stepSize is larger than one it means that we have to downsample
+            // the output. This is because there were not enough wavelet levels to do
+            // the resolution dropping for this component.
+
+            // The reason why downsampling is done here and not in the ImageWriter is
+            // that different components might have different number of wavlet levels
+            // and thus it is easier to downsample the components here (so that we can 
+            // just write out the samples normally in ImageWriter.
+            for(i = 0,iStep = 0; iStep < subbandSize.iHeight; i++,iStep += stepSize)
+                {
+                for(j = 0,jStep = 0; jStep < subbandSize.iWidth; j++,jStep += stepSize)
+                    {
+                    // Downsample the component so that downsampled image is in the
+                    // upper left-hand corner.
+                    component->Data()[i][j] = component->Data()[iStep][jStep];
+                    }
+                }
+            }
+
+
+
+        if ( numOfComponents >= 3 ) 
+            {
+            if ( aTile.ColorTransformation() || 
+                ( aImageWriter.CSCode() == 18 || aImageWriter.CSCode() == 16 ) )
+                {
+                // Wait til we finish decoding all components before writing out the image
+                if ( compIndex < 2 )
+                    {
+                    continue;   //lint !e960    Continue is OK.
+                    }
+                }
+            else if ( aImageWriter.CSCode() == 0 )
+                {
+                // This case is also valid when no CSCode is defined, e.g. no file format is present
+                if( numOfComponents <= 3 )
+                    {
+                    if ( compIndex < 2 )
+                        {
+                        continue;   //lint !e960    Continue is OK.
+                        }
+                    }
+                else
+                    {
+                    // Proceed to outputImageL
+                    }
+                }
+            }   //lint !e961    no else is needed here at the end of if...else if
+
+        // Write out the tile image
+        aImageWriter.OutputImageL( aTile, compIndex );
+
+        }   // end of each component in the tile
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::DecodeTileBlockL
+// Decode a single tile with lower memory using 256x256 blocks 
+// for the inverse wavelet transform
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kSynthesis::DecodeTileBlockL( CJ2kImageWriter& aImageWriter, 
+                                      CJ2kEntropyDecoder& aEntropyDecoder,
+                                      CJ2kImageInfo& aImageInfo,
+                                      CJ2kTileInfo& aTile )
+    {
+    if ( aImageInfo.Crop() )
+        {
+        // If this tile doesn't belong to the crop area, continue
+        if ( !aImageInfo.TileMaskAt( aTile.SotMarker().iIsot ) )
+            {
+            return;
+            }
+        }
+
+    CJ2kComponentInfo* componentInfo = 0;
+    TInt32  maxSize = 0;
+    TUint16 compIndex = 0;
+    TUint16 numOfComponents = aImageInfo.NumOfComponents();
+
+    // Find the largest width or height
+    for ( compIndex = 0; compIndex < numOfComponents; ++compIndex )
+        {
+        componentInfo = CONST_CAST( CJ2kComponentInfo*, &aTile.ComponentAt( compIndex ) );
+        maxSize = Max( maxSize, Max( componentInfo->ComponentCanvas().Height(), 
+                                     componentInfo->ComponentCanvas().Width() ) );
+        }
+
+    maxSize = KMaxBlockSupportSize;
+
+    maxSize += 2 * ( KFilterExtension + 1 );
+    AllocBufferL( maxSize );
+
+    TSize subbandSize( 0, 0 );
+    TUint16 bandIndex = 0;
+    TUint16 blockIndex = 0;
+
+    CJ2kSubband* subband = 0;
+    CJ2kPacket* packet = 0;
+    CJ2kCodeBlock* codeblock = 0;
+
+    TUint8  quantStyle = 0;
+    TUint8  bitDepth = 0;
+    TUint8  cblkStyle = 0;
+    TUint8  levelIndex = 0;
+    TUint32 packetIndex = 0;
+    TUint32 blockXCoord = 0;
+    TUint32 blockYCoord = 0;
+    TUint32 compXCoord = 0;
+    TUint32 compYCoord = 0;
+    TInt32 blockXEnd = 0;
+    TInt32 blockYEnd = 0;
+    TRect supportRegion( 0, 0, 0 , 0 );
+    TRect parentSupportRegion( 0, 0, 0 , 0 );
+    TPoint regionOffset( 0, 0 );
+    TInt16 tmpLevelIndex = 0;
+    TSize thisCompSize( 0, 0 );
+    TSize firstCompSize( 0, 0 );
+    TSize regionSize( 0, 0 );
+    TPoint tileEndPoint( 0, 0 );
+    TPoint tileStartPoint( 0, 0 );
+    TPoint blockStepSize( 0, 0 );
+
+    CJ2kWriterComponentInfo* component = 0;
+    RPointerArray<CJ2kPacket>* packetList;
+    TSizMarker& sizMarker = CONST_CAST( TSizMarker&, aImageInfo.SizMarker() );
+
+    aEntropyDecoder.SetNewSizeL( aImageInfo.MaxBlockSize() );
+    componentInfo = CONST_CAST( CJ2kComponentInfo*, &aTile.ComponentAt( 0 ) );
+    
+    // Get the resolution level for this component
+    iWaveletLevels = (TInt16)( componentInfo->Levels() - aImageInfo.LevelDrop() );
+    if ( iWaveletLevels < 0 )
+        {
+        iWaveletLevels = 0;
+        }
+
+    // Get the top subband ( original image )
+    subband = CONST_CAST( CJ2kSubband*, componentInfo->SubbandAt( (TUint8)iWaveletLevels ) );
+    if ( subband->SubbandResLevel() != 0 )
+        {
+        subband = subband->Parent();
+        }
+
+    subbandSize = subband->SubbandCanvasSize();
+    tileEndPoint.iX = subbandSize.iWidth;
+    tileEndPoint.iY = subbandSize.iHeight;
+    tileStartPoint.iX = componentInfo->ComponentCanvas().iTl.iX;
+    tileStartPoint.iY = componentInfo->ComponentCanvas().iTl.iY;
+
+    // Loop on 256x256 blocks to reduce the memory required to perform the inverse wavelet
+    // First set as starting point the canvas coordinates of this component
+    blockXCoord = 0;
+    blockYCoord = 0;
+    blockStepSize.iX = KWaveletBlockSize;
+    blockStepSize.iY = KWaveletBlockSize;
+
+    for ( ; blockYCoord < (TUint32)tileEndPoint.iY; blockYCoord += KWaveletBlockSize )
+        {
+        // Start from the left border of this tile
+        blockXCoord = 0;
+
+        for ( ; blockXCoord < ( TUint32 )tileEndPoint.iX; blockXCoord += KWaveletBlockSize )
+            {
+            // For each component in the tile
+            for ( compIndex = 0; compIndex < aImageInfo.NumOfComponents(); ++compIndex )
+                {
+                compXCoord = blockXCoord;
+                compYCoord = blockYCoord;
+
+                componentInfo = CONST_CAST( CJ2kComponentInfo*, &aTile.ComponentAt( compIndex ) );
+
+                // Skip the component when height or width is 0
+                if ( componentInfo->ComponentCanvas().Height() == 0 ||
+                     componentInfo->ComponentCanvas().Width() == 0  )
+                    {
+                    continue;   //lint !e960    Continue is OK.
+                    }
+
+                // Here we have to add a check that if we have sub sampled component together with color transform,
+                // we have to subsample also the block dimensions ( so that the inverse color transform is performed
+                // correctly.
+                blockStepSize.iX = KWaveletBlockSize;
+                blockStepSize.iY = KWaveletBlockSize;
+                if ( aImageInfo.NumOfComponents() == 3 )
+                    {
+                    if ( sizMarker.iXRsiz[1] == 2 * sizMarker.iXRsiz[0] &&
+                         sizMarker.iXRsiz[2] == 2 * sizMarker.iXRsiz[0] )
+                        {
+                        if ( sizMarker.iXRsiz[1] == 2 * sizMarker.iXRsiz[0] &&
+                             sizMarker.iXRsiz[2] == 2 * sizMarker.iXRsiz[0] )
+                            {
+                            if( compIndex == 1 || compIndex == 2 )
+                                {
+                                blockStepSize.iX = KWaveletBlockSize >> 1;
+                                blockStepSize.iY = KWaveletBlockSize >> 1;
+                                compXCoord >>= 1;
+                                compYCoord >>= 1;
+                                }
+                            }
+                        else
+                            {
+                            if( compIndex == 1 || compIndex == 2 )
+                                {
+                                blockStepSize.iX = KWaveletBlockSize >> 1;
+                                compXCoord >>= 1;
+                                blockStepSize.iY = KWaveletBlockSize;
+                                }
+                            }
+                        }
+                    }
+
+                // Check for component truncation
+                if ( aImageInfo.ComponentDrop() )
+                    {
+                    if ( aImageWriter.SingleFileOutput() )
+                        {
+                        if ( compIndex == ( aImageInfo.ComponentDrop() - 1 ) )
+                            {
+                            numOfComponents = compIndex;
+                            }
+                        else
+                            {
+                            continue;   //lint !e960    Continue is OK.
+                            }
+                        }
+                    else
+                        {
+                        if ( compIndex != ( aImageInfo.ComponentDrop() - 1 ) )
+                            {
+                            continue;   //lint !e960    Continue is OK.
+                            }
+                        }
+                    }
+
+                // Get the resolution level for this component
+                iWaveletLevels = (TInt16)( componentInfo->Levels() - aImageInfo.LevelDrop() );
+
+                TInt32 stepSize = 1;
+                if ( iWaveletLevels < 0 )
+                    {
+                    TInt32 i;
+
+                    // Compute the output step size, the stepSize indicates how much more 
+                    // resolution has to be dropped if the image didn't have enough wavelet
+                    // levels to begin with. One indicates no extra resolution drop (write
+                    // each sample) and for each extra drop skip half of the samples, i.e.
+                    // stepSize is 2^extraLevels in case extra drop is needed.
+                    
+                    // Adjust the tile starting points and the stepSize
+                    for ( i = 0; i < (-iWaveletLevels); i++ )
+                        {
+                        // Double the step size for every extra level dropped.
+                        stepSize *= 2;
+                        }
+            
+        
+                    iWaveletLevels = 0;
+                    }
+
+                // Get the top subband ( original image )
+                subband = CONST_CAST( CJ2kSubband*, componentInfo->SubbandAt( (TUint8)iWaveletLevels ) );
+
+                if ( subband->SubbandResLevel() != 0 )
+                    {
+                    subband = subband->Parent();
+                    }
+
+                subbandSize = subband->SubbandCanvasSize();
+
+                // Skip the component when subband's height or width is 0
+                if ( subbandSize.iWidth == 0 || subbandSize.iHeight == 0 )
+                    {
+                    continue;   //lint !e960    Continue is OK.
+                    }
+
+                // Check that the block doesn't exceed the boundary of this component
+                if( (TInt32)compXCoord+blockStepSize.iX > subbandSize.iWidth )
+                    {
+                    blockXEnd = subbandSize.iWidth;
+                    }
+                else
+                    {
+                    blockXEnd = compXCoord+blockStepSize.iX;
+                    }
+                if( (TInt32)compYCoord+blockStepSize.iY > subbandSize.iHeight )
+                    {
+                    blockYEnd = subbandSize.iHeight;
+                    }
+                else
+                    {
+                    blockYEnd = compYCoord+blockStepSize.iY;
+                    }
+
+                // Store the block size on the first component in case the others are sub sampled
+                if( compIndex == 0 )
+                    {
+                    firstCompSize.iWidth = blockXEnd - blockXCoord;
+                    firstCompSize.iHeight = blockYEnd - blockYCoord;
+                    }
+
+                // Store the block size of this component
+                thisCompSize.iWidth = blockXEnd - compXCoord;
+                thisCompSize.iHeight = blockYEnd - compYCoord;
+
+                // This component could be sampled so that the block doesn't "exist" 
+                // in this component, if so move to next component
+                if( thisCompSize.iWidth <= 0 || thisCompSize.iHeight <= 0 )         
+                    {
+                    continue;   //lint !e960    Continue is OK.
+                    }
+
+                component = CONST_CAST( CJ2kWriterComponentInfo*, &aImageWriter.WriterComponentAt( compIndex ) );
+                
+                // Have to allocate memory for each component in the image writer                
+                subbandSize.iWidth = subbandSize.iHeight = KMaxBlockSupportSize;
+                component->AllocDataL( subbandSize );
+
+                bitDepth = aImageInfo.DepthOfComponent( compIndex );
+        
+                // Get the right number of levels and transform type 
+                // reversible == 1 for 5x3 filter and == 0 for 9x7 filter
+                iReversible = componentInfo->IsReversible();
+                iROIShift = componentInfo->RoiShift();
+
+                quantStyle = componentInfo->QuantizationStyle();
+                cblkStyle = componentInfo->CodeBlockStyle();
+
+                // The support region is the region needed on current level to 
+                // compute the samples in current block.
+                supportRegion.iTl.iX = compXCoord;
+                supportRegion.iTl.iY = compYCoord;
+                supportRegion.iBr.iX = blockXEnd;
+                supportRegion.iBr.iY = blockYEnd;
+
+                // For each resolution level in the component
+                for ( levelIndex = 0; levelIndex <= iWaveletLevels; levelIndex++ )
+                    {
+                    // The support region is the region needed on current level to compute the samples in current block.
+                    supportRegion.iTl.iX = compXCoord;
+                    supportRegion.iTl.iY = compYCoord;
+                    supportRegion.iBr.iX = blockXEnd;
+                    supportRegion.iBr.iY = blockYEnd;
+                    parentSupportRegion = supportRegion;
+                    regionOffset.iX = regionOffset.iY = 0;
+
+                    // Compute the support region of the parent level of the bands that are to be processed
+                    // The support region is computed depending on the level we process currently.
+                    for( tmpLevelIndex = iWaveletLevels; tmpLevelIndex > levelIndex; tmpLevelIndex-- )
+                        {
+                        // Get the subband on this ( temp )level in order to find out if high-pass first is true or not
+                        subband = CONST_CAST( CJ2kSubband*, componentInfo->SubbandAt( (TUint8)( tmpLevelIndex ) ) );
+
+                        // Level zero has the same support as level 1, so don't update the support for level zero.
+                        if( tmpLevelIndex != 1 )
+                            {
+                            // Compute the new crop coordinates for the subbands on this level
+                            if( iReversible )
+                                {
+                                // Support region for low-pass bands for 5x3 filter
+
+                                // If this band is computed high-pass first, then one extra low-pass coefficient is needed from left.
+                                // This is due to the fact that for Output[2n+1], we need five samples H[n-1], L[n], H[n], L[n+1] and H[n+1], but when high-pass 
+                                // is computed first, we actually need samples H[n-1], L[n-1], H[n], L[n] and H[n+1], where L are the low-pass filtered samples
+                                // and H are the high-pass filtered samples.
+                                if( subband->Parent()->HighPassFirst().iX )
+                                    {
+                                    parentSupportRegion.iTl.iX = ( ( ( parentSupportRegion.iTl.iX >> 1 ) - 1 ) > 0 ) ?  //lint !e702    The shifted values cannot be negative here
+                                                                 ( ( parentSupportRegion.iTl.iX >> 1 ) - 1 ) : 0; //lint !e702    The shifted values cannot be negative here
+                                    }
+                                else
+                                    {
+                                    parentSupportRegion.iTl.iX = parentSupportRegion.iTl.iX >> 1; //lint !e702    The shifted values cannot be negative here
+                                    }
+                                // If this band is computed high-pass first, then one extra low-pass coefficient is needed from above.
+                                if( subband->Parent()->HighPassFirst().iY )
+                                    {
+                                    parentSupportRegion.iTl.iY = ( ( ( parentSupportRegion.iTl.iY >> 1 ) - 1 )>0 ) ?  //lint !e702    The shifted values cannot be negative here
+                                                                 ( ( parentSupportRegion.iTl.iY >> 1 ) - 1 ) : 0; //lint !e702    The shifted values cannot be negative here
+                                    }
+                                else
+                                    {
+                                    parentSupportRegion.iTl.iY = parentSupportRegion.iTl.iY >> 1; //lint !e702    The shifted values cannot be negative here
+                                    }
+
+                                parentSupportRegion.iBr.iX = ( ( parentSupportRegion.iBr.iX ) >> 1 ) + 1; //lint !e702    The shifted values cannot be negative here
+                                parentSupportRegion.iBr.iY = ( ( parentSupportRegion.iBr.iY ) >> 1 ) + 1; //lint !e702    The shifted values cannot be negative here
+                                }
+                            else
+                                {
+                                // Support region for low-pass bands for 9x7 filter
+                                // If this band is computed high-pass first, then one extra low-pass coefficient is needed ( from left ).
+                                if( subband->Parent()->HighPassFirst().iX )
+                                    {
+                                    parentSupportRegion.iTl.iX = ( ( parentSupportRegion.iTl.iX >> 1 )-2 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
+                                                                 ( parentSupportRegion.iTl.iX >> 1 )-2 : 0; //lint !e702    the shifted values cannot be negative here
+                                    }
+                                else
+                                    {
+                                    parentSupportRegion.iTl.iX = ( ( ( parentSupportRegion.iTl.iX >> 1 ) - 1 ) > 0 ) ? //lint !e702    The shifted values cannot be negative here
+                                                                 ( ( parentSupportRegion.iTl.iX >> 1 ) - 1 ) : 0; //lint !e702    the shifted values cannot be negative here
+                                    }
+                                if( subband->Parent()->HighPassFirst().iY )
+                                    {
+                                    parentSupportRegion.iTl.iY = ( ( ( parentSupportRegion.iTl.iY >> 1 ) - 2 ) > 0 ) ? //lint !e702    The shifted values cannot be negative here
+                                                                 ( ( parentSupportRegion.iTl.iY >> 1 ) - 2 ) : 0; //lint !e702    the shifted values cannot be negative here
+                                    }
+                                else
+                                    {
+                                    parentSupportRegion.iTl.iY = ( ( ( parentSupportRegion.iTl.iY >> 1 ) - 1 ) > 0 ) ? //lint !e702    The shifted values cannot be negative here
+                                                                 ( ( parentSupportRegion.iTl.iY >> 1 ) - 1 ) : 0; //lint !e702    the shifted values cannot be negative here
+                                    }
+
+                                parentSupportRegion.iBr.iX = ( ( parentSupportRegion.iBr.iX ) >> 1 ) + 2; //lint !e702    the shifted values cannot be negative here
+                                parentSupportRegion.iBr.iY = ( ( parentSupportRegion.iBr.iY ) >> 1 ) + 2; //lint !e702    the shifted values cannot be negative here
+                                }
+                            }
+                        }
+
+
+                    subband = CONST_CAST( CJ2kSubband*, componentInfo->SubbandAt( levelIndex ) );
+
+                    // For each subband in the resolution level
+                    do    
+                        {
+                        bandIndex = ( quantStyle == 1 ) ? (TUint16)0 : subband->SubbandTreeIndex();
+
+                        // Get the right magnitude_bits for this band
+                        iMagnitudeBitsHere = componentInfo->MagnitudeBits( bandIndex );
+
+                        // If iWaveletLevels == 0, do not update the supportRegion, since there is no wavelet decomposition ( zero levels )
+                        if( iWaveletLevels != 0 )
+                            {
+                            // Now compute the support region for this band depending on whether it is LL, LH, HL or HH
+                            // Use the support region of the parent for computation.
+                            //
+                            if( iReversible )
+                                {
+                                if( ( subband->SubbandType() ) == 0 || ( subband->SubbandType() ) == 2 )
+                                    {
+                                    if( subband->Parent()->HighPassFirst().iX )
+                                        {
+                                        supportRegion.iTl.iX = ( ( parentSupportRegion.iTl.iX >> 1 )-1 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
+                                                               ( parentSupportRegion.iTl.iX >> 1 )-1 : 0; //lint !e702    the shifted values cannot be negative here
+                                        }
+                                    else
+                                        {
+                                        supportRegion.iTl.iX = parentSupportRegion.iTl.iX >> 1;     //lint !e702    the shifted value cannot be negative here
+                                        }
+                                    }
+                                else
+                                    {
+                                    supportRegion.iTl.iX = ( ( parentSupportRegion.iTl.iX >> 1 )-1 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
+                                                           ( parentSupportRegion.iTl.iX >> 1 )-1 : 0; //lint !e702    the shifted values cannot be negative here
+                                    }
+
+
+                                if( ( subband->SubbandType() ) == 0 || ( subband->SubbandType() ) == 1 )
+                                    {
+                                    if( subband->Parent()->HighPassFirst().iY )
+                                        {
+                                        supportRegion.iTl.iY = ( ( parentSupportRegion.iTl.iY >> 1 )-1 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
+                                                               ( parentSupportRegion.iTl.iY >> 1 )-1 : 0; //lint !e702    the shifted values cannot be negative here
+                                        }
+                                    else
+                                        {
+                                        supportRegion.iTl.iY = parentSupportRegion.iTl.iY >>1;      //lint !e702    the shifted value cannot be negative here
+                                        }
+                                    }
+                                else
+                                    {
+                                    supportRegion.iTl.iY = ( ( parentSupportRegion.iTl.iY >> 1 )-1 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
+                                                           ( parentSupportRegion.iTl.iY >> 1 )-1 : 0; //lint !e702    the shifted values cannot be negative here
+                                    }
+
+                                // Compute the offset for this level
+                                regionOffset.iX = parentSupportRegion.iTl.iX - 2*supportRegion.iTl.iX;
+                                regionOffset.iY = parentSupportRegion.iTl.iY - 2*supportRegion.iTl.iY;
+
+                                // Support region's bottom right corner for each band is ( supportParent.iBr>>1 )+1
+                                supportRegion.iBr.iX = ( ( parentSupportRegion.iBr.iX ) >> 1 ) + 1; //lint !e702    the shifted value cannot be negative here
+                                supportRegion.iBr.iY = ( ( parentSupportRegion.iBr.iY ) >> 1 ) + 1; //lint !e702    the shifted value cannot be negative here
+                                }
+                            else        // irreversible ( 9x7 ) filter 
+                                {
+                                // For low-pass filtering, the offset for the output is 1
+                                if( ( subband->SubbandType() ) == 0 || ( subband->SubbandType() ) == 2 )
+                                    {
+                                    if( subband->Parent()->HighPassFirst().iX )
+                                        {
+                                        supportRegion.iTl.iX = ( ( parentSupportRegion.iTl.iX >> 1 )-2 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
+                                                               ( parentSupportRegion.iTl.iX >> 1 )-2 : 0; //lint !e702    the shifted values cannot be negative here
+                                        }
+                                    else
+                                        {
+                                        supportRegion.iTl.iX = ( ( parentSupportRegion.iTl.iX >> 1 )-1 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
+                                                               ( parentSupportRegion.iTl.iX >> 1 )-1 : 0; //lint !e702    the shifted values cannot be negative here
+                                        }
+
+                                    }
+                                else
+                                    {
+                                    supportRegion.iTl.iX = ( ( parentSupportRegion.iTl.iX >> 1 )-2 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
+                                                           ( parentSupportRegion.iTl.iX >> 1 )-2 : 0; //lint !e702    the shifted values cannot be negative here
+                                    }
+
+                                if( ( subband->SubbandType() ) == 0 || ( subband->SubbandType() ) == 1 )
+                                    {
+                                    if( subband->Parent()->HighPassFirst().iY )
+                                        {
+                                        supportRegion.iTl.iY = ( ( parentSupportRegion.iTl.iY >> 1 )-2 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
+                                                               ( parentSupportRegion.iTl.iY >> 1 )-2 : 0; //lint !e702    the shifted values cannot be negative here
+                                        }
+                                    else
+                                        {
+                                        supportRegion.iTl.iY = ( ( parentSupportRegion.iTl.iY >> 1 )-1 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
+                                                               ( parentSupportRegion.iTl.iY >> 1 )-1 : 0; //lint !e702    the shifted values cannot be negative here
+                                        }   
+                                    }
+                                else
+                                    {
+                                    supportRegion.iTl.iY = ( ( parentSupportRegion.iTl.iY >> 1 )-2 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
+                                                           ( parentSupportRegion.iTl.iY >> 1 )-2 : 0; //lint !e702    the shifted values cannot be negative here
+                                    }
+
+                                // Compute the offset for this level
+                                regionOffset.iY = parentSupportRegion.iTl.iY - 2*supportRegion.iTl.iY;
+                                regionOffset.iX = parentSupportRegion.iTl.iX - 2*supportRegion.iTl.iX;
+
+                                // Support region's bottom right corner for each band is ( supportParent.iBr>>1 )+2
+                                supportRegion.iBr.iX = ( ( parentSupportRegion.iBr.iX ) >> 1 ) + 2; //lint !e702    the shifted value cannot be negative here
+                                supportRegion.iBr.iY = ( ( parentSupportRegion.iBr.iY ) >> 1 ) + 2; //lint !e702    the shifted value cannot be negative here
+                                }
+                            }
+
+                        // Check that the support region doesn't exceed the band boundaries
+                        if( supportRegion.iBr.iX > subband->SubbandCanvasSize().iWidth )
+                            {
+                            supportRegion.iBr.iX = subband->SubbandCanvasSize().iWidth;
+                            }
+                        if( supportRegion.iBr.iY > subband->SubbandCanvasSize().iHeight )
+                            {
+                            supportRegion.iBr.iY = subband->SubbandCanvasSize().iHeight;
+                            }
+
+                        // Store the low-band's dimensions here to later compute the size of the whole region ( low-band plus high-band ).
+                        if( subband->SubbandType() == 2 )
+                            {
+                            regionSize.iWidth = supportRegion.Width();
+                            }
+                        if( subband->SubbandType() == 1 )
+                            {
+                            regionSize.iHeight = supportRegion.Height();
+                            }
+        
+                        // Compute the Quantization parameters here, so we don't repeat that for every codeblock/precinct
+                        ComputeQuantizationParameters( *componentInfo, bandIndex, subband->SubbandGain(), bitDepth );
+
+                        // Set the lookup table for entropy decoder
+                        aEntropyDecoder.SetCurrentZCLUT( (TUint8)( subband->SubbandType() ) );
+
+                        packetList = CONST_CAST( RPointerArray<CJ2kPacket>*, &subband->PacketList() );    //lint !e665 the first parameter cannot be parenthesized here
+                        
+                        // For each packet in the subband
+                        for ( packetIndex = 0; packetIndex < componentInfo->NumOfPackets( levelIndex ); 
+                              ++packetIndex )
+                            {
+                            packet = ( *packetList )[packetIndex];
+
+                            // For each codeblock in the packet
+                            for ( blockIndex = 0; blockIndex < packet->NumOfBlocks(); ++blockIndex )
+                                {
+                                codeblock = CONST_CAST( CJ2kCodeBlock*, &packet->CodeBlockAt( blockIndex ) );
+                                
+                                const TRect& cbCanvas = codeblock->CodeBlockCanvas();
+                                
+                                TInt32 startRow = cbCanvas.iTl.iY - subband->SubbandCanvas().iTl.iY;
+                                TInt32 startCol = cbCanvas.iTl.iX - subband->SubbandCanvas().iTl.iX;
+                                TInt32 cblkHeight = cbCanvas.Height();
+                                TInt32 cblkWidth = cbCanvas.Width();
+                                TInt32 startRowCblk = 0;
+                                TInt32 startColCblk = 0;
+                                TInt32 startRowImage = 0;
+                                TInt32 startColImage = 0;
+                                
+                                if( startRow >= supportRegion.iBr.iY || startCol >= supportRegion.iBr.iX ||
+                                    ( startRow+cblkHeight ) <= supportRegion.iTl.iY ||
+                                    ( startCol+cblkWidth ) <= supportRegion.iTl.iX )
+                                    { 
+                                    }
+                                else 
+                                    {
+                                    // Compute the start column from which to copy from ( in the codeblock ) and where to copy to ( in the image block )
+                                    if( startCol <= supportRegion.iTl.iX )
+                                        {
+                                        startColCblk  = supportRegion.iTl.iX - startCol;    // Ignore samples outside supportRegion
+                                        startColImage = 0;              // First block, start from supportRegion's start
+                                        cblkWidth -= startColCblk;      // Ignore samples outside supportRegion
+                                        }
+                                    else
+                                        {
+                                        startColCblk  = 0;                              // First block, start from supportRegion's start
+                                        startColImage = startCol-supportRegion.iTl.iX;  // First block, start from supportRegion's start
+                                        }
+                                    // If the last block extends outside supportRegion, we have to adjust codeblock's width
+                                    if( ( startCol+cbCanvas.Width() ) > supportRegion.iBr.iX )
+                                        {
+                                        cblkWidth -= ( ( startCol+cbCanvas.Width() ) - supportRegion.iBr.iX );  // Ignore samples outside supportRegion
+                                        }
+                                    
+                                    // Compute the start row from which to copy from ( in the codeblock ) and where to copy to ( in the image block )
+                                    if( startRow <= supportRegion.iTl.iY )
+                                        {
+                                        startRowCblk  = supportRegion.iTl.iY - startRow;    // ignore samples outside supportRegion
+                                        startRowImage = 0;                                  // First block, start from supportRegion's start
+                                        cblkHeight -= startRowCblk;                         // Ignore samples outside supportRegion
+                                        }
+                                    else
+                                        {
+                                        startRowCblk  = 0;                              // First block, start from supportRegion's start
+                                        startRowImage = startRow-supportRegion.iTl.iY;  // First block, start from supportRegion's start
+                                        }
+                                    // If the last block extends outside supportRegion, we have to adjust codeblock's height
+                                    if( ( startRow+cbCanvas.Height() ) > supportRegion.iBr.iY )
+                                        {
+                                        cblkHeight -= ( ( startRow+cbCanvas.Height() ) - supportRegion.iBr.iY );    // ignore samples outside supportRegion
+                                        }
+                                                                        
+                                    // There is coded data in the codeblock
+                                    if ( codeblock->DataLength() )
+                                        {                                        
+                                        // Decode the codeblock
+                                        aEntropyDecoder.DecodeCodeblock( *codeblock, cblkStyle, 
+                                                                         (TUint8)( iMagnitudeBitsHere + iROIShift ) );
+                                            
+                                        codeblock->SetCodeBlockDecoded();
+
+                                        CopyDataToBlock( aEntropyDecoder, component->Data(), *subband, quantStyle, 
+                                                         startRowCblk, startColCblk, startRowImage, 
+                                                         startColImage, cblkHeight, cblkWidth );
+                                        }
+                                    else
+                                        {
+                                        // Empty codeblock, fill the corresponding area with zero, since other wise there might be data left from lower levels.
+                                        FillDataWithZeros( component->Data(), *subband, startRowImage, startColImage, cblkHeight, cblkWidth );
+                                        }
+                                    }
+                                
+                                } // end of each codeblock
+                            }  // end of each packet
+
+                        // Get the sibling subband
+                        subband = subband->NextSubbandRaster();
+
+                        } while ( subband ); // end of each subband in the resolution level
+
+                    // Now that we have processed all the blocks on this level, we can perform inverse wavelet transform on this level
+                    // On resolution level zero, we don't have to inverse transform
+                    if( levelIndex != 0 )
+                        {
+                        // The size of the inverse transformed region is the size of the low- ( stored in "regionSize" ) 
+                        // and high-pass ( the supportRegion is always for HH-band, when we reach this point ) parts combined
+                        regionSize = regionSize + supportRegion.Size();
+
+                        subband = CONST_CAST( CJ2kSubband*, componentInfo->SubbandAt( levelIndex ) );
+                        SingleLevelWaveletInverse( component->Data(), subband, regionOffset, regionSize, levelIndex );
+                        }
+                    }  // end of each resolution level in the component
+
+                // Check whether extra downsampling is needed
+                if( stepSize > 1 )
+                    {
+                    
+                    TInt32 i,j;
+                    TInt32 iStep,jStep;
+                    
+                    // If the stepSize is larger than one it means that we have to downsample
+                    // the output. This is because there were not enough wavelet levels to do
+                    // the resolution dropping for this component.
+                    
+                    // The reason why downsampling is done here and not in the ImageWriter is
+                    // that different components might have different number of wavlet levels
+                    // and thus it is easier to downsample the components here (so that we can 
+                    // just write out the samples normally in ImageWriter.
+                    for( i = 0,iStep = 0; iStep<KMaxBlockSupportSize; i++,iStep += stepSize)
+                        {
+                        for( j = 0,jStep = 0; jStep<KMaxBlockSupportSize; j++,jStep += stepSize)
+                            {
+                            
+                            // Downsample the component so that downsampled image is in the
+                            // upper left-hand corner.
+                            component->Data()[i][j] = component->Data()[iStep][jStep];
+                            }
+                        }
+                    }
+
+                if ( numOfComponents >= 3 ) 
+                    {
+                    if ( aTile.ColorTransformation() || 
+                        ( aImageWriter.CSCode() == 18 || aImageWriter.CSCode() == 16 ) )
+                        {
+                        // Wait til we finish decoding all components before writing out the image
+                        if ( compIndex < 2 )
+                            {
+                            continue;   //lint !e960    Continue is OK.
+                            }
+                        }
+                    else if ( aImageWriter.CSCode() == 0 )
+                        {
+                        // This case is also valid when no CSCode is defined, e.g. no file format is present
+                        if( numOfComponents <= 3 )
+                            {
+                            if ( compIndex < 2 )
+                                {
+                                continue;   //lint !e960    Continue is OK.
+                                }
+                            }
+                        else
+                            {
+                            // Proceed to outputBlockL
+                            }
+                        }
+                    }   //lint !e961    no else is needed here at the end of if...else if
+
+                aImageWriter.OutputBlockL( aTile, compIndex, blockXCoord, blockYCoord, firstCompSize, thisCompSize );
+                }   // end of each component in the tile
+            }   // end of loop on the 256x256 blocks
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::OneDimReversibleFilter
+// Perform one dimensional synthesis using reversible 5/3 filter
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kSynthesis::OneDimReversibleFilter( TInt32 aStartPos, TInt32 aEndPos )
+    {
+    if ( ( aEndPos - aStartPos ) == 1 )
+        {
+        if ( aStartPos )
+            {
+            iOutputBuffer[aStartPos] = iInputBuffer[aStartPos] / 2;
+            }
+        else
+            {
+            iOutputBuffer[aStartPos] = iInputBuffer[aStartPos];
+            }
+        }
+    else
+        {
+        aEndPos++;
+        TInt32 idx = 0;
+        for ( idx = 0; idx < aEndPos; idx += 2 )
+            {
+            iOutputBuffer[idx] = iInputBuffer[idx] - 
+                                 ( ( iInputBuffer[idx - 1] + iInputBuffer[idx + 1] + 2 ) >> 2 );    //lint !e704 shifting is OK.
+            }
+
+        for ( idx = 1; idx < aEndPos; idx += 2 )
+            {
+            iOutputBuffer[idx] = iInputBuffer[idx] + 
+                                 ( ( iOutputBuffer[idx - 1] + iOutputBuffer[idx + 1] ) >> 1 );      //lint !e704 shifting is OK.
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::PerformExtension
+// Performs one dimensional symmetric extension of the line of pixels from
+// the 2 extensions of the line.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kSynthesis::PerformExtension( TInt32 aStartPos, TInt32 aEndPos )
+    {
+    TInt32* high = iInputBuffer + aEndPos - 1;
+    TInt32 dir = 1;
+    TInt32 posLeft  = aStartPos;
+    TInt32 posRight = aEndPos - 1;
+  
+    for ( TInt32 idx = 1; idx <= KFilterExtension; ++idx )
+        {
+        posLeft += dir;
+        posRight -= dir;
+        iInputBuffer[aStartPos - idx] = iInputBuffer[posLeft];
+        high[idx] = iInputBuffer[posRight];
+
+        if ( posLeft == ( aEndPos - 1 ) )
+            {
+            dir = -1;
+            }
+        if ( dir == -1 )
+            {
+            if ( posLeft == aStartPos )
+                {
+                dir = 1;
+                }
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::OneDimIrrevFilter
+// Perform one dimensional synthesis using irreversible 9/7 filter
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kSynthesis::OneDimIrrevFilter( TInt32 aStartPos, 
+                                       TInt32 aEndPos,
+                                       TUint8 aLevel,
+                                       TUint8 aVertical )
+    {
+    if ( ( aEndPos - aStartPos ) == 1 )
+        {
+        if ( aStartPos )
+            {
+            iOutputBuffer[aStartPos] = iInputBuffer[aStartPos] / 2;
+            }
+        else
+            {
+            iOutputBuffer[aStartPos] = iInputBuffer[aStartPos];
+            }
+        }
+    else
+        {
+        // First the low-pass parts
+        TInt32 idx = aStartPos + ( aStartPos % 2 );
+        for ( ; idx < aEndPos; idx += 2 )
+            {
+            iOutputBuffer[idx] = iTapsLow[0] * iInputBuffer[idx] + 
+                                 iTapsLow[2] * ( iInputBuffer[idx - 2] + iInputBuffer[idx + 2] );
+            }
+
+        idx = aStartPos + ( ( aStartPos + 1 ) % 2 );
+        for ( ; idx < aEndPos; idx += 2 )
+            {
+            iOutputBuffer[idx] = iTapsLow[1] * ( iInputBuffer[idx - 1] + iInputBuffer[idx + 1] ) +
+                                 iTapsLow[3] * ( iInputBuffer[idx - 3] + iInputBuffer[idx + 3] );
+            }
+    
+        // Then the high-pass parts 
+        idx = aStartPos + ( ( aStartPos + 1 ) % 2 );
+        for ( ; idx < aEndPos; idx += 2 )
+            {
+            iOutputBuffer[idx] += iTapsHigh[0] * iInputBuffer[idx] +
+                                  iTapsHigh[2] * ( iInputBuffer[idx - 2] + iInputBuffer[idx + 2] ) +
+                                  iTapsHigh[4] * ( iInputBuffer[idx - 4] + iInputBuffer[idx + 4] );
+            }
+
+        idx = aStartPos + ( aStartPos % 2 );
+        for ( ; idx < aEndPos; idx += 2 )
+            {
+            iOutputBuffer[idx] += iTapsHigh[1] * ( iInputBuffer[idx - 1] + iInputBuffer[idx + 1] ) +
+                                  iTapsHigh[3] * ( iInputBuffer[idx - 3] + iInputBuffer[idx + 3] ); 
+            }
+
+        TInt32 offset = 0;
+        TInt32 downshift = 0;
+
+        // Finally downshift all the samples
+        if ( !aVertical || ( aLevel != 0 ) )
+            {
+            downshift = KFilterShift;
+            }
+        else
+            {
+            downshift = KFilterShift + KWaveletShift;
+            }
+
+        offset = ( (TUint32)( 1 << downshift ) >> 1 );
+        idx = aStartPos;
+
+        for ( ; idx < aEndPos; idx++ )
+            {
+            iOutputBuffer[idx] = ( iOutputBuffer[idx] + offset ) >> downshift;    //lint !e704 shifting is OK.
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::OneDimFiltering
+// Perform one dimensional filtering
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kSynthesis::OneDimFiltering( TInt32 aStartPos, 
+                                     TInt32 aEndPos,
+                                     TUint8 aLevel,
+                                     TUint8 aVertical )
+    {
+    // Extend the signals ( at the start and end )
+    PerformExtension( aStartPos, aEndPos );
+
+    if ( iReversible )
+        {
+        OneDimReversibleFilter( aStartPos, aEndPos );
+        }
+    else
+        {
+        OneDimIrrevFilter( aStartPos, aEndPos, aLevel, aVertical );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::HorizontalFilter
+// Perform one dimensional horizontal filtering
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kSynthesis::HorizontalFilter( TPrecInt** aImage, 
+                                      TInt32 aRow,
+                                      TUint32 aXtcSiz, 
+                                      CJ2kSubband* aSubband )
+    {
+    TInt32 endPos = 0;
+    TInt32 startPos = aSubband->HighPassFirst().iX;
+  
+    TInt32* rowImage = (TInt32*)aImage[aRow];
+    TInt32* rowImageHigh = rowImage + aSubband->ChildAt( CJ2kSubband::EBandLL )->SubbandCanvasSize().iWidth; 
+    TInt32* iterator = iInputBuffer;
+
+    // Low-pass is first
+    if ( !startPos )  
+        {
+        for ( endPos = aXtcSiz >> 1; endPos > 0; endPos-- )
+            {
+            *iterator++ = *rowImage++;
+            *iterator++ = *rowImageHigh++;
+            }
+        if ( aXtcSiz % 2 )  // One extra sample for low-pass
+            {
+            *iterator = *rowImage;
+            }
+        }
+    else  // High-pass is first
+        {
+        iterator++;
+        for ( endPos = aXtcSiz >> 1; endPos > 0; endPos-- )
+            {
+            *iterator++ = *rowImageHigh++;
+            *iterator++ = *rowImage++;
+            }
+        if ( aXtcSiz % 2 )  // One extra sample for high-pass
+            {
+            *iterator = *rowImageHigh;
+            }
+        }
+  
+    endPos = aXtcSiz + startPos; 
+
+    OneDimFiltering( startPos, endPos, aSubband->SubbandLevel(), 0 ); 
+    Mem::Copy( aImage[aRow], iOutputBuffer + startPos, aXtcSiz * sizeof( TPrecInt ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::VerticalFilter
+// Perform one dimensional vertical filtering
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kSynthesis::VerticalFilter( TPrecInt **aImage, 
+                                    TInt32 aColumn,
+                                    TUint32 aYtcSiz, 
+                                    CJ2kSubband *aSubband )
+    {
+    TInt32 startPos = aSubband->HighPassFirst().iY;
+    TInt32 highStart = aSubband->ChildAt( CJ2kSubband::EBandLL )->SubbandCanvasSize().iHeight;
+    TInt32 highStop = aSubband->SubbandCanvasSize().iHeight;
+    TInt32 *iterator = iInputBuffer;
+ 
+    TInt32 lowIndex = 0;
+    TInt32 highIndex = highStart;
+    if ( !startPos )
+        {
+        for ( ; highIndex < highStop; lowIndex++, highIndex++ )
+            {
+            *iterator++ = aImage[lowIndex][aColumn];
+            *iterator++ = aImage[highIndex][aColumn];
+            }
+        if ( aYtcSiz % 2 )
+            {
+            *iterator = aImage[lowIndex][aColumn];
+            }
+        }
+    else 
+        {
+        iterator++;
+        for ( ; lowIndex < highStart; highIndex++, lowIndex++ )
+            {
+            *iterator++ = aImage[highIndex][aColumn];
+            *iterator++ = aImage[lowIndex][aColumn];
+            }
+        if ( aYtcSiz % 2 )
+            {
+            *iterator = aImage[highIndex][aColumn];
+            }
+        }
+
+    OneDimFiltering( startPos, startPos + aYtcSiz, aSubband->SubbandLevel(), 1 );  
+    iOutputBuffer += ( startPos + aYtcSiz - 1 );
+
+    for ( lowIndex = aYtcSiz - 1; lowIndex >= 0; lowIndex-- )
+        {
+        aImage[lowIndex][aColumn] = *iOutputBuffer--;
+        }
+    iOutputBuffer += ( 1 - startPos );
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::TwoDimFiltering
+// Perform two dimensional inverse wavelet transformation
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kSynthesis::TwoDimFiltering( TPrecInt **aImage, 
+                                     TInt32 aXtcSiz, 
+                                     TInt32 aYtcSiz, 
+                                     CJ2kSubband *aSubband )
+    {
+    TInt32 index = 0;
+
+    for ( index = aYtcSiz - 1; index >= 0; index-- )
+        {
+        HorizontalFilter( aImage, index, aXtcSiz, aSubband );
+        }
+
+    for ( index = aXtcSiz - 1; index >= 0; index-- )
+        {
+        VerticalFilter( aImage, index, aYtcSiz, aSubband );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::FullWaveletInverse
+// Perform a full inverse wavelet transformation
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kSynthesis::FullWaveletInverse( TPrecInt **aImage, CJ2kSubband *aSubband )
+    {
+    TSize  canvas( 0, 0 );
+    TUint8 reduceLevels = 0;
+    
+    // If truncating resolution levels, we have to compute the reduced levels,
+    // so that the final WAVELET_SHIFT in case of 9x7 filter is performed.
+    if ( aSubband->SubbandLevel() > iWaveletLevels )
+        {
+        reduceLevels = (TUint8)( aSubband->SubbandLevel() - iWaveletLevels );
+        }
+
+    for ( TUint8 levelIndex = (TUint8)iWaveletLevels; levelIndex > 0; levelIndex-- )
+        {
+        // The next lines assume that subband points to the LL-band and
+        // it is then moved to point to the parent i.e. to the last 
+        // _decomposition level_ of the wavelet transform.
+        aSubband = aSubband->Parent();
+
+        // Adjust the level in case of resolution truncation
+        aSubband->SetSubbandLevel( (TUint8)( aSubband->SubbandLevel() - reduceLevels ) );
+
+        canvas = aSubband->SubbandCanvasSize();
+        if ( canvas.iWidth > 0 && canvas.iHeight > 0 )
+            {
+            TwoDimFiltering( aImage, canvas.iWidth, canvas.iHeight, aSubband );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::ComputeQuantizationParameters
+// Compute the quantization parameters for a particular subband in the component
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kSynthesis::ComputeQuantizationParameters( const CJ2kComponentInfo& aComponentInfo,
+                                                   TInt16 aBandIndex,
+                                                   TUint8 aBandGain,
+                                                   TUint8 aBitDepth )
+    {
+    if ( iROIShift != 0 )  
+        {
+        // ROI shifting is used
+        if ( aComponentInfo.QuantizationStyle() == 0 )
+            {
+            // Compute the shift for the codeblock's data, which is
+            // IMPLEMENTATION PRECISION -1( for sign ) - subband's range -
+            // the guard bits. 
+            iDataShift = ( KImplementationPrecision - 1 ) - iMagnitudeBitsHere;
+            }
+        else  // Irreversible case
+            {  
+            // Because we have integer arithmetic only, we subtract WAVELET_SHIFT from the shift.
+            // This is to compensate for the fractional bits of the inverse quantized wavelet
+            // coefficients.
+            iDataShift = ( KImplementationPrecision - 1 ) - iMagnitudeBitsHere - KWaveletShift;
+
+            // The quantization step is computed from the equation
+            // step = ( 2^( Range-Exponent ) )*( 1+( Mantissa/( 2^11 ) ) ), where Range is the dynamic 
+            // range of this subband ( = bitdepth + gain ). ( see Annex E of the standard for more
+            // information ).
+            //
+            // The "iStepExponent" is the shift needed to remove "iStepValue"'s fractional
+            // bits. The "iStepValue" is the shifted quantization step. Shifting back
+            // is done right after computing the quantized coefficient.
+            iStepExponent = aBitDepth + aBandGain - aComponentInfo.Exponent( aBandIndex ) - KStepBits;
+            iStepValue = aComponentInfo.Mantissa( aBandIndex ) + ( 1 << KStepBits );
+            }
+
+        // Compute the shift for the data inside the ROI
+        iROIDataShift = iDataShift - iROIShift;      
+        }
+    else  
+        {
+        // ROI is not present
+        if ( aComponentInfo.QuantizationStyle() == 0 )
+            {
+            // Compute the shift for the codeblock's data, which is
+            // IMPLEMENTATION PRECISION-1( for sign ) - subband's range -
+            // the guard bits. 
+            iDataShift = ( KImplementationPrecision - 1 ) - iMagnitudeBitsHere;
+            // Shift all the samples in the codeblock
+            }
+        else  // Irreversible case 
+            {
+            // Because we have integer arithmetic only, we subtract WAVELET_SHIFT from the shift.
+            // This is to compensate for the fractional bits of the inverse quantized wavelet
+            // coefficients.
+            iDataShift = ( KImplementationPrecision - 1 ) - iMagnitudeBitsHere - KWaveletShift;
+
+            // To prevent overflows we check if the "shift" is at least 12. The minimum downshift of 12 is 
+            // derived from the computation of "value*iStepValue", where "value" is downshifted previously by "shift"
+            // and "iStepValue" is at maximum 12 bits ( since iStepValue = mantissa + 1<<KStepBits, where mantissa is
+            // a 11-bit value and KStepBits is 11 ).
+            //
+            TInt32 iExtraBits = 0;
+            // If the implementation precision is 16 then we don't have to check if the shift is at least 12.
+            // This is because we use 32 bits for the computation and thus have at least 16 zero most significant 
+            // bits at the "value".
+
+            
+            if ( iDataShift < 12 )    // Test to prevent overflows 
+                {
+                iExtraBits = 12 - iDataShift;
+                iDataShift += iExtraBits;
+                }
+
+            // The quantization step is computed from the equation
+            // step = ( 2^( Range-Exponent ) )*( 1+( Mantissa/( 2^11 ) ) ), where Range is the dynamic 
+            // range of this subband ( = bitdepth + gain ). ( see Annex E of the standard for more
+            // information ).
+            //
+            // The "iStepExponent" is the shift needed to remove "iStepValue"'s fractional
+            // bits. The "iStepValue" is the shifted quantization step. Shifting back
+            // is done right after computing the quantized coefficient.
+            //
+            iStepExponent = aBitDepth + aBandGain - aComponentInfo.Exponent( aBandIndex ) - KStepBits;
+
+            // Test to prevent overflows
+            iStepExponent += iExtraBits;
+      
+            iStepValue = aComponentInfo.Mantissa( aBandIndex ) + ( 1 << KStepBits );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::CopyDataToImage
+// Apply inverse quantization and ROI shifting on the decoded
+// codeblock and copy to the image writer
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kSynthesis::CopyDataToImage( CJ2kEntropyDecoder& aEntropyDecoder, TPrecInt** aImageBlock, 
+                                     CJ2kSubband& aSubband, CJ2kCodeBlock& aCodeblock,
+                                     TUint8 aQuantizationStyle )
+    {
+    TPrecInt* buffer = 0;    // To buffer one row of the aImageBlock
+    TPrecInt* imageRow = 0;  // One row of the image
+    TPrecInt valueInt = 0;
+    TInt32 value = 0;
+    TInt32 j = 0;
+
+    const TRect& cbCanvas = aCodeblock.CodeBlockCanvas();
+
+    TInt32 startRow = cbCanvas.iTl.iY - aSubband.SubbandCanvas().iTl.iY + aSubband.SubbandOrigin().iY;
+    TInt32 startCol = cbCanvas.iTl.iX - aSubband.SubbandCanvas().iTl.iX + aSubband.SubbandOrigin().iX;
+    TInt32 endRow = startRow + cbCanvas.Height() - 1;
+    TInt32 endCol = startCol + cbCanvas.Width();
+
+    TInt32 cols = endCol - startCol - 1;
+
+    if ( iROIShift )  // ROI shifting is used
+        {
+        // Compute mask to determine which samples are in ROI
+        // for mask ROI coefficients
+        TInt32 mask = ( ( 1 << iMagnitudeBitsHere ) - 1 ) << ( ( KImplementationPrecision - 1 ) - iMagnitudeBitsHere );
+        TInt32 mask2 = ( ~mask ) & KMaximumPrecisionInteger;
+        TInt32 mask3 = ( ( 1 << iROIShift ) - 1 ) << ( ( KImplementationPrecision - 1 ) - iROIShift );
+        TInt32 maskShift = ( ~mask3 ) & KMaximumPrecisionInteger;
+
+        if ( !aQuantizationStyle )
+            {
+            // Shift all the samples in the codeblock
+            TInt32 roiDataShift = ( iROIDataShift < 0 ) ? -iROIDataShift : iROIDataShift;
+            
+            for ( ; endRow >= startRow; endRow-- )
+                {
+                buffer = aEntropyDecoder.iData[endRow - startRow] + cols;
+                for ( j = endCol - 1; j >= startCol; j-- )
+                    {
+                    value = ( *buffer-- );
+                    if ( !( value & mask ) ) // Background
+                        {
+                        // iROIDataShift can never be negative here!
+                        if ( iROIDataShift < 0 )
+                            {
+                            aImageBlock[endRow][j] = ( value < 0 ) ? -( ( value & KMaximumPrecisionInteger ) << roiDataShift ) 
+                                                                    : ( value  << roiDataShift );               //lint !e704 value is positive here
+                            }
+                        else
+                            {
+                            aImageBlock[endRow][j] = ( value < 0 ) ? -( ( value & maskShift ) >> roiDataShift )  //lint !e704 value&maskShift is positive, so no risk of right shifting negative values
+                                                                    : ( ( value & maskShift ) >> roiDataShift );  //lint !e704 value&maskShift is positive
+                            }
+                        }
+                    else  // ROI
+                        {
+                        if ( value & mask2 ) 
+                            {
+                            // Decoded more than magbits bit-planes, set
+                            // quantization mid-interval approx. bit just after
+                            // the magbits.
+                            value &= ( ~mask2 );
+                            }
+
+                        aImageBlock[endRow][j] = ( value < 0 ) ? -( ( value & KMaximumPrecisionInteger ) >> iDataShift )
+                                                                : ( value >> iDataShift );                      //lint !e704 value is positive here
+                        }
+                    }
+                }
+            }
+        else  // Irreversible case
+            {
+            // Shift all the samples in the codeblock
+            TInt32 stepExponent = ( iStepExponent < 0 ) ? -iStepExponent : iStepExponent;
+
+            // Divide into two cases depending on the sign of the iStepExponent to speed up coding
+            if ( iStepExponent < 0 )
+                {
+                for ( ; endRow >= startRow; endRow-- )
+                    {
+                    buffer = aEntropyDecoder.iData[endRow - startRow] + cols;
+                    for ( j = endCol - 1; j >= startCol; j-- )
+                        {
+                        value = ( *buffer-- );
+
+                        // Divide into two cases depending on whether value is negative
+                        if ( value < 0 )
+                            {
+                            if ( !( value & mask ) ) // Background
+                                {
+                                value = ( ( value & maskShift ) >> iROIDataShift );     //lint !e704 value&maskShift is positive
+                                valueInt = -( ( value * iStepValue ) >> stepExponent );  //lint !e704 ( value*iStepValue )&KMaximumPrecisionInteger is positive
+                                }
+                            else  // ROI
+                                {
+                                if ( value & mask2 ) 
+                                    {
+                                    // Decoded more than magbits bit-planes, set
+                                    // quantization mid-interval approx. bit just after
+                                    // the magbits.
+                                    value = ( value & ( ~mask2 ) ) | ( 1 << ( KImplementationPrecision - 2 - iMagnitudeBitsHere ) );
+                                    }
+
+                                value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
+                                valueInt = -( ( value * iStepValue ) >> stepExponent );  //lint !e704 ( value*iStepValue )&KMaximumPrecisionInteger is positive
+                                }
+                            }
+                        else    // Value is non-negative
+                            {
+                            if ( !( value & mask ) ) // background
+                                {
+                                value = ( ( value & maskShift ) >> iROIDataShift );     //lint !e704 value&maskShift is positive
+                                valueInt = ( ( value * iStepValue ) >> stepExponent );  //lint !e704 value*iStepValue is positive
+                                }
+                            else  // ROI
+                                {
+                                if ( value & mask2 ) 
+                                    {
+                                    // Decoded more than magbits bit-planes, set
+                                    // quantization mid-interval approx. bit just after
+                                    // the magbits.
+                                    value = ( value & ( ~mask2 ) ) | ( 1 << ( KImplementationPrecision - 2 - iMagnitudeBitsHere ) );
+                                    }
+
+                                value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
+                                valueInt = ( ( value * iStepValue ) >> stepExponent );  //lint !e704 value*iStepValue is positive
+                                }
+                            }
+
+                        aImageBlock[endRow][j] = valueInt;       
+                        }
+                    }
+                }
+            else    // iStepExponent is non-negative
+                {
+                for ( ; endRow >= startRow; endRow-- )
+                    {
+                    buffer = aEntropyDecoder.iData[endRow - startRow] + cols;
+                    for ( j = endCol - 1; j >= startCol; j-- )
+                        {
+                        value = ( *buffer-- );
+
+                        // Divide into two cases depending on whether value is negative
+                        if ( value < 0 )
+                            {
+
+                            // Change value to be positive
+                            value = -value;
+
+                            if ( !( value & mask ) ) // Background
+                                {
+                                value = ( ( value & maskShift ) >> iROIDataShift );   //lint !e704 value&maskShift is positive
+                                valueInt = ( ( value * iStepValue ) << stepExponent );
+                                }
+                            else  // ROI
+                                {
+                                if ( value & mask2 ) 
+                                    {
+                                    // Decoded more than magbits bit-planes, set
+                                    // quantization mid-interval approx. bit just after
+                                    // the magbits.
+                                    value = ( value & ( ~mask2 ) ) | ( 1 << ( KImplementationPrecision - 2 - iMagnitudeBitsHere ) );
+                                    }
+
+                                value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
+                                valueInt = ( ( value * iStepValue ) << stepExponent );
+                                }
+
+                            // Change the sign back to negative
+                            aImageBlock[endRow][j] = -valueInt;
+                            }
+                        else    // Value is non-negative
+                            {
+                            if ( !( value & mask ) ) // Background
+                                {
+                                value = ( ( value & maskShift ) >> iROIDataShift );   //lint !e704 value&maskShift is positive
+                                valueInt = ( ( value * iStepValue ) << stepExponent );
+                                }
+                            else  // ROI
+                                {
+                                if ( value & mask2 ) 
+                                    {
+                                    // Decoded more than magbits bit-planes, set
+                                    // quantization mid-interval approx. bit just after
+                                    // the magbits.
+                                    value = ( value & ( ~mask2 ) ) | ( 1 << ( KImplementationPrecision - 2 - iMagnitudeBitsHere ) );
+                                    }
+
+                                value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
+                                valueInt = ( ( value * iStepValue ) << stepExponent );
+                                }
+                            aImageBlock[endRow][j] = valueInt;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    else  // ROI is not present
+        {
+        if ( !aQuantizationStyle )
+            {
+            // Shift all the samples in the codeblock
+            TInt32 i = endRow - startRow;
+            for ( ; endRow >= startRow; endRow--, i-- )
+                {
+                imageRow = aImageBlock[endRow] + endCol - 1;
+                buffer = aEntropyDecoder.iData[i] + cols;
+                for ( j = endCol - 1; j >= startCol; j-- )
+                    {
+                    value = *buffer--;
+                    if ( value < 0 )
+                        {
+                        *imageRow-- = -( ( value & KMaximumPrecisionInteger ) >> iDataShift );
+                        }
+                    else
+                        {
+                        *imageRow-- = value >> iDataShift;            //lint !e704 value is positive here
+                        }
+                    }
+                }
+            }
+        else  // Irreversible case 
+            {
+            // Shift all the samples in the codeblock 
+            TInt32 stepExponent = ( iStepExponent < 0 ) ? -iStepExponent : iStepExponent;
+            
+            // Divide into two cases depending on the sign of the iStepExponent to speed up coding
+            if ( iStepExponent < 0 )
+                {
+                for ( ; endRow >= startRow; endRow-- )
+                    {
+                    buffer = aEntropyDecoder.iData[endRow - startRow] + cols;
+                    for ( j = endCol - 1;  j >= startCol; j-- )
+                        {
+                        value = ( *buffer-- );
+
+                        if ( value < 0 )   // Negative value
+                            {
+                            value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
+                            aImageBlock[endRow][j] = (TPrecInt)( -( ( value * iStepValue ) >> stepExponent ) );  //lint !e704 value*iStepValue is positive
+                            }
+                        else
+                            {
+                            value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
+                            aImageBlock[endRow][j] = (TPrecInt)( ( value * iStepValue ) >> stepExponent );     //lint !e704 value*iStepValue is positive
+                            }
+                        }
+                    }
+                }
+            else    // iStepExponent is non-negative
+                {
+                for ( ; endRow >= startRow; endRow-- )
+                    {
+                    buffer = aEntropyDecoder.iData[endRow - startRow] + cols;
+                    for ( j = endCol - 1;  j >= startCol; j-- )
+                        {
+                        value = ( *buffer-- );
+
+                        if ( value < 0 )   // Negative value
+                            {
+                            value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
+                            aImageBlock[endRow][j] = (TPrecInt)( -( ( value * iStepValue ) << stepExponent ) );
+                            }
+                        else
+                            {
+                            value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
+                            aImageBlock[endRow][j] = (TPrecInt)( ( value * iStepValue ) << stepExponent );
+                            }
+                        }
+                    }
+                }
+            }
+        }
+  
+    // If number of levels is zero then we have to do the 
+    // inverse wavelet shifting here.
+    //
+    if ( iWaveletLevels == 0 )
+        {
+        endRow = startRow + cbCanvas.Height();
+        endCol = startCol + cbCanvas.Width();
+
+        if ( aQuantizationStyle )
+            {
+            for ( TInt32 i = endRow - 1; i >= startRow; i-- )
+                {
+                for ( j = endCol - 1; j >= startCol; j-- )
+                    {
+                    aImageBlock[i][j] >>= KWaveletShift; //lint !e704 shifting is OK.
+                    }
+                }
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::AllocBufferL
+// Allocate internal buffer based on the requested size
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kSynthesis::AllocBufferL( TInt32 aSize )
+    {
+    // Allocate memory for the input and output buffers
+    TInt32 totalSize = aSize * sizeof( TInt32 );
+
+    if ( iIOBufferSize )
+        {
+        // Resize only when the request buffer is larger than current buffer
+        if ( iIOBufferSize < totalSize )
+            {
+            iInputBuffer -= ( KFilterExtension + 1 );
+            TInt32* tmpBuffer = STATIC_CAST( TInt32*, User::ReAlloc( iInputBuffer, totalSize ) );
+            if ( !tmpBuffer )
+                {
+                iInputBuffer += ( KFilterExtension + 1 );
+                User::Leave( KErrNoMemory );
+                }
+            iInputBuffer = tmpBuffer;
+            iInputBuffer += ( KFilterExtension + 1 );
+
+            iOutputBuffer -= ( KFilterExtension + 1 );
+            tmpBuffer = STATIC_CAST( TInt32*, User::ReAlloc( iOutputBuffer, totalSize ) );
+            if ( !tmpBuffer )
+                {
+                iOutputBuffer += ( KFilterExtension + 1 );
+                User::Leave( KErrNoMemory );
+                }
+            iOutputBuffer = tmpBuffer;
+            iOutputBuffer += ( KFilterExtension + 1 );
+
+            iIOBufferSize = totalSize;
+            }
+        }
+    else
+        {
+        // First time buffer allocation
+        iInputBuffer = STATIC_CAST( TInt32*, User::Alloc( totalSize ) );
+        if ( !iInputBuffer )
+            {
+            User::Leave( KErrNoMemory );
+            }
+        iInputBuffer += ( KFilterExtension + 1 );
+        iOutputBuffer = STATIC_CAST( TInt32*, User::Alloc( totalSize ) );
+        if ( !iOutputBuffer )
+            {
+            User::Leave( KErrNoMemory );
+            }
+        iOutputBuffer += ( KFilterExtension + 1 );
+        iIOBufferSize = totalSize;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::HorizontalBlockFilter
+// Perform one dimensional horizontal filtering ( block-based ).
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kSynthesis::HorizontalBlockFilter( TPrecInt** aImage, TInt32 aRow,
+                                           TUint32 aXtcSiz, CJ2kSubband* aSubband,
+                                           TInt32 aXOffset, TUint8 aCurrentLevel )
+    {
+    TInt32 endPos = 0;
+    TInt32 startPos = aSubband->HighPassFirst().iX;
+  
+    TInt32* rowImage = (TInt32*)aImage[aRow];
+    TInt32* rowImageHigh = rowImage + KWaveletBlockMidPoint; 
+    TInt32* iterator = iInputBuffer;
+
+    // Insert one extra ( dummy, i.e. zero-valued ) low-pass sample.
+    // This sample is not actually needed in computations, but now we can use the same 
+    // functions for filtering for block-based and normal wavelet.
+    if( !startPos && ( aXOffset > 0 ) )      
+        {
+
+        // The need for one extra sample derives from the fact that the support region
+        // for the high-pass is extends one sample further than the low-pass region.
+        *iterator++ = 0;
+        *iterator++ = *rowImageHigh++;
+
+        // Increment aXtcSiz by one to account for the dummy sample
+        aXtcSiz++;
+        }
+
+    if ( !startPos )  // Low-pass first
+        {
+        for ( endPos = aXtcSiz >> 1; endPos > 0; endPos-- )
+            {
+            *iterator++ = *rowImage++;
+            *iterator++ = *rowImageHigh++;
+            }
+        if ( aXtcSiz % 2 )  // One extra sample for low-pass
+            {
+            *iterator = *rowImage;
+            }
+        }
+    else  // High-pass first
+        {
+        iterator++;
+        for ( endPos = aXtcSiz >> 1; endPos > 0; endPos-- )
+            {
+            *iterator++ = *rowImageHigh++;
+            *iterator++ = *rowImage++;
+            }
+        if ( aXtcSiz % 2 )  // One extra sample for high-pass
+            {
+            *iterator = *rowImageHigh;
+            }
+        }
+  
+    endPos = aXtcSiz + startPos; 
+
+    OneDimFiltering( startPos, endPos, (TUint8)( iWaveletLevels - aCurrentLevel ), 0 ); 
+
+    // Copy row back to image, take care of offset
+    Mem::Copy( aImage[aRow], iOutputBuffer + startPos + ( aXOffset ), ( aXtcSiz - ( aXOffset ) ) * sizeof( TPrecInt ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::VerticalBlockFilter
+// Perform one dimensional vertical filtering ( block-based )
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kSynthesis::VerticalBlockFilter( TPrecInt** aImage, TInt32 aColumn, TUint32 aYtcSiz, 
+                                         CJ2kSubband* aSubband, TInt32 aYOffset,
+                                         TUint8 aCurrentLevel )
+    {
+    TInt32 startPos = aSubband->HighPassFirst().iY;
+    TInt32 highStart = KWaveletBlockMidPoint;
+    TInt32* iterator = iInputBuffer;
+ 
+    TInt32 lowIndex = 0;
+    TInt32 highIndex = highStart;
+
+    // Insert one extra ( dummy, i.e. zero-valued ) low-pass sample.
+    if( !startPos && ( aYOffset > 0 ) )      
+        {
+        *iterator++ = 0;
+        *iterator++ = aImage[highIndex++][aColumn];
+
+        // Increment aYtcSiz by one to account for the dummy sample
+        aYtcSiz++;
+        }
+
+    TInt32 highStop = KWaveletBlockMidPoint + ( aYtcSiz >> 1 );
+    TInt32 lowStop = aYtcSiz >> 1;
+
+    if ( !startPos )
+        {
+        for ( ; highIndex < highStop; lowIndex++, highIndex++ )
+            {
+            *iterator++ = aImage[lowIndex][aColumn];
+            *iterator++ = aImage[highIndex][aColumn];
+            }
+        if ( aYtcSiz % 2 )
+            {
+            *iterator = aImage[lowIndex][aColumn];
+            }
+        }
+    else 
+        {
+        iterator++;
+        for ( ; lowIndex < lowStop; highIndex++, lowIndex++ )
+            {
+            *iterator++ = aImage[highIndex][aColumn];
+            *iterator++ = aImage[lowIndex][aColumn];
+            }
+        if ( aYtcSiz % 2 )
+            {
+            *iterator = aImage[highIndex][aColumn];
+            }
+        }
+
+    OneDimFiltering( startPos, startPos + aYtcSiz, (TUint8)( iWaveletLevels - aCurrentLevel ), 1 );  
+    iOutputBuffer += ( startPos + aYtcSiz - 1 );
+
+    // Copy column back to image, take care of offset
+    for ( lowIndex = ( aYtcSiz - 1 - aYOffset ); lowIndex >= 0; lowIndex-- )
+        {
+        aImage[lowIndex][aColumn] = *iOutputBuffer--;
+        }
+    iOutputBuffer += ( 1 - startPos - aYOffset );
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::TwoDimBlockFiltering
+// Perform two dimensional inverse wavelet transformation ( block-based )
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kSynthesis::TwoDimBlockFiltering( TPrecInt** aImage, TSize aRegion, CJ2kSubband* aSubband,
+                                         TPoint aOffset, TUint8 aCurrentLevel )
+    {
+    TInt32 index = 0;
+    TUint32 xtcSiz = aRegion.iWidth;
+    TUint32 ytcSiz = aRegion.iHeight;
+
+    // For block filtering we have the data in two blocks ( column-wise ), 
+    // from 0 to ( ytcsiz+1 )>>1 ( +1 to take care of odd number of samples ) 
+    // and from KWaveletBlockMidPoint to KWaveletBlockMidPoint+( ( ytcsiz+1 )>>1 ).
+    index = KWaveletBlockMidPoint + ( ( ytcSiz+1 ) >> 1 ) - 1;
+
+    // First apply horizontal filter to the ( vertically ) high-pass samples
+    for ( ; index >= KWaveletBlockMidPoint; index-- )
+        {
+        HorizontalBlockFilter( aImage, index, xtcSiz, aSubband, aOffset.iX, aCurrentLevel );
+        }
+
+    // Then apply horizontal filter to the ( vertically ) low-pass samples
+    index = ( ( ytcSiz+1 ) >> 1 ) - 1;
+    for ( ; index >= 0; index-- )
+        {
+       HorizontalBlockFilter( aImage, index, xtcSiz, aSubband, aOffset.iX, aCurrentLevel );
+        }
+
+    // Because of the horizontal filtering, the data is now in one block row-wise, thus
+    // two loops are not needed for vertical fitering.
+    index = xtcSiz-1-( (TUint32)( aOffset.iX ) >> 1 );
+    for ( ; index >= 0; index-- )
+        {
+        VerticalBlockFilter( aImage, index, ytcSiz, aSubband, aOffset.iY, aCurrentLevel );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::SingleLevelWaveletInverse
+// Perform a full inverse wavelet transformation ( block-based )
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kSynthesis::SingleLevelWaveletInverse( TPrecInt **aImage, CJ2kSubband *aSubband, 
+                                               TPoint aOffset, TSize aRegion, TUint8 aCurrentLevel )
+    {
+    if ( aRegion.iWidth > 0 && aRegion.iHeight > 0 )
+        {
+        aSubband = aSubband->Parent();
+        TwoDimBlockFiltering( aImage, aRegion, aSubband, aOffset, aCurrentLevel );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::CopyDataToBlock
+// Apply inverse quantization and ROI shifting on the decoded
+// codeblock and copy to the image writer ( block-based ).
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kSynthesis::CopyDataToBlock( CJ2kEntropyDecoder& aEntropyDecoder, TPrecInt** aImageBlock, 
+                                     CJ2kSubband& aSubband, TUint8 aQuantizationStyle,
+                                     TInt32 aStartRowCblk, TInt32 aStartColCblk,
+                                     TInt32 aStartRowImage, TInt32 aStartColImage,
+                                     TInt32 aCblkHeight, TInt32 aCblkWidth )
+    {
+    TPrecInt* buffer = 0;    // To buffer one row of the image_block
+    TPrecInt* imageRow = 0;  // One row of the image
+    TPrecInt valueInt = 0;
+    TInt32 value = 0;
+    TInt32 j = 0;
+
+    TInt32 startRowImageBlock = aStartRowImage; // Start row's index in the image to copy to 
+    TInt32 startColImageBlock = aStartColImage; // Start column's index in the image to copy to 
+
+    TUint8 aBandIndex = (TUint8)( aSubband.SubbandType() );
+
+    // Adjust the place where to copy the data according to the subband type 
+    // ( i.e. whether we have LL, HL, LH or HH band ).
+    if( aBandIndex == 1 )
+        {
+        startColImageBlock += KWaveletBlockMidPoint;
+        }
+    else if( aBandIndex == 2 )
+        {
+        startRowImageBlock += KWaveletBlockMidPoint;
+        }
+    else if( aBandIndex == 3 )
+        {
+        startRowImageBlock += KWaveletBlockMidPoint;
+        startColImageBlock += KWaveletBlockMidPoint;
+        }
+
+    // Compute the end of the copy region
+    TInt32 endRowImageBlock = startRowImageBlock + aCblkHeight - 1; //lint !e961    no else is needed here at the end of if...else if
+    TInt32 endColImageBlock = startColImageBlock + aCblkWidth;
+
+    // Index of the row to copy from in the codeblock
+    TInt32 codeblockRow = aStartRowCblk + aCblkHeight-1;
+
+    // Index of the row to copy from in the codeblock
+    TInt32 codeblockColumn = aStartColCblk + aCblkWidth-1;
+
+    if ( iROIShift )  // ROI shifting is used
+        {
+        // Compute mask to determine which samples are in ROI
+        // for mask ROI coefficients
+        TInt32 mask = ( ( 1 << iMagnitudeBitsHere ) - 1 ) << ( ( KImplementationPrecision - 1 ) - iMagnitudeBitsHere );
+        TInt32 mask2 = ( ~mask ) & KMaximumPrecisionInteger;
+        TInt32 mask3 = ( ( 1 << iROIShift ) - 1 ) << ( ( KImplementationPrecision - 1 ) - iROIShift );
+        TInt32 maskShift = ( ~mask3 ) & KMaximumPrecisionInteger;
+
+        if ( !aQuantizationStyle )
+            {
+            // Shift all the samples in the codeblock
+            TInt32 roiDataShift = ( iROIDataShift < 0 ) ? -iROIDataShift : iROIDataShift;
+            
+            for ( ; endRowImageBlock >= startRowImageBlock; endRowImageBlock--,codeblockRow-- )
+                {
+                buffer = aEntropyDecoder.iData[codeblockRow] + codeblockColumn;
+                for ( j = endColImageBlock-1; j >= startColImageBlock; j-- )
+                    {
+                    value = ( *buffer-- );
+                    if ( !( value & mask ) ) // Background
+                        {
+                        if ( iROIDataShift < 0 )
+                            {
+                            aImageBlock[endRowImageBlock][j] = ( value < 0 ) ? -( ( value & KMaximumPrecisionInteger ) << roiDataShift ) 
+                                                             : ( value  << roiDataShift );
+                            }
+                        else
+                            {
+                            aImageBlock[endRowImageBlock][j] = ( value < 0 ) ? -( ( value & maskShift ) >> roiDataShift )     //lint !e704 value&maskShift is positive, so no risk of right shifting negative values 
+                                                             : ( ( value & maskShift ) >> roiDataShift );              //lint !e704 value&maskShift is positive, so no risk of right shifting negative values
+                            }
+                        }
+                    else  // ROI
+                        {
+                        if ( value & mask2 ) 
+                            {
+                            // Decoded more than magbits bit-planes, set
+                            // quantization mid-interval approx. bit just after
+                            // the magbits.
+                            value &= ( ~mask2 );
+                            }
+                        aImageBlock[endRowImageBlock][j] = ( value < 0 ) ? -( ( value & KMaximumPrecisionInteger ) >> iDataShift )
+                                                         : ( value >> iDataShift );              //lint !e704 value is positive here
+                        }
+                    }
+                }
+            }
+        else  // Irreversible case
+            {
+            // Shift all the samples in the codeblock
+            TInt32 stepExponent = ( iStepExponent < 0 ) ? -iStepExponent : iStepExponent;
+
+            // Divide into two cases depending on the sign of the iStepExponent to speed up coding
+            if ( iStepExponent < 0 )
+                {
+                for ( ; endRowImageBlock >= startRowImageBlock; endRowImageBlock--, codeblockRow-- )
+                    {
+                    buffer = aEntropyDecoder.iData[codeblockRow] + codeblockColumn;
+                    for ( j = endColImageBlock-1; j >= startColImageBlock; j-- )
+                        {
+                        value = ( *buffer-- );
+
+                        // Divide into two cases depending on whether value is negative
+                        if ( value < 0 )
+                            {
+                            if ( !( value & mask ) ) // Background
+                                {
+                                value = ( ( value & maskShift ) >> iROIDataShift );         //lint !e704 value&maskShift is positive, so no risk of right shifting negative values
+                                valueInt = -( ( value * iStepValue ) >> stepExponent );     //lint !e704 value*iStepValue is positive
+                                }
+                            else  // ROI
+                                {
+                                if ( value & mask2 ) 
+                                    {
+                                    // Decoded more than magbits bit-planes, set
+                                    // quantization mid-interval approx. bit just after
+                                    // the magbits.
+                                    value = ( value & ( ~mask2 ) ) | ( 1 << ( KImplementationPrecision - 2 - iMagnitudeBitsHere ) );
+                                    }
+
+                                value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
+                                valueInt = -( ( value * iStepValue ) >> stepExponent );      //lint !e704 value*iStepValue is positive
+                                }
+                            }
+                        else    // Value is non-negative
+                            {
+                            if ( !( value & mask ) ) // Background
+                                {
+                                value = ( ( value & maskShift ) >> iROIDataShift );         //lint !e704 value&maskShift is positive, so no risk of right shifting negative values
+                                valueInt = ( ( value * iStepValue ) >> stepExponent );      //lint !e704 value*iStepValue is positive
+                                }
+                            else  // ROI
+                                {
+                                if ( value & mask2 ) 
+                                    {
+                                    // Decoded more than magbits bit-planes, set
+                                    // quantization mid-interval approx. bit just after
+                                    // the magbits.
+                                    value = ( value & ( ~mask2 ) ) | ( 1 << ( KImplementationPrecision - 2 - iMagnitudeBitsHere ) );
+                                    }
+
+                                value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
+                                valueInt = ( ( value * iStepValue ) >> stepExponent );      //lint !e704 value*iStepValue is positive
+                                }
+                            }
+
+                        aImageBlock[endRowImageBlock][j] = valueInt;
+                        }
+                    }
+                }
+            else    // iStepExponent is non-negative
+                {
+                for ( ; endRowImageBlock >= startRowImageBlock; endRowImageBlock--,codeblockRow-- )
+                    {
+                    buffer = aEntropyDecoder.iData[codeblockRow] + codeblockColumn;
+                    for ( j = endColImageBlock-1; j >= startColImageBlock; j-- )
+                        {
+                        value = ( *buffer-- );
+                        if ( !( value & mask ) ) // Background
+                            {
+                            if ( value < 0 )   // Get the sign
+                                {
+                                value = -( ( value & maskShift ) >> iROIDataShift );          //lint !e704 value&maskShift is positive, so no risk of right shifting negative values
+                                }
+                            else
+                                {
+                                value = ( ( value & maskShift ) >> iROIDataShift );           //lint !e704 value&maskShift is positive, so no risk of right shifting negative values
+                                }
+                            
+                            valueInt = ( ( value * iStepValue ) << stepExponent );
+                            }
+                        else  // ROI
+                            {
+                            if ( value & mask2 ) 
+                                {
+                                // Decoded more than magbits bit-planes, set
+                                // quantization mid-interval approx. bit just after
+                                // the magbits.
+                                value = ( value & ( ~mask2 ) ) | ( 1 << ( KImplementationPrecision - 2 - iMagnitudeBitsHere ) );
+                                }
+                            if ( value < 0 )
+                                {
+                                value = -( ( value & KMaximumPrecisionInteger ) >> iDataShift );
+                                }
+                            else
+                                {
+                                value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
+                                }
+                            
+                            valueInt = ( ( value * iStepValue ) << stepExponent );
+                            }
+                        aImageBlock[endRowImageBlock][j] = valueInt;
+                        }
+                    }
+                }
+            }
+        }
+    else  // ROI is not present
+        {
+        if ( !aQuantizationStyle )
+            {
+            // Shift all the samples in the codeblock
+            TInt32 i = codeblockRow;
+            for ( ; endRowImageBlock >= startRowImageBlock; endRowImageBlock--, i-- )
+                {
+                imageRow = aImageBlock[endRowImageBlock] + endColImageBlock - 1;
+                buffer = aEntropyDecoder.iData[i] + codeblockColumn;
+
+                for ( j = endColImageBlock-1; j >= startColImageBlock; j-- )
+                    {
+                    value = *buffer--;
+                    if ( value < 0 )
+                        {
+                        *imageRow-- = -( ( value & KMaximumPrecisionInteger ) >> iDataShift );
+                        }
+                    else
+                        {
+                        *imageRow-- = value >> iDataShift;          //lint !e704 value is positive here
+                        }
+                    }
+                }
+            }
+        else  // Irreversible case 
+            {
+            // Shift all the samples in the codeblock 
+            TInt32 stepExponent = ( iStepExponent < 0 ) ? -iStepExponent : iStepExponent;
+            
+            // Divide into two cases depending on the sign of the iStepExponent to speed up coding
+            if ( iStepExponent < 0 )
+                {
+                for ( ; endRowImageBlock >= startRowImageBlock; endRowImageBlock--,codeblockRow-- )
+                    {
+                    buffer = aEntropyDecoder.iData[codeblockRow] + codeblockColumn;
+                    for ( j = endColImageBlock-1;  j >= startColImageBlock; j-- )
+                        {
+                        value = ( *buffer-- );
+
+                        if ( value < 0 )   // Negative value
+                            {
+                            value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
+                            aImageBlock[endRowImageBlock][j] = (TPrecInt)( -( ( value * iStepValue ) >> stepExponent ) ); //lint !e704 value*iStepValue is positive
+                            }
+                        else
+                            {
+                            value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
+                            aImageBlock[endRowImageBlock][j] = (TPrecInt)( ( value * iStepValue ) >> stepExponent );    //lint !e704 value*iStepValue is positive
+                            }
+                        }
+                    }
+                }
+            else    // iStepExponent is non-negative
+                {
+                for ( ; endRowImageBlock >= startRowImageBlock; endRowImageBlock--,codeblockRow-- )
+                    {
+                    buffer = aEntropyDecoder.iData[codeblockRow] + codeblockColumn;
+                    for ( j = endColImageBlock-1;  j >= startColImageBlock; j-- )
+                        {
+                        value = ( *buffer-- );
+
+                        if ( value < 0 )   // Negative value
+                            {
+                            value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
+                            aImageBlock[endRowImageBlock][j] = (TPrecInt)( -( ( value * iStepValue ) << stepExponent ) );
+                            }
+                        else
+                            {
+                            value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
+                            aImageBlock[endRowImageBlock][j] = (TPrecInt)( ( value * iStepValue ) << stepExponent );
+                            }
+                        }
+                    }
+                }
+            }
+        }
+  
+    // If number of levels is zero then we have to do the 
+    // inverse wavelet shifting here.
+    //
+    if ( iWaveletLevels == 0 )
+        {
+        endRowImageBlock = startRowImageBlock + aCblkHeight;
+        endColImageBlock = startColImageBlock + aCblkWidth;
+
+        if ( aQuantizationStyle )
+            {
+            for ( TInt32 i = endRowImageBlock - 1; i >= startRowImageBlock; i-- )
+                {
+                for ( j = endColImageBlock - 1; j >= startColImageBlock; j-- )
+                    {
+                    aImageBlock[i][j] >>= KWaveletShift; //lint !e704 shifting is OK.
+                    }
+                }
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kSynthesis::FillDataWithZeros
+// Fill a block in image writer with zeros ( corresponding to an empty block )
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kSynthesis::FillDataWithZeros( TPrecInt** aImageBlock, CJ2kSubband& aSubband, 
+                                       TInt32 aStartRowImage, TInt32 aStartColImage,
+                                       TInt32 aCblkHeight, TInt32 aCblkWidth )
+    {
+    TPrecInt* imageRow = 0; // One row of the image
+    TInt32 j = 0;
+
+    TInt32 startRowImageBlock = aStartRowImage; // Start row's index in the image to copy to 
+    TInt32 startColImageBlock = aStartColImage; // Start column's index in the image to copy to 
+
+    TUint8 aBandIndex = (TUint8)( aSubband.SubbandType() );
+
+    // Adjust the place where to copy the data according to the subband type 
+    // ( i.e. whether we have LL, HL, LH or HH band ).
+    if( aBandIndex == 1 )
+        {
+        startColImageBlock += KWaveletBlockMidPoint;
+        }
+    else if( aBandIndex == 2 )
+        {
+        startRowImageBlock += KWaveletBlockMidPoint;
+        }
+    else if( aBandIndex == 3 )
+        {
+        startRowImageBlock += KWaveletBlockMidPoint;
+        startColImageBlock += KWaveletBlockMidPoint;
+        }
+
+    // Compute the end of the copy region
+    TInt32 endRowImageBlock = startRowImageBlock + aCblkHeight - 1; //lint !e961    no else is needed here at the end of if...else if
+    TInt32 endColImageBlock = startColImageBlock + aCblkWidth;
+
+    // Shift all the samples in the codeblock
+    for ( ; endRowImageBlock >= startRowImageBlock; endRowImageBlock-- )
+        {
+        imageRow = aImageBlock[endRowImageBlock] + endColImageBlock - 1;
+        for ( j = endColImageBlock-1; j >= startColImageBlock; j-- )
+            {
+             *imageRow-- = 0;
+            }
+        }
+    }
+