imagingmodules/jp2kcodec/Src/JP2KConvert.cpp
changeset 0 469c91dae73b
equal deleted inserted replaced
-1:000000000000 0:469c91dae73b
       
     1 /*
       
     2 * Copyright (c) 2003-2006 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:  JPEG2000 image encoder/decoder plugin class.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include "JP2KImageUtils.h"
       
    21 #include "JP2KFormat.h"
       
    22 #include "JP2KConvert.h"
       
    23 #include "JP2KStreamReader.h"
       
    24 #include "JP2KImageClientMain.h"
       
    25 #include "JP2KCodec.h"
       
    26 #include <barsc.h>
       
    27 #include <imageconversion.h>
       
    28 #include <barsread.h>
       
    29 #include <bautils.h>
       
    30 #include <e32math.h>
       
    31 #include <101F862D_extra.rsg>
       
    32 #include <icl/icl_uids.hrh>
       
    33 #include "JP2KUids.hrh"
       
    34 #include <JP2KImageData.h>
       
    35 
       
    36 // EXTERNAL DATA STRUCTURES
       
    37 
       
    38 // EXTERNAL FUNCTION PROTOTYPES  
       
    39 
       
    40 // CONSTANTS
       
    41 
       
    42 // MACROS
       
    43 
       
    44 // LOCAL CONSTANTS AND MACROS
       
    45 _LIT( KJ2KPanicCategory, "J2KConvertPlugin" );
       
    46 
       
    47 // MODULE DATA STRUCTURES
       
    48 
       
    49 // LOCAL FUNCTION PROTOTYPES
       
    50 
       
    51 // FORWARD DECLARATIONS
       
    52 
       
    53 // ============================ MEMBER FUNCTIONS ===============================
       
    54 
       
    55 // -----------------------------------------------------------------------------
       
    56 // CJp2kDecoder::NewL
       
    57 // Two-phased constructor.
       
    58 // -----------------------------------------------------------------------------
       
    59 //
       
    60 CJp2kDecoder* CJp2kDecoder::NewL()
       
    61     {
       
    62     return new ( ELeave ) CJp2kDecoder;
       
    63     }
       
    64 
       
    65 // Destructor
       
    66 CJp2kDecoder::~CJp2kDecoder()
       
    67     {
       
    68     // Call base class Cleanup(), else there is a possibility
       
    69     // of memory leak
       
    70     CImageDecoderPlugin::Cleanup();
       
    71     }
       
    72 
       
    73 // -----------------------------------------------------------------------------
       
    74 // CJp2kDecoder::ImageType
       
    75 // Get the image type uid of this plugin.
       
    76 // (other items were commented in a header).
       
    77 // -----------------------------------------------------------------------------
       
    78 //
       
    79 void CJp2kDecoder::ImageType( TInt aFrameNumber, TUid& aImageType, TUid& aImageSubType ) const
       
    80     {
       
    81     __ASSERT_ALWAYS( aFrameNumber == 0, Panic( EFrameNumberOutOfRange ) );
       
    82 
       
    83     TUid uid = {KImageTypeJ2KUid};
       
    84     aImageType = uid;
       
    85     aImageSubType = KNullUid;
       
    86     }
       
    87 
       
    88 // -----------------------------------------------------------------------------
       
    89 // CJp2kDecoder::NumberOfImageComments
       
    90 // Get the number of image comment.
       
    91 // -----------------------------------------------------------------------------
       
    92 //
       
    93 TInt CJp2kDecoder::NumberOfImageComments() const
       
    94     {
       
    95     __ASSERT_ALWAYS( IsImageHeaderProcessingComplete(), Panic( EHeaderProcessingNotComplete ) );
       
    96 
       
    97     const TUid commentUid = { KJ2KCommentUid };
       
    98     const CFrameImageData& frameImageData = FrameData( 0 );
       
    99     const TInt imageDataCount = frameImageData.ImageDataCount();
       
   100     const TImageDataBlock *imageData = 0;
       
   101     TInt imageCommentCount = 0;
       
   102     for ( TInt index = 0; index < imageDataCount; ++index )
       
   103         {
       
   104         imageData = frameImageData.GetImageData( index );
       
   105         if ( imageData->DataType() == commentUid )
       
   106             {
       
   107             imageCommentCount++;
       
   108             }
       
   109         }
       
   110     return imageCommentCount;
       
   111     }
       
   112 
       
   113 // -----------------------------------------------------------------------------
       
   114 // CJp2kDecoder::ImageCommentL
       
   115 // Get the image comment.
       
   116 // (other items were commented in a header).
       
   117 // -----------------------------------------------------------------------------
       
   118 //
       
   119 HBufC* CJp2kDecoder::ImageCommentL( TInt aCommentNumber ) const
       
   120     {
       
   121     __ASSERT_ALWAYS( IsImageHeaderProcessingComplete(), Panic( EHeaderProcessingNotComplete ) );
       
   122     __ASSERT_ALWAYS( ( aCommentNumber >= 0 ) && ( aCommentNumber < NumberOfImageComments() ), 
       
   123                      Panic( ECommentNumberOutOfRange ) );
       
   124     
       
   125     HBufC *comment = 0;
       
   126 
       
   127     if( FrameData( 0 ).ImageDataCount() > 0 )
       
   128         {
       
   129         const TUid commentUid = { KJ2KCommentUid };
       
   130         const CFrameImageData& frameImageData = FrameData( 0 );
       
   131         const TInt imageDataCount = frameImageData.ImageDataCount();
       
   132         const TImageDataBlock *imageData = 0;
       
   133         TInt commentCount = 0;
       
   134         for ( TInt index = 0; index < imageDataCount; ++index )
       
   135             {
       
   136             imageData = frameImageData.GetImageData( index );
       
   137             if ( imageData->DataType() == commentUid )
       
   138                 {
       
   139                 if ( commentCount == aCommentNumber )
       
   140                     {
       
   141                     index = imageDataCount; // Break from the for loop
       
   142                     }
       
   143                 else
       
   144                     {
       
   145                     commentCount++;
       
   146                     }
       
   147                 }
       
   148             }
       
   149 
       
   150         if( imageData != 0 )
       
   151             {
       
   152             const TJp2kComment *jp2kComment = STATIC_CAST( const TJp2kComment*, imageData );
       
   153             comment = HBufC::NewL( jp2kComment->iComment->Length() );
       
   154 
       
   155             // Create 16 bit copy of the 8 bit original
       
   156             comment->Des().Copy( *( jp2kComment->iComment ) );
       
   157             }
       
   158         }
       
   159     return comment;
       
   160     }
       
   161 
       
   162 // -----------------------------------------------------------------------------
       
   163 // CJp2kDecoder::NumberOfFrameComments
       
   164 // Get the number of frame comment.
       
   165 // (other items were commented in a header).
       
   166 // -----------------------------------------------------------------------------
       
   167 //
       
   168 TInt CJp2kDecoder::NumberOfFrameComments( TInt aFrameNumber ) const
       
   169     {
       
   170     __ASSERT_ALWAYS( IsImageHeaderProcessingComplete(), Panic( EHeaderProcessingNotComplete ) );
       
   171     __ASSERT_ALWAYS( aFrameNumber == 0, Panic( EFrameNumberOutOfRange ) );
       
   172    
       
   173     return NumberOfImageComments();
       
   174     }
       
   175 
       
   176 // -----------------------------------------------------------------------------
       
   177 // CJp2kDecoder::FrameCommentL
       
   178 // Get the frame comment.
       
   179 // (other items were commented in a header).
       
   180 // -----------------------------------------------------------------------------
       
   181 //
       
   182 HBufC* CJp2kDecoder::FrameCommentL( TInt aFrameNumber, TInt aCommentNumber ) const
       
   183     {
       
   184     __ASSERT_ALWAYS( IsImageHeaderProcessingComplete(), Panic( EHeaderProcessingNotComplete ) );
       
   185     __ASSERT_ALWAYS( aFrameNumber == 0, Panic( EFrameNumberOutOfRange ) );
       
   186 
       
   187     return ImageCommentL( aCommentNumber );
       
   188     }
       
   189 
       
   190 // -----------------------------------------------------------------------------
       
   191 // CJp2kDecoder::FrameInfoStringsL
       
   192 // Retrieve frame information and format it according to info stored in .rss file.
       
   193 // (other items were commented in a header).
       
   194 // -----------------------------------------------------------------------------
       
   195 //
       
   196 CFrameInfoStrings* CJp2kDecoder::FrameInfoStringsL( RFs& aFs, TInt aFrameNumber )
       
   197     {
       
   198     const TUid KJp2kCodecDllUid = { KJ2KCodecDllUidValue };
       
   199 
       
   200     RResourceFile resourceFile;
       
   201     OpenExtraResourceFileLC( aFs, KJp2kCodecDllUid, resourceFile );
       
   202 
       
   203     HBufC8* resourceInfo = resourceFile.AllocReadLC( THEDECODERINFO );
       
   204     TResourceReader resourceReader;
       
   205     resourceReader.SetBuffer( resourceInfo );
       
   206 
       
   207     TBuf<KCodecResourceStringMax> info;
       
   208     TBuf<KCodecResourceStringMax> templte;
       
   209 
       
   210     const TFrameInfo& frameInfo = FrameInfo( aFrameNumber );
       
   211     CFrameInfoStrings* frameInfoStrings = CFrameInfoStrings::NewLC();
       
   212 
       
   213     info = resourceReader.ReadTPtrC();
       
   214     frameInfoStrings->SetDecoderL( info );
       
   215 
       
   216     info = resourceReader.ReadTPtrC();
       
   217     frameInfoStrings->SetFormatL( info );
       
   218 
       
   219     TInt width = frameInfo.iOverallSizeInPixels.iWidth;
       
   220     TInt height = frameInfo.iOverallSizeInPixels.iHeight;
       
   221     TInt depth = frameInfo.iBitsPerPixel;
       
   222 
       
   223     templte = resourceReader.ReadTPtrC();
       
   224     info.Format( templte, width, height );
       
   225     frameInfoStrings->SetDimensionsL( info );
       
   226 
       
   227     CDesCArrayFlat* resourceArray = resourceReader.ReadDesCArrayL();
       
   228     CleanupStack::PushL( resourceArray );
       
   229     TUint formatIndex = ( frameInfo.iFlags & TFrameInfo::EColor ) ? 1 : 0;
       
   230     templte = ( *resourceArray )[formatIndex];
       
   231     CleanupStack::PopAndDestroy( resourceArray );
       
   232     info.Format( templte, depth );
       
   233     frameInfoStrings->SetDepthL( info );
       
   234 
       
   235     resourceArray = resourceReader.ReadDesCArrayL();
       
   236     CleanupStack::PushL( resourceArray );
       
   237     formatIndex = 0;
       
   238     info = ( *resourceArray )[formatIndex];
       
   239     CleanupStack::PopAndDestroy( resourceArray );
       
   240     frameInfoStrings->SetDetailsL( info );
       
   241 
       
   242     CleanupStack::Pop( frameInfoStrings );
       
   243     CleanupStack::PopAndDestroy( 2 ); // resourceInfo + resourceFile
       
   244     return frameInfoStrings;
       
   245     }
       
   246 
       
   247 // -----------------------------------------------------------------------------
       
   248 // CJp2kDecoder::FrameHeaderBlockSize
       
   249 // Returns the frame header block size.
       
   250 // (other items were commented in a header).
       
   251 // -----------------------------------------------------------------------------
       
   252 //
       
   253 TInt CJp2kDecoder::FrameHeaderBlockSize( TInt aFrameNumber ) const
       
   254     {
       
   255     __ASSERT_ALWAYS( aFrameNumber == 0, Panic( EFrameNumberOutOfRange ) );
       
   256 
       
   257     return KJ2kInputBufferSize;
       
   258     }
       
   259 
       
   260 // -----------------------------------------------------------------------------
       
   261 // CJp2kDecoder::FrameBlockSize
       
   262 // Returns the frame block size.
       
   263 // (other items were commented in a header).
       
   264 // -----------------------------------------------------------------------------
       
   265 //
       
   266 TInt CJp2kDecoder::FrameBlockSize(TInt aFrameNumber) const
       
   267     {
       
   268     __ASSERT_ALWAYS( aFrameNumber == 0, Panic( EFrameNumberOutOfRange ) );
       
   269 
       
   270     return KJ2kInputBufferSize;
       
   271     }
       
   272 
       
   273 // -----------------------------------------------------------------------------
       
   274 // CJp2kDecoder::DoConvert
       
   275 // Override the default DoConvert to split out the parsing and decoding
       
   276 // process into multiple steps.
       
   277 // (other items were commented in a header).
       
   278 // -----------------------------------------------------------------------------
       
   279 //
       
   280 void CJp2kDecoder::DoConvert()
       
   281     {
       
   282     TFrameState codecState = EFrameIncomplete;
       
   283     TInt errCode = KErrNone;
       
   284 
       
   285     CJp2kReadCodec *j2kCodec = static_cast<CJp2kReadCodec*>( ImageReadCodec() );
       
   286 
       
   287     if ( !j2kCodec->IsDecodeTile() )
       
   288         {
       
   289         // parsing of a tile-part
       
   290         TRAP( errCode, PrepareForProcessFrameL() );
       
   291         if ( errCode != KErrNone )
       
   292             {
       
   293             RequestComplete( errCode );
       
   294             return;
       
   295             }
       
   296 
       
   297         TBufPtr8& sourceData = SourceData();
       
   298         TInt sourceLength = sourceData.Length();
       
   299         if ( sourceLength != 0 )
       
   300             {
       
   301             TRAP( errCode, codecState = j2kCodec->ProcessFrameL( sourceData ) );
       
   302             
       
   303             if ( j2kCodec->IsDecodeTile() )
       
   304                 {
       
   305                 // tile-part contains all compressed data
       
   306                 // and proceed to the decoding
       
   307                 SelfComplete( KErrNone );
       
   308                 return;
       
   309                 }
       
   310             }
       
   311         // continue on parsing the tile-part
       
   312         HandleProcessFrameResult( errCode, codecState );
       
   313         }
       
   314     else
       
   315         {
       
   316         // decoding of the tile-part
       
   317         TRAP( errCode, codecState = j2kCodec->DecodeTileL() );
       
   318 
       
   319         if ( errCode == KErrNone )
       
   320             {
       
   321             if ( j2kCodec->IsDecodeTile() )
       
   322                 {
       
   323                 // continue on decoding the tile-part
       
   324                 // if we split the decoding into multiple steps
       
   325                 SelfComplete( KErrNone );
       
   326                 return;
       
   327                 }
       
   328             }
       
   329         // either continue on parsing the next tile-part
       
   330         // or done with the whole image
       
   331         HandleProcessFrameResult( errCode, codecState );
       
   332         }
       
   333     }
       
   334 
       
   335 // -----------------------------------------------------------------------------
       
   336 // CJp2kDecoder::CJp2kDecoder
       
   337 // C++ default constructor can NOT contain any code, that
       
   338 // might leave.
       
   339 // -----------------------------------------------------------------------------
       
   340 //
       
   341 CJp2kDecoder::CJp2kDecoder()
       
   342     {
       
   343     }  
       
   344 
       
   345 // -----------------------------------------------------------------------------
       
   346 // CJp2kDecoder::ReadFormatL
       
   347 // JP2 File Format detection state machine.
       
   348 // (other items were commented in a header).
       
   349 // -----------------------------------------------------------------------------
       
   350 //
       
   351 void CJp2kDecoder::ReadFormatL()
       
   352     {
       
   353     // Verify the JP2 file format if it exist
       
   354     iCallFromFramework = ETrue;
       
   355 
       
   356     while ( iState != EStateInCodestreamBox )
       
   357         {
       
   358         switch ( iState )
       
   359             {
       
   360             case EStateInSignatureBox:
       
   361                 {
       
   362                 ReadSignatureBoxL();
       
   363                 break;
       
   364                 }
       
   365             case EStateInFileTypeBox:
       
   366                 {
       
   367                 ReadFileTypeBoxL();
       
   368                 break;
       
   369                 }
       
   370             case EStateInJP2SuperBox:
       
   371                 {
       
   372                 ReadJp2HeaderBoxL();
       
   373                 break;
       
   374                 }
       
   375             case EStateInIPRBox:
       
   376                 {
       
   377                 ReadIPRBoxL();
       
   378                 break;
       
   379                 }
       
   380             case EStateInXMLBox:
       
   381                 {
       
   382                 ReadXMLBoxL();
       
   383                 break;
       
   384                 }
       
   385             case EStateInUUIDBox:
       
   386                 {
       
   387                 ReadUUIDBoxL();
       
   388                 break;
       
   389                 }
       
   390             case EStateInUUIDInfoBox:
       
   391                 {
       
   392                 ReadUUIDInfoBoxL();
       
   393                 break;
       
   394                 }
       
   395             case EStateInUnknown:
       
   396                 {
       
   397                 if ( iCallFromFramework )
       
   398                     {
       
   399                     // Always read the length and type of the box
       
   400                     ReadDataL( iLastRead, iBufferDes, KJ2kBoxTypeLength );
       
   401 
       
   402                     if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength )
       
   403                         {
       
   404                         if ( ( iJ2kInfo.iCSOffset != 0 ) && 
       
   405                              ( (TUint32)iBufferDes.Length() == 0 ) )
       
   406                             {
       
   407                             // We have reach the end of file/stream and 
       
   408                             // CodeStream box has been recognized
       
   409                             iState = EStateInCodestreamBox;
       
   410                             }
       
   411                         else
       
   412                             {
       
   413                             // Need more data from the ICL framework
       
   414                             User::Leave( KErrUnderflow );
       
   415                             }
       
   416                         }
       
   417                     iPtr = iBufferDes.Ptr();
       
   418                     }
       
   419 
       
   420                 if ( iState != EStateInCodestreamBox )
       
   421                     {
       
   422                     // Length and Type of next box
       
   423                     iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
   424                     iBoxType = PtrReadUtil::ReadBigEndianUint32( iPtr );
       
   425 
       
   426                     // Update the internal state based on the iBoxType
       
   427                     UpdateStateFromBoxTypeL();
       
   428 
       
   429                     if ( iState != EStateInCodestreamBox )
       
   430                         {
       
   431                         // Corrupted box length
       
   432                         if ( ( (TInt32)iBoxLength ) < 0 )
       
   433                             {
       
   434                             User::Leave( KErrCorrupt );
       
   435                             }
       
   436                         }
       
   437                     }
       
   438                 break;
       
   439                 }
       
   440             default:
       
   441                 {
       
   442                 break;
       
   443                 }
       
   444             }
       
   445         iCallFromFramework = EFalse;
       
   446         }
       
   447 
       
   448     // When the code reach here, it means that we have found the 
       
   449     // codestream box in JP2 file format or the codestream SOC itself
       
   450     // in case of the JP2 file format, all the boxes after the
       
   451     // codestream box will not be read and parsed.
       
   452     
       
   453     // In JP2 file format, iLastRead points to codestream box
       
   454     // in JP2 codestream, iLastRead points to SOC marker
       
   455     // it is the offset that ICL framework used to read
       
   456     // in more data from the image file.
       
   457     SetStartPosition( iJ2kInfo.iCSOffset );
       
   458 
       
   459     // Always set the image data length to KMaxTInt32
       
   460     SetDataLength( KMaxTInt );
       
   461 
       
   462     // Fill up the image related information, if it is
       
   463     // in JP2 file format, else defer the setting of the
       
   464     // image info til SIZ marker in the codestream has
       
   465     // been processed.
       
   466     if ( iJ2kInfo.iOption & TJ2kInfo::EJP2file )
       
   467         {
       
   468         TFrameInfo& imageInfo = CONST_CAST( TFrameInfo&, ImageInfo() );
       
   469         imageInfo.iOverallSizeInPixels = iJ2kInfo.iImageSize;
       
   470         imageInfo.iFrameCoordsInPixels.SetRect( TPoint( 0, 0 ), iJ2kInfo.iImageSize );
       
   471         imageInfo.iFrameSizeInTwips = iJ2kInfo.iImageSizeInTwips;
       
   472 
       
   473         if ( iJ2kInfo.iBPCList.Count() > 0 )
       
   474             {
       
   475             // Calculate based on the bitdepth per component
       
   476             for ( TUint16 index = 0; index < iJ2kInfo.iNC; ++index )
       
   477                 {
       
   478                 imageInfo.iBitsPerPixel += ( ( 0x7f & iJ2kInfo.iBPCList[index] ) + 1 );
       
   479                 }
       
   480             }
       
   481         else
       
   482             {            
       
   483             if ( iJ2kInfo.iBPC == KJ2kIsBPCBoxExist )
       
   484                 {
       
   485                 User::Leave( KErrCorrupt );
       
   486                 }
       
   487 
       
   488             // Has the same bitdepth on each component
       
   489             imageInfo.iBitsPerPixel = ( ( 0x7f & iJ2kInfo.iBPC ) + 1 ) * iJ2kInfo.iNC;
       
   490             }
       
   491         imageInfo.iFlags |= TFrameInfo::ECanDither;
       
   492 
       
   493         // Decoder is able to handle scaleable resolution
       
   494         imageInfo.iFlags |= TFrameInfo::EConstantAspectRatio;
       
   495 
       
   496         if ( iJ2kInfo.iEnumCS != KJ2kColourSpecGrayScale )
       
   497             {
       
   498             imageInfo.iFlags |= TFrameInfo::EColor;
       
   499             }
       
   500         
       
   501         // No animation.
       
   502         imageInfo.iDelay = 0;
       
   503 
       
   504         switch ( imageInfo.iBitsPerPixel )
       
   505             {
       
   506             case 1:
       
   507                 {
       
   508                 imageInfo.iFrameDisplayMode = EGray2;
       
   509                 break;
       
   510                 }
       
   511             case 2:
       
   512                 {
       
   513                 imageInfo.iFrameDisplayMode = EGray4;
       
   514                 break;
       
   515                 }
       
   516             case 4:
       
   517                 {
       
   518                 imageInfo.iFrameDisplayMode = ( imageInfo.iFlags & TFrameInfo::EColor ) ? EColor16 : EGray16;
       
   519                 break;
       
   520                 }
       
   521             case 8:
       
   522                 {
       
   523                 imageInfo.iFrameDisplayMode = ( imageInfo.iFlags & TFrameInfo::EColor ) ? EColor16M : EGray256;
       
   524                 break;
       
   525                 }
       
   526             case 12:
       
   527                 {
       
   528                 imageInfo.iFrameDisplayMode = ( imageInfo.iFlags & TFrameInfo::EColor ) ? EColor4K : EGray256;
       
   529                 break;
       
   530                 }
       
   531             case 16:
       
   532                 {
       
   533                 imageInfo.iFrameDisplayMode = EColor64K;
       
   534                 break;
       
   535                 }
       
   536             case 24:
       
   537                 {
       
   538                 imageInfo.iFrameDisplayMode = EColor16M;
       
   539                 break;
       
   540                 }
       
   541             default:
       
   542                 {
       
   543                 imageInfo.iFrameDisplayMode = EColor64K;
       
   544                 break;
       
   545                 }
       
   546             }
       
   547         }
       
   548     }
       
   549 
       
   550 // -----------------------------------------------------------------------------
       
   551 // CJp2kDecoder::ReadSignatureBoxL
       
   552 // Verify and process the Signature box.
       
   553 // (other items were commented in a header).
       
   554 // -----------------------------------------------------------------------------
       
   555 //
       
   556 void CJp2kDecoder::ReadSignatureBoxL(  )
       
   557     {
       
   558     // Validate the Signature Box
       
   559     __ASSERT_ALWAYS( iLastRead == 0, Panic( EInvalidState ) );
       
   560 
       
   561     // Read the Signature box + the next box's Length and Type
       
   562     ReadDataL( iLastRead, iBufferDes, KJ2kFileInformationSize );
       
   563 
       
   564     if ( (TUint32)iBufferDes.Length() < KJ2kSigBoxLength )
       
   565         {
       
   566         // Need more data from the ICL framework
       
   567         User::Leave( KErrUnderflow );
       
   568         }
       
   569 
       
   570     iPtr = iBufferDes.Ptr();
       
   571 
       
   572     if ( ( PtrReadUtil::ReadBigEndianUint32Inc( iPtr ) != KJ2kSigBoxLength ) ||
       
   573          ( PtrReadUtil::ReadBigEndianUint32Inc( iPtr ) != KJ2kSigBoxType )   ||
       
   574          ( PtrReadUtil::ReadBigEndianUint32Inc( iPtr ) != KJ2kSigBoxContent ) )
       
   575         {
       
   576         // Unrecognized signature box
       
   577         User::Leave( KErrCorrupt );
       
   578         }
       
   579 
       
   580     // File Type box shall immediately follow the Signature box
       
   581     iLastRead = KJ2kSigBoxLength;
       
   582     iState = EStateInFileTypeBox;
       
   583 
       
   584     // JP2 file format
       
   585     iJ2kInfo.iOption |= TJ2kInfo::EJP2file;
       
   586 
       
   587     if ( iBufferDes.Length() < KJ2kFileInformationSize )
       
   588         {
       
   589         // Need more data from the ICL framework
       
   590         User::Leave( KErrUnderflow );
       
   591         }
       
   592     }
       
   593 
       
   594 // -----------------------------------------------------------------------------
       
   595 // CJp2kDecoder::ReadFileTypeBoxL
       
   596 // Verify and process the File Type box.
       
   597 // (other items were commented in a header).
       
   598 // -----------------------------------------------------------------------------
       
   599 //
       
   600 void CJp2kDecoder::ReadFileTypeBoxL()
       
   601     {
       
   602     // Validate the File Type Box's Length and Type
       
   603     if ( iCallFromFramework )
       
   604         {
       
   605         __ASSERT_ALWAYS( iLastRead == KJ2kSigBoxLength, Panic( EInvalidState ) );
       
   606 
       
   607         ReadDataL( iLastRead, iBufferDes, KJ2kBoxTypeLength );
       
   608 
       
   609         if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength )
       
   610             {
       
   611             // Need more data from the ICL framework
       
   612             User::Leave( KErrUnderflow );
       
   613             }
       
   614 
       
   615         iPtr = iBufferDes.Ptr();
       
   616         }
       
   617 
       
   618     iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
   619     iBoxType = PtrReadUtil::ReadBigEndianUint32( iPtr );
       
   620 
       
   621     if ( ( (TInt32)iBoxLength ) <= 0 || iBoxType != KJ2kFileTypeBox || iBoxLength > KJ2kFileTypeBoxMaxLength )
       
   622         {
       
   623         // Unrecognized file type box or corrupted box length
       
   624         User::Leave( KErrCorrupt );
       
   625         }
       
   626 
       
   627     TUint8 xlBoxExist = 0;
       
   628     if ( iBoxLength == 1 )
       
   629         {
       
   630         // The XLBox shall exist and contains the actual length of the box
       
   631         // XLBox is 8 bytes width
       
   632         ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, KJ2kBoxTypeLength );
       
   633 
       
   634         if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength )
       
   635             {
       
   636             // Need more data from the ICL framework
       
   637             User::Leave( KErrUnderflow );
       
   638             }
       
   639 
       
   640         iPtr = iBufferDes.Ptr();
       
   641         iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
   642         iBoxLength += PtrReadUtil::ReadBigEndianUint32( iPtr );
       
   643         xlBoxExist = 1;
       
   644         }
       
   645 
       
   646     if ( ( (TInt32)iBoxLength ) <= 0 || ( ( (TInt32)iBoxLength - 16 ) / 4 ) <= 0 )
       
   647         {
       
   648         // Must include at least one CL field in the Compatibility list
       
   649         User::Leave( KErrCorrupt );
       
   650         }
       
   651 
       
   652     // Read the File Type box + the next box's Length and Type
       
   653     ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, iBoxLength );
       
   654 
       
   655     if ( (TUint32)iBufferDes.Length() < iBoxLength - KJ2kBoxTypeLength )
       
   656         {
       
   657         // Need more data from the ICL framework
       
   658         User::Leave( KErrUnderflow );
       
   659         }
       
   660 
       
   661     iPtr = iBufferDes.Ptr();
       
   662 
       
   663     // Substract next box's KJ2kBoxTypeLength
       
   664     const TUint8 *ptrLimit = iPtr + iBoxLength - KJ2kBoxTypeLength;
       
   665 
       
   666     // Advance the pointer by 8 bytes if XLBox exists
       
   667     iPtr += ( xlBoxExist * KJ2kBoxTypeLength );
       
   668 
       
   669     // Check Brand ( BR ) or Major Version
       
   670     if ( PtrReadUtil::ReadBigEndianUint32Inc( iPtr ) != KJ2kFileTypeBrand )
       
   671         {
       
   672         // It is ok at this point if Major Version does not match
       
   673         iPtr += 0;
       
   674         }
       
   675 
       
   676     // Check Minor Version ( MinV )
       
   677     if ( PtrReadUtil::ReadBigEndianUint32Inc( iPtr ) != KJ2kFileTypeMinV )
       
   678         {
       
   679         // It is ok at this point if Minor Version does not match
       
   680         iPtr += 0;
       
   681         }
       
   682 
       
   683     // Check Compatibility List ( CL )
       
   684     TBool clFound = EFalse;
       
   685     TUint32 clField = 0;
       
   686     while ( ( iPtr + 4 ) <= ptrLimit  )
       
   687         {
       
   688         clField = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
   689         if ( clField == KJ2kFileTypeBrand )
       
   690             {
       
   691             clFound = ETrue;
       
   692             }
       
   693         else if ( clField == KJ2kFileTypeProfile0 )
       
   694             {
       
   695             iJ2kInfo.iOption |= TJ2kInfo::EProfile0;
       
   696             }
       
   697         else if ( clField == KJ2kFileTypeProfile1 )
       
   698             {
       
   699             iJ2kInfo.iOption |= TJ2kInfo::EProfile1;
       
   700             }
       
   701         else
       
   702             {
       
   703             // other file types require no action
       
   704             }
       
   705         }
       
   706 
       
   707     if ( !clFound || iPtr != ptrLimit )
       
   708         {
       
   709         // Unrecognized compatibility list or data misaligned
       
   710         User::Leave( KErrCorrupt );
       
   711         }
       
   712 
       
   713     iLastRead += iBoxLength;
       
   714     iState = EStateInUnknown;
       
   715 
       
   716     if ( (TUint32)iBufferDes.Length() < iBoxLength )
       
   717         {
       
   718         // Need more data from the ICL framework
       
   719         User::Leave( KErrUnderflow );
       
   720         }
       
   721     }
       
   722 
       
   723 // -----------------------------------------------------------------------------
       
   724 // CJp2kDecoder::ReadJp2HeaderBoxL
       
   725 // Verify and process the JP2 Header box ( superbox ).
       
   726 // (other items were commented in a header).
       
   727 // -----------------------------------------------------------------------------
       
   728 //
       
   729 void CJp2kDecoder::ReadJp2HeaderBoxL()
       
   730     {
       
   731     // Since we are getting data from ICL framework
       
   732     // we have no control of when will be the EOF
       
   733     if ( iBoxLength == 0 )
       
   734         {
       
   735         User::Leave( KErrCorrupt );
       
   736         }
       
   737 
       
   738     TUint8 xlBoxExist = 0;
       
   739     if ( iBoxLength == 1 )
       
   740         {
       
   741         // The XLBox shall exist and contains the actual length of the box
       
   742         // XLBox is 8 bytes width
       
   743         ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, KJ2kBoxTypeLength );
       
   744 
       
   745         if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength )
       
   746             {
       
   747             // Need more data from the ICL framework
       
   748             User::Leave( KErrUnderflow );
       
   749             }
       
   750 
       
   751         iPtr = iBufferDes.Ptr();
       
   752         iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
   753         iBoxLength += PtrReadUtil::ReadBigEndianUint32( iPtr );
       
   754         xlBoxExist = 1;
       
   755         }
       
   756 
       
   757     // Corrupted box length
       
   758     if ( ( (TInt32)iBoxLength ) <= 0 )
       
   759         {
       
   760         User::Leave( KErrCorrupt );
       
   761         }
       
   762 
       
   763     // Validate the JP2 Header Super Box
       
   764     // Read the JP2 box + the next box's Length and Type
       
   765     ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, iBoxLength );
       
   766 
       
   767     if ( (TUint32)iBufferDes.Length() < iBoxLength - KJ2kBoxTypeLength )
       
   768         {
       
   769         // Need more data from the ICL framework
       
   770         User::Leave( KErrUnderflow );
       
   771         }
       
   772 
       
   773     // Make sure that JP2 Header box contains enough data
       
   774     // for Image Header box
       
   775     if ( iBoxLength - KJ2kBoxTypeLength < KJ2kImageHeaderBoxLength )
       
   776         {
       
   777         // Missing Image Header box
       
   778         User::Leave( KErrCorrupt );
       
   779         }
       
   780 
       
   781     iPtr = iBufferDes.Ptr();
       
   782 
       
   783     // Advance the pointer by 8 bytes if XLBox exists
       
   784     iPtr += ( xlBoxExist * KJ2kBoxTypeLength );
       
   785 
       
   786     // Image Header box shall be the first box within JP2 Header box
       
   787     ReadImageHeaderBoxL();
       
   788 
       
   789     TUint32 subBoxLength = 0;
       
   790     TUint32 subBoxType = 0;
       
   791 
       
   792     // Substract next box's Length and Type
       
   793     const TUint8 *ptrLimit = iPtr + iBoxLength - KJ2kBoxTypeLength - KJ2kImageHeaderBoxLength;
       
   794     TInt32 length = ptrLimit - iPtr;
       
   795     TBool  csFound = EFalse;
       
   796 
       
   797     while ( length > 0 )
       
   798         {
       
   799         if ( ( ptrLimit - iPtr ) < 8  )
       
   800             {
       
   801             // Not enough room for box data
       
   802             User::Leave( KErrCorrupt );
       
   803             }
       
   804 
       
   805         subBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
   806         subBoxType = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
   807 
       
   808         if ( subBoxLength == 1 )
       
   809             {
       
   810             // The XLBox shall exist and contains the actual length of the box
       
   811             // XLBox is 8 bytes width
       
   812             subBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
   813             subBoxLength += PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
   814             length -= KJ2kBoxTypeLength;
       
   815             subBoxLength -= KJ2kBoxTypeLength;
       
   816             }
       
   817 
       
   818         if ( ( (TInt32)subBoxLength ) < 0 || ( subBoxLength <= 8 ) || ( ( iPtr + subBoxLength - KJ2kBoxTypeLength ) > ptrLimit ) )
       
   819             {
       
   820             // Not enough room for subbox data or corrupted subbox length
       
   821             User::Leave( KErrCorrupt );
       
   822             }
       
   823 
       
   824         switch ( subBoxType )
       
   825             {
       
   826             case KJ2kColourSpecBoxType:
       
   827                 {
       
   828                 if ( !csFound )
       
   829                     {
       
   830                     // Colour Spec Box
       
   831                     ReadColorSpecBoxL( subBoxLength );
       
   832                     csFound = ETrue;
       
   833                     }
       
   834                 else
       
   835                     {
       
   836                     // Ignore the second Colour Spec Box,
       
   837                     // just advance the iterator pointer
       
   838                     iPtr += subBoxLength - KJ2kBoxTypeLength;
       
   839                     }
       
   840                 break;
       
   841                 }
       
   842             case KJ2kResolutionBoxType:
       
   843                 {
       
   844                 // Resolution box ( superbox )
       
   845                 ReadResolutionBoxL( ptrLimit, subBoxLength );
       
   846                 break;
       
   847                 }
       
   848             case KJ2kBitsPerCompBoxType:
       
   849                 {
       
   850                 // Bits Per Component Box
       
   851                 ReadBitsPerCompBoxL( subBoxLength );
       
   852                 break;
       
   853                 }
       
   854             case KJ2kPaletterBoxType:
       
   855                 {
       
   856                 // Palette Box
       
   857                 ReadPaletteBoxL();
       
   858                 break;
       
   859                 }
       
   860             case KJ2kComponentMapBoxType:
       
   861                 {
       
   862                 // Component Mapping Box
       
   863                 ReadComponentMapBoxL( subBoxLength );
       
   864                 break;
       
   865                 }
       
   866             case KJ2kChannelDefBoxType:
       
   867                 {
       
   868                 // Channel Definition Box
       
   869                 ReadChannelDefBoxL( subBoxLength );
       
   870                 break;
       
   871                 }
       
   872             default:
       
   873                 {
       
   874                 // Unrecognized Box
       
   875                 User::Leave( KErrCorrupt );
       
   876                 break;
       
   877                 }
       
   878             }
       
   879         length -= subBoxLength;
       
   880         }
       
   881 
       
   882     iLastRead += iBoxLength;
       
   883     iState = EStateInUnknown;
       
   884 
       
   885     // JP2 Header processed
       
   886     iJ2kInfo.iOption |= TJ2kInfo::EJP2Header;
       
   887 
       
   888     if ( (TUint32)iBufferDes.Length() < iBoxLength )
       
   889         {
       
   890         // Need more data from the ICL framework
       
   891         User::Leave( KErrUnderflow );
       
   892         }
       
   893     }
       
   894 
       
   895 // -----------------------------------------------------------------------------
       
   896 // CJp2kDecoder::ReadImageHeaderBoxL
       
   897 // Verify and process the Image Header box ( in JP2 Header box ).
       
   898 // (other items were commented in a header).
       
   899 // -----------------------------------------------------------------------------
       
   900 //
       
   901 void CJp2kDecoder::ReadImageHeaderBoxL()
       
   902     {
       
   903     // Validate the Image Header Box
       
   904     if ( ( PtrReadUtil::ReadBigEndianUint32Inc( iPtr ) != KJ2kImageHeaderBoxLength ) ||
       
   905          ( PtrReadUtil::ReadBigEndianUint32Inc( iPtr ) != KJ2kImageHeaderBoxType ) )
       
   906         {
       
   907         // Unrecognized Image Header box
       
   908         User::Leave( KErrCorrupt );
       
   909         }
       
   910 
       
   911     iJ2kInfo.iImageSize.iHeight = (TInt)PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
   912     iJ2kInfo.iImageSize.iWidth = (TInt)PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
   913     iJ2kInfo.iNC  = PtrReadUtil::ReadBigEndianUint16Inc( iPtr );
       
   914     iJ2kInfo.iBPC = *iPtr++;
       
   915 
       
   916     if ( (iJ2kInfo.iImageSize.iHeight <= 0) || (iJ2kInfo.iImageSize.iWidth <= 0) ||
       
   917          (iJ2kInfo.iNC == 0) || (iJ2kInfo.iBPC == 0) )
       
   918         {
       
   919         // Corrupted image parameters
       
   920         User::Leave( KErrCorrupt );
       
   921         }
       
   922 
       
   923     if ( *iPtr++ != KJ2kImageHeaderCompressionType )
       
   924         {
       
   925         // Unrecognized compression type
       
   926         User::Leave( KErrCorrupt );
       
   927         }
       
   928 
       
   929     // Check color space - UnkC
       
   930     TUint8 value = *iPtr++;
       
   931     if ( value == 0 || value == 1 )
       
   932         {
       
   933         iJ2kInfo.iOption |= ( value == 0 ) ? TJ2kInfo::EColorSpec : 0;
       
   934         }
       
   935     else
       
   936         {
       
   937         // Unrecognized color space
       
   938         User::Leave( KErrCorrupt );
       
   939         }
       
   940 
       
   941     // Check intellectual property - IPR 
       
   942     value = *iPtr++;
       
   943     if ( value == 0 || value == 1 )
       
   944         {
       
   945         iJ2kInfo.iOption |= value;
       
   946         }
       
   947     else
       
   948         {
       
   949         // Unrecognized intellectual property
       
   950         User::Leave( KErrCorrupt );
       
   951         }
       
   952     }
       
   953 
       
   954 // -----------------------------------------------------------------------------
       
   955 // CJp2kDecoder::ReadColorSpecBoxL
       
   956 // Verify and process the Colour Specification box ( in JP2 Header box ).
       
   957 // (other items were commented in a header).
       
   958 // -----------------------------------------------------------------------------
       
   959 //
       
   960 void CJp2kDecoder::ReadColorSpecBoxL( const TUint32 aBoxLength )
       
   961     {
       
   962     // Validate the Color Specification Box
       
   963     TUint8 method = *iPtr++;
       
   964 
       
   965     if ( method != 1 && method != 2 )
       
   966         {
       
   967         // Unrecognized method
       
   968         User::Leave( KErrCorrupt );
       
   969         }
       
   970 
       
   971     // Ignore the precedence
       
   972     iPtr++;
       
   973 
       
   974     // Ignore the approximation
       
   975     iPtr++;
       
   976 
       
   977     if ( method == 1 )
       
   978         {
       
   979         // Method must be 1 if we reach this point
       
   980         iJ2kInfo.iEnumCS = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
   981         switch ( iJ2kInfo.iEnumCS )
       
   982             {
       
   983             case 16:
       
   984             case 17:
       
   985             case 18:
       
   986             case 21:
       
   987             case 22:
       
   988                 {
       
   989                 break;
       
   990                 }
       
   991             default:
       
   992                 {
       
   993                 // Unrecognized colour specification
       
   994                 User::Leave( KErrNotSupported );
       
   995                 break;
       
   996                 }
       
   997             }
       
   998         }
       
   999     else
       
  1000         {
       
  1001         // ICC profile
       
  1002         TUint32 length = (TUint32)( aBoxLength - KJ2kBoxTypeLength - 3 );
       
  1003         iJ2kInfo.iICCProfile = HBufC8::NewL( length );
       
  1004         iJ2kInfo.iICCProfile->Des().Append( iPtr, length );
       
  1005         iPtr += length;
       
  1006         }
       
  1007     }
       
  1008 
       
  1009 // -----------------------------------------------------------------------------
       
  1010 // CJp2kDecoder::ReadBitsPerCompBoxL
       
  1011 // Verify and process the Bits Per Component box ( in JP2 Header box ).
       
  1012 // (other items were commented in a header).
       
  1013 // -----------------------------------------------------------------------------
       
  1014 //
       
  1015 void CJp2kDecoder::ReadBitsPerCompBoxL( TUint32 aBoxLength )
       
  1016     {
       
  1017     if ( iJ2kInfo.iBPC != KJ2kIsBPCBoxExist )
       
  1018         {
       
  1019         // Should not happen but we just advance 
       
  1020         // the iterator and ignore the whole box
       
  1021         iPtr += aBoxLength - KJ2kBoxTypeLength;
       
  1022         return;
       
  1023         }
       
  1024 
       
  1025     // Validate the Bits Per Component Box
       
  1026     if ( ( aBoxLength - KJ2kBoxTypeLength ) != iJ2kInfo.iNC  )
       
  1027         {
       
  1028         // Unrecognized number of components
       
  1029         User::Leave( KErrCorrupt );
       
  1030         }
       
  1031 
       
  1032     while ( aBoxLength > KJ2kBoxTypeLength )
       
  1033         {
       
  1034         User::LeaveIfError( iJ2kInfo.iBPCList.Append( *iPtr++ ) );
       
  1035 
       
  1036         --aBoxLength;
       
  1037         }
       
  1038     }
       
  1039 
       
  1040 // -----------------------------------------------------------------------------
       
  1041 // CJp2kDecoder::ReadResolutionBoxL
       
  1042 // Verify and process the Resolution box ( in JP2 Header box, 
       
  1043 // (other items were commented in a header).
       
  1044 // -----------------------------------------------------------------------------
       
  1045 //
       
  1046 void CJp2kDecoder::ReadResolutionBoxL( const TUint8 *aPtrLimit, TUint32 aBoxLength )
       
  1047     {
       
  1048     TUint32 subBoxLength = 0;
       
  1049     TUint32 subBoxType = 0;
       
  1050 
       
  1051     aBoxLength -= KJ2kBoxTypeLength;
       
  1052     while ( aBoxLength > 0 )
       
  1053         {
       
  1054         if ( (TUint32)( aPtrLimit - iPtr ) < KJ2kResSubBoxLength )
       
  1055             {
       
  1056             // Not enough room for subbox data
       
  1057             User::Leave( KErrCorrupt );
       
  1058             }
       
  1059 
       
  1060         subBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
  1061         subBoxType = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
  1062 
       
  1063         if ( subBoxLength == 1 )
       
  1064             {
       
  1065             // The XLBox shall exist and contains the actual length of the box
       
  1066             // XLBox is 8 bytes width
       
  1067             subBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
  1068             subBoxLength += PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
  1069             aBoxLength -= KJ2kBoxTypeLength;
       
  1070             subBoxLength -= KJ2kBoxTypeLength;
       
  1071             }
       
  1072 
       
  1073         if ( subBoxLength != KJ2kResSubBoxLength )
       
  1074             {
       
  1075             // Corrupted resolution box length, both sub boxes have length of 18
       
  1076             User::Leave( KErrCorrupt );
       
  1077             }
       
  1078 
       
  1079         if ( subBoxType == KJ2kCaptureResBoxType )
       
  1080             {
       
  1081             ReadCaptureResBoxL( subBoxLength );
       
  1082             }
       
  1083         else if ( subBoxType == KJ2kDisplayResBoxType )
       
  1084             {
       
  1085             ReadDisplayResBoxL(  );
       
  1086             }
       
  1087         else
       
  1088             {
       
  1089             // Unrecognized box in Resolution super box
       
  1090             User::Leave( KErrCorrupt );
       
  1091             }
       
  1092         aBoxLength -= subBoxLength;
       
  1093         }
       
  1094     }
       
  1095 
       
  1096 // -----------------------------------------------------------------------------
       
  1097 // CJp2kDecoder::ReadDisplayResBoxL
       
  1098 // Verify and process the Default Display Resolution box ( in Resolution box ).
       
  1099 // (other items were commented in a header).
       
  1100 // -----------------------------------------------------------------------------
       
  1101 //
       
  1102 void CJp2kDecoder::ReadDisplayResBoxL()
       
  1103     {
       
  1104     // Store default display resolution
       
  1105     TUint16 verNum = PtrReadUtil::ReadBigEndianUint16Inc( iPtr );
       
  1106     TUint16 verDen = PtrReadUtil::ReadBigEndianUint16Inc( iPtr );
       
  1107     TUint16 horNum = PtrReadUtil::ReadBigEndianUint16Inc( iPtr );
       
  1108     TUint16 horDen = PtrReadUtil::ReadBigEndianUint16Inc( iPtr );
       
  1109     TUint8  verExp = *iPtr++;
       
  1110     TUint8  horExp = *iPtr++;
       
  1111     TReal   tenPow = 0.0;
       
  1112 
       
  1113     // Check  the validity of the parameters
       
  1114     if((verNum == 0) || (verDen == 0) || (horNum == 0) || (horDen == 0))
       
  1115         {
       
  1116         // Values corrupted, do not try to compute the SizeInTwips
       
  1117         return;
       
  1118         }
       
  1119 
       
  1120     User::LeaveIfError( Math::Pow10( tenPow, verExp ) );
       
  1121 
       
  1122     TReal result = ( iJ2kInfo.iImageSize.iWidth / ( ( (TReal)verNum / verDen ) * tenPow ) ) / KJ2kTwipM;
       
  1123     iJ2kInfo.iImageSizeInTwips.iWidth = (TInt)result;
       
  1124 
       
  1125     User::LeaveIfError( Math::Pow10( tenPow,horExp ) );
       
  1126 
       
  1127     result = ( iJ2kInfo.iImageSize.iHeight / ( ( (TReal)horNum / horDen ) * tenPow ) ) / KJ2kTwipM;
       
  1128     iJ2kInfo.iImageSizeInTwips.iHeight = (TInt)result;
       
  1129     }
       
  1130 
       
  1131 // -----------------------------------------------------------------------------
       
  1132 // CJp2kDecoder::ReadCaptureResBoxL
       
  1133 // Verify and process the Capture Resolution box ( in Resolution box ).
       
  1134 // (other items were commented in a header).
       
  1135 // -----------------------------------------------------------------------------
       
  1136 //
       
  1137 void CJp2kDecoder::ReadCaptureResBoxL( const TUint32 aBoxLength )
       
  1138     {
       
  1139     // Ignore the capture resolution
       
  1140     iPtr += aBoxLength - KJ2kBoxTypeLength;
       
  1141     }
       
  1142 
       
  1143 // -----------------------------------------------------------------------------
       
  1144 // CJp2kDecoder::ReadPaletteBoxL
       
  1145 // Verify and process the Palette box ( in JP2 Header box ).
       
  1146 // (other items were commented in a header).
       
  1147 // -----------------------------------------------------------------------------
       
  1148 //
       
  1149 void CJp2kDecoder::ReadPaletteBoxL()
       
  1150     {
       
  1151     // Validate the Palette Box
       
  1152     TUint16 entries = PtrReadUtil::ReadBigEndianUint16Inc( iPtr );
       
  1153     TUint8  npc = *iPtr++;
       
  1154 
       
  1155     if((entries > KMaxPaletteEntries) || (entries == 0))
       
  1156         {
       
  1157         // Number of entries must be between 1 and 1024
       
  1158         User::Leave( KErrCorrupt );
       
  1159         }
       
  1160 
       
  1161     TInt rowIndex = 0;
       
  1162     TInt columnIndex = 0;
       
  1163     RArray<TUint> bpcInBytes;
       
  1164     TUint8 bpc = 0;
       
  1165 
       
  1166     for ( rowIndex = 0; rowIndex < npc; ++rowIndex )
       
  1167         {
       
  1168         bpc = *iPtr++;
       
  1169         User::LeaveIfError( iJ2kInfo.iPalette.iBList.Append( bpc ) );
       
  1170 
       
  1171         bpc = (TUint8)( ( 0x7f & bpc ) + 1 );
       
  1172         User::LeaveIfError( bpcInBytes.Append( (TUint)( ( bpc % 8 ) ? bpc / 8 + 1 : bpc / 8 ) ) );
       
  1173         }
       
  1174 
       
  1175     RArray<TUint> *cList;
       
  1176     CleanupClosePushL( bpcInBytes );
       
  1177 
       
  1178     for ( rowIndex = 0; rowIndex < entries; ++rowIndex )
       
  1179         {
       
  1180         cList = new ( ELeave ) RArray<TUint>( npc );
       
  1181         CleanupStack::PushL( cList );
       
  1182         CleanupClosePushL( *cList );
       
  1183 
       
  1184         for ( columnIndex = 0; columnIndex < npc; ++columnIndex )
       
  1185             {
       
  1186             switch ( bpcInBytes[columnIndex] )
       
  1187                 {
       
  1188                 case 1:
       
  1189                     {
       
  1190                     User::LeaveIfError( cList->Append( (TUint)*iPtr++ ) );
       
  1191                     break;
       
  1192                     }
       
  1193                 case 2:
       
  1194                     {
       
  1195                     User::LeaveIfError( cList->Append( (TUint)PtrReadUtil::ReadBigEndianUint16Inc( iPtr ) ) );
       
  1196                     break;
       
  1197                     }
       
  1198                 case 3:
       
  1199                     {
       
  1200                     bpc = *iPtr++;
       
  1201                     User::LeaveIfError( cList->Append( ( (TUint)bpc << 16 ) | PtrReadUtil::ReadBigEndianUint16Inc( iPtr ) ) );
       
  1202                     break;
       
  1203                     }
       
  1204                 case 4:
       
  1205                     {
       
  1206                     User::LeaveIfError( cList->Append( PtrReadUtil::ReadBigEndianUint32Inc( iPtr ) ) );
       
  1207                     break;
       
  1208                     }
       
  1209                 default:
       
  1210                     {
       
  1211                     // Unrecognized index
       
  1212                     User::Leave( KErrCorrupt );
       
  1213                     break;
       
  1214                     }
       
  1215                 }
       
  1216             }
       
  1217         User::LeaveIfError( iJ2kInfo.iPalette.iC2DArray.Append( cList ) );
       
  1218         CleanupStack::Pop(2);
       
  1219         }
       
  1220     CleanupStack::PopAndDestroy();
       
  1221     }
       
  1222 
       
  1223 // -----------------------------------------------------------------------------
       
  1224 // CJp2kDecoder::ReadComponentMapBoxL
       
  1225 // Verify and process the Component Mapping box ( in JP2 Header box ).
       
  1226 // (other items were commented in a header).
       
  1227 // -----------------------------------------------------------------------------
       
  1228 //
       
  1229 void CJp2kDecoder::ReadComponentMapBoxL( TUint32 aBoxLength )
       
  1230     {
       
  1231     // Validate the Component Mapping Box
       
  1232     if ( ( aBoxLength - KJ2kBoxTypeLength ) % 4 != 0 )
       
  1233         {
       
  1234         // Misaligned Component Mapping box
       
  1235         User::Leave( KErrCorrupt );    
       
  1236         }
       
  1237 
       
  1238     TUint16 cmp = 0;
       
  1239     TUint8 mtyp = 0;
       
  1240     TUint8 pcol = 0;
       
  1241 
       
  1242     while ( aBoxLength > KJ2kBoxTypeLength )
       
  1243         {
       
  1244         cmp = PtrReadUtil::ReadBigEndianUint16Inc( iPtr );
       
  1245 
       
  1246         if(cmp > KMaxComponents)
       
  1247             {
       
  1248             // Illegal component index
       
  1249             User::Leave( KErrCorrupt );    
       
  1250             }
       
  1251 
       
  1252         mtyp = *iPtr++;
       
  1253         pcol = *iPtr++;
       
  1254         if ( mtyp == 0 || mtyp == 1 )
       
  1255             {
       
  1256             if ( mtyp == 0 && pcol != 0 )
       
  1257                 {
       
  1258                 // Unrecognized matching between MTYP and PCOL
       
  1259                 User::Leave( KErrCorrupt );
       
  1260                 }
       
  1261             }
       
  1262         else
       
  1263             {
       
  1264             // Unrecognized MTYP
       
  1265             User::Leave( KErrCorrupt );
       
  1266             }
       
  1267 
       
  1268         User::LeaveIfError( iJ2kInfo.iCMPList.Append( TComponentMap( cmp, mtyp, pcol ) ) );
       
  1269         aBoxLength -= 4;
       
  1270         }
       
  1271     }
       
  1272 
       
  1273 // -----------------------------------------------------------------------------
       
  1274 // CJp2kDecoder::ReadChannelDefBoxL
       
  1275 // Verify and process the Channel Definition box ( in JP2 Header box ).
       
  1276 // (other items were commented in a header).
       
  1277 // -----------------------------------------------------------------------------
       
  1278 //
       
  1279 void CJp2kDecoder::ReadChannelDefBoxL( TUint32 aBoxLength )
       
  1280     {
       
  1281     // Validate the Channel Definition Box
       
  1282     TUint16 entries = PtrReadUtil::ReadBigEndianUint16Inc( iPtr );
       
  1283     if ( ( aBoxLength - KJ2kBoxTypeLength - 2 ) / 6 != entries )
       
  1284         {
       
  1285         // Misaligned Channel Definition box
       
  1286         User::Leave( KErrCorrupt );
       
  1287         }
       
  1288 
       
  1289     TUint16 cn = 0;
       
  1290     TUint16 typ = 0;
       
  1291     TUint16 asoc = 0;
       
  1292 
       
  1293     while ( entries != 0 )
       
  1294         {
       
  1295         cn   = PtrReadUtil::ReadBigEndianUint16Inc( iPtr );
       
  1296         typ  = PtrReadUtil::ReadBigEndianUint16Inc( iPtr );
       
  1297         asoc = PtrReadUtil::ReadBigEndianUint16Inc( iPtr );
       
  1298         User::LeaveIfError( iJ2kInfo.iCNList.Append( TChannelDefinition( cn, typ, asoc ) ) );
       
  1299         --entries;
       
  1300         }
       
  1301     }
       
  1302 
       
  1303 // -----------------------------------------------------------------------------
       
  1304 // CJp2kDecoder::ReadIPRBoxL
       
  1305 // Verify and process the IPR box .
       
  1306 // (other items were commented in a header).
       
  1307 // -----------------------------------------------------------------------------
       
  1308 //
       
  1309 void CJp2kDecoder::ReadIPRBoxL()
       
  1310     {
       
  1311     // Check whether this IPR box is the last box in the file
       
  1312     if ( iBoxLength == 0 )
       
  1313         {
       
  1314         // This IPR box is the last box in the file
       
  1315         if ( iJ2kInfo.iCSOffset != 0 )
       
  1316             {
       
  1317             // CodeStream box has been recognized
       
  1318             // Since we are not able to read til the
       
  1319             // end of file/stream, we will skip this
       
  1320             // IPR box
       
  1321             iState = EStateInCodestreamBox;
       
  1322             return;
       
  1323             }
       
  1324         else
       
  1325             {
       
  1326             // The CodeStream box is missing from the file
       
  1327             // and nothing can be decoded
       
  1328             User::Leave( KErrCorrupt );
       
  1329             }
       
  1330         }
       
  1331 
       
  1332     TUint xlBoxExist = 0;
       
  1333     if ( iBoxLength == 1 )
       
  1334         {
       
  1335         // The XLBox shall exist and contains the actual length of the box
       
  1336         // XLBox is 8 bytes width
       
  1337         ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, KJ2kBoxTypeLength );
       
  1338 
       
  1339         if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength )
       
  1340             {
       
  1341             // Need more data from the ICL framework
       
  1342             User::Leave( KErrUnderflow );
       
  1343             }
       
  1344 
       
  1345         iPtr = iBufferDes.Ptr();
       
  1346         iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
  1347         iBoxLength += PtrReadUtil::ReadBigEndianUint32( iPtr );
       
  1348         xlBoxExist = 1;
       
  1349         }
       
  1350 
       
  1351     // Corrupted box length
       
  1352     if ( ( (TInt32)iBoxLength ) < 0 )
       
  1353         {
       
  1354         User::Leave( KErrCorrupt );
       
  1355         }
       
  1356 
       
  1357     // Check whether this IPR box is the last box in the file
       
  1358     if ( iBoxLength == 0 )
       
  1359         {
       
  1360         // This IPR box is the last box in the file
       
  1361         if ( iJ2kInfo.iCSOffset != 0 )
       
  1362             {
       
  1363             // CodeStream box has been recognized
       
  1364             // Since we are not able to read til the
       
  1365             // end of file/stream, we will skip this
       
  1366             // IPR box
       
  1367             iState = EStateInCodestreamBox;
       
  1368             return;
       
  1369             }
       
  1370         else
       
  1371             {
       
  1372             // The CodeStream box is missing from the file
       
  1373             // and nothing can be decoded
       
  1374             User::Leave( KErrCorrupt );
       
  1375             }
       
  1376         }
       
  1377 
       
  1378     // Validate the IPR Box
       
  1379     // Read the IPR box + the next box's Length and Type
       
  1380     ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, iBoxLength );
       
  1381 
       
  1382     if ( (TUint32)iBufferDes.Length() < iBoxLength - KJ2kBoxTypeLength )
       
  1383         {
       
  1384         // Need more data from the ICL framework
       
  1385         User::Leave( KErrUnderflow );
       
  1386         }
       
  1387 
       
  1388     iPtr = iBufferDes.Ptr();
       
  1389 
       
  1390     // Advance the pointer by 8 bytes if XLBox exists
       
  1391     iPtr += ( xlBoxExist * KJ2kBoxTypeLength );
       
  1392 
       
  1393     TInt length = iBoxLength - ( ( 1 + xlBoxExist ) * KJ2kBoxTypeLength );
       
  1394 
       
  1395     HBufC8 *iprBuffer = HBufC8::NewLC( length );
       
  1396     iprBuffer->Des().Append( iPtr, length );
       
  1397     iPtr += length;
       
  1398 
       
  1399     User::LeaveIfError( iJ2kInfo.iIPRList.Append( iprBuffer ) );
       
  1400     CleanupStack::Pop(); // iprBuffer
       
  1401 
       
  1402     iLastRead += iBoxLength;
       
  1403     iState = EStateInUnknown;
       
  1404 
       
  1405     if ( (TUint32)iBufferDes.Length() < iBoxLength )
       
  1406         {
       
  1407         // Test the end of file/stream 
       
  1408         ReadDataL( iLastRead, iBufferDes, 1 );
       
  1409         if ( ( (TUint32)iBufferDes.Length() == 0 ) &&
       
  1410              ( iJ2kInfo.iCSOffset != 0 ) )
       
  1411             {
       
  1412             // CodeStream box has been recognized
       
  1413             iState = EStateInCodestreamBox;
       
  1414             }
       
  1415         else
       
  1416             {
       
  1417             // Need more data from the ICL framework
       
  1418             User::Leave( KErrUnderflow );
       
  1419             }
       
  1420         }
       
  1421     }
       
  1422 
       
  1423 // -----------------------------------------------------------------------------
       
  1424 // CJp2kDecoder::ReadXMLBoxL
       
  1425 // Verify and process the XML box.
       
  1426 // (other items were commented in a header).
       
  1427 // -----------------------------------------------------------------------------
       
  1428 //
       
  1429 void CJp2kDecoder::ReadXMLBoxL()
       
  1430     {
       
  1431     // Check whether this XML box is the last box in the file
       
  1432     if ( iBoxLength == 0 )
       
  1433         {
       
  1434         // This XML box is the last box in the file
       
  1435         if ( iJ2kInfo.iCSOffset != 0 )
       
  1436             {
       
  1437             // CodeStream box has been recognized
       
  1438             // Since we are not able to read til the
       
  1439             // end of file/stream, we will skip this
       
  1440             // XML box
       
  1441             iState = EStateInCodestreamBox;
       
  1442             return;
       
  1443             }
       
  1444         else
       
  1445             {
       
  1446             // The CodeStream box is missing from the file
       
  1447             // and nothing can be decoded
       
  1448             User::Leave( KErrCorrupt );
       
  1449             }
       
  1450         }
       
  1451 
       
  1452     TUint xlBoxExist = 0;
       
  1453     if ( iBoxLength == 1 )
       
  1454         {
       
  1455         // The XLBox shall exist and contains the actual length of the box
       
  1456         // XLBox is 8 bytes width
       
  1457         ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, KJ2kBoxTypeLength );
       
  1458 
       
  1459         if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength )
       
  1460             {
       
  1461             // Need more data from the ICL framework
       
  1462             User::Leave( KErrUnderflow );
       
  1463             }
       
  1464 
       
  1465         iPtr = iBufferDes.Ptr();
       
  1466         iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
  1467         iBoxLength += PtrReadUtil::ReadBigEndianUint32( iPtr );
       
  1468         xlBoxExist = 1;
       
  1469         }
       
  1470 
       
  1471     // Corrupted box length
       
  1472     if ( ( (TInt32)iBoxLength ) < 0 )
       
  1473         {
       
  1474         User::Leave( KErrCorrupt );
       
  1475         }
       
  1476 
       
  1477     // Check whether this XML box is the last box in the file
       
  1478     if ( iBoxLength == 0 )
       
  1479         {
       
  1480         // This XML box is the last box in the file
       
  1481         if ( iJ2kInfo.iCSOffset != 0 )
       
  1482             {
       
  1483             // CodeStream box has been recognized
       
  1484             // Since we are not able to read til the
       
  1485             // end of file/stream, we will skip this
       
  1486             // XML box
       
  1487             iState = EStateInCodestreamBox;
       
  1488             return;
       
  1489             }
       
  1490         else
       
  1491             {
       
  1492             // The CodeStream box is missing from the file
       
  1493             // and nothing can be decoded
       
  1494             User::Leave( KErrCorrupt );
       
  1495             }
       
  1496         }
       
  1497 
       
  1498     // Validate the XML Box
       
  1499     // Read the XML box + the next box's Length and Type
       
  1500     ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, iBoxLength );
       
  1501 
       
  1502     if ( (TUint32)iBufferDes.Length() < iBoxLength - KJ2kBoxTypeLength )
       
  1503         {
       
  1504         // Need more data from the ICL framework
       
  1505         User::Leave( KErrUnderflow );
       
  1506         }
       
  1507 
       
  1508     iPtr = iBufferDes.Ptr();
       
  1509 
       
  1510     // Advance the pointer by 8 bytes if XLBox exists
       
  1511     iPtr += ( xlBoxExist * KJ2kBoxTypeLength );
       
  1512 
       
  1513     TInt length = iBoxLength - ( ( 1 + xlBoxExist ) * KJ2kBoxTypeLength );
       
  1514 
       
  1515     HBufC8 *xmlBuffer = HBufC8::NewLC( length );
       
  1516     xmlBuffer->Des().Append( iPtr, length );
       
  1517     iPtr += length;
       
  1518 
       
  1519     User::LeaveIfError( iJ2kInfo.iXMLList.Append( xmlBuffer ) );
       
  1520     CleanupStack::Pop(); // xmlBuffer
       
  1521 
       
  1522     iLastRead += iBoxLength;
       
  1523     iState = EStateInUnknown;
       
  1524 
       
  1525     if ( (TUint32)iBufferDes.Length() < iBoxLength )
       
  1526         {
       
  1527         // Test the end of file 
       
  1528         ReadDataL( iLastRead, iBufferDes, 1 );
       
  1529         if ( ( (TUint32)iBufferDes.Length() == 0 ) &&
       
  1530              ( iJ2kInfo.iCSOffset != 0 ) )
       
  1531             {
       
  1532             // CodeStream box has been recognized
       
  1533             iState = EStateInCodestreamBox;
       
  1534             }
       
  1535         else
       
  1536             {
       
  1537             // Need more data from the ICL framework
       
  1538             User::Leave( KErrUnderflow );
       
  1539             }
       
  1540         }
       
  1541     }
       
  1542 
       
  1543 // -----------------------------------------------------------------------------
       
  1544 // CJp2kDecoder::ReadUUIDBoxL
       
  1545 // Verify and process UUID box.
       
  1546 // (other items were commented in a header).
       
  1547 // -----------------------------------------------------------------------------
       
  1548 //
       
  1549 void CJp2kDecoder::ReadUUIDBoxL()
       
  1550     {
       
  1551     // Check whether this UUID box is the last box in the file
       
  1552     if ( iBoxLength == 0 )
       
  1553         {
       
  1554         // This UUID box is the last box in the file
       
  1555         if ( iJ2kInfo.iCSOffset != 0 )
       
  1556             {
       
  1557             // CodeStream box has been recognized
       
  1558             // Since we are not able to read til the
       
  1559             // end of file/stream, we will skip this
       
  1560             // UUID box
       
  1561             iState = EStateInCodestreamBox;
       
  1562             return;
       
  1563             }
       
  1564         else
       
  1565             {
       
  1566             // The CodeStream box is missing from the file
       
  1567             // and nothing can be decoded
       
  1568             User::Leave( KErrCorrupt );
       
  1569             }
       
  1570         }
       
  1571 
       
  1572     TUint xlBoxExist = 0;
       
  1573     if ( iBoxLength == 1 )
       
  1574         {
       
  1575         // The XLBox shall exist and contains the actual length of the box
       
  1576         // XLBox is 8 bytes width
       
  1577         ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, KJ2kBoxTypeLength );
       
  1578 
       
  1579         if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength )
       
  1580             {
       
  1581             // Need more data from the ICL framework
       
  1582             User::Leave( KErrUnderflow );
       
  1583             }
       
  1584 
       
  1585         iPtr = iBufferDes.Ptr();
       
  1586         iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
  1587         iBoxLength += PtrReadUtil::ReadBigEndianUint32( iPtr );
       
  1588         xlBoxExist = 1;
       
  1589         }
       
  1590 
       
  1591     // Corrupted box length
       
  1592     if ( ( (TInt32)iBoxLength ) < 0 )
       
  1593         {
       
  1594         User::Leave( KErrCorrupt );
       
  1595         }
       
  1596 
       
  1597     // Check whether this UUID box is the last box in the file
       
  1598     if ( iBoxLength == 0 )
       
  1599         {
       
  1600         // This UUID box is the last box in the file
       
  1601         if ( iJ2kInfo.iCSOffset != 0 )
       
  1602             {
       
  1603             // CodeStream box has been recognized
       
  1604             // Since we are not able to read til the
       
  1605             // end of file/stream, we will skip this
       
  1606             // UUID box
       
  1607             iState = EStateInCodestreamBox;
       
  1608             return;
       
  1609             }
       
  1610         else
       
  1611             {
       
  1612             // The CodeStream box is missing from the file
       
  1613             // and nothing can be decoded
       
  1614             User::Leave( KErrCorrupt );
       
  1615             }
       
  1616         }
       
  1617 
       
  1618     // Validate the UUID Box
       
  1619     // Read the UUID box + the next box's Length and Type
       
  1620     ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, iBoxLength );
       
  1621 
       
  1622     if ( (TUint32)iBufferDes.Length() < iBoxLength - KJ2kBoxTypeLength )
       
  1623         {
       
  1624         // Need more data from the ICL framework
       
  1625         User::Leave( KErrUnderflow );
       
  1626         }
       
  1627 
       
  1628     iPtr = iBufferDes.Ptr();
       
  1629 
       
  1630     // Advance the pointer by 8 bytes if XLBox exists
       
  1631     iPtr += ( xlBoxExist * KJ2kBoxTypeLength );
       
  1632 
       
  1633     TInt length = iBoxLength - ( ( 1 + xlBoxExist ) * KJ2kBoxTypeLength );
       
  1634 
       
  1635     HBufC8 *uuidBuffer = HBufC8::NewLC( length );
       
  1636     uuidBuffer->Des().Append( iPtr, length );
       
  1637     iPtr += length;
       
  1638 
       
  1639     User::LeaveIfError( iJ2kInfo.iUUIDList.Append( uuidBuffer ) );
       
  1640     CleanupStack::Pop(); // uuidBuffer
       
  1641 
       
  1642     iLastRead += iBoxLength;
       
  1643     iState = EStateInUnknown;
       
  1644 
       
  1645     if ( (TUint32)iBufferDes.Length() < iBoxLength )
       
  1646         {
       
  1647         // Test the end of file 
       
  1648         ReadDataL( iLastRead, iBufferDes, 1 );
       
  1649         if ( ( (TUint32)iBufferDes.Length() == 0 ) &&
       
  1650              ( iJ2kInfo.iCSOffset != 0 ) )
       
  1651             {
       
  1652             // CodeStream box has been recognized
       
  1653             iState = EStateInCodestreamBox;
       
  1654             }
       
  1655         else
       
  1656             {
       
  1657             // Need more data from the ICL framework
       
  1658             User::Leave( KErrUnderflow );
       
  1659             }
       
  1660         }
       
  1661     }
       
  1662 
       
  1663 // -----------------------------------------------------------------------------
       
  1664 // CJp2kDecoder::ReadUUIDInfoBoxL
       
  1665 // Verify and process the UUID Info box ( superbox ).
       
  1666 // (other items were commented in a header).
       
  1667 // -----------------------------------------------------------------------------
       
  1668 //
       
  1669 void CJp2kDecoder::ReadUUIDInfoBoxL()
       
  1670     {
       
  1671     // Check whether this UUIDInfo box is the last box in the file
       
  1672     if ( iBoxLength == 0 )
       
  1673         {
       
  1674         // This UUIDInfo box is the last box in the file
       
  1675         if ( iJ2kInfo.iCSOffset != 0 )
       
  1676             {
       
  1677             // CodeStream box has been recognized
       
  1678             // Since we are not able to read til the
       
  1679             // end of file/stream, we will skip this
       
  1680             // UUIDInfo box
       
  1681             iState = EStateInCodestreamBox;
       
  1682             return;
       
  1683             }
       
  1684         else
       
  1685             {
       
  1686             // The CodeStream box is missing from the file
       
  1687             // and nothing can be decoded
       
  1688             User::Leave( KErrCorrupt );
       
  1689             }
       
  1690         }
       
  1691 
       
  1692     TUint xlBoxExist = 0;
       
  1693     if ( iBoxLength == 1 )
       
  1694         {
       
  1695         // The XLBox shall exist and contains the actual length of the box
       
  1696         // XLBox is 8 bytes width
       
  1697         ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, KJ2kBoxTypeLength );
       
  1698 
       
  1699         if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength )
       
  1700             {
       
  1701             // Need more data from the ICL framework
       
  1702             User::Leave( KErrUnderflow );
       
  1703             }
       
  1704 
       
  1705         iPtr = iBufferDes.Ptr();
       
  1706         iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
  1707         iBoxLength += PtrReadUtil::ReadBigEndianUint32( iPtr );
       
  1708         xlBoxExist = 1;
       
  1709         }
       
  1710 
       
  1711     // Corrupted box length
       
  1712     if ( ( (TInt32)iBoxLength ) < 0 )
       
  1713         {
       
  1714         User::Leave( KErrCorrupt );
       
  1715         }
       
  1716 
       
  1717     // Check whether this UUIDInfo box is the last box in the file
       
  1718     if ( iBoxLength == 0 )
       
  1719         {
       
  1720         // This UUIDInfo box is the last box in the file
       
  1721         if ( iJ2kInfo.iCSOffset != 0 )
       
  1722             {
       
  1723             // CodeStream box has been recognized
       
  1724             // Since we are not able to read til the
       
  1725             // end of file/stream, we will skip this
       
  1726             // UUIDInfo box
       
  1727             iState = EStateInCodestreamBox;
       
  1728             return;
       
  1729             }
       
  1730         else
       
  1731             {
       
  1732             // The CodeStream box is missing from the file
       
  1733             // and nothing can be decoded
       
  1734             User::Leave( KErrCorrupt );
       
  1735             }
       
  1736         }
       
  1737 
       
  1738     // Validate the UUIDInfo Box
       
  1739     // Read the UUIDInfo box + the next box's Length and Type
       
  1740     ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, iBoxLength );
       
  1741 
       
  1742     if ( (TUint32)iBufferDes.Length() < iBoxLength - KJ2kBoxTypeLength )
       
  1743         {
       
  1744         // Need more data from the ICL framework
       
  1745         User::Leave( KErrUnderflow );
       
  1746         }
       
  1747 
       
  1748     iPtr = iBufferDes.Ptr();
       
  1749 
       
  1750     // Substract next box's Length and Type
       
  1751     const TUint8 *ptrLimit = iPtr + iBoxLength - KJ2kBoxTypeLength;
       
  1752 
       
  1753     // Advance the pointer by 8 bytes if XLBox exists
       
  1754     iPtr += ( xlBoxExist * KJ2kBoxTypeLength );
       
  1755 
       
  1756     TUint32 subBoxLength = 0;
       
  1757     TUint32 subBoxType = 0;
       
  1758 
       
  1759     TInt32 length = ptrLimit - iPtr;
       
  1760     TInt32 dataLength = 0;
       
  1761     TInt32 order = 0;
       
  1762 
       
  1763     HBufC8 *listBuffer = 0;
       
  1764     HBufC8 *urlBuffer = 0;
       
  1765 
       
  1766     while ( length > 0 )
       
  1767         {
       
  1768         if ( ( ptrLimit - iPtr ) < 8  )
       
  1769             {
       
  1770             // Not enough room for box data
       
  1771             User::Leave( KErrCorrupt );
       
  1772             }
       
  1773 
       
  1774         subBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
  1775         subBoxType = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
  1776 
       
  1777         if ( subBoxLength == 1 )
       
  1778             {
       
  1779             // The XLBox shall exist and contains the actual length of the box
       
  1780             // XLBox is 8 bytes width
       
  1781             subBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
  1782             subBoxLength += PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
  1783             length -= KJ2kBoxTypeLength;
       
  1784             subBoxLength -= KJ2kBoxTypeLength;
       
  1785             }
       
  1786 
       
  1787         if ( ( (TInt32)subBoxLength < 0 ) || ( subBoxLength <= 8 ) || ( ( iPtr + subBoxLength - KJ2kBoxTypeLength ) > ptrLimit ) )
       
  1788             {
       
  1789             // Not enough room for subbox data or corrupted subbox length
       
  1790             User::Leave( KErrCorrupt );
       
  1791             }
       
  1792 
       
  1793         switch ( subBoxType )
       
  1794             {
       
  1795             case KJ2kUUIDListBoxType:
       
  1796                 {
       
  1797                 // Validate the UUIDInfo List box
       
  1798                 // NU | ID-0 | ... | ID-n
       
  1799                 // where NU is 2 bytes unsigned specifying the number of IDs
       
  1800                 //       ID is 16 bytes UUID 
       
  1801                 TUint16 nuField = PtrReadUtil::ReadBigEndianUint16( iPtr );
       
  1802                 if ( ( subBoxLength - ( 2 + KJ2kBoxTypeLength ) ) != 
       
  1803                      ( (TUint32)( nuField * KJ2KUuidIDSize ) ) )
       
  1804                     {
       
  1805                     // UUIDInfo List box does not confirm to standard format
       
  1806                     User::Leave( KErrCorrupt );
       
  1807                     }
       
  1808 
       
  1809                 if ( listBuffer )
       
  1810                     {
       
  1811                     // There should be one UUIDInfo List box
       
  1812                     User::Leave( KErrCorrupt );
       
  1813                     }
       
  1814 
       
  1815                 dataLength = subBoxLength - KJ2kBoxTypeLength;
       
  1816                 listBuffer = HBufC8::NewLC( dataLength );
       
  1817                 listBuffer->Des().Append( iPtr, dataLength );
       
  1818                 iPtr += ( dataLength );
       
  1819 
       
  1820                 if ( order == 0 )
       
  1821                     {
       
  1822                     // Increment the order if UUIDInfo List box come first
       
  1823                     ++order;
       
  1824                     }
       
  1825                 break;
       
  1826                 }
       
  1827             case KJ2kUUIDUrlBoxType:
       
  1828                 {
       
  1829                 // Validate the UUIDInfo Data Entry Url box
       
  1830                 if ( urlBuffer )
       
  1831                     {
       
  1832                     // There should be one UUIDInfo Data Entry Url box
       
  1833                     User::Leave( KErrCorrupt );
       
  1834                     }
       
  1835 
       
  1836                 dataLength = subBoxLength - KJ2kBoxTypeLength;
       
  1837                 urlBuffer = HBufC8::NewLC( dataLength );
       
  1838                 urlBuffer->Des().Append( iPtr, dataLength );
       
  1839                 iPtr += ( dataLength );
       
  1840 
       
  1841                 if ( order == 0 )
       
  1842                     {
       
  1843                     // Decrement the order if UUIDInfo Data Entry Url box come first
       
  1844                     --order;
       
  1845                     }
       
  1846                 break;
       
  1847                 }
       
  1848             default:
       
  1849                 {
       
  1850                 // Unrecognized Box
       
  1851                 User::Leave( KErrCorrupt );
       
  1852                 break;
       
  1853                 }
       
  1854             }
       
  1855         length -= subBoxLength;
       
  1856         }
       
  1857 
       
  1858     if ( listBuffer || urlBuffer )
       
  1859         {
       
  1860         if ( !( listBuffer ) )
       
  1861             {
       
  1862             // Create a dummy place holder
       
  1863             listBuffer = HBufC8::NewLC( 1 );
       
  1864             }
       
  1865 
       
  1866         if ( !( urlBuffer ) )
       
  1867             {
       
  1868             // Create a dummy place holder
       
  1869             urlBuffer = HBufC8::NewLC( 1 );
       
  1870             }
       
  1871 
       
  1872         if ( order < 0 )
       
  1873             {
       
  1874             // UUIDInfo Data Entry Url box come first
       
  1875             User::LeaveIfError( iJ2kInfo.iUUIDInfoListList.Append( listBuffer ) );
       
  1876             CleanupStack::Pop( 1 ); // listBuffer
       
  1877 
       
  1878             User::LeaveIfError( iJ2kInfo.iUUIDInfoUrlList.Append( urlBuffer ) );
       
  1879             CleanupStack::Pop( 1 ); // urlBuffer
       
  1880             }
       
  1881         else
       
  1882             {
       
  1883             // UUIDInfo List box come first
       
  1884             User::LeaveIfError( iJ2kInfo.iUUIDInfoUrlList.Append( urlBuffer ) );
       
  1885             CleanupStack::Pop( 1 ); // urlBuffer
       
  1886 
       
  1887             User::LeaveIfError( iJ2kInfo.iUUIDInfoListList.Append( listBuffer ) );
       
  1888             CleanupStack::Pop( 1 ); // listBuffer
       
  1889             }
       
  1890         }
       
  1891     else
       
  1892         {
       
  1893         // UUIDInfo box does not containing any
       
  1894         // UUIDInfo List box or UUIDInfo Data Entry Url box
       
  1895         User::Leave( KErrCorrupt );
       
  1896         }
       
  1897 
       
  1898     iLastRead += iBoxLength;
       
  1899     iState = EStateInUnknown;
       
  1900 
       
  1901     if ( (TUint32)iBufferDes.Length() < iBoxLength )
       
  1902         {
       
  1903         // Test the end of file 
       
  1904         ReadDataL( iLastRead, iBufferDes, 1 );
       
  1905         if ( ( (TUint32)iBufferDes.Length() == 0 ) &&
       
  1906              ( iJ2kInfo.iCSOffset != 0 ) )
       
  1907             {
       
  1908             // CodeStream box has been recognized
       
  1909             iState = EStateInCodestreamBox;
       
  1910             }
       
  1911         else
       
  1912             {
       
  1913             // Need more data from the ICL framework
       
  1914             User::Leave( KErrUnderflow );
       
  1915             }
       
  1916         }
       
  1917     }
       
  1918 
       
  1919 // -----------------------------------------------------------------------------
       
  1920 // CJp2kDecoder::IgnoreBoxL
       
  1921 // Ignore the content of the box and advance the iterator to the next box.
       
  1922 // (other items were commented in a header).
       
  1923 // -----------------------------------------------------------------------------
       
  1924 //
       
  1925 void CJp2kDecoder::IgnoreBoxL()
       
  1926     {
       
  1927     // Check whether this box is the last box in the file
       
  1928     if ( iBoxLength == 0 )
       
  1929         {
       
  1930         // This box is the last box in the file
       
  1931         if ( iJ2kInfo.iCSOffset != 0 )
       
  1932             {
       
  1933             // CodeStream box has been recognized
       
  1934             // Since we are not able to read til the
       
  1935             // end of file/stream, we will skip this
       
  1936             // box
       
  1937             iState = EStateInCodestreamBox;
       
  1938             return;
       
  1939             }
       
  1940         else
       
  1941             {
       
  1942             // The CodeStream box is missing from the file
       
  1943             // and nothing can be decoded
       
  1944             User::Leave( KErrCorrupt );
       
  1945             }
       
  1946         }
       
  1947 
       
  1948     if ( iBoxLength == 1 )
       
  1949         {
       
  1950         // The XLBox shall exist and contains the actual length of the box
       
  1951         // XLBox is 8 bytes width
       
  1952         ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, KJ2kBoxTypeLength );
       
  1953 
       
  1954         if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength )
       
  1955             {
       
  1956             // Need more data from the ICL framework
       
  1957             User::Leave( KErrUnderflow );
       
  1958             }
       
  1959 
       
  1960         iPtr = iBufferDes.Ptr();
       
  1961         iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
  1962         iBoxLength += PtrReadUtil::ReadBigEndianUint32( iPtr );
       
  1963         }
       
  1964 
       
  1965     // Corrupted box length
       
  1966     if ( ( (TInt32)iBoxLength ) < 0 )
       
  1967         {
       
  1968         User::Leave( KErrCorrupt );
       
  1969         }
       
  1970 
       
  1971     // Check whether this box is the last box in the file
       
  1972     if ( iBoxLength == 0 )
       
  1973         {
       
  1974         // This box is the last box in the file
       
  1975         if ( iJ2kInfo.iCSOffset != 0 )
       
  1976             {
       
  1977             // CodeStream box has been recognized
       
  1978             // Since we are not able to read til the
       
  1979             // end of file/stream, we will skip this
       
  1980             // box
       
  1981             iState = EStateInCodestreamBox;
       
  1982             return;
       
  1983             }
       
  1984         else
       
  1985             {
       
  1986             // The CodeStream box is missing from the file
       
  1987             // and nothing can be decoded
       
  1988             User::Leave( KErrCorrupt );
       
  1989             }
       
  1990         }
       
  1991 
       
  1992     // Read and ignore the validation of the box
       
  1993     ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, iBoxLength );
       
  1994 
       
  1995     if ( (TUint32)iBufferDes.Length() < iBoxLength - KJ2kBoxTypeLength )
       
  1996         {
       
  1997         // Need more data from the ICL framework
       
  1998         User::Leave( KErrUnderflow );
       
  1999         }
       
  2000 
       
  2001     iPtr = iBufferDes.Ptr();
       
  2002 
       
  2003     iLastRead += iBoxLength;
       
  2004     iState = EStateInUnknown;
       
  2005 
       
  2006     iPtr += iBoxLength - KJ2kBoxTypeLength;
       
  2007     if ( (TUint32)iBufferDes.Length() < iBoxLength )
       
  2008         {
       
  2009         // Test the end of file 
       
  2010         ReadDataL( iLastRead, iBufferDes, 1 );
       
  2011         if ( ( (TUint32)iBufferDes.Length() == 0 ) &&
       
  2012              ( iJ2kInfo.iCSOffset != 0 ) )
       
  2013             {
       
  2014             // CodeStream box has been recognized
       
  2015             iState = EStateInCodestreamBox;
       
  2016             }
       
  2017         else
       
  2018             {
       
  2019             // Need more data from the ICL framework
       
  2020             User::Leave( KErrUnderflow );
       
  2021             }
       
  2022         }
       
  2023     }
       
  2024 
       
  2025 // -----------------------------------------------------------------------------
       
  2026 // CJp2kDecoder::UpdateStateFromBoxTypeL
       
  2027 // Update the current state according to the box type
       
  2028 // (other items were commented in a header).
       
  2029 // -----------------------------------------------------------------------------
       
  2030 //
       
  2031 void CJp2kDecoder::UpdateStateFromBoxTypeL()
       
  2032     {
       
  2033     switch ( iBoxType )
       
  2034         {
       
  2035         case KJ2kSigBoxType:
       
  2036             {
       
  2037             iState = EStateInSignatureBox;
       
  2038             break;
       
  2039             }
       
  2040         case KJ2kJP2HeaderBoxType:
       
  2041             {
       
  2042             iState = EStateInJP2SuperBox;
       
  2043             break;
       
  2044             }
       
  2045         case KJ2kCodestreamBoxType:
       
  2046             {
       
  2047             if ( iJ2kInfo.iOption & TJ2kInfo::EJP2file )
       
  2048                 {
       
  2049                 if ( !( iJ2kInfo.iOption & TJ2kInfo::EJP2Header ) )
       
  2050                     {
       
  2051                     // In JP2 file format, CodeStream box
       
  2052                     // can not come before JP2 Header box
       
  2053                     User::Leave( KErrCorrupt );
       
  2054                     }
       
  2055 
       
  2056                 // Save the CodeStream box's length
       
  2057                 iJ2kInfo.iCSBoxLength = iBoxLength;
       
  2058                 iJ2kInfo.iCSOffset = iLastRead;
       
  2059 
       
  2060                 if ( iBoxLength == 0 )
       
  2061                     {
       
  2062                     // CodeStream box is the last box in the file
       
  2063                     iState = EStateInCodestreamBox;
       
  2064                     }
       
  2065                 else
       
  2066                     {
       
  2067                     // Continue checking any boxes after the CodeStream box
       
  2068                     if ( iBoxLength == 1 )
       
  2069                         {
       
  2070                         // The XLBox shall exist and contains the actual length of the box
       
  2071                         // XLBox is 8 bytes width
       
  2072                         ReadDataL( iLastRead + KJ2kBoxTypeLength, iBufferDes, KJ2kBoxTypeLength );
       
  2073 
       
  2074                         if ( (TUint32)iBufferDes.Length() < KJ2kBoxTypeLength )
       
  2075                             {
       
  2076                             // Need more data from the ICL framework
       
  2077                             User::Leave( KErrUnderflow );
       
  2078                             }
       
  2079 
       
  2080                         iPtr = iBufferDes.Ptr();
       
  2081                         iBoxLength = PtrReadUtil::ReadBigEndianUint32Inc( iPtr );
       
  2082                         iBoxLength += PtrReadUtil::ReadBigEndianUint32( iPtr );
       
  2083                         }
       
  2084 
       
  2085                     // Corrupted box length
       
  2086                     if ( ( (TInt32)iBoxLength ) < 0 )
       
  2087                         {
       
  2088                         User::Leave( KErrCorrupt );
       
  2089                         }
       
  2090                     
       
  2091                     iLastRead += iBoxLength;
       
  2092                     // Test the end of file 
       
  2093                     ReadDataL( iLastRead, iBufferDes, KJ2kBoxTypeLength );
       
  2094                     if ( (TUint32)iBufferDes.Length() == 0 )
       
  2095                         {
       
  2096                         // CodeStream box is the last box in the file
       
  2097                         iState = EStateInCodestreamBox;
       
  2098                         }
       
  2099                     else if ( (TUint32)iBufferDes.Length() == KJ2kBoxTypeLength )
       
  2100                         {
       
  2101                         iPtr = iBufferDes.Ptr();
       
  2102                         }
       
  2103                     else
       
  2104                         {
       
  2105                         // Need more data from the ICL framework
       
  2106                         User::Leave( KErrUnderflow );
       
  2107                         }
       
  2108                     }
       
  2109                 }
       
  2110             else
       
  2111                 {
       
  2112                 // CodeStream box must exist in file format only
       
  2113                 User::Leave( KErrCorrupt );
       
  2114                 }
       
  2115             break;
       
  2116             }
       
  2117         case KJ2kIPRBoxType:
       
  2118             {
       
  2119             iState = EStateInIPRBox;
       
  2120             break;
       
  2121             }
       
  2122         case KJ2kXMLBoxType:
       
  2123             {
       
  2124             iState = EStateInXMLBox;
       
  2125             break;
       
  2126             }
       
  2127         case KJ2kUUIDBoxType:
       
  2128             {
       
  2129             iState = EStateInUUIDBox;
       
  2130             break;
       
  2131             }
       
  2132         case KJ2kUUIDInfoBoxType:
       
  2133             {
       
  2134             iState = EStateInUUIDInfoBox;
       
  2135             break;
       
  2136             }
       
  2137         default:
       
  2138             {
       
  2139             // Check if the first 4 bytes read
       
  2140             // is SOC + SIZ
       
  2141             if ( iBoxLength == KJ2kSOCType )
       
  2142                 {
       
  2143                 if ( iJ2kInfo.iOption & TJ2kInfo::EJP2file )
       
  2144                     {
       
  2145                     // JP2 codestream shouldn't in JP2 file format
       
  2146                     User::Leave( KErrCorrupt );
       
  2147                     }
       
  2148 
       
  2149                 // SOC + SIZ marker - JP2 Codestream
       
  2150                 iState = EStateInCodestreamBox;
       
  2151                 iJ2kInfo.iCSOffset = iLastRead;
       
  2152                 }
       
  2153             else
       
  2154                 {
       
  2155                 // Unrecognized box type
       
  2156                 // there are two ways of handling this
       
  2157                 // 1. stop parsing and Leave with an KErrCorrupt error
       
  2158                 //    User::Leave( KErrCorrupt );
       
  2159                 // 2. just ignore the box and continue on parsing the 
       
  2160                 //    next box.
       
  2161                 IgnoreBoxL();
       
  2162                 }
       
  2163             break;
       
  2164             }
       
  2165         }
       
  2166     }
       
  2167 
       
  2168 // -----------------------------------------------------------------------------
       
  2169 // CJp2kDecoder::ScanDataL
       
  2170 // Called from ICL framework to instantiate decoder and parse header.
       
  2171 // (other items were commented in a header).
       
  2172 // -----------------------------------------------------------------------------
       
  2173 //
       
  2174 void CJp2kDecoder::ScanDataL()
       
  2175     {
       
  2176     ReadFormatL();
       
  2177 
       
  2178     ASSERT( ImageReadCodec() == NULL );
       
  2179 
       
  2180     CJp2kReadCodec* imageReadCodec = CJp2kReadCodec::NewL( iJ2kInfo );
       
  2181     SetImageReadCodec( imageReadCodec );
       
  2182 
       
  2183     ReadFrameHeadersL();
       
  2184     }
       
  2185 
       
  2186 // ========================== OTHER EXPORTED FUNCTIONS =========================
       
  2187 
       
  2188 // -----------------------------------------------------------------------------
       
  2189 // Global panic function, From JP2KImageClientMain.h
       
  2190 // -----------------------------------------------------------------------------
       
  2191 //
       
  2192 GLDEF_C void Panic( TIclPanic aError ) //lint !e759 already in module
       
  2193     {
       
  2194     User::Panic( KJ2KPanicCategory, aError );
       
  2195     }
       
  2196