imagingmodules/jp2kcodec/Src/JP2KEntropyDecoder.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 09:22:31 +0200
changeset 0 469c91dae73b
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* 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:  Entropy decoder functionality..
*
*/


// INCLUDE FILES
#include "JP2KCodeBlock.h"
#include "JP2KTileInfo.h"
#include "JP2KImageInfo.h"
#include "JP2KEntropyDecoder.h"

// EXTERNAL DATA STRUCTURES

// EXTERNAL FUNCTION PROTOTYPES  

// CONSTANTS

// Mq decoder state information, all of the 47 states contain
// the probability estimate of LPS in hexadecimal, the next
// mps state index, the next lps state index and the flag
// indicating a mps switch.
const TUint32 KMqQeStates[KNumberOriginalMQEntries] =  {0x5601,0x3401,0x1801,0x0ac1,0x0521,0x0221,0x5601,
                                                        0x5401,0x4801,0x3801,0x3001,0x2401,0x1c01,0x1601,
                                                        0x5601,0x5401,0x5101,0x4801,0x3801,0x3401,0x3001,
                                                        0x2801,0x2401,0x2201,0x1c01,0x1801,0x1601,0x1401,
                                                        0x1201,0x1101,0x0ac1,0x09c1,0x08a1,0x0521,0x0441,
                                                        0x02a1,0x0221,0x0141,0x0111,0x0085,0x0049,0x0025,
                                                        0x0015,0x0009,0x0005,0x0001,0x5601};

const TInt32 KMqMpsStates[KNumberOriginalMQEntries] =  {1,2,3,4,5,38,7,8,9,10,11,12,13,29,15,16,17,18,19,
                                                        20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,
                                                        36,37,38,39,40,41,42,43,44,45,45,46};

const TInt32 KMqLpsStates[KNumberOriginalMQEntries] =  {1,6,9,12,29,33,6,14,14,14,17,18,20,21,14,14,15,16,
                                                        17,18,19,19,20,21,22,23,24,25,26,27,28,29,30,31,
                                                        32,33,34,35,36,37,38,39,40,41,42,43,46};

const TInt32 KMqSwitchFlagStates[KNumberOriginalMQEntries] =  {1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,
                                                               0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                                                               0,0,0,0,0,0,0};

