imagingmodules/jp2kcodec/Src/JP2KImageInfo.cpp
changeset 0 469c91dae73b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/imagingmodules/jp2kcodec/Src/JP2KImageInfo.cpp	Thu Dec 17 09:22:31 2009 +0200
@@ -0,0 +1,848 @@
+/*
+* 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:  CJ2kImageInfo class used to collect image related
+*                information such as Main Header, SIZ marker and
+*                list of tiles. It's also implement the
+*                MJ2kPacketHeaderReader interface for reading the
+*                packet header from PPM marker.
+*
+*/
+
+
+// INCLUDE FILES
+#include <icl/imagecodec.h>
+#include "JP2KImageUtils.h"
+#include "JP2KFormat.h"
+#include "JP2KStreamReader.h"
+#include "JP2KTileInfo.h"
+#include "JP2KImageInfo.h"
+#include "JP2KCodec.h"
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES  
+
+// CONSTANTS
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+
+// FORWARD DECLARATIONS
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::CJ2kImageInfo
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CJ2kImageInfo::CJ2kImageInfo() : 
+    iLastTilePartProcessed( -1 )
+    {
+    }
+
+// Destructor
+CJ2kImageInfo::~CJ2kImageInfo()
+    {
+    delete iTile;
+    iTile= 0;
+
+    delete iPpm;
+    iPpm = 0;
+
+    // iPpmBuffer not owned.    
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::AppendCOCL
+// Verify and append COC to the main header
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kImageInfo::AppendCOCL( TCOCMarker *aMarker )
+    {
+    for ( TUint16 index = 0; index < iMainMarker.iCoc.Count(); ++index )
+        {
+        if ( iMainMarker.iCoc[index]->iCcoc == aMarker->iCcoc )
+            {
+            // No more than one COC per component
+           delete aMarker;
+           aMarker = 0;
+
+           return;
+            }
+        }
+    User::LeaveIfError( iMainMarker.iCoc.Append( aMarker ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::AppendQCCL
+// Verify and append QCC to the main header
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kImageInfo::AppendQCCL( TQCCMarker *aMarker )
+    {
+    for ( TUint16 index = 0; index < iMainMarker.iQcc.Count(); ++index )
+        {
+        if ( iMainMarker.iQcc[index]->iCqcc == aMarker->iCqcc )
+            {
+            // No more than one QCC per component
+            delete aMarker;
+            aMarker = 0;
+
+            return;
+            }
+        }
+    User::LeaveIfError( iMainMarker.iQcc.Append( aMarker ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::AppendRGNL
+// Verify and append RGN to the main header
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kImageInfo::AppendRGNL( TRGNMarker *aMarker )
+    {
+    for ( TUint16 index = 0; index < iMainMarker.iRgn.Count(); ++index )
+        {
+        if ( iMainMarker.iRgn[index]->iCrgn == aMarker->iCrgn )
+            {
+            // no more than one RGN per component
+            delete aMarker;
+            aMarker = 0;
+
+            return;
+            }
+        }
+    User::LeaveIfError( iMainMarker.iRgn.Append( aMarker ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::AppendPOCL
+// Verify and append POC to the main header
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kImageInfo::AppendPOCL( TPOCMarker *aMarker )
+    {
+    if ( iMainMarker.iPoc == 0 )
+        {
+        iMainMarker.iPoc = aMarker;
+        }
+    else
+        {
+        // Appending the content of the POC to the
+        // existing main header POC
+        for ( TInt index = 0; index < aMarker->iPpoc.Count(); ++index )
+            {
+            User::LeaveIfError( iMainMarker.iPoc->iRSpoc.Append( aMarker->iRSpoc[index] ) );
+            User::LeaveIfError( iMainMarker.iPoc->iCSpoc.Append( aMarker->iCSpoc[index] ) );
+            User::LeaveIfError( iMainMarker.iPoc->iLYEpoc.Append( aMarker->iLYEpoc[index] ) );
+            User::LeaveIfError( iMainMarker.iPoc->iREpoc.Append( aMarker->iREpoc[index] ) );
+            User::LeaveIfError( iMainMarker.iPoc->iCEpoc.Append( aMarker->iCEpoc[index] ) );
+            User::LeaveIfError( iMainMarker.iPoc->iPpoc.Append( aMarker->iPpoc[index] ) );
+            }
+        // At most one POC may exist in main header
+        delete aMarker;
+        aMarker = 0;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::AppendCRGL
+// Verify and append CRG to the main header
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kImageInfo::AppendCRGL( TCRGMarker *aMarker )
+    {
+    if ( iMainMarker.iCrg == 0 )
+        {
+        iMainMarker.iCrg = aMarker;
+        }
+    else
+        {
+        // Appending the content of the CRG to the
+        // existing main header CRG
+        for ( TInt index = 0; index < aMarker->iXYcrg.Count(); ++index )
+            {
+            User::LeaveIfError( iMainMarker.iCrg->iXYcrg.Append( aMarker->iXYcrg[index] ) );
+            }
+        // At most one CRG may exist in main header
+        delete aMarker;
+        aMarker = 0;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::AppendCOML
+// Verify and append COM to the main header
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kImageInfo::AppendCOML( const TCOMMarker *aMarker )
+    {
+    User::LeaveIfError( iMainMarker.iCom.Append( aMarker ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::GetCodingStyle
+// Retrieve the right Coding Style Marker
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kImageInfo::GetCodingStyle( TCODMarker*& aCod, TCOCMarker*& aCoc,
+                                    const CJ2kTileInfo& aTile, TUint16 aComponentIndex )
+    {
+    // Tile part COC > tile part COD > main header COC > main header COD
+    aCod = 0;
+    aCoc = 0;
+    TUint16 index = 0;
+    TUint16 cocCount = 0;
+    const TTileMarker &tileMarker = aTile.TileMarker();
+
+    cocCount = (TUint16)tileMarker.iCoc.Count();
+    if ( cocCount )
+        {
+        for ( index = 0; index < cocCount; ++index )
+            {
+            if ( tileMarker.iCoc[index]->iCcoc == aComponentIndex )
+                {
+                aCoc = tileMarker.iCoc[index];
+                return;
+                }
+            }
+        }
+    if ( tileMarker.iCod )
+        {
+        aCod = tileMarker.iCod;
+        return;
+        }
+
+    cocCount = (TUint16)iMainMarker.iCoc.Count();
+    if ( cocCount )
+        {
+        for ( index = 0; index < cocCount; ++index )
+            {
+            if ( iMainMarker.iCoc[index]->iCcoc == aComponentIndex )
+                {
+                aCoc = iMainMarker.iCoc[index];
+                return;
+                }
+            }
+        }
+    aCod = &iMainMarker.iCod;
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::GetQuantization
+// Retrieve the right Quantization Marker
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kImageInfo::GetQuantization( TQCDMarker*& aQcd, TQCCMarker*& aQcc,
+                                     const CJ2kTileInfo& aTile, TUint16 aComponentIndex )
+    {
+    // Tile part QCC > tile part QCD > main header QCC > main header QCD
+    aQcd = 0;
+    aQcc = 0;
+    TUint16 index = 0;
+    TUint16 qccCount = 0;
+    const TTileMarker &tileMarker = aTile.TileMarker();
+
+    qccCount = (TUint16)tileMarker.iQcc.Count();
+    if ( qccCount )
+        {
+        for ( index = 0; index < qccCount; ++index )
+            {
+            if ( tileMarker.iQcc[index]->iCqcc == aComponentIndex )
+                {
+                aQcc = tileMarker.iQcc[index];
+                return;
+                }
+            }
+        }
+    if ( tileMarker.iQcd )
+        {
+        aQcd = tileMarker.iQcd;
+        return;
+        }
+
+    qccCount = (TUint16)iMainMarker.iQcc.Count();
+    if ( qccCount )
+        {
+        for ( index = 0; index < qccCount; ++index )
+            {
+            if ( iMainMarker.iQcc[index]->iCqcc == aComponentIndex )
+                {
+                aQcc = iMainMarker.iQcc[index];
+                return;
+                }
+            }
+        }
+    aQcd = &iMainMarker.iQcd;
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::GetRegion
+// Retrieve the right Region of Interest Marker
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kImageInfo::GetRegion( TRGNMarker*& aRgn, const CJ2kTileInfo& aTile, TUint16 aComponentIndex ) const
+    {
+    // Tile part RGN > main header RGN
+    aRgn = 0;
+    TUint16 index = 0;
+    TUint16 rgnCount = 0;
+    const TTileMarker &tileMarker = aTile.TileMarker();
+
+    rgnCount = (TUint16)tileMarker.iRgn.Count();
+    if ( rgnCount )
+        {
+        for ( index = 0; index < rgnCount; ++index )
+            {
+            if ( tileMarker.iRgn[index]->iCrgn == aComponentIndex )
+                {
+                aRgn = tileMarker.iRgn[index];
+                return;
+                }
+            }
+        }
+
+    rgnCount = (TUint16)iMainMarker.iRgn.Count();
+    if ( rgnCount )
+        {
+        for ( index = 0; index < rgnCount; ++index )
+            {
+            if ( iMainMarker.iRgn[index]->iCrgn == aComponentIndex )
+                {
+                aRgn = iMainMarker.iRgn[index];
+                return;
+                }
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::GetFromTLM
+// Retrieve the tile length field from TLM marker
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kImageInfo::GetFromTLM( TSotMarker& aSotMarker ) const
+    {
+    TTLMMarker* tlm = 0;
+    TUint16     tileIndex = 0;
+    TUint16     dIndex = 0;
+
+    for ( TInt index = 0; index < iMainMarker.iTlm.Count(); ++index )
+        {
+        tlm = iMainMarker.iTlm[index];
+        dIndex = 0;
+        if ( tlm->iTtlm.Count() == 0 )
+            {
+            // One tile-part per tile and the tiles are
+            // in index order without omission or repetition
+            while ( dIndex < tlm->iPtlm.Count() )
+                {
+                if ( dIndex == aSotMarker.iIsot )
+                    {
+                    aSotMarker.iPsot = tlm->iPtlm[dIndex];
+                    return;
+                    }
+                ++dIndex;
+                }
+            }
+        else
+            {
+            while ( dIndex < tlm->iTtlm.Count() )
+                {
+                // Looking for the right tile
+                if ( tlm->iTtlm[dIndex] == aSotMarker.iIsot )
+                    {
+                    // Looking for the right tile-part
+                    if ( tileIndex == aSotMarker.iTPsot )
+                        {
+                        aSotMarker.iPsot = tlm->iPtlm[dIndex];
+                        return;
+                        }
+                    ++tileIndex;
+                    }
+                ++dIndex;
+                }
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::UsePPM
+// Set up to read the packet header from the PPM marker
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kImageInfo::UsePPM( CJ2kTileInfo& aTile )
+    {
+    if ( iPpm->iPtr == iPpm->iPtrEnd )
+        {
+        iPpm->iPtr = 4;
+        iPpm->iPtrEnd = iPpm->iPtr + iMainMarker.iPpm[iLastTilePartProcessed]->iNppm;
+        iPpmBuffer = iMainMarker.iPpm[iLastTilePartProcessed]->iIppm;
+        }
+    aTile.SetPacketHeaderReader( this );
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::DoCompactMainHeaderL
+// Re-arrange the PPM and PLM buffers
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kImageInfo::DoCompactMainHeaderL()
+    {
+    RPointerArray<TPLMMarker>& plmList = iMainMarker.iPlm;
+    if ( plmList.Count() )
+        {
+        TPLMMarker *plmMarker = 0;
+        TPLMMarker *prevMarker = 0;
+        TUint8 checkNplm = ETrue;
+        TUint8 continuation = EFalse;
+        TUint8 length = 0;
+        const TUint8 *ptr = 0;
+        TUint32 remainder = 0;
+        TInt index = 0;
+
+        for ( index = 0; index < plmList.Count(); ++index )
+            {
+            plmMarker = plmList[index];
+            if ( checkNplm )
+                {
+                ptr = plmMarker->iIplm->Ptr();
+                length = *ptr;
+                if ( length != ( TUint8 )( plmMarker->iNplm - 1 ) )
+                    {
+                    // Incomplete PLM marker
+                    // there is a continuation of data in the next PLM marker
+                    // and concatenation is needed
+                    plmMarker->iIplm = plmMarker->iIplm->ReAllocL( length + 1 );
+                    remainder = (TUint32)( length - ( plmMarker->iNplm - 1 ) );
+                    plmMarker->iNplm = length;
+                    prevMarker = plmMarker;
+                    checkNplm = EFalse;
+                    }
+                else
+                    {
+                    // It is a complete PLM marker
+                    plmMarker->iNplm = length;
+                    }
+                }
+            else
+                {
+                // Concatenate with the previous PLM marker
+                continuation = ETrue;
+                TPtr8 previous = prevMarker->iIplm->Des();
+                previous.Append( plmMarker->iIplm->Ptr(), plmMarker->iNplm );
+                remainder = (TUint32)( remainder - plmMarker->iNplm );
+                plmMarker->iNplm = 0;
+                if ( remainder == 0 )
+                    {
+                    checkNplm = ETrue;
+                    }
+                }
+            }
+        if ( continuation )
+            {
+            index = 0;
+            while ( index < plmList.Count() )
+                {
+                plmMarker = plmList[index];
+                if ( plmMarker->iNplm )
+                    {
+                    ++index;
+                    }
+                else
+                    {
+                    // Remove PPM marker which has been concatenated
+                    plmList.Remove( index );
+                    delete plmMarker;
+                    }
+                }
+            }
+        // Do not use PLM segment.
+        plmList.ResetAndDestroy();
+        }
+
+    RPointerArray<TPPMMarker>& ppmList = iMainMarker.iPpm;
+    if ( ppmList.Count() > 0 )
+        {
+        iPpm = new ( ELeave ) TPPMStream;
+        Mem::FillZ( iPpm, sizeof( TPPMStream ) );
+
+        TPPMMarker *ppmMarker = 0;
+        TPPMMarker *prevMarker = 0;
+        TUint8  checkNppm = ETrue;
+        TUint8  continuation = EFalse;
+        const TUint8 *ptr = 0;
+        TUint32 length = 0;
+        TUint32 remainder = 0;
+        TInt index = 0;
+        TUint8 zppm = 0;
+
+        for ( index = 0; index < ppmList.Count(); ++index )
+            {
+            ppmMarker = ppmList[index];
+            if ( checkNppm )
+                {
+                ptr = ppmMarker->iIppm->Ptr();
+                length = PtrReadUtil::ReadBigEndianUint32( ptr );
+                if ( length != (TUint32)( ppmMarker->iNppm - 4 ) )
+                    {
+                    if ( length > (TUint32)( ppmMarker->iNppm - 4 ) )
+                        {
+                        // Incomplete PPM marker
+                        // there is a continuation of data in the next PPM marker
+                        // and concatenation is needed
+                        ppmMarker->iZppm = zppm++;
+                        ppmMarker->iIppm = ppmMarker->iIppm->ReAllocL( length + 4 );
+                        remainder = (TUint32)( length - ( ppmMarker->iNppm - 4 ) );
+                        ppmMarker->iNppm = length;
+                        prevMarker = ppmMarker;
+                        checkNppm = EFalse;
+                        }
+                    else
+                        {
+                        // We should split the PPM marker into smaller PPM marker
+                        TInt location = 0;
+                        ppmList.Remove( index );
+                        remainder = ppmMarker->iNppm;
+                        while ( remainder >= ( length + 4 ) )
+                            {
+                            prevMarker = new ( ELeave ) TPPMMarker;
+                            CleanupStack::PushL( prevMarker );
+
+                            prevMarker->iZppm = ( location ? (TUint8)0 : zppm++ );
+                            prevMarker->iNppm = length + ( location ? 4 : 0 );
+                            prevMarker->iIppm = HBufC8::NewL( length + 4 );
+                            prevMarker->iIppm->Des().Append( ptr, length + 4 );
+                            User::LeaveIfError( ppmList.Insert( prevMarker, index + location ) );
+                            CleanupStack::Pop();
+                            ++location;
+                            ptr += ( length + 4 );
+                            remainder -= ( length + 4 );
+                            if ( remainder > 4 )
+                                {
+                                length = PtrReadUtil::ReadBigEndianUint32( ptr );
+                                }
+                            else
+                                {
+                                length = 0;
+                                }
+                            }
+                        if ( remainder )
+                            {
+                            // Incomplete PPM marker
+                            prevMarker = new ( ELeave ) TPPMMarker;
+                            CleanupStack::PushL( prevMarker );
+
+                            prevMarker->iNppm = remainder;
+                            prevMarker->iIppm = HBufC8::NewL( remainder );
+                            prevMarker->iIppm->Des().Append( ptr, remainder );
+                            User::LeaveIfError( ppmList.Insert( prevMarker, index + location ) );
+                            CleanupStack::Pop();
+                            }
+                        delete ppmMarker;
+                        ppmMarker = 0;
+                        }
+                    }
+                else
+                    {
+                    // It is a complete PPM marker, adjust the Nppm to length
+                    ppmMarker->iZppm = zppm++;
+                    ppmMarker->iNppm = length;
+                    }
+                }
+            else
+                {
+                continuation = ETrue;
+                if ( ppmMarker->iNppm <= remainder )
+                    {
+                    // Concatenate with the previous PPM marker
+                    TPtr8 previous = prevMarker->iIppm->Des();
+                    previous.Append( ppmMarker->iIppm->Ptr(), ppmMarker->iNppm );
+                    remainder = ( TUint32 )( remainder - ppmMarker->iNppm );
+                    ppmMarker->iNppm = 0;
+                    if ( remainder == 0 )
+                        {
+                        checkNppm = ETrue;
+                        }
+                    }
+                else
+                    {
+                    checkNppm = ETrue;
+                    // Partially concatenate with the previous PPM marker
+                    TPtr8 previous = prevMarker->iIppm->Des();
+                    previous.Append( ppmMarker->iIppm->Ptr(), remainder );
+
+                    // We should split the PPM marker into smaller PPM marker
+                    TInt location = 0;
+                    ppmList.Remove( index );
+                    ptr = ppmMarker->iIppm->Ptr() + remainder;
+                    length = PtrReadUtil::ReadBigEndianUint32( ptr );
+                    remainder = ( TUint32 )( ppmMarker->iNppm - remainder );
+                    while ( remainder >= ( length + 4 ) )
+                        {
+                        prevMarker = new ( ELeave ) TPPMMarker;
+                        CleanupStack::PushL( prevMarker );
+
+                        prevMarker->iZppm = ( location ? (TUint8)0 : zppm++ );
+                        prevMarker->iNppm = length + ( location ? 4 : 0 );
+                        prevMarker->iIppm = HBufC8::NewL( length + 4 );
+                        prevMarker->iIppm->Des().Append( ptr, length + 4 );
+                        User::LeaveIfError( ppmList.Insert( prevMarker, index + location ) );
+                        CleanupStack::Pop();
+                        ++location;
+                        ptr += ( length + 4 );
+                        remainder -= ( length + 4 );
+                        if ( remainder > 4 )
+                            {
+                            length = PtrReadUtil::ReadBigEndianUint32( ptr );
+                            }
+                        else
+                            {
+                            length = 0;
+                            }
+                        }
+                    if ( remainder )
+                        {
+                        // Incomplete PPM marker
+                        prevMarker = new ( ELeave ) TPPMMarker;
+                        CleanupStack::PushL( prevMarker );
+
+                        prevMarker->iNppm = remainder;
+                        prevMarker->iIppm = HBufC8::NewL( remainder );
+                        prevMarker->iIppm->Des().Append( ptr, remainder );
+                        User::LeaveIfError( ppmList.Insert( prevMarker, index + location ) );
+                        CleanupStack::Pop();
+                        }
+                    delete ppmMarker;
+                    ppmMarker = 0; 
+                    }
+                }
+            }
+        if ( continuation )
+            {
+            index = 0;
+            while ( index < ppmList.Count() )
+                {
+                ppmMarker = ppmList[index];
+                if ( ppmMarker->iNppm )
+                    {
+                    ++index;
+                    }
+                else
+                    {
+                    // Remove PPM marker which has been concatenated
+                    ppmList.Remove( index );
+                    delete ppmMarker;
+                    ppmMarker = 0;
+                    }
+                }
+            }
+        }
+
+    // Do not use the COM segment at this release
+    if ( iMainMarker.iCom.Count() )
+        {
+        iMainMarker.iCom.ResetAndDestroy();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::IsPPM
+// Is packet header should be read from PPM marker
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUint8 CJ2kImageInfo::IsPPM() const
+    {
+    if ( iPpm )
+        {
+        if ( iPpm->iPtr < iPpm->iPtrEnd )
+            {
+            return ETrue;
+            }
+        else if ( iLastTilePartProcessed < iMainMarker.iPpm.Count() )
+            {
+            return ETrue;
+            }
+        else
+            {
+            return EFalse;
+            }
+        }
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::ReadEPHMarker
+// Try to consume the EPH marker if there is one.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUint8 CJ2kImageInfo::ReadEPHMarker()
+    {
+    if ( iPpm && ( iPpm->iPtrEnd - iPpm->iPtr ) >= 2 )
+        {
+        const TUint8 *ptr = iPpmBuffer->Ptr();
+        ptr += iPpm->iPtr;
+        if ( PtrReadUtil::ReadBigEndianUint16( ptr ) == KEPH )
+            {
+            iPpm->iPtr += 2;
+            }
+        }
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::ReadBit
+// Read a bit from the packet header stream.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUint8 CJ2kImageInfo::ReadBit( TUint8& aBit )
+    {
+    if ( iPpm->iPos == 0 )
+        {
+        if ( iPpm->iPtr < iPpm->iPtrEnd )
+            {
+            // Stream contains some packet header data
+            iPpm->iData = ( *iPpmBuffer )[iPpm->iPtr++];
+            iPpm->iPos = iPpm->iNextPos;
+            if ( iPpm->iNextPos == 0x08 && iPpm->iData == 0xff )
+                {
+                iPpm->iNextPos = 0x07;
+                }
+            else
+                {
+                iPpm->iNextPos = 0x08;
+                }
+            }
+        else
+            {
+            // No more data
+            return ETrue;
+            }
+        }
+    aBit = (TUint8)( ( iPpm->iData >> ( --iPpm->iPos ) ) & 0x01 );
+
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::ReadBits
+// Read some bits from the packet header stream.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUint8 CJ2kImageInfo::ReadBits( TUint8& aBit, TUint8 aBitLen )
+    {
+    aBit = (TUint8)0;
+    TUint8 bit;
+    for ( TInt8 index = (TInt8)( aBitLen - 1 ); index >= 0; --index )
+        {
+        if ( !ReadBit( bit ) )
+            {
+            aBit |= ( bit << index );
+            }
+        else
+            {
+            return ETrue;
+            }
+        }
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::ReadBits
+// Read some bits from the packet header stream.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUint8 CJ2kImageInfo::ReadBits( TUint32& aBit, TUint8 aBitLen )
+    {
+    aBit = (TUint32)0;
+    TUint8 bit = 0;
+    for ( TInt8 index = (TInt8)( aBitLen - 1 ); index >= 0; --index )
+        {
+        if ( !ReadBit( bit ) )
+            {
+            aBit |= ( bit << index );
+            }
+        else
+            {
+            return ETrue;
+            }
+        }
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::StartReadBit
+// Start reading from packet header stream.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUint8 CJ2kImageInfo::StartReadBit()
+    {
+    if ( iPpm && iPpm->iPtr < iPpm->iPtrEnd )
+        {
+        // Stream contains some packet header data
+        iPpm->iData = ( *iPpmBuffer )[iPpm->iPtr++];
+        iPpm->iPos = iPpm->iNextPos = 0x08;
+        if ( iPpm->iData == 0xff )
+            {
+            iPpm->iNextPos = 0x07;
+            }
+
+        return EFalse;
+        }
+    return ETrue;
+    }
+
+// -----------------------------------------------------------------------------
+// CJ2kImageInfo::AlignReader
+// Align the stream to the next byte boundary if necessary.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CJ2kImageInfo::AlignReader()
+    {
+    if ( iPpm->iNextPos == 0x07 )
+        {
+        if ( iPpm->iPtr < iPpm->iPtrEnd )
+            {
+            ++iPpm->iPtr;
+            }
+        }
+    iPpm->iData = iPpm->iPos = iPpm->iNextPos = 0;
+    }
+