imagingmodules/jp2kcodec/Src/JP2KImageInfo.cpp
changeset 0 469c91dae73b
equal deleted inserted replaced
-1:000000000000 0:469c91dae73b
       
     1 /*
       
     2 * Copyright (c) 2003, 2004 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  CJ2kImageInfo class used to collect image related
       
    15 *                information such as Main Header, SIZ marker and
       
    16 *                list of tiles. It's also implement the
       
    17 *                MJ2kPacketHeaderReader interface for reading the
       
    18 *                packet header from PPM marker.
       
    19 *
       
    20 */
       
    21 
       
    22 
       
    23 // INCLUDE FILES
       
    24 #include <icl/imagecodec.h>
       
    25 #include "JP2KImageUtils.h"
       
    26 #include "JP2KFormat.h"
       
    27 #include "JP2KStreamReader.h"
       
    28 #include "JP2KTileInfo.h"
       
    29 #include "JP2KImageInfo.h"
       
    30 #include "JP2KCodec.h"
       
    31 
       
    32 // EXTERNAL DATA STRUCTURES
       
    33 
       
    34 // EXTERNAL FUNCTION PROTOTYPES  
       
    35 
       
    36 // CONSTANTS
       
    37 
       
    38 // MACROS
       
    39 
       
    40 // LOCAL CONSTANTS AND MACROS
       
    41 
       
    42 // MODULE DATA STRUCTURES
       
    43 
       
    44 // LOCAL FUNCTION PROTOTYPES
       
    45 
       
    46 // FORWARD DECLARATIONS
       
    47 
       
    48 // ============================ MEMBER FUNCTIONS ===============================
       
    49 
       
    50 // -----------------------------------------------------------------------------
       
    51 // CJ2kImageInfo::CJ2kImageInfo
       
    52 // C++ default constructor can NOT contain any code, that
       
    53 // might leave.
       
    54 // -----------------------------------------------------------------------------
       
    55 //
       
    56 CJ2kImageInfo::CJ2kImageInfo() : 
       
    57     iLastTilePartProcessed( -1 )
       
    58     {
       
    59     }
       
    60 
       
    61 // Destructor
       
    62 CJ2kImageInfo::~CJ2kImageInfo()
       
    63     {
       
    64     delete iTile;
       
    65     iTile= 0;
       
    66 
       
    67     delete iPpm;
       
    68     iPpm = 0;
       
    69 
       
    70     // iPpmBuffer not owned.    
       
    71     }
       
    72 
       
    73 // -----------------------------------------------------------------------------
       
    74 // CJ2kImageInfo::AppendCOCL
       
    75 // Verify and append COC to the main header
       
    76 // (other items were commented in a header).
       
    77 // -----------------------------------------------------------------------------
       
    78 //
       
    79 void CJ2kImageInfo::AppendCOCL( TCOCMarker *aMarker )
       
    80     {
       
    81     for ( TUint16 index = 0; index < iMainMarker.iCoc.Count(); ++index )
       
    82         {
       
    83         if ( iMainMarker.iCoc[index]->iCcoc == aMarker->iCcoc )
       
    84             {
       
    85             // No more than one COC per component
       
    86            delete aMarker;
       
    87            aMarker = 0;
       
    88 
       
    89            return;
       
    90             }
       
    91         }
       
    92     User::LeaveIfError( iMainMarker.iCoc.Append( aMarker ) );
       
    93     }
       
    94 
       
    95 // -----------------------------------------------------------------------------
       
    96 // CJ2kImageInfo::AppendQCCL
       
    97 // Verify and append QCC to the main header
       
    98 // (other items were commented in a header).
       
    99 // -----------------------------------------------------------------------------
       
   100 //
       
   101 void CJ2kImageInfo::AppendQCCL( TQCCMarker *aMarker )
       
   102     {
       
   103     for ( TUint16 index = 0; index < iMainMarker.iQcc.Count(); ++index )
       
   104         {
       
   105         if ( iMainMarker.iQcc[index]->iCqcc == aMarker->iCqcc )
       
   106             {
       
   107             // No more than one QCC per component
       
   108             delete aMarker;
       
   109             aMarker = 0;
       
   110 
       
   111             return;
       
   112             }
       
   113         }
       
   114     User::LeaveIfError( iMainMarker.iQcc.Append( aMarker ) );
       
   115     }
       
   116 
       
   117 // -----------------------------------------------------------------------------
       
   118 // CJ2kImageInfo::AppendRGNL
       
   119 // Verify and append RGN to the main header
       
   120 // (other items were commented in a header).
       
   121 // -----------------------------------------------------------------------------
       
   122 //
       
   123 void CJ2kImageInfo::AppendRGNL( TRGNMarker *aMarker )
       
   124     {
       
   125     for ( TUint16 index = 0; index < iMainMarker.iRgn.Count(); ++index )
       
   126         {
       
   127         if ( iMainMarker.iRgn[index]->iCrgn == aMarker->iCrgn )
       
   128             {
       
   129             // no more than one RGN per component
       
   130             delete aMarker;
       
   131             aMarker = 0;
       
   132 
       
   133             return;
       
   134             }
       
   135         }
       
   136     User::LeaveIfError( iMainMarker.iRgn.Append( aMarker ) );
       
   137     }
       
   138 
       
   139 // -----------------------------------------------------------------------------
       
   140 // CJ2kImageInfo::AppendPOCL
       
   141 // Verify and append POC to the main header
       
   142 // (other items were commented in a header).
       
   143 // -----------------------------------------------------------------------------
       
   144 //
       
   145 void CJ2kImageInfo::AppendPOCL( TPOCMarker *aMarker )
       
   146     {
       
   147     if ( iMainMarker.iPoc == 0 )
       
   148         {
       
   149         iMainMarker.iPoc = aMarker;
       
   150         }
       
   151     else
       
   152         {
       
   153         // Appending the content of the POC to the
       
   154         // existing main header POC
       
   155         for ( TInt index = 0; index < aMarker->iPpoc.Count(); ++index )
       
   156             {
       
   157             User::LeaveIfError( iMainMarker.iPoc->iRSpoc.Append( aMarker->iRSpoc[index] ) );
       
   158             User::LeaveIfError( iMainMarker.iPoc->iCSpoc.Append( aMarker->iCSpoc[index] ) );
       
   159             User::LeaveIfError( iMainMarker.iPoc->iLYEpoc.Append( aMarker->iLYEpoc[index] ) );
       
   160             User::LeaveIfError( iMainMarker.iPoc->iREpoc.Append( aMarker->iREpoc[index] ) );
       
   161             User::LeaveIfError( iMainMarker.iPoc->iCEpoc.Append( aMarker->iCEpoc[index] ) );
       
   162             User::LeaveIfError( iMainMarker.iPoc->iPpoc.Append( aMarker->iPpoc[index] ) );
       
   163             }
       
   164         // At most one POC may exist in main header
       
   165         delete aMarker;
       
   166         aMarker = 0;
       
   167         }
       
   168     }
       
   169 
       
   170 // -----------------------------------------------------------------------------
       
   171 // CJ2kImageInfo::AppendCRGL
       
   172 // Verify and append CRG to the main header
       
   173 // (other items were commented in a header).
       
   174 // -----------------------------------------------------------------------------
       
   175 //
       
   176 void CJ2kImageInfo::AppendCRGL( TCRGMarker *aMarker )
       
   177     {
       
   178     if ( iMainMarker.iCrg == 0 )
       
   179         {
       
   180         iMainMarker.iCrg = aMarker;
       
   181         }
       
   182     else
       
   183         {
       
   184         // Appending the content of the CRG to the
       
   185         // existing main header CRG
       
   186         for ( TInt index = 0; index < aMarker->iXYcrg.Count(); ++index )
       
   187             {
       
   188             User::LeaveIfError( iMainMarker.iCrg->iXYcrg.Append( aMarker->iXYcrg[index] ) );
       
   189             }
       
   190         // At most one CRG may exist in main header
       
   191         delete aMarker;
       
   192         aMarker = 0;
       
   193         }
       
   194     }
       
   195 
       
   196 // -----------------------------------------------------------------------------
       
   197 // CJ2kImageInfo::AppendCOML
       
   198 // Verify and append COM to the main header
       
   199 // (other items were commented in a header).
       
   200 // -----------------------------------------------------------------------------
       
   201 //
       
   202 void CJ2kImageInfo::AppendCOML( const TCOMMarker *aMarker )
       
   203     {
       
   204     User::LeaveIfError( iMainMarker.iCom.Append( aMarker ) );
       
   205     }
       
   206 
       
   207 // -----------------------------------------------------------------------------
       
   208 // CJ2kImageInfo::GetCodingStyle
       
   209 // Retrieve the right Coding Style Marker
       
   210 // (other items were commented in a header).
       
   211 // -----------------------------------------------------------------------------
       
   212 //
       
   213 void CJ2kImageInfo::GetCodingStyle( TCODMarker*& aCod, TCOCMarker*& aCoc,
       
   214                                     const CJ2kTileInfo& aTile, TUint16 aComponentIndex )
       
   215     {
       
   216     // Tile part COC > tile part COD > main header COC > main header COD
       
   217     aCod = 0;
       
   218     aCoc = 0;
       
   219     TUint16 index = 0;
       
   220     TUint16 cocCount = 0;
       
   221     const TTileMarker &tileMarker = aTile.TileMarker();
       
   222 
       
   223     cocCount = (TUint16)tileMarker.iCoc.Count();
       
   224     if ( cocCount )
       
   225         {
       
   226         for ( index = 0; index < cocCount; ++index )
       
   227             {
       
   228             if ( tileMarker.iCoc[index]->iCcoc == aComponentIndex )
       
   229                 {
       
   230                 aCoc = tileMarker.iCoc[index];
       
   231                 return;
       
   232                 }
       
   233             }
       
   234         }
       
   235     if ( tileMarker.iCod )
       
   236         {
       
   237         aCod = tileMarker.iCod;
       
   238         return;
       
   239         }
       
   240 
       
   241     cocCount = (TUint16)iMainMarker.iCoc.Count();
       
   242     if ( cocCount )
       
   243         {
       
   244         for ( index = 0; index < cocCount; ++index )
       
   245             {
       
   246             if ( iMainMarker.iCoc[index]->iCcoc == aComponentIndex )
       
   247                 {
       
   248                 aCoc = iMainMarker.iCoc[index];
       
   249                 return;
       
   250                 }
       
   251             }
       
   252         }
       
   253     aCod = &iMainMarker.iCod;
       
   254     }
       
   255 
       
   256 // -----------------------------------------------------------------------------
       
   257 // CJ2kImageInfo::GetQuantization
       
   258 // Retrieve the right Quantization Marker
       
   259 // (other items were commented in a header).
       
   260 // -----------------------------------------------------------------------------
       
   261 //
       
   262 void CJ2kImageInfo::GetQuantization( TQCDMarker*& aQcd, TQCCMarker*& aQcc,
       
   263                                      const CJ2kTileInfo& aTile, TUint16 aComponentIndex )
       
   264     {
       
   265     // Tile part QCC > tile part QCD > main header QCC > main header QCD
       
   266     aQcd = 0;
       
   267     aQcc = 0;
       
   268     TUint16 index = 0;
       
   269     TUint16 qccCount = 0;
       
   270     const TTileMarker &tileMarker = aTile.TileMarker();
       
   271 
       
   272     qccCount = (TUint16)tileMarker.iQcc.Count();
       
   273     if ( qccCount )
       
   274         {
       
   275         for ( index = 0; index < qccCount; ++index )
       
   276             {
       
   277             if ( tileMarker.iQcc[index]->iCqcc == aComponentIndex )
       
   278                 {
       
   279                 aQcc = tileMarker.iQcc[index];
       
   280                 return;
       
   281                 }
       
   282             }
       
   283         }
       
   284     if ( tileMarker.iQcd )
       
   285         {
       
   286         aQcd = tileMarker.iQcd;
       
   287         return;
       
   288         }
       
   289 
       
   290     qccCount = (TUint16)iMainMarker.iQcc.Count();
       
   291     if ( qccCount )
       
   292         {
       
   293         for ( index = 0; index < qccCount; ++index )
       
   294             {
       
   295             if ( iMainMarker.iQcc[index]->iCqcc == aComponentIndex )
       
   296                 {
       
   297                 aQcc = iMainMarker.iQcc[index];
       
   298                 return;
       
   299                 }
       
   300             }
       
   301         }
       
   302     aQcd = &iMainMarker.iQcd;
       
   303     }
       
   304 
       
   305 // -----------------------------------------------------------------------------
       
   306 // CJ2kImageInfo::GetRegion
       
   307 // Retrieve the right Region of Interest Marker
       
   308 // (other items were commented in a header).
       
   309 // -----------------------------------------------------------------------------
       
   310 //
       
   311 void CJ2kImageInfo::GetRegion( TRGNMarker*& aRgn, const CJ2kTileInfo& aTile, TUint16 aComponentIndex ) const
       
   312     {
       
   313     // Tile part RGN > main header RGN
       
   314     aRgn = 0;
       
   315     TUint16 index = 0;
       
   316     TUint16 rgnCount = 0;
       
   317     const TTileMarker &tileMarker = aTile.TileMarker();
       
   318 
       
   319     rgnCount = (TUint16)tileMarker.iRgn.Count();
       
   320     if ( rgnCount )
       
   321         {
       
   322         for ( index = 0; index < rgnCount; ++index )
       
   323             {
       
   324             if ( tileMarker.iRgn[index]->iCrgn == aComponentIndex )
       
   325                 {
       
   326                 aRgn = tileMarker.iRgn[index];
       
   327                 return;
       
   328                 }
       
   329             }
       
   330         }
       
   331 
       
   332     rgnCount = (TUint16)iMainMarker.iRgn.Count();
       
   333     if ( rgnCount )
       
   334         {
       
   335         for ( index = 0; index < rgnCount; ++index )
       
   336             {
       
   337             if ( iMainMarker.iRgn[index]->iCrgn == aComponentIndex )
       
   338                 {
       
   339                 aRgn = iMainMarker.iRgn[index];
       
   340                 return;
       
   341                 }
       
   342             }
       
   343         }
       
   344     }
       
   345 
       
   346 // -----------------------------------------------------------------------------
       
   347 // CJ2kImageInfo::GetFromTLM
       
   348 // Retrieve the tile length field from TLM marker
       
   349 // (other items were commented in a header).
       
   350 // -----------------------------------------------------------------------------
       
   351 //
       
   352 void CJ2kImageInfo::GetFromTLM( TSotMarker& aSotMarker ) const
       
   353     {
       
   354     TTLMMarker* tlm = 0;
       
   355     TUint16     tileIndex = 0;
       
   356     TUint16     dIndex = 0;
       
   357 
       
   358     for ( TInt index = 0; index < iMainMarker.iTlm.Count(); ++index )
       
   359         {
       
   360         tlm = iMainMarker.iTlm[index];
       
   361         dIndex = 0;
       
   362         if ( tlm->iTtlm.Count() == 0 )
       
   363             {
       
   364             // One tile-part per tile and the tiles are
       
   365             // in index order without omission or repetition
       
   366             while ( dIndex < tlm->iPtlm.Count() )
       
   367                 {
       
   368                 if ( dIndex == aSotMarker.iIsot )
       
   369                     {
       
   370                     aSotMarker.iPsot = tlm->iPtlm[dIndex];
       
   371                     return;
       
   372                     }
       
   373                 ++dIndex;
       
   374                 }
       
   375             }
       
   376         else
       
   377             {
       
   378             while ( dIndex < tlm->iTtlm.Count() )
       
   379                 {
       
   380                 // Looking for the right tile
       
   381                 if ( tlm->iTtlm[dIndex] == aSotMarker.iIsot )
       
   382                     {
       
   383                     // Looking for the right tile-part
       
   384                     if ( tileIndex == aSotMarker.iTPsot )
       
   385                         {
       
   386                         aSotMarker.iPsot = tlm->iPtlm[dIndex];
       
   387                         return;
       
   388                         }
       
   389                     ++tileIndex;
       
   390                     }
       
   391                 ++dIndex;
       
   392                 }
       
   393             }
       
   394         }
       
   395     }
       
   396 
       
   397 // -----------------------------------------------------------------------------
       
   398 // CJ2kImageInfo::UsePPM
       
   399 // Set up to read the packet header from the PPM marker
       
   400 // (other items were commented in a header).
       
   401 // -----------------------------------------------------------------------------
       
   402 //
       
   403 void CJ2kImageInfo::UsePPM( CJ2kTileInfo& aTile )
       
   404     {
       
   405     if ( iPpm->iPtr == iPpm->iPtrEnd )
       
   406         {
       
   407         iPpm->iPtr = 4;
       
   408         iPpm->iPtrEnd = iPpm->iPtr + iMainMarker.iPpm[iLastTilePartProcessed]->iNppm;
       
   409         iPpmBuffer = iMainMarker.iPpm[iLastTilePartProcessed]->iIppm;
       
   410         }
       
   411     aTile.SetPacketHeaderReader( this );
       
   412     }
       
   413 
       
   414 // -----------------------------------------------------------------------------
       
   415 // CJ2kImageInfo::DoCompactMainHeaderL
       
   416 // Re-arrange the PPM and PLM buffers
       
   417 // (other items were commented in a header).
       
   418 // -----------------------------------------------------------------------------
       
   419 //
       
   420 void CJ2kImageInfo::DoCompactMainHeaderL()
       
   421     {
       
   422     RPointerArray<TPLMMarker>& plmList = iMainMarker.iPlm;
       
   423     if ( plmList.Count() )
       
   424         {
       
   425         TPLMMarker *plmMarker = 0;
       
   426         TPLMMarker *prevMarker = 0;
       
   427         TUint8 checkNplm = ETrue;
       
   428         TUint8 continuation = EFalse;
       
   429         TUint8 length = 0;
       
   430         const TUint8 *ptr = 0;
       
   431         TUint32 remainder = 0;
       
   432         TInt index = 0;
       
   433 
       
   434         for ( index = 0; index < plmList.Count(); ++index )
       
   435             {
       
   436             plmMarker = plmList[index];
       
   437             if ( checkNplm )
       
   438                 {
       
   439                 ptr = plmMarker->iIplm->Ptr();
       
   440                 length = *ptr;
       
   441                 if ( length != ( TUint8 )( plmMarker->iNplm - 1 ) )
       
   442                     {
       
   443                     // Incomplete PLM marker
       
   444                     // there is a continuation of data in the next PLM marker
       
   445                     // and concatenation is needed
       
   446                     plmMarker->iIplm = plmMarker->iIplm->ReAllocL( length + 1 );
       
   447                     remainder = (TUint32)( length - ( plmMarker->iNplm - 1 ) );
       
   448                     plmMarker->iNplm = length;
       
   449                     prevMarker = plmMarker;
       
   450                     checkNplm = EFalse;
       
   451                     }
       
   452                 else
       
   453                     {
       
   454                     // It is a complete PLM marker
       
   455                     plmMarker->iNplm = length;
       
   456                     }
       
   457                 }
       
   458             else
       
   459                 {
       
   460                 // Concatenate with the previous PLM marker
       
   461                 continuation = ETrue;
       
   462                 TPtr8 previous = prevMarker->iIplm->Des();
       
   463                 previous.Append( plmMarker->iIplm->Ptr(), plmMarker->iNplm );
       
   464                 remainder = (TUint32)( remainder - plmMarker->iNplm );
       
   465                 plmMarker->iNplm = 0;
       
   466                 if ( remainder == 0 )
       
   467                     {
       
   468                     checkNplm = ETrue;
       
   469                     }
       
   470                 }
       
   471             }
       
   472         if ( continuation )
       
   473             {
       
   474             index = 0;
       
   475             while ( index < plmList.Count() )
       
   476                 {
       
   477                 plmMarker = plmList[index];
       
   478                 if ( plmMarker->iNplm )
       
   479                     {
       
   480                     ++index;
       
   481                     }
       
   482                 else
       
   483                     {
       
   484                     // Remove PPM marker which has been concatenated
       
   485                     plmList.Remove( index );
       
   486                     delete plmMarker;
       
   487                     }
       
   488                 }
       
   489             }
       
   490         // Do not use PLM segment.
       
   491         plmList.ResetAndDestroy();
       
   492         }
       
   493 
       
   494     RPointerArray<TPPMMarker>& ppmList = iMainMarker.iPpm;
       
   495     if ( ppmList.Count() > 0 )
       
   496         {
       
   497         iPpm = new ( ELeave ) TPPMStream;
       
   498         Mem::FillZ( iPpm, sizeof( TPPMStream ) );
       
   499 
       
   500         TPPMMarker *ppmMarker = 0;
       
   501         TPPMMarker *prevMarker = 0;
       
   502         TUint8  checkNppm = ETrue;
       
   503         TUint8  continuation = EFalse;
       
   504         const TUint8 *ptr = 0;
       
   505         TUint32 length = 0;
       
   506         TUint32 remainder = 0;
       
   507         TInt index = 0;
       
   508         TUint8 zppm = 0;
       
   509 
       
   510         for ( index = 0; index < ppmList.Count(); ++index )
       
   511             {
       
   512             ppmMarker = ppmList[index];
       
   513             if ( checkNppm )
       
   514                 {
       
   515                 ptr = ppmMarker->iIppm->Ptr();
       
   516                 length = PtrReadUtil::ReadBigEndianUint32( ptr );
       
   517                 if ( length != (TUint32)( ppmMarker->iNppm - 4 ) )
       
   518                     {
       
   519                     if ( length > (TUint32)( ppmMarker->iNppm - 4 ) )
       
   520                         {
       
   521                         // Incomplete PPM marker
       
   522                         // there is a continuation of data in the next PPM marker
       
   523                         // and concatenation is needed
       
   524                         ppmMarker->iZppm = zppm++;
       
   525                         ppmMarker->iIppm = ppmMarker->iIppm->ReAllocL( length + 4 );
       
   526                         remainder = (TUint32)( length - ( ppmMarker->iNppm - 4 ) );
       
   527                         ppmMarker->iNppm = length;
       
   528                         prevMarker = ppmMarker;
       
   529                         checkNppm = EFalse;
       
   530                         }
       
   531                     else
       
   532                         {
       
   533                         // We should split the PPM marker into smaller PPM marker
       
   534                         TInt location = 0;
       
   535                         ppmList.Remove( index );
       
   536                         remainder = ppmMarker->iNppm;
       
   537                         while ( remainder >= ( length + 4 ) )
       
   538                             {
       
   539                             prevMarker = new ( ELeave ) TPPMMarker;
       
   540                             CleanupStack::PushL( prevMarker );
       
   541 
       
   542                             prevMarker->iZppm = ( location ? (TUint8)0 : zppm++ );
       
   543                             prevMarker->iNppm = length + ( location ? 4 : 0 );
       
   544                             prevMarker->iIppm = HBufC8::NewL( length + 4 );
       
   545                             prevMarker->iIppm->Des().Append( ptr, length + 4 );
       
   546                             User::LeaveIfError( ppmList.Insert( prevMarker, index + location ) );
       
   547                             CleanupStack::Pop();
       
   548                             ++location;
       
   549                             ptr += ( length + 4 );
       
   550                             remainder -= ( length + 4 );
       
   551                             if ( remainder > 4 )
       
   552                                 {
       
   553                                 length = PtrReadUtil::ReadBigEndianUint32( ptr );
       
   554                                 }
       
   555                             else
       
   556                                 {
       
   557                                 length = 0;
       
   558                                 }
       
   559                             }
       
   560                         if ( remainder )
       
   561                             {
       
   562                             // Incomplete PPM marker
       
   563                             prevMarker = new ( ELeave ) TPPMMarker;
       
   564                             CleanupStack::PushL( prevMarker );
       
   565 
       
   566                             prevMarker->iNppm = remainder;
       
   567                             prevMarker->iIppm = HBufC8::NewL( remainder );
       
   568                             prevMarker->iIppm->Des().Append( ptr, remainder );
       
   569                             User::LeaveIfError( ppmList.Insert( prevMarker, index + location ) );
       
   570                             CleanupStack::Pop();
       
   571                             }
       
   572                         delete ppmMarker;
       
   573                         ppmMarker = 0;
       
   574                         }
       
   575                     }
       
   576                 else
       
   577                     {
       
   578                     // It is a complete PPM marker, adjust the Nppm to length
       
   579                     ppmMarker->iZppm = zppm++;
       
   580                     ppmMarker->iNppm = length;
       
   581                     }
       
   582                 }
       
   583             else
       
   584                 {
       
   585                 continuation = ETrue;
       
   586                 if ( ppmMarker->iNppm <= remainder )
       
   587                     {
       
   588                     // Concatenate with the previous PPM marker
       
   589                     TPtr8 previous = prevMarker->iIppm->Des();
       
   590                     previous.Append( ppmMarker->iIppm->Ptr(), ppmMarker->iNppm );
       
   591                     remainder = ( TUint32 )( remainder - ppmMarker->iNppm );
       
   592                     ppmMarker->iNppm = 0;
       
   593                     if ( remainder == 0 )
       
   594                         {
       
   595                         checkNppm = ETrue;
       
   596                         }
       
   597                     }
       
   598                 else
       
   599                     {
       
   600                     checkNppm = ETrue;
       
   601                     // Partially concatenate with the previous PPM marker
       
   602                     TPtr8 previous = prevMarker->iIppm->Des();
       
   603                     previous.Append( ppmMarker->iIppm->Ptr(), remainder );
       
   604 
       
   605                     // We should split the PPM marker into smaller PPM marker
       
   606                     TInt location = 0;
       
   607                     ppmList.Remove( index );
       
   608                     ptr = ppmMarker->iIppm->Ptr() + remainder;
       
   609                     length = PtrReadUtil::ReadBigEndianUint32( ptr );
       
   610                     remainder = ( TUint32 )( ppmMarker->iNppm - remainder );
       
   611                     while ( remainder >= ( length + 4 ) )
       
   612                         {
       
   613                         prevMarker = new ( ELeave ) TPPMMarker;
       
   614                         CleanupStack::PushL( prevMarker );
       
   615 
       
   616                         prevMarker->iZppm = ( location ? (TUint8)0 : zppm++ );
       
   617                         prevMarker->iNppm = length + ( location ? 4 : 0 );
       
   618                         prevMarker->iIppm = HBufC8::NewL( length + 4 );
       
   619                         prevMarker->iIppm->Des().Append( ptr, length + 4 );
       
   620                         User::LeaveIfError( ppmList.Insert( prevMarker, index + location ) );
       
   621                         CleanupStack::Pop();
       
   622                         ++location;
       
   623                         ptr += ( length + 4 );
       
   624                         remainder -= ( length + 4 );
       
   625                         if ( remainder > 4 )
       
   626                             {
       
   627                             length = PtrReadUtil::ReadBigEndianUint32( ptr );
       
   628                             }
       
   629                         else
       
   630                             {
       
   631                             length = 0;
       
   632                             }
       
   633                         }
       
   634                     if ( remainder )
       
   635                         {
       
   636                         // Incomplete PPM marker
       
   637                         prevMarker = new ( ELeave ) TPPMMarker;
       
   638                         CleanupStack::PushL( prevMarker );
       
   639 
       
   640                         prevMarker->iNppm = remainder;
       
   641                         prevMarker->iIppm = HBufC8::NewL( remainder );
       
   642                         prevMarker->iIppm->Des().Append( ptr, remainder );
       
   643                         User::LeaveIfError( ppmList.Insert( prevMarker, index + location ) );
       
   644                         CleanupStack::Pop();
       
   645                         }
       
   646                     delete ppmMarker;
       
   647                     ppmMarker = 0; 
       
   648                     }
       
   649                 }
       
   650             }
       
   651         if ( continuation )
       
   652             {
       
   653             index = 0;
       
   654             while ( index < ppmList.Count() )
       
   655                 {
       
   656                 ppmMarker = ppmList[index];
       
   657                 if ( ppmMarker->iNppm )
       
   658                     {
       
   659                     ++index;
       
   660                     }
       
   661                 else
       
   662                     {
       
   663                     // Remove PPM marker which has been concatenated
       
   664                     ppmList.Remove( index );
       
   665                     delete ppmMarker;
       
   666                     ppmMarker = 0;
       
   667                     }
       
   668                 }
       
   669             }
       
   670         }
       
   671 
       
   672     // Do not use the COM segment at this release
       
   673     if ( iMainMarker.iCom.Count() )
       
   674         {
       
   675         iMainMarker.iCom.ResetAndDestroy();
       
   676         }
       
   677     }
       
   678 
       
   679 // -----------------------------------------------------------------------------
       
   680 // CJ2kImageInfo::IsPPM
       
   681 // Is packet header should be read from PPM marker
       
   682 // (other items were commented in a header).
       
   683 // -----------------------------------------------------------------------------
       
   684 //
       
   685 TUint8 CJ2kImageInfo::IsPPM() const
       
   686     {
       
   687     if ( iPpm )
       
   688         {
       
   689         if ( iPpm->iPtr < iPpm->iPtrEnd )
       
   690             {
       
   691             return ETrue;
       
   692             }
       
   693         else if ( iLastTilePartProcessed < iMainMarker.iPpm.Count() )
       
   694             {
       
   695             return ETrue;
       
   696             }
       
   697         else
       
   698             {
       
   699             return EFalse;
       
   700             }
       
   701         }
       
   702     return EFalse;
       
   703     }
       
   704 
       
   705 // -----------------------------------------------------------------------------
       
   706 // CJ2kImageInfo::ReadEPHMarker
       
   707 // Try to consume the EPH marker if there is one.
       
   708 // (other items were commented in a header).
       
   709 // -----------------------------------------------------------------------------
       
   710 //
       
   711 TUint8 CJ2kImageInfo::ReadEPHMarker()
       
   712     {
       
   713     if ( iPpm && ( iPpm->iPtrEnd - iPpm->iPtr ) >= 2 )
       
   714         {
       
   715         const TUint8 *ptr = iPpmBuffer->Ptr();
       
   716         ptr += iPpm->iPtr;
       
   717         if ( PtrReadUtil::ReadBigEndianUint16( ptr ) == KEPH )
       
   718             {
       
   719             iPpm->iPtr += 2;
       
   720             }
       
   721         }
       
   722     return EFalse;
       
   723     }
       
   724 
       
   725 // -----------------------------------------------------------------------------
       
   726 // CJ2kImageInfo::ReadBit
       
   727 // Read a bit from the packet header stream.
       
   728 // (other items were commented in a header).
       
   729 // -----------------------------------------------------------------------------
       
   730 //
       
   731 TUint8 CJ2kImageInfo::ReadBit( TUint8& aBit )
       
   732     {
       
   733     if ( iPpm->iPos == 0 )
       
   734         {
       
   735         if ( iPpm->iPtr < iPpm->iPtrEnd )
       
   736             {
       
   737             // Stream contains some packet header data
       
   738             iPpm->iData = ( *iPpmBuffer )[iPpm->iPtr++];
       
   739             iPpm->iPos = iPpm->iNextPos;
       
   740             if ( iPpm->iNextPos == 0x08 && iPpm->iData == 0xff )
       
   741                 {
       
   742                 iPpm->iNextPos = 0x07;
       
   743                 }
       
   744             else
       
   745                 {
       
   746                 iPpm->iNextPos = 0x08;
       
   747                 }
       
   748             }
       
   749         else
       
   750             {
       
   751             // No more data
       
   752             return ETrue;
       
   753             }
       
   754         }
       
   755     aBit = (TUint8)( ( iPpm->iData >> ( --iPpm->iPos ) ) & 0x01 );
       
   756 
       
   757     return EFalse;
       
   758     }
       
   759 
       
   760 // -----------------------------------------------------------------------------
       
   761 // CJ2kImageInfo::ReadBits
       
   762 // Read some bits from the packet header stream.
       
   763 // (other items were commented in a header).
       
   764 // -----------------------------------------------------------------------------
       
   765 //
       
   766 TUint8 CJ2kImageInfo::ReadBits( TUint8& aBit, TUint8 aBitLen )
       
   767     {
       
   768     aBit = (TUint8)0;
       
   769     TUint8 bit;
       
   770     for ( TInt8 index = (TInt8)( aBitLen - 1 ); index >= 0; --index )
       
   771         {
       
   772         if ( !ReadBit( bit ) )
       
   773             {
       
   774             aBit |= ( bit << index );
       
   775             }
       
   776         else
       
   777             {
       
   778             return ETrue;
       
   779             }
       
   780         }
       
   781     return EFalse;
       
   782     }
       
   783 
       
   784 // -----------------------------------------------------------------------------
       
   785 // CJ2kImageInfo::ReadBits
       
   786 // Read some bits from the packet header stream.
       
   787 // (other items were commented in a header).
       
   788 // -----------------------------------------------------------------------------
       
   789 //
       
   790 TUint8 CJ2kImageInfo::ReadBits( TUint32& aBit, TUint8 aBitLen )
       
   791     {
       
   792     aBit = (TUint32)0;
       
   793     TUint8 bit = 0;
       
   794     for ( TInt8 index = (TInt8)( aBitLen - 1 ); index >= 0; --index )
       
   795         {
       
   796         if ( !ReadBit( bit ) )
       
   797             {
       
   798             aBit |= ( bit << index );
       
   799             }
       
   800         else
       
   801             {
       
   802             return ETrue;
       
   803             }
       
   804         }
       
   805     return EFalse;
       
   806     }
       
   807 
       
   808 // -----------------------------------------------------------------------------
       
   809 // CJ2kImageInfo::StartReadBit
       
   810 // Start reading from packet header stream.
       
   811 // (other items were commented in a header).
       
   812 // -----------------------------------------------------------------------------
       
   813 //
       
   814 TUint8 CJ2kImageInfo::StartReadBit()
       
   815     {
       
   816     if ( iPpm && iPpm->iPtr < iPpm->iPtrEnd )
       
   817         {
       
   818         // Stream contains some packet header data
       
   819         iPpm->iData = ( *iPpmBuffer )[iPpm->iPtr++];
       
   820         iPpm->iPos = iPpm->iNextPos = 0x08;
       
   821         if ( iPpm->iData == 0xff )
       
   822             {
       
   823             iPpm->iNextPos = 0x07;
       
   824             }
       
   825 
       
   826         return EFalse;
       
   827         }
       
   828     return ETrue;
       
   829     }
       
   830 
       
   831 // -----------------------------------------------------------------------------
       
   832 // CJ2kImageInfo::AlignReader
       
   833 // Align the stream to the next byte boundary if necessary.
       
   834 // (other items were commented in a header).
       
   835 // -----------------------------------------------------------------------------
       
   836 //
       
   837 void CJ2kImageInfo::AlignReader()
       
   838     {
       
   839     if ( iPpm->iNextPos == 0x07 )
       
   840         {
       
   841         if ( iPpm->iPtr < iPpm->iPtrEnd )
       
   842             {
       
   843             ++iPpm->iPtr;
       
   844             }
       
   845         }
       
   846     iPpm->iData = iPpm->iPos = iPpm->iNextPos = 0;
       
   847     }
       
   848