// MQCoder initial states
const TInt32 KMqInitStates[KNumberContexts] = {46,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

// MACROS

// LOCAL CONSTANTS AND MACROS

// MODULE DATA STRUCTURES

// LOCAL FUNCTION PROTOTYPES

// FORWARD DECLARATIONS

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// J2KEntropyStream::ReadByteFromStream
// Read a byte from the input stream
// ( other items were commented in a header ).
// -----------------------------------------------------------------------------
//
TUint8 J2KEntropyStream::ReadByteFromStream()
    {
    if ( iPosition < iNumBytes )
        {
        return ( TUint8 )iBuffer[iPosition++];
        }
    else
        {
        // 0xFF to represent EOF
        return ( 0xFF );   
        }
    }

// -----------------------------------------------------------------------------
// J2KEntropyStream::ReadBitFromStream
// Read a bit from the input stream
// ( other items were commented in a header ).
// -----------------------------------------------------------------------------
//
TUint8 J2KEntropyStream::ReadBitFromStream() 
    {
    if ( iTinyBufferPos == 0 )
        {
        // Input the byte buffer
        iTinyBuffer = ReadByteFromStream();

        if ( iDelayedFF )
            {
            iTinyBufferPos = 7;
            }
        else
            {
            iTinyBufferPos = 8;
            }

        if ( iTinyBuffer != 0xFF ) // No bit-stuffing needed
            {
            iDelayedFF = 0;
            }
        else  // We need to do bit stuffing on next byte
            {
            iDelayedFF = 1;
            }
        }

    return (TUint8)( ( iTinyBuffer >> ( --iTinyBufferPos ) ) & 0x01 );
    }

// -----------------------------------------------------------------------------
// J2KEntropyStream::CheckPrediction
// Check a prediction termination for raw coding
// ( other items were commented in a header ).
// -----------------------------------------------------------------------------
//
TEntropyErrorState J2KEntropyStream::CheckPrediction()
    {
    // Error resilient sequence in last byte
    TInt32 errorResSeq = 0; 
 
    // If tiny buffer is empty and equal to 0xFF, 
    // get the next byte for error resilience marker
    if ( iTinyBufferPos == 0 && iTinyBuffer == 0xFF ) 
        {
        iTinyBuffer = ReadByteFromStream();
        iTinyBufferPos = 7;
        }
  
    // Search for the error resilience marker
    if ( iTinyBufferPos > 0 ) 
        {
        // Get the error resilience sequence
        errorResSeq = iTinyBuffer & ( ( 1 << iTinyBufferPos ) - 1 );

        // Compare the read error resilience marker to the constant 01010101 byte
        if ( errorResSeq != ( KErrorResilienceTermination >> ( 8 - iTinyBufferPos ) ) ) 
            {
            return EEntropyCodingError;
            }
        }
  
    // If we are not at the end of this stream, 
    // next byte should be smaller than 0x80.
    if ( iPosition < iNumBytes )
        {
        if ( iTinyBuffer == 0xFF && iTinyBufferPos == 1 ) 
            {
            if ( ReadByteFromStream() >= 0x80 ) 
                {
                return EEntropyCodingError;
                }
            }
        else 
            {
            if ( ReadByteFromStream() != 0xFF ) 
                {
                return EEntropyCodingError;
                }
            }
        }

    // No error detected
    return ENoError;
    }

// -----------------------------------------------------------------------------
// J2KEntropyStream::ResetInputStream
// Reset the input stream
// ( other items were commented in a header ).
// -----------------------------------------------------------------------------
//
void J2KEntropyStream::ResetInputStream()
    {
    // Initialize the stream parameters. Note that stream->position is not reset here,
    // it is reset only when the stream is created for the first time.
    iTinyBuffer = 0;
    iTinyBufferPos = 0;
    iDelayedFF = 0;
    }

// ============================ MEMBER FUNCTIONS ===============================

// Destructor
J2KMQCoder::~J2KMQCoder()
    {
    iOriginalStates.ResetAndDestroy();
    iContextList.ResetAndDestroy();
    }

// -----------------------------------------------------------------------------
// J2KMQCoder::MqByteIn
// Read a byte from the input stream
// ( other items were commented in a header ).
// -----------------------------------------------------------------------------
//
void J2KMQCoder::MqByteIn()
    {
    if ( !iMarker )
        {
        if ( iB == 0xff )
            {
            iB = iInputStream.ReadByteFromStream();

            if ( iB > 0x8f )
                {
                iMarker = 1;
                iCT = 8;
                }
            else
                {
                iC += 0xFE00 - ( iB << 9 );
                iCT = 7;
                }
            }
        else
            {
            iB = iInputStream.ReadByteFromStream();
            iC += 0xFF00 - ( iB << 8 );
            iCT = 8;
            }   
        }
    else
        {
        iCT = 8;
        }
    }

// -----------------------------------------------------------------------------
// J2KMQCoder::MqDecodeSymbol
// Decode the symbol
// ( other items were commented in a header ).
// -----------------------------------------------------------------------------
//
TUint8 J2KMQCoder::MqDecodeSymbol( TInt32 aContextIndex )
    {
    // Set the current context to point to the right place in the context list
    iCurrentContext = iContextList[aContextIndex];
    iCurrentState = iCurrentContext->iState;

    iA -= iCurrentState->iQe;

    // Decision returned ( i.e. decoded symbol )
    TInt32 decision = 0;  
    if ( ( iC >> 16 ) < iA )  // Chigh >= A
        {
        MpsExchange( decision );
        }
    else   // lps exchange
        {
        LpsExchange( decision );
        }

    // Return decision 
    return (TUint8)decision;   
    }

// -----------------------------------------------------------------------------
// J2KMQCoder::MqInitDecoder
// Initialize the MQCoder
// ( other items were commented in a header ).
// -----------------------------------------------------------------------------
//
void J2KMQCoder::MqInitDecoder()
    {
    iMarker = 0;
    iB = iInputStream.ReadByteFromStream();

    // Software conventions decoder initialization 
    iC = ( iB ^ 0xFF ) << 16;
    MqByteIn();
  
    iC <<= 7;
    iCT -= 7;
    iA = 0x8000;
    }

// -----------------------------------------------------------------------------
// J2KMQCoder::MqCheckPrediction
// Check the prediction termination
// ( other items were commented in a header ).
// -----------------------------------------------------------------------------
//
TEntropyErrorState J2KMQCoder::MqCheckPrediction()
    {
    // If no marker was found, B should be == 0xFF and counter zero, 
    // otherwise there is an error
    if ( !iMarker && ( iCT != 0 || iB != 0xFF ) ) 
        {
        return EEntropyCodingError;
        }
  
    // If counter CT is 1, no need to check any further
    if ( iCT == 1 )
        {
        return ENoError;
        }
  
    // If counter CT is zero, then next byte must be larger than 0x8F, if the terminating
    // marker has not been reached yet
    if ( iCT == 0 )  
        {
        if ( !iMarker ) 
            {
            // Get next byte and check that it is larger than 0x8F
            iB = iInputStream.ReadByteFromStream();
            if ( iB <= 0x8F )
                {
                return EEntropyCodingError;
                }
            }
        // Set the counter back to 8
        iCT = 8;
        }

    // Number of bits that where added in the termination process
    // Compute the number of bits, k for error resilience information
    TUint32 k = (TUint32)( iCT - 1 );
  
    // Check for a coded LPS.
    TUint32 q = 0x8000 >> k;
  
    // Check that we can decode an LPS interval of probability 'q'
    iA -= q;
    if ( ( iC >> 16 ) < iA )   // software convention
        {
        // MPS interval was decoded, thus error occured
        return EEntropyCodingError;
        }
 
    // Check for coded LPS interval.
    iA = q;

    do  // Renormalization
        {
        if ( iCT == 0 )
            {
            MqByteIn();
            }

        iA <<= 1;
        iC <<= 1;
        iCT--;

        } while ( iA < 0x8000 );
  
    // No error was found
    return ENoError;
    }

// -----------------------------------------------------------------------------
// J2KMQCoder::ResetMqContexts
// Reset the MQCoder context list to the original state
// ( other items were commented in a header ).
// -----------------------------------------------------------------------------
//
void J2KMQCoder::ResetMqContexts()
    {
    // Reset all context states to initial states and set the mps
    // of every context to 0.
    for ( TInt32 i = KNumberContexts - 1; i >= 0; i-- )
        {
        iContextList[i]->iState = iOriginalStates[KMqInitStates[i]];
        iContextList[i]->iMPS = 0;
        }
    }

// -----------------------------------------------------------------------------
// J2KMQCoder::ResetMQDecoder
// Initialze MQCoder and reset the context
// ( other items were commented in a header ).
// -----------------------------------------------------------------------------
//
void J2KMQCoder::ResetMQDecoder( TInt32 aSegmentLength )
    {
    // Reset all contexts ( states and mps )
    ResetMqContexts();              
    iInputStream.ResetInputStream();
    iInputStream.iPosition = 0;
    iInputStream.iNumBytes = aSegmentLength;
    MqInitDecoder();
    }

// -----------------------------------------------------------------------------
// J2KMQCoder::InitializeOrigMqTable
// Initialize MQCoder original states table
// ( other items were commented in a header ).
// -----------------------------------------------------------------------------
//
void J2KMQCoder::InitializeOrigMqTable()
    {
    for ( TUint8 i = 0; i < KNumberOriginalMQEntries; i++ )
        {
        iOriginalStates[i]->iQe = KMqQeStates[i];
        iOriginalStates[i]->iNextMPS = iOriginalStates[KMqMpsStates[i]];
        iOriginalStates[i]->iNextLPS = iOriginalStates[KMqLpsStates[i]];
        iOriginalStates[i]->iSwitchFlag = KMqSwitchFlagStates[i];
        }
    }

// -----------------------------------------------------------------------------
// J2KMQCoder::ReNormalize
// Renormalize 
// ( other items were commented in a header ).
// -----------------------------------------------------------------------------
//
void J2KMQCoder::ReNormalize()
    {
    do
        {
        if ( iCT == 0 )
            {
            MqByteIn();
            }

        iA <<= 1;
        iC <<= 1;
        --iCT;
        } while ( !( iA & 0x8000 ) );
    }

// -----------------------------------------------------------------------------
// J2KMQCoder::MpsExchange
// MPS exchange
// ( other items were commented in a header ).
// -----------------------------------------------------------------------------
//
void J2KMQCoder::MpsExchange( TInt32& aD )
    {
    aD = iCurrentContext->iMPS;
    if ( !( iA & 0x8000 ) )
        {
        if ( iA < iCurrentState->iQe )
            {
            aD ^= 1;
            if ( iCurrentState->iSwitchFlag )
                {
                iCurrentContext->iMPS ^= 1;
                }

            iCurrentContext->iState = iCurrentState->iNextLPS;
            }
        else
            {
            iCurrentContext->iState = iCurrentState->iNextMPS;
            }

        ReNormalize();
        }
    }

// -----------------------------------------------------------------------------
// J2KMQCoder::LpsExchange
// LPS exchange
// ( other items were commented in a header ).
// -----------------------------------------------------------------------------
//
void J2KMQCoder::LpsExchange( TInt32& aD )
    {
    iC -= iA << 16;
    aD = iCurrentContext->iMPS;
    if ( iA < iCurrentState->iQe )
        {
        iCurrentContext->iState = iCurrentState->iNextMPS;
        }
    else
        {
        aD ^= 1;
        if ( iCurrentState->iSwitchFlag )
            {
            iCurrentContext->iMPS ^= 1;
            }

        iCurrentContext->iState = iCurrentState->iNextLPS;
        }
    iA = iCurrentState->iQe;
    ReNormalize(  );
    }

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CJ2kEntropyDecoder* CJ2kEntropyDecoder::NewL( CJ2kImageInfo& aImageInfo )
    {
    CJ2kEntropyDecoder *self = new ( ELeave ) CJ2kEntropyDecoder;

    CleanupStack::PushL( self );
    self->ConstructL( aImageInfo );
    CleanupStack::Pop();

    return self;
    }

// Destructor
CJ2kEntropyDecoder::~CJ2kEntropyDecoder()
    {  
    delete iMRLutBuf;
    iMRLutBuf = 0;

    delete iSCLutBuf;
    iSCLutBuf = 0;
  
    delete iZcLutLL;
    iZcLutLL = 0;

    delete iZcLutHL;
    iZcLutHL = 0;

    delete iZcLutHH;
    iZcLutHH = 0;
    
    TJ2kUtils::Free2DArray( iData );
    User::Free( iStates );
    }

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::SetNewSizeL
// Set the size of internal buffer and other control data
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CJ2kEntropyDecoder::SetNewSizeL( const TSize& aSize )
    {
    if ( aSize.iWidth <= iCurrentSize.iWidth &&
         aSize.iHeight <= iCurrentSize.iHeight )
        {
        return;
        }
    else
        {
        iCurrentSize = aSize;

        TJ2kUtils::Free2DArray( iData );
        iData = 0;
        iData = TJ2kUtils::Alloc2DArrayL( iCurrentSize.iHeight, iCurrentSize.iWidth );

        iMaxBlockWidth = (TUint8)( iCurrentSize.iWidth );

        // We can compute some parameters for entropy decoding here not to compute them for every pass!!!
        iBlockDataWidth        = iMaxBlockWidth;
        iStateWidth            = iMaxBlockWidth + 2;
        iStateSize             = ( iCurrentSize.iHeight + 2 ) * ( iCurrentSize.iWidth + 2 );
        iDataSamplesPerStripe  = iBlockDataWidth * KStripeHeight;
        iStateSamplesPerStripe = iStateWidth * KStripeHeight;

        TInt16* ptrTemp = STATIC_CAST( TInt16*, User::ReAlloc( iStates, iStateSize * sizeof( TInt16 ) ) );
        if ( !ptrTemp )
            {
            User::Leave( KErrNoMemory );
            }
        iStates = ptrTemp;
        }
    }

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::SetCurrentZCLUT
// Set the current pointer to point to the right LUT depending on  the current subband
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CJ2kEntropyDecoder::SetCurrentZCLUT( TUint8 aBandIndex )
    {
    if ( aBandIndex == 1 )
        {
        // For HL band
        iCurrentZcLutPtr = (TUint8*)iZcLutHL->Des().Ptr();
        }
    else if ( aBandIndex == 3 )
        {
        // For HH band
        iCurrentZcLutPtr = (TUint8*)iZcLutHH->Des().Ptr();
        }
    else 
        {
        // For LL and LH band
        iCurrentZcLutPtr = (TUint8*)iZcLutLL->Des().Ptr();
        }
    }

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::DecodeCodeblock
// Decode the coded codeblock
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CJ2kEntropyDecoder::DecodeCodeblock( CJ2kCodeBlock& aCodeblock, TUint8 aCblkStyle, 
                                          TUint8 aMagBits )
    {
    TInt32 startBitplane = 0;     // The bitplane where coding starts
    TInt32 endBitplane = 0;       // The last coded bitplane
    TInt32 terminationLength = 0;
    TUint8 tempPassIndex = 0;
    TUint8 passIndex = 0;

    iMQDecoder.iInputStream.iBuffer = CONST_CAST( TUint8*, aCodeblock.Data() );
    TSize codeBlockSize = aCodeblock.CodeBlockCanvas().Size();

    iVerticalCausalContextUsed     = ( ( aCblkStyle & EVerticalStripe ) != 0 );
    iResetContexts                 = ( ( aCblkStyle & EResetContext ) != 0 );
    iPredictableTerminationUsed    = ( ( aCblkStyle & EPredictableTermination ) != 0 );
    TUint8 terminateEachPass       = ( ( aCblkStyle & ETermination ) != 0 );
    TUint8 segmentationSymbolsUsed = ( ( aCblkStyle & ESegmentationSymbols ) != 0 );
    TUint8 arithmeticBypass        = ( ( aCblkStyle & EArithmeticBypass ) != 0 );
    aCodeblock.ResetPassIndex();
  
  
    // Initialize the stream and the mq coder for this code block:
    // also set mq coder's stream to point to aCodeblock's stream 
    if ( !arithmeticBypass && !terminateEachPass )  // No termination
        {
        iMQDecoder.ResetMQDecoder( aCodeblock.DataLength() );
        }
    else
        {
        // Compute the length of the first terminated segment. If we are 
        // terminating on each pass, terminated lengths are equal to 
        // codeblock lengths. On the other hand if we are using arithmetic
        // bypass ( without terminating each pass ), the first termination length
        // is the codeblock lengths summed up to the point where we have last AC
        // pass before first raw coding pass.

        if ( terminateEachPass )
            {
            terminationLength = aCodeblock.CblkLength( (TUint16)passIndex++ );
            }
        else  // AC bypass without termination on each pass
            {
            // Loop adding codeblock lengths until enough passes have been consumed 
            while ( ( tempPassIndex < KFirstBypassTermIndex ) && ( passIndex <= aCodeblock.LastPass() ) )
                {
                tempPassIndex = (TUint8)( tempPassIndex + aCodeblock.PassesPerSegment( passIndex ) );
                terminationLength = (TUint32)( terminationLength + aCodeblock.CblkLength( passIndex++ ) );
                }
            }

        // Now initialize the iMQDecoder with the right terminated length
        iMQDecoder.ResetMQDecoder( terminationLength );
        }
  
    // Initialize data array 
    for ( TInt i = codeBlockSize.iHeight - 1; i >= 0; i-- )
        {
        Mem::FillZ( iData[i], codeBlockSize.iWidth * sizeof( TPrecInt ) );
        }
  
    // Initialize iStates array
    Mem::FillZ( iStates, iStateSize * sizeof( TInt16 ) );
  
    // Compute different bitplanes; empty bitplanes tells how many bitplanes are 
    // empty in this codeblock compared to the whole subband, iStartBitplane gives
    // the index of the first bitplane to be coded for this block and iEndBitplane
    // is the index of the last bitplane coded for this codeblock.
  
    // Compute coded block's magnitude bits 
    aMagBits = (TUint8)( aMagBits - aCodeblock.EmptyBitplanes() );
    startBitplane = ( KImplementationPrecision - 2 ) - aCodeblock.EmptyBitplanes();
    endBitplane = startBitplane - aMagBits;
 
    // Compute the number of stripes for this codeblock 
    iNumStripes = (TUint16)( ( codeBlockSize.iHeight + KStripeHeight - 1 ) / KStripeHeight );
    iBlockWidth = codeBlockSize.iWidth;

    // Compute the last stripe's height once, 
    // so that we don't have to compute it for all passes!
    iLastStripeHeight = codeBlockSize.iHeight - ( iNumStripes - 1 ) * KStripeHeight;

    iCurrentBitplane = (TUint8)( startBitplane );

    // First do only the normalization pass 
    iTerminateThisPass = ( terminateEachPass || ( iCurrentBitplane == endBitplane ) );

    CleanupPass( segmentationSymbolsUsed );

    aCodeblock.IncrementPassIndex();

    iCurrentBitplane--;
  
    // Then repeat the three passes: significance, refinement and normalization 
    // for the remaining bitplanes.
    while ( aCodeblock.PassIndex() <= aCodeblock.LastPass() )
        {
        // Significance pass, terminate only if terminating after each pass
        iTerminateThisPass = terminateEachPass;

        if ( ( arithmeticBypass == 0 ) || ( aCodeblock.PassIndex() < KFirstLazyPassIndex ) )
            {
            if ( terminateEachPass )  // if last pass was terminated, initialize MQ-coder
                {
                // Update the number of available TUint8s for this terminated sequence
                iMQDecoder.iInputStream.iNumBytes += aCodeblock.CblkLength( passIndex++ );
                iMQDecoder.MqInitDecoder();
                }

            SignificancePass();
            }
        else
            {
            // if we are here, then the previous pass was terminated
            if ( terminateEachPass )
                {
                // Update the number of available bytes for this terminated sequence 
                iMQDecoder.iInputStream.iNumBytes += aCodeblock.CblkLength( passIndex++ );
                }
            else  // AC bypass without termination on each pass 
                {
                // Here we have two cases:
                // 1. If this codeblock length is for this pass only, then for the terminated length 
                //    we have to add the next pass codeblock length also. 
                // 2. This codeblock length is for both this pass ( significance ) and the next pass 
                //    ( refinement ). Terminated length is equal to the CblkLength[iPassIndex].
                if ( aCodeblock.PassesPerSegment( passIndex ) == 2 )
                    {
                    iMQDecoder.iInputStream.iNumBytes += aCodeblock.CblkLength( passIndex++ );
                    }
                else
                    {
                    iMQDecoder.iInputStream.iNumBytes += aCodeblock.CblkLength( passIndex ) + 
                                                         aCodeblock.CblkLength( (TUint16)( passIndex + 1 ) );
                    passIndex += 2;
                    }
                }
            iMQDecoder.iInputStream.ResetInputStream();
            LazySignificancePass();
            }
    
        aCodeblock.IncrementPassIndex();
        if ( aCodeblock.PassIndex() > aCodeblock.LastPass() )
            {
            // We have fully decoded this codeblock
            return;
            }
    
        // Magnitude refinement pass, terminate if raw coding or termination after each pass
        iTerminateThisPass = ( terminateEachPass || ( arithmeticBypass && ( aCodeblock.PassIndex() > 
                                                                            KFirstLazyPassIndex ) ) );

        if ( arithmeticBypass == 0 || ( aCodeblock.PassIndex() < KFirstLazyPassIndex ) )
            {
            if ( terminateEachPass ) // if previous pass was terminated, initialize MQ-coder 
                {
                // Update the number of available bytes for this terminated sequence
                iMQDecoder.iInputStream.iNumBytes += aCodeblock.CblkLength( passIndex++ );
                iMQDecoder.MqInitDecoder();
                }

            RefinementPass();
            }
        else
            {
            if ( terminateEachPass )  // if previous pass was terminated
                {
                // Update the number of available bytes for this terminated sequence
                iMQDecoder.iInputStream.iNumBytes += aCodeblock.CblkLength( passIndex++ );
                iMQDecoder.iInputStream.ResetInputStream();
                }

            LazyRefinementPass();
            }
    
        aCodeblock.IncrementPassIndex();
        if ( aCodeblock.PassIndex() > aCodeblock.LastPass() )
            {
            // We have fully decoded this codeblock
            return;
            }
    
        // Cleanup pass, terminate if coding raw, termination after each pass, last bitplane
        // before starting raw coding or last bitplane in this codeblock.
        iTerminateThisPass = ( terminateEachPass || ( iCurrentBitplane == endBitplane ) || 
                             ( arithmeticBypass && ( aCodeblock.PassIndex() >= KFirstLazyPassIndex ) ) );
    
        // If last ( AC ) pass was terminated, initialize MQ-coder
        if ( terminateEachPass || ( arithmeticBypass && ( aCodeblock.PassIndex() > KFirstLazyPassIndex ) ) )
            {
            // Update the number of available bytes for this terminated sequence
            iMQDecoder.iInputStream.iNumBytes += aCodeblock.CblkLength( passIndex++ );
            iMQDecoder.MqInitDecoder();
            }

        CleanupPass( segmentationSymbolsUsed );
    
        aCodeblock.IncrementPassIndex();
        if ( aCodeblock.PassIndex() > aCodeblock.LastPass() )
            {
            // We have fully decoded this codeblock
            return;
            }

        // move onto next bitplane
        if ( iCurrentBitplane == 0 )  // This might happen with 16-bit and ROI
            {
            // We have fully decoded this codeblock
            return;
            }

        iCurrentBitplane--;
        }
    }

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CJ2kEntropyDecoder::ConstructL( CJ2kImageInfo& aImageInfo )
    {
    iCurrentSize = aImageInfo.MaxBlockSize();

    for ( TUint16 i = 0; i < KNumberContexts; i++ )
        {
        J2KEntropyContexts *context = new ( ELeave ) J2KEntropyContexts;
        CleanupStack::PushL( context );
        User::LeaveIfError( iMQDecoder.iContextList.Append( context ) );
        CleanupStack::Pop(1);
        }

    for ( TUint16 ii = 0; ii < KNumberOriginalMQEntries; ii++ )
        {
        J2KEntropyStates *state = new ( ELeave ) J2KEntropyStates;
        CleanupStack::PushL( state );
        User::LeaveIfError( iMQDecoder.iOriginalStates.Append( state ) );
        CleanupStack::Pop(1);
        }

    // Allocate memory for the SC Look up table
    iSCLutBuf = HBufC8::NewL( KLutSize );
    iSCLut = CONST_CAST( TUint8*, iSCLutBuf->Des().Ptr() );

    // Allocate memory for the MR Look up table
    iMRLutBuf = HBufC8::NewL( KLutSize );
    iMRLut = CONST_CAST( TUint8*, iMRLutBuf->Des().Ptr() );

    // Allocate memory for the Zero coding Look up table
    iZcLutLL = HBufC8::NewL( ( 1 << KZcLutBits ) );
    iZcLutHL = HBufC8::NewL( ( 1 << KZcLutBits ) );
    iZcLutHH = HBufC8::NewL( ( 1 << KZcLutBits ) );

    iData = TJ2kUtils::Alloc2DArrayL( iCurrentSize.iHeight, iCurrentSize.iWidth );

    iMaxBlockWidth = (TUint16)( iCurrentSize.iWidth );

    // We can compute some parameters for entropy decoding here not to compute them for every pass!!!
    iBlockDataWidth        = iMaxBlockWidth;
    iStateWidth            = iMaxBlockWidth + 2;
    iStateSize             = ( iCurrentSize.iHeight + 2 ) * ( iCurrentSize.iWidth + 2 );
    iDataSamplesPerStripe  = iBlockDataWidth * KStripeHeight;
    iStateSamplesPerStripe = iStateWidth * KStripeHeight;

    iStates = STATIC_CAST( TInt16*, User::AllocL( iStateSize * sizeof( TInt16 ) ) );

    // Initialization of the MQ tables needed since
    // the original table could not be used as it was constant!
    iMQDecoder.InitializeOrigMqTable();

    iMaxBitDepth = 0;
    for ( TUint16 iii = 0; iii < aImageInfo.NumOfComponents(); ++iii )
        {
        iMaxBitDepth = Max( iMaxBitDepth, aImageInfo.DepthOfComponent( iii ) );
        }

    // Initialize ZC lookup table
    InitializeZCLut();

    // Initialize SC/MR lookup table
    InitializeScMrLut();
    }

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::InitializeZCLut
// Initialize ZC lookup table
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CJ2kEntropyDecoder::InitializeZCLut()
    {
    // Create pointers for all the ZC LUT's
    TUint8* iZcLutLLPtr = CONST_CAST( TUint8*, iZcLutLL->Des().Ptr() );
    TUint8* iZcLutHLPtr = CONST_CAST( TUint8*, iZcLutHL->Des().Ptr() );
    TUint8* iZcLutHHPtr = CONST_CAST( TUint8*, iZcLutHH->Des().Ptr() );

    TInt32 ctxt = 0; 
    TUint16 sh = 0;     // horizontal sum
    TUint16 sv = 0;     // vertical sum
    TUint16 sd = 0;     // diagonal sum

    for ( TUint16 i = 0; i <= KZcMask; i++ )
        {
        sh = (TUint16)( ( ( i >> KPositionRight ) & 1 ) + ( ( i >> KPositionLeft ) & 1 ) );
        sv = (TUint16)( ( ( i >> KPositionDown ) & 1 ) + ( ( i >> KPositionUp ) & 1 ) );
        sd = (TUint16)( ( ( i >> KPositionUpperLeft ) & 1 ) + ( ( i >> KPositionUpperRight ) & 1 ) + 
                      ( ( i >> KPositionLowerLeft ) & 1 ) + ( ( i >> KPositionLowerRight ) & 1 ) );

        if ( sh == 2 )
            {
            ctxt = 10;
            }
        else if ( sh == 1 )
            {
            if ( sv )
                {
                ctxt = 9;
                }
            else if ( sd )
                {
                ctxt = 8;
                }
            else
                {
                ctxt = 7;
                }
            }
        else
            {
            if ( sv )
                {
                ctxt = 4 + sv;
                }
            else
                {
                ctxt = 2 + ( ( sd > 2 ) ? 2 : sd );
                }
            }

        iZcLutLLPtr[i] = (TUint8) ctxt;


        if ( sv == 2 )
            {
            ctxt = 10;
            }
        else if ( sv == 1 )
            {
            if ( sh )
                {
                ctxt = 9;
                }
            else if ( sd )
                {
                ctxt = 8;
                }
            else
                {
                ctxt = 7;
                }
            }
        else
            {
            if ( sh )
                {
                ctxt = 4 + sh;
                }
            else
                {
                ctxt = 2 + ( ( sd > 2 ) ? 2 : sd );
                }
            }

        iZcLutHLPtr[i] = (TUint8) ctxt;
    
        if ( sd >= 3 )
            {
            ctxt = 10;
            }
        else if ( sd == 2 )
            {
            if ( ( sv + sh ) >= 1 )
                {
                ctxt = 9;
                }
            else
                {
                ctxt = 8;
                }
            }
        else if ( sd == 1 )
            {
            ctxt = 5 + ( ( ( sv + sh ) > 2 ) ? 2 : ( sv + sh ) );
            }
        else
            {
            ctxt = 2 + ( ( ( sv + sh ) > 2 ) ? 2 : ( sv + sh ) );
            }
    
        iZcLutHHPtr[i] = (TUint8) ctxt;
        } 
    }

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::InitializeScMrLut
// Initialize SC/MR lookup table
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CJ2kEntropyDecoder::InitializeScMrLut()
    {
    TInt32 ctxt = 0; 
    TInt32 vpos = 0;    // vert +
    TInt32 vneg = 0;    // vert -
    TInt32 hpos = 0;    // hor +
    TInt32 hneg = 0;    // hor -
    TInt32 hc = 0;      // horizontal contribution
    TInt32 vc = 0;      // vertical contribution
    TInt16 predict = 0; // the xor bit for differentiating states. ( positioned at the 6th bit )

    for ( TUint8 i = 0; i < 16; i++ )
        {
        vpos = i & 1;
        vneg = ( i >> 1 ) & 1;
        hpos = ( i >> 2 ) & 1;
        hneg = ( i >> 3 ) & 1;
        hc = hpos - hneg;
        vc = vpos - vneg;
        predict = 0;
        if ( hc < 0 )
            {
            predict = 1;
            hc = -hc;
            vc = -vc;
            }
        if ( hc == 0 )
            {
            if ( vc < 0 )
                {
                predict = 1;
                vc = -vc;
                }
            ctxt = 11 + vc;
            }
        else
            {
            ctxt = 14 + vc;
            }

        iSCLut[i] = (TUint8) ( ctxt | ( predict << KPredictionBit ) );
        }
    iMRLut[0] = 16;
    iMRLut[1] = 17;
    iMRLut[2] = 18;
    }

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::GetCausal
// Get the casual
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CJ2kEntropyDecoder::GetCausal( TPrecInt*& aDataCol, TInt16*& aStateCol )
    {
    TInt32 vpos = 0;
    TInt32 vneg = 0;
    TUint16 state = 0;
    TInt16 causalityMask = 0;

    aDataCol--;
    for ( TInt32 col = iStateWidth; col > 0; col-- )
        {
        state = *aStateCol;
        vpos = 0;
        vneg = 0;
        if ( ( ( state >> KPositionDown ) & 1 ) == 1 )
            {
            if ( ( ( state >> KPositionUp ) & 1 ) == 1 )
                {
                if ( col < iStateWidth )
                    {
                    if ( *aDataCol >= 0 )
                        {
                        vneg = 1;
                        }
                    else
                        {
                        vpos = 1;
                        }
                    }
                }
            else
                { 
                vpos = 1;
                vneg = 1;
                }
            }
        causalityMask = (TInt16)( ~( ( KStateDown| KStateLowerLeft | KStateLowerRight ) | 
                                     ( vneg << KPositionVerNeg ) | ( vpos << KPositionVerPos ) ) );

        ( *aStateCol ) &= causalityMask;
        aDataCol++;
        aStateCol++;
        }
    }

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::DecodeSignificance
// Decode the significance bit
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CJ2kEntropyDecoder::DecodeSignificance( TPrecInt*& aDataValue, TInt16*& aStateValue, TPrecInt aMask )
    {
    TUint32 state = *aStateValue;
    TInt32 context = state & KZcMask;
    if ( ( state & KStateSignificant ) == 0 && context > 0 )
        { 
        if ( iMQDecoder.MqDecodeSymbol( iCurrentZcLutPtr[context] ) != 0 )
            {
            TUint32 ctxt = iSCLut[( state >> KScShift ) & KScLutMask];
            TInt32 symbol = iMQDecoder.MqDecodeSymbol( ( ctxt & KScLutMask ) ) ^ ( ( ctxt >> KPredictionBit ) & 1 );
            *aDataValue = ( symbol << KSignShift ) | aMask;
            *aStateValue |= KStateSignificant | KStateVisited;
            UpdateSignificance( aStateValue, symbol );
            }
        else
            {
            ( *aStateValue ) |= KStateVisited;
            }
        }
    }

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::DecodeRawSignificance
// Decode the lazy significance bit
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CJ2kEntropyDecoder::DecodeRawSignificance( TPrecInt*& aDataValue, TInt16*& aStateValue, TPrecInt aMask )
    {
    TInt32 state = *aStateValue;
    if ( ( state & KStateSignificant ) == 0 && ( state & KZcMask ) > 0 )
        { 
        if ( iMQDecoder.iInputStream.ReadBitFromStream() )
            {
            TInt32 symbol = iMQDecoder.iInputStream.ReadBitFromStream();
            *aDataValue = ( symbol << KSignShift ) | aMask;
            *aStateValue |= KStateSignificant | KStateVisited;
            UpdateSignificance( aStateValue, symbol );
            }
        else
            {
            ( *aStateValue ) |= KStateVisited;
            }
        }
    }

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::DecodeRefinement
// Decode the refinement bit
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CJ2kEntropyDecoder::DecodeRefinement( TPrecInt*& aDataValue, TInt16*& aStateValue, 
                                           TPrecInt aMask, TInt32 aResetMask )
    {
    TInt32 state = *aStateValue;
    if ( ( state & ( KStateSignificant | KStateVisited ) ) == KStateSignificant )
        {
        TInt16 mrContext = (TInt16)( state & KStatePreviousMR );
        TInt32 ctxt = 0;
        if ( mrContext )
            {
            ctxt = 2;
            }
        else
            {
            if ( ( state & KZcMask ) == 0 )
                {
                ctxt = 0;
                }
            else
                {
                ctxt = 1;
                }
            } 
        TInt32 symbol = iMQDecoder.MqDecodeSymbol( iMRLut[ctxt] );
        ( *aDataValue ) &= aResetMask;
        ( *aDataValue ) |= ( symbol << iCurrentBitplane ) | aMask;
        ( *aStateValue ) |= KStatePreviousMR;
        }
    }

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::DecodeRawRefinement
// Decode the lazy refinement bit
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CJ2kEntropyDecoder::DecodeRawRefinement( TPrecInt*& aDataValue, TInt16*& aStateValue, 
                                              TPrecInt aMask, TInt32 aResetMask )
    {
    if ( ( ( *aStateValue ) & ( KStateSignificant | KStateVisited ) ) == KStateSignificant )
        {
        TInt32 symbol = iMQDecoder.iInputStream.ReadBitFromStream();
        ( *aDataValue ) &= aResetMask;
        ( *aDataValue ) |= ( symbol << iCurrentBitplane ) | aMask;
        ( *aStateValue ) |= KStatePreviousMR;
        }
    }

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::DecodeNormalization
// Perform the normalization
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CJ2kEntropyDecoder::DecodeNormalization( TPrecInt*& aDataValue, TInt16*& aStateValue, 
                                              TPrecInt aMask, TInt32& aZCValue )
    {
    TUint32 state = *aStateValue;
    if ( state < (TUint32)KStateVisited )
        {
        TInt32 symbol = 0;
        TUint32 ctxt = 0;
        if ( aZCValue == 1 )
            {
            ( *aStateValue ) &= ~KStateVisited;
            if ( iMQDecoder.MqDecodeSymbol( iCurrentZcLutPtr[state & KZcMask] ) != 0 )
                {
                ctxt = iSCLut[( state >> KScShift ) & KScLutMask];
                symbol = iMQDecoder.MqDecodeSymbol( ( ctxt & KScLutMask ) ) ^( ( ctxt >> KPredictionBit ) & 1 );
                ( *aDataValue ) = ( symbol << KSignShift ) | aMask;
                ( *aStateValue ) |= KStateSignificant;
                UpdateSignificance( aStateValue, symbol );
                aZCValue = 1;
                }
            }
        else
            {
            ctxt = iSCLut[( state >> KScShift ) & KScLutMask];
            symbol = iMQDecoder.MqDecodeSymbol( ( ctxt & KScLutMask ) ) ^ ( ( ctxt >> KPredictionBit ) & 1 );
            ( *aDataValue ) = ( symbol << KSignShift ) | aMask;
            ( *aStateValue ) |= KStateSignificant; \
            UpdateSignificance( aStateValue, symbol );
            aZCValue = 1; 
            }
        } 
    else
        {
        ( *aStateValue ) &= ( ~KStateVisited );
        }
    }

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::UpdateSignificance
// Update the significance
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CJ2kEntropyDecoder::UpdateSignificance( TInt16*& aStateValue, TInt32 aSymbol )
    {
    TInt16* u = ( aStateValue ) - ( iStateWidth );
    TInt16* d = ( aStateValue ) + ( iStateWidth );
    u[-1] |= KStateLowerRight;
    u[1] |= KStateLowerLeft;
    d[-1] |= KStateUpperRight;
    d[1] |= KStateUpperLeft;

    if ( aSymbol != 0 )
        {
        aStateValue[-1] |= KStateRight | KStateHorNegative;
        aStateValue[1] |= KStateLeft | KStateHorNegative;
        *d |= KStateUp | KStateVerNegative;
        *u |= KStateDown | KStateVerNegative;
        }
    else
        {
        aStateValue[-1] |= KStateRight | KStateHorPositive;
        aStateValue[1] |= KStateLeft | KStateHorPositive;
        *d |= KStateUp | KStateVerPositive;
        *u |= KStateDown | KStateVerPositive;
        }
    }

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::SignificancePass
// Perform the significance pass
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CJ2kEntropyDecoder::SignificancePass()
    {
    // Mask for the current bitplane is actually also an approximation of the 
    // lower bitplanes, i.e. mask might be 00001100 for the fourth bitplane instead
    // of 00001000, thus the data will be increased by the current bitplane and
    // half of the sum of the lower bitplanes.
    TPrecInt mask = ( 1 << iCurrentBitplane ) | ( 1 << ( iCurrentBitplane - 1 ) );
  
    TPrecInt* dataRow = &( iData[0][0] );
    TInt16*   stateRow = CONST_CAST( TInt16*, GetFirstStateRow(  ) );

    TPrecInt* dataCol = 0;
    TPrecInt* dataValue = 0; 
    TInt16*   stateCol = 0;
    TInt16*   stateValue = 0;
    
    // Column index in the stripe
    TInt32 col = 0; 
    TInt32 row = 0;

    // Code stripe by stripe
    for ( TInt32 s = iNumStripes - 1; s > 0; s-- )
        {
        // If using stripe causal context formation, reset necessary bits
        // in state of first line in next stripe ( not on last
        // stripe ).
        if ( iVerticalCausalContextUsed )
            {
            dataCol = dataRow + 2 * iBlockDataWidth;
            stateCol = stateRow + iStateSamplesPerStripe - iStateWidth - 1;
            GetCausal( dataCol, stateCol );
            }
  
        dataCol = dataRow;
        stateCol = stateRow;
    
        // Scan column by column in each stripe
        for ( col = iBlockWidth; col > 0; col--, dataCol++, stateCol++ )
            {
            stateValue = stateCol;
            dataValue = dataCol;

            for ( row = KStripeHeight; row > 0; row-- )
                {
                DecodeSignificance( dataValue, stateValue, mask );
                dataValue += iBlockDataWidth;
                stateValue += iStateWidth;
                }
            }

        dataRow += iDataSamplesPerStripe;
        stateRow += iStateSamplesPerStripe;
        }

    // Deal with the last stripe separately
    dataCol = dataRow;
    stateCol = stateRow;
    
    // Scan column by column in each stripe
    for ( col = iBlockWidth; col > 0; col--, dataCol++, stateCol++ )
        {
        stateValue = stateCol;
        dataValue = dataCol;

        for ( row = iLastStripeHeight; row > 0; row-- )
            {
            DecodeSignificance( dataValue, stateValue, mask );
            if ( row > 1 )
                {
                dataValue += iBlockDataWidth;
                }
            stateValue += iStateWidth;
            }
        }

    // If there is predictable termination, check for errors
    if ( iTerminateThisPass && iPredictableTerminationUsed )
        {
        iErrorState = iMQDecoder.MqCheckPrediction();
        }
  
    // Reset the MQ context states if we need to
    if ( iResetContexts )
        {
        iMQDecoder.ResetMqContexts();
        }
    }

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::LazySignificancePass
// Perform the lazy significance pass
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CJ2kEntropyDecoder::LazySignificancePass()
    {
    // Mask for the current bitplane 
    TPrecInt mask = ( 1 << iCurrentBitplane ) | ( 1 << ( iCurrentBitplane - 1 ) );
  
    TPrecInt* dataRow = &( iData[0][0] );
    TInt16*   stateRow = CONST_CAST( TInt16*, GetFirstStateRow() );
    TPrecInt* dataCol = 0;
    TPrecInt* dataValue = 0; 
    TInt16* stateCol = 0;
    TInt16* stateValue = 0;

    // Column index in the stripe
    TInt32 col = 0; 
    TInt32 row = 0;

    for ( TInt32 s = iNumStripes - 1; s > 0; s-- )
        {
        // If using stripe causal context formation, reset necessary bits
        // in state of first line in next stripe ( not on last
        // stripe ).
        if ( iVerticalCausalContextUsed )
            {
            dataCol = dataRow + 2 * iBlockDataWidth;
            stateCol = stateRow + iStateSamplesPerStripe - iStateWidth - 1;
            GetCausal( dataCol, stateCol );
            }

        // Scan column by column in each stripe
        dataCol = dataRow;
        stateCol = stateRow;
    
        // Scan column by column in each stripe 
        for ( col = iBlockWidth; col > 0; col--, dataCol++, stateCol++ )
            {
            stateValue = stateCol;
            dataValue = dataCol;

            for ( row = KStripeHeight; row > 0; row-- )
                {
                DecodeRawSignificance( dataValue, stateValue, mask );
                dataValue += iBlockDataWidth;
                stateValue += iStateWidth;
                }
            }
        dataRow += iDataSamplesPerStripe;
        stateRow += iStateSamplesPerStripe;
        }

    // Deal with the last stripe separately
    // Scan column by column in each stripe
    dataCol = dataRow;
    stateCol = stateRow;
  
    // Line index
    TInt32 l = 0;
    
    // Scan column by column in each stripe 
    for ( col = iBlockWidth; col > 0; col--, dataCol++, stateCol++ )
        {
        stateValue = stateCol;
        dataValue = dataCol;

        l = iLastStripeHeight;
        DecodeRawSignificance( dataValue, stateValue, mask );
        if ( --l <= 0 )
            {
            continue;   //lint !e960    Continue is OK, no need to go end of for.
            }
    
        dataValue += iBlockDataWidth;
        stateValue += iStateWidth;
        DecodeRawSignificance( dataValue, stateValue, mask );
        if ( --l <= 0 )
            {
            continue;   //lint !e960    Continue is OK, no need to go end of for.
            }
    
        dataValue += iBlockDataWidth;
        stateValue += iStateWidth;
        DecodeRawSignificance( dataValue, stateValue, mask );
        if ( --l <= 0 )
            {
            continue;   //lint !e960    Continue is OK, no need to go end of for.
            }
    
        dataValue += iBlockDataWidth;
        stateValue += iStateWidth;
        DecodeRawSignificance( dataValue, stateValue, mask );

        }
  
    // If there is predictable termination, check for errors 
    if ( iTerminateThisPass && iPredictableTerminationUsed )
        {
        iErrorState = iMQDecoder.iInputStream.CheckPrediction();
        }
    }

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::RefinementPass
// Perform the refinement pass
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CJ2kEntropyDecoder::RefinementPass()
    {
    // To reset the effects of the approximation done in significance and
    // normalization passes we have the resetmask.
    TInt32 resetMask = ( -1 ) << ( iCurrentBitplane + 1 );
    TUint32 mask = ( ( TUint32 )( 1 << iCurrentBitplane ) ) >> 1;
  
    TPrecInt* dataRow = &( iData[0][0] );
    TInt16*   stateRow = CONST_CAST( TInt16*, GetFirstStateRow() );

    TPrecInt* dataCol = 0;
    TPrecInt* dataValue = 0; 
    TInt16* stateCol = 0;
    TInt16* stateValue = 0;

    // Column index in the stripe
    TInt32 col = 0; 
    TInt32 row = 0;
  
    // Code stripe by stripe 
    for ( TInt32 s = iNumStripes - 1; s > 0; s-- )
        {
        // If using stripe causal context formation, reset necessary bits
        // in state of first line in next stripe ( not on last
        // stripe ).
        if ( iVerticalCausalContextUsed )
            {
            dataCol = dataRow + 2 * iBlockDataWidth;
            stateCol = stateRow + iStateSamplesPerStripe - iStateWidth - 1;
            GetCausal( dataCol, stateCol );
            }
    
        // Scan column by column in each stripe
        dataCol = dataRow;
        stateCol = stateRow;
    
        // Scan column by column in each stripe
        for ( col = iBlockWidth; col > 0; col--, dataCol++, stateCol++ )
            {
            dataValue  = dataCol;
            stateValue = stateCol;

            for ( row = KStripeHeight; row > 0; row-- )
                {
                DecodeRefinement( dataValue, stateValue, mask, resetMask );
                dataValue += iBlockDataWidth;
                stateValue += iStateWidth;
                }
            }
        dataRow += iDataSamplesPerStripe;
        stateRow += iStateSamplesPerStripe;
        }

    // Deal with the last stripe separately
    // Scan column by column in each stripe
    dataCol = dataRow;
    stateCol = stateRow;
  
    // Scan column by column in the last stripe
    for ( col = iBlockWidth; col > 0; col--, dataCol++, stateCol++ )
        {
        dataValue  = dataCol;
        stateValue = stateCol;

        for ( row = iLastStripeHeight; row > 0; row-- )
            {
            DecodeRefinement( dataValue, stateValue, mask, resetMask );
            if ( row > 1 )
                {
                dataValue += iBlockDataWidth;
                }
            stateValue += iStateWidth;
            }
        }
  
    // If there is predictable termination, check for errors 
    if ( iTerminateThisPass && iPredictableTerminationUsed )
        {
        iErrorState = iMQDecoder.MqCheckPrediction();
        }
  
    // Reset the MQ context states if we need to
    if ( iResetContexts )
        {
        iMQDecoder.ResetMqContexts();
        }
    }

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::LazyRefinementPass
// Perform the lazy refinement pass
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CJ2kEntropyDecoder::LazyRefinementPass()
    {  
    TInt32 resetMask = ( -1 ) << ( iCurrentBitplane + 1 );
    TUint32 mask = ( ( TUint32 )( 1 << iCurrentBitplane ) ) >> 1;
    TPrecInt* dataRow = &( iData[0][0] );
    TInt16*   stateRow = CONST_CAST( TInt16*, GetFirstStateRow() );
    TPrecInt* dataCol = 0;
    TPrecInt* dataValue = 0; 
    TInt16* stateCol = 0;
    TInt16* stateValue = 0;

    // Column index in the stripe
    TInt32 col = 0; 
    TInt32 row = 0;

    // Code stripe by stripe
    for ( TInt32 s = iNumStripes - 1; s > 0; s-- )
        {
        // If using stripe causal context formation, reset necessary bits
        // in state of first line in next stripe ( not on last
        // stripe ).
        if ( iVerticalCausalContextUsed )
            {
            dataCol = dataRow + 2 * iBlockDataWidth;
            stateCol = stateRow + iStateSamplesPerStripe - iStateWidth - 1;
            GetCausal( dataCol, stateCol );
            }
    
        // Scan column by column in each stripe
        dataCol = dataRow;
        stateCol = stateRow;
    
        // Scan column by column in each stripe
        for ( col = iBlockWidth; col > 0; col--, dataCol++, stateCol++ )
            {
            dataValue  = dataCol;
            stateValue = stateCol;
            for ( row = KStripeHeight; row > 0; row-- )
                {
                DecodeRawRefinement( dataValue, stateValue, mask, resetMask );
                dataValue += iBlockDataWidth;
                stateValue += iStateWidth;
                }
            }
        dataRow += iDataSamplesPerStripe;
        stateRow += iStateSamplesPerStripe;
        }

    // Deal with the last stripe separately
    // Scan column by column in each stripe
    dataCol = dataRow;
    stateCol = stateRow;
  
    // Scan column by column in each stripe
    for ( col = iBlockWidth; col > 0; col--, dataCol++, stateCol++ )
        {
        dataValue  = dataCol;
        stateValue = stateCol;

        for ( row = iLastStripeHeight; row > 0; row-- )
            {
            DecodeRawRefinement( dataValue, stateValue, mask, resetMask );
            dataValue += iBlockDataWidth;
            stateValue += iStateWidth;
            }
        stateValue = stateCol;
        dataValue = dataCol;
        }
  
    // If there is predictable termination, check for errors
    if ( iTerminateThisPass && iPredictableTerminationUsed )
        {
        iErrorState = iMQDecoder.iInputStream.CheckPrediction();
        }

    // Because this is always terminated, reset stream
    iMQDecoder.iInputStream.ResetInputStream();
    }

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::CleanupPass
// Perform the cleanup pass
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CJ2kEntropyDecoder::CleanupPass( TUint8 aSegSymbols )
    {
    TInt32 zcCoding = 0;

    // Symbol to be coded 
    TInt32 symbol = 0;   
  
    TPrecInt mask = ( 1 << iCurrentBitplane ) | ( 1 << ( iCurrentBitplane - 1 ) );
  
    TPrecInt* dataRow = &( iData[0][0] );
    TInt16* stateRow = CONST_CAST( TInt16*, GetFirstStateRow() );
    TPrecInt* dataCol = 0;
    TPrecInt* dataValue = 0; 
    TInt16* stateCol = 0;
    TInt16* stateValue = 0;

    // Column index in the stripe
    TInt32 col = 0; 
    TInt32 row = 0;

    // Code stripe by stripe
    for ( TInt32 s = iNumStripes - 1; s > 0; s-- )
        {
        // If using stripe causal context formation, reset necessary bits
        // in state of first line in next stripe 
        if ( iVerticalCausalContextUsed )
            {
            dataCol = dataRow + 2 * iBlockDataWidth;
            stateCol = stateRow + iStateSamplesPerStripe - iStateWidth - 1;
            GetCausal( dataCol, stateCol );
            }
    
        // Scan column by column in each stripe
        dataCol = dataRow;
        stateCol = stateRow;
    
        for ( col = iBlockWidth; col > 0; col--, dataCol++, stateCol++ )
            {
            stateValue = stateCol;
            dataValue = dataCol;

            // If sample is insignificant and not yet visited in the
            // current bitplane, then apply the normalization pass
            if ( ( *stateValue == 0 ) &&
                ( stateValue += iStateWidth, ( *stateValue ) == 0 ) &&    //lint !e960    Comma is OK.
                ( stateValue += iStateWidth, ( *stateValue ) == 0 ) &&    //lint !e960    Comma is OK.
                ( stateValue += iStateWidth, ( *stateValue ) == 0 ) )      //lint !e960    Comma is OK.
                {
                // Use RLC
                if ( iMQDecoder.MqDecodeSymbol( KRlcContext ) != 0 ) //some sample( s ) not zero
                    {
                    // Decode the symbol most significant bit first 
                    symbol  = (TUint8)( iMQDecoder.MqDecodeSymbol( KUniformContext ) << 1 );    // MSB 
                    symbol |= (TUint8)( iMQDecoder.MqDecodeSymbol( KUniformContext ) & 0x01 );  // LSB
          
                    // Update data and state pointers
                    stateValue = stateCol + symbol * iStateWidth;
                    dataValue  = dataCol + symbol * iBlockDataWidth;

                    // Set zcCoding flag to zero 
                    zcCoding = 0;
                    row = KStripeHeight - symbol;
                    }
                else // All samples zero 
                    {
                    // Move to next column
                    continue;   //lint !e960    Continue is OK, no need to go end of for.
                    }
                }
            else  // No RLC used 
                {
                stateValue = stateCol;

                // Set zcCoding flag to one
                zcCoding = 1;
                row = KStripeHeight;
                }

            for ( ; row > 0; row-- )
                {
                DecodeNormalization( dataValue, stateValue, mask, zcCoding );
                dataValue += iBlockDataWidth;
                stateValue += iStateWidth;
                }
            }
        dataRow += iDataSamplesPerStripe;
        stateRow += iStateSamplesPerStripe;
        }
  
    // Deal with last stripe separately
    // Scan column by column in each stripe
    dataCol = dataRow;
    stateCol = stateRow;
  
    // Scan column by column in each stripe
    for ( col = iBlockWidth; col > 0; col--, stateCol++, dataCol++ )
        {
        stateValue = stateCol;
        dataValue = dataCol;

        // If sample is insignificant and not yet visited in the
        // current bitplane, then apply the normalization pass
        if( ( iLastStripeHeight == KStripeHeight ) && ( *stateValue ==0 ) &&
           ( stateValue += iStateWidth, ( *stateValue ) == 0 ) &&    //lint !e960    Comma is OK.
           ( stateValue += iStateWidth, ( *stateValue ) == 0 ) &&    //lint !e960    Comma is OK.
           ( stateValue += iStateWidth, ( *stateValue ) == 0 ) )      //lint !e960    Comma is OK.
            {
            // Use RLC:
            if ( iMQDecoder.MqDecodeSymbol( KRlcContext ) != 0 )  //some sample( s ) not zero
                {
                // Decode the symbol most significant bit first
                symbol  = ( TUint8 )( iMQDecoder.MqDecodeSymbol( KUniformContext ) << 1 );   // MSB 
                symbol |= ( TUint8 )( iMQDecoder.MqDecodeSymbol( KUniformContext ) & 0x01 ); // LSB 
        
                // Update data and state pointers 
                stateValue = stateCol + symbol * iStateWidth;
                dataValue  = dataCol + symbol * iBlockDataWidth;

                // Set zcCoding flag to zero
                zcCoding = 0;
                row = KStripeHeight - symbol;
                }
            else   // All samples zero
                {
                // Move to next column
                continue;      //lint !e960    Continue is OK, no need to go end of for.
                }
            }
        else  // No RLC used 
            {
            row = iLastStripeHeight;
            stateValue = stateCol;

            // Set zcCoding flag to one 
            zcCoding = 1;
            }

        for ( ; row > 0; row-- )
            {
            DecodeNormalization( dataValue, stateValue, mask, zcCoding );
            if ( row > 1 )
                {
                dataValue += iBlockDataWidth;
                }
            stateValue += iStateWidth;
            }
        }
  
    // Decode a segment marker if we need to
    if ( aSegSymbols )
        {
        symbol  = (TUint8)( iMQDecoder.MqDecodeSymbol( KUniformContext ) << 3 );
        symbol |= (TUint8)( iMQDecoder.MqDecodeSymbol( KUniformContext ) << 2 );
        symbol |= (TUint8)( iMQDecoder.MqDecodeSymbol( KUniformContext ) << 1 );
        symbol |= (TUint8)( iMQDecoder.MqDecodeSymbol( KUniformContext ) );

        if ( symbol != KSegmentationMarker )
            {
            iErrorState = EEntropyCodingError;
            }
        } 
  
    // If there is predictable termination, check for errors 
    if ( iTerminateThisPass && iPredictableTerminationUsed )
        {
        iErrorState = iMQDecoder.MqCheckPrediction();
        }
  
    // Reset the MQ context states if we need to
    if ( iResetContexts )
        {
        iMQDecoder.ResetMqContexts();
        }
    }

// -----------------------------------------------------------------------------
// CJ2kEntropyDecoder::GetFirstStateRow
// Get the first state row
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
const TInt16* CJ2kEntropyDecoder::GetFirstStateRow() const
    {
    return iStates + ( iStateWidth + 1 );
    }