imagingmodules/jp2kcodec/Src/JP2KSynthesis.cpp
changeset 0 469c91dae73b
equal deleted inserted replaced
-1:000000000000 0:469c91dae73b
       
     1 /*
       
     2 * Copyright (c) 2003, 2004 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  CJ2kSynthesis class used to perform inverse quantization and
       
    15 *                inverse DWT.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include "JP2KTileInfo.h"
       
    22 #include "JP2KImageInfo.h"
       
    23 #include "JP2KImageWriter.h"
       
    24 #include "JP2KEntropyDecoder.h"
       
    25 #include "JP2KCodeBlock.h"
       
    26 #include "JP2KPacket.h"
       
    27 #include "JP2KSubband.h"
       
    28 #include "JP2KComponentInfo.h"
       
    29 #include "JP2KSynthesis.h"
       
    30 
       
    31 // EXTERNAL DATA STRUCTURES
       
    32 
       
    33 // EXTERNAL FUNCTION PROTOTYPES  
       
    34 
       
    35 // CONSTANTS
       
    36 
       
    37 // MACROS
       
    38 
       
    39 // LOCAL CONSTANTS AND MACROS
       
    40 
       
    41 // MODULE DATA STRUCTURES
       
    42 
       
    43 // LOCAL FUNCTION PROTOTYPES
       
    44 
       
    45 // FORWARD DECLARATIONS
       
    46 
       
    47 // ============================ MEMBER FUNCTIONS ===============================
       
    48 
       
    49 // -----------------------------------------------------------------------------
       
    50 // CJ2kSynthesis::CJ2kSynthesis
       
    51 // C++ default constructor can NOT contain any code, that
       
    52 // might leave.
       
    53 // -----------------------------------------------------------------------------
       
    54 //
       
    55 CJ2kSynthesis::CJ2kSynthesis() 
       
    56     {
       
    57     // Set up the filter taps for irreversible filter
       
    58     iTapsLow[0] = KFixedLow9x70;
       
    59     iTapsLow[1] = KFixedLow9x71;
       
    60     iTapsLow[2] = KFixedLow9x72;
       
    61     iTapsLow[3] = KFixedLow9x73;
       
    62   
       
    63     iTapsHigh[0] = KFixedHigh9x70;
       
    64     iTapsHigh[1] = KFixedHigh9x71;
       
    65     iTapsHigh[2] = KFixedHigh9x72;
       
    66     iTapsHigh[3] = KFixedHigh9x73;
       
    67     iTapsHigh[4] = KFixedHigh9x74;
       
    68     }
       
    69 
       
    70 // Destructor
       
    71 CJ2kSynthesis::~CJ2kSynthesis()
       
    72     {
       
    73     if ( iInputBuffer )
       
    74         {
       
    75         iInputBuffer  -= ( KFilterExtension + 1 );
       
    76         User::Free( iInputBuffer );
       
    77         iInputBuffer = 0;
       
    78         }
       
    79     if ( iOutputBuffer )
       
    80         {
       
    81         iOutputBuffer -= ( KFilterExtension + 1 );
       
    82         User::Free( iOutputBuffer );
       
    83         iOutputBuffer = 0;
       
    84         }
       
    85     }
       
    86 
       
    87 // -----------------------------------------------------------------------------
       
    88 // CJ2kSynthesis::DecodeTileL
       
    89 // Decode a single tile
       
    90 // (other items were commented in a header).
       
    91 // -----------------------------------------------------------------------------
       
    92 //
       
    93 void CJ2kSynthesis::DecodeTileL( CJ2kImageWriter& aImageWriter, 
       
    94                                  CJ2kEntropyDecoder& aEntropyDecoder,
       
    95                                  CJ2kImageInfo& aImageInfo,
       
    96                                  CJ2kTileInfo& aTile )
       
    97     {
       
    98     if ( aImageInfo.Crop() )
       
    99         {
       
   100         // If this tile doesn't belong to the crop area, continue
       
   101         if ( !aImageInfo.TileMaskAt( aTile.SotMarker().iIsot ) )
       
   102             {
       
   103             return;
       
   104             }
       
   105         }
       
   106 
       
   107     CJ2kComponentInfo* componentInfo = 0;
       
   108     TInt32 maxSize = 0;
       
   109     TUint16 compIndex = 0;
       
   110     TUint16 numOfComponents = aImageInfo.NumOfComponents();
       
   111 
       
   112     // Find the largest width or height
       
   113     for ( compIndex = 0; compIndex < numOfComponents; ++compIndex )
       
   114         {
       
   115         componentInfo = CONST_CAST( CJ2kComponentInfo*, &aTile.ComponentAt( compIndex ) );
       
   116         maxSize = Max( maxSize, Max( componentInfo->ComponentCanvas().Height(), 
       
   117                                      componentInfo->ComponentCanvas().Width() ) );
       
   118         }
       
   119 
       
   120     maxSize += 2 * ( KFilterExtension + 1 );
       
   121     AllocBufferL( maxSize );
       
   122 
       
   123     TSize   subbandSize( 0, 0 );
       
   124     TUint16 bandIndex = 0;
       
   125     TUint16 blockIndex = 0;
       
   126 
       
   127     CJ2kSubband*   subband = 0;
       
   128     CJ2kPacket*    packet = 0;
       
   129     CJ2kCodeBlock* codeblock = 0;
       
   130 
       
   131     TUint8  quantStyle = 0;
       
   132     TUint8  bitDepth = 0;
       
   133     TUint8  cblkStyle = 0;
       
   134     TUint8  levelIndex = 0;
       
   135     TUint32 packetIndex = 0;
       
   136 
       
   137     CJ2kWriterComponentInfo* component = 0;
       
   138     RPointerArray<CJ2kPacket>* packetList;
       
   139 
       
   140     aEntropyDecoder.SetNewSizeL( aImageInfo.MaxBlockSize() );
       
   141 
       
   142     // For each component in the tile
       
   143     for ( compIndex = 0; compIndex < aImageInfo.NumOfComponents(); ++compIndex )
       
   144         {
       
   145         componentInfo = CONST_CAST( CJ2kComponentInfo*, &aTile.ComponentAt( compIndex ) );
       
   146 
       
   147         // Skip the component when height or width is 0
       
   148         if ( componentInfo->ComponentCanvas().Height() == 0 ||
       
   149              componentInfo->ComponentCanvas().Width() == 0  )
       
   150             {
       
   151             continue;   //lint !e960    Continue is OK.
       
   152             }
       
   153 
       
   154         // Check for component truncation
       
   155         if ( aImageInfo.ComponentDrop() )
       
   156             {
       
   157             if ( aImageWriter.SingleFileOutput() )
       
   158                 {
       
   159                 if ( compIndex == ( aImageInfo.ComponentDrop() - 1 ) )
       
   160                     {
       
   161                     numOfComponents = compIndex;
       
   162                     }
       
   163                 else
       
   164                     {
       
   165                     continue;   //lint !e960    Continue is OK.
       
   166                     }
       
   167                 }
       
   168             else
       
   169                 {
       
   170                 if ( compIndex != ( aImageInfo.ComponentDrop() - 1 ) )
       
   171                     {
       
   172                     continue;   //lint !e960    Continue is OK.
       
   173                     }
       
   174                 }
       
   175             }
       
   176 
       
   177         // Get the resolution level for this component
       
   178         iWaveletLevels = (TInt16)( componentInfo->Levels() - aImageInfo.LevelDrop() );
       
   179 
       
   180         TInt32 stepSize = 1;
       
   181         if ( iWaveletLevels < 0 )
       
   182             {
       
   183             TInt32 i;
       
   184 
       
   185             // Compute the output step size, the stepSize indicates how much more 
       
   186             // resolution has to be dropped if the image didn't have enough wavelet
       
   187             // levels to begin with. One indicates no extra resolution drop (write
       
   188             // each sample) and for each extra drop skip half of the samples, i.e.
       
   189             // stepSize is 2^extraLevels in case extra drop is needed.
       
   190         
       
   191             // Adjust the tile starting points and the stepSize
       
   192             for ( i = 0; i < (-iWaveletLevels); i++ )
       
   193                 {
       
   194                 // Double the step size for every extra level dropped.
       
   195                 stepSize *= 2;
       
   196                 }
       
   197         
       
   198             iWaveletLevels = 0;
       
   199             }
       
   200 
       
   201         // Get the top subband ( original image )
       
   202         subband = CONST_CAST( CJ2kSubband*, componentInfo->SubbandAt( (TUint8)iWaveletLevels ) );
       
   203 
       
   204         if ( subband->SubbandResLevel() != 0 )
       
   205             {
       
   206             subband = subband->Parent();
       
   207             }
       
   208 
       
   209         subbandSize = subband->SubbandCanvasSize();
       
   210 
       
   211         // Skip the component when subband's height or width is 0
       
   212         if ( subbandSize.iWidth == 0 || subbandSize.iHeight == 0 )
       
   213             {
       
   214             continue;   //lint !e960    Continue is OK.
       
   215             }
       
   216 
       
   217         component = CONST_CAST( CJ2kWriterComponentInfo*, &aImageWriter.WriterComponentAt( compIndex ) );
       
   218 
       
   219         // Have to allocate memory for each component in the image writer
       
   220         component->AllocDataL( subbandSize );
       
   221 
       
   222         bitDepth = aImageInfo.DepthOfComponent( compIndex );
       
   223         
       
   224         // Get the right number of levels and transform type 
       
   225         // reversible == 1 for 5x3 filter and == 0 for 9x7 filter
       
   226         iReversible = componentInfo->IsReversible();
       
   227         iROIShift   = componentInfo->RoiShift();
       
   228 
       
   229         quantStyle  = componentInfo->QuantizationStyle();
       
   230         cblkStyle   = componentInfo->CodeBlockStyle();
       
   231 
       
   232         // For each resolution level in the component
       
   233         for ( levelIndex = 0; levelIndex <= iWaveletLevels; levelIndex++ )
       
   234             {
       
   235             subband = CONST_CAST( CJ2kSubband*, componentInfo->SubbandAt( levelIndex ) );
       
   236 
       
   237             // For each subband in the resolution level
       
   238             do    
       
   239                 {
       
   240                 bandIndex = ( quantStyle == 1 ) ? (TUint16)0 : subband->SubbandTreeIndex();
       
   241 
       
   242                 // Get the right magnitude bits for this band
       
   243                 iMagnitudeBitsHere = componentInfo->MagnitudeBits( bandIndex );
       
   244         
       
   245                 // Compute the Quantization parameters here, so we don't repeat that for every codeblock/precinct
       
   246                 ComputeQuantizationParameters( *componentInfo, bandIndex, subband->SubbandGain(), bitDepth );
       
   247 
       
   248                 // Set the lookup table for entropy decoder
       
   249                 aEntropyDecoder.SetCurrentZCLUT( (TUint8)( subband->SubbandType() ) );
       
   250 
       
   251                 packetList = CONST_CAST( RPointerArray<CJ2kPacket>*, &subband->PacketList() );    //lint !e665 the first parameter cannot be parenthesized here
       
   252 
       
   253                 // For each packet in the subband
       
   254                 for ( packetIndex = 0; packetIndex < componentInfo->NumOfPackets( levelIndex ); ++packetIndex )
       
   255                     {
       
   256                     packet = ( *packetList )[packetIndex];
       
   257 
       
   258                     // For each codeblock in the packet
       
   259                     for ( blockIndex = 0; blockIndex < packet->NumOfBlocks(); ++blockIndex )
       
   260                         {
       
   261                         codeblock = CONST_CAST( CJ2kCodeBlock*, &packet->CodeBlockAt( blockIndex ) );
       
   262 
       
   263                         // There is coded data in the codeblock
       
   264                         if ( codeblock->DataLength() )
       
   265                             {
       
   266                             // Decode the codeblock
       
   267                             aEntropyDecoder.DecodeCodeblock( *codeblock, cblkStyle, (TUint8)( iMagnitudeBitsHere + iROIShift ) );
       
   268 
       
   269                             // Copy data from the decoded codeblock for inverse quantization and ROI shifting
       
   270                             CopyDataToImage( aEntropyDecoder, component->Data(), *subband, *codeblock, quantStyle );
       
   271                             }
       
   272                         } // end of each codeblock
       
   273                     }  // end of each packet
       
   274 
       
   275                 // Get the sibling subband
       
   276                 subband = subband->NextSubbandRaster();
       
   277 
       
   278                 } while ( subband ); // end of each subband in the resolution level
       
   279 
       
   280             }  // end of each resolution level in the component
       
   281     
       
   282         // Point to the LL-band before calling inverse wavelet transform
       
   283         subband = CONST_CAST( CJ2kSubband*, componentInfo->SubbandAt( 0 ) );
       
   284 
       
   285         // Perform a full inverse wavelet transformation
       
   286         FullWaveletInverse( component->Data(), subband );
       
   287 
       
   288 
       
   289         // Check whether extra downsampling is needed
       
   290         if(stepSize > 1)
       
   291             {
       
   292             TInt32 i,j;
       
   293             TInt32 iStep,jStep;
       
   294 
       
   295             // If the stepSize is larger than one it means that we have to downsample
       
   296             // the output. This is because there were not enough wavelet levels to do
       
   297             // the resolution dropping for this component.
       
   298 
       
   299             // The reason why downsampling is done here and not in the ImageWriter is
       
   300             // that different components might have different number of wavlet levels
       
   301             // and thus it is easier to downsample the components here (so that we can 
       
   302             // just write out the samples normally in ImageWriter.
       
   303             for(i = 0,iStep = 0; iStep < subbandSize.iHeight; i++,iStep += stepSize)
       
   304                 {
       
   305                 for(j = 0,jStep = 0; jStep < subbandSize.iWidth; j++,jStep += stepSize)
       
   306                     {
       
   307                     // Downsample the component so that downsampled image is in the
       
   308                     // upper left-hand corner.
       
   309                     component->Data()[i][j] = component->Data()[iStep][jStep];
       
   310                     }
       
   311                 }
       
   312             }
       
   313 
       
   314 
       
   315 
       
   316         if ( numOfComponents >= 3 ) 
       
   317             {
       
   318             if ( aTile.ColorTransformation() || 
       
   319                 ( aImageWriter.CSCode() == 18 || aImageWriter.CSCode() == 16 ) )
       
   320                 {
       
   321                 // Wait til we finish decoding all components before writing out the image
       
   322                 if ( compIndex < 2 )
       
   323                     {
       
   324                     continue;   //lint !e960    Continue is OK.
       
   325                     }
       
   326                 }
       
   327             else if ( aImageWriter.CSCode() == 0 )
       
   328                 {
       
   329                 // This case is also valid when no CSCode is defined, e.g. no file format is present
       
   330                 if( numOfComponents <= 3 )
       
   331                     {
       
   332                     if ( compIndex < 2 )
       
   333                         {
       
   334                         continue;   //lint !e960    Continue is OK.
       
   335                         }
       
   336                     }
       
   337                 else
       
   338                     {
       
   339                     // Proceed to outputImageL
       
   340                     }
       
   341                 }
       
   342             }   //lint !e961    no else is needed here at the end of if...else if
       
   343 
       
   344         // Write out the tile image
       
   345         aImageWriter.OutputImageL( aTile, compIndex );
       
   346 
       
   347         }   // end of each component in the tile
       
   348     }
       
   349 
       
   350 // -----------------------------------------------------------------------------
       
   351 // CJ2kSynthesis::DecodeTileBlockL
       
   352 // Decode a single tile with lower memory using 256x256 blocks 
       
   353 // for the inverse wavelet transform
       
   354 // (other items were commented in a header).
       
   355 // -----------------------------------------------------------------------------
       
   356 //
       
   357 void CJ2kSynthesis::DecodeTileBlockL( CJ2kImageWriter& aImageWriter, 
       
   358                                       CJ2kEntropyDecoder& aEntropyDecoder,
       
   359                                       CJ2kImageInfo& aImageInfo,
       
   360                                       CJ2kTileInfo& aTile )
       
   361     {
       
   362     if ( aImageInfo.Crop() )
       
   363         {
       
   364         // If this tile doesn't belong to the crop area, continue
       
   365         if ( !aImageInfo.TileMaskAt( aTile.SotMarker().iIsot ) )
       
   366             {
       
   367             return;
       
   368             }
       
   369         }
       
   370 
       
   371     CJ2kComponentInfo* componentInfo = 0;
       
   372     TInt32  maxSize = 0;
       
   373     TUint16 compIndex = 0;
       
   374     TUint16 numOfComponents = aImageInfo.NumOfComponents();
       
   375 
       
   376     // Find the largest width or height
       
   377     for ( compIndex = 0; compIndex < numOfComponents; ++compIndex )
       
   378         {
       
   379         componentInfo = CONST_CAST( CJ2kComponentInfo*, &aTile.ComponentAt( compIndex ) );
       
   380         maxSize = Max( maxSize, Max( componentInfo->ComponentCanvas().Height(), 
       
   381                                      componentInfo->ComponentCanvas().Width() ) );
       
   382         }
       
   383 
       
   384     maxSize = KMaxBlockSupportSize;
       
   385 
       
   386     maxSize += 2 * ( KFilterExtension + 1 );
       
   387     AllocBufferL( maxSize );
       
   388 
       
   389     TSize subbandSize( 0, 0 );
       
   390     TUint16 bandIndex = 0;
       
   391     TUint16 blockIndex = 0;
       
   392 
       
   393     CJ2kSubband* subband = 0;
       
   394     CJ2kPacket* packet = 0;
       
   395     CJ2kCodeBlock* codeblock = 0;
       
   396 
       
   397     TUint8  quantStyle = 0;
       
   398     TUint8  bitDepth = 0;
       
   399     TUint8  cblkStyle = 0;
       
   400     TUint8  levelIndex = 0;
       
   401     TUint32 packetIndex = 0;
       
   402     TUint32 blockXCoord = 0;
       
   403     TUint32 blockYCoord = 0;
       
   404     TUint32 compXCoord = 0;
       
   405     TUint32 compYCoord = 0;
       
   406     TInt32 blockXEnd = 0;
       
   407     TInt32 blockYEnd = 0;
       
   408     TRect supportRegion( 0, 0, 0 , 0 );
       
   409     TRect parentSupportRegion( 0, 0, 0 , 0 );
       
   410     TPoint regionOffset( 0, 0 );
       
   411     TInt16 tmpLevelIndex = 0;
       
   412     TSize thisCompSize( 0, 0 );
       
   413     TSize firstCompSize( 0, 0 );
       
   414     TSize regionSize( 0, 0 );
       
   415     TPoint tileEndPoint( 0, 0 );
       
   416     TPoint tileStartPoint( 0, 0 );
       
   417     TPoint blockStepSize( 0, 0 );
       
   418 
       
   419     CJ2kWriterComponentInfo* component = 0;
       
   420     RPointerArray<CJ2kPacket>* packetList;
       
   421     TSizMarker& sizMarker = CONST_CAST( TSizMarker&, aImageInfo.SizMarker() );
       
   422 
       
   423     aEntropyDecoder.SetNewSizeL( aImageInfo.MaxBlockSize() );
       
   424     componentInfo = CONST_CAST( CJ2kComponentInfo*, &aTile.ComponentAt( 0 ) );
       
   425     
       
   426     // Get the resolution level for this component
       
   427     iWaveletLevels = (TInt16)( componentInfo->Levels() - aImageInfo.LevelDrop() );
       
   428     if ( iWaveletLevels < 0 )
       
   429         {
       
   430         iWaveletLevels = 0;
       
   431         }
       
   432 
       
   433     // Get the top subband ( original image )
       
   434     subband = CONST_CAST( CJ2kSubband*, componentInfo->SubbandAt( (TUint8)iWaveletLevels ) );
       
   435     if ( subband->SubbandResLevel() != 0 )
       
   436         {
       
   437         subband = subband->Parent();
       
   438         }
       
   439 
       
   440     subbandSize = subband->SubbandCanvasSize();
       
   441     tileEndPoint.iX = subbandSize.iWidth;
       
   442     tileEndPoint.iY = subbandSize.iHeight;
       
   443     tileStartPoint.iX = componentInfo->ComponentCanvas().iTl.iX;
       
   444     tileStartPoint.iY = componentInfo->ComponentCanvas().iTl.iY;
       
   445 
       
   446     // Loop on 256x256 blocks to reduce the memory required to perform the inverse wavelet
       
   447     // First set as starting point the canvas coordinates of this component
       
   448     blockXCoord = 0;
       
   449     blockYCoord = 0;
       
   450     blockStepSize.iX = KWaveletBlockSize;
       
   451     blockStepSize.iY = KWaveletBlockSize;
       
   452 
       
   453     for ( ; blockYCoord < (TUint32)tileEndPoint.iY; blockYCoord += KWaveletBlockSize )
       
   454         {
       
   455         // Start from the left border of this tile
       
   456         blockXCoord = 0;
       
   457 
       
   458         for ( ; blockXCoord < ( TUint32 )tileEndPoint.iX; blockXCoord += KWaveletBlockSize )
       
   459             {
       
   460             // For each component in the tile
       
   461             for ( compIndex = 0; compIndex < aImageInfo.NumOfComponents(); ++compIndex )
       
   462                 {
       
   463                 compXCoord = blockXCoord;
       
   464                 compYCoord = blockYCoord;
       
   465 
       
   466                 componentInfo = CONST_CAST( CJ2kComponentInfo*, &aTile.ComponentAt( compIndex ) );
       
   467 
       
   468                 // Skip the component when height or width is 0
       
   469                 if ( componentInfo->ComponentCanvas().Height() == 0 ||
       
   470                      componentInfo->ComponentCanvas().Width() == 0  )
       
   471                     {
       
   472                     continue;   //lint !e960    Continue is OK.
       
   473                     }
       
   474 
       
   475                 // Here we have to add a check that if we have sub sampled component together with color transform,
       
   476                 // we have to subsample also the block dimensions ( so that the inverse color transform is performed
       
   477                 // correctly.
       
   478                 blockStepSize.iX = KWaveletBlockSize;
       
   479                 blockStepSize.iY = KWaveletBlockSize;
       
   480                 if ( aImageInfo.NumOfComponents() == 3 )
       
   481                     {
       
   482                     if ( sizMarker.iXRsiz[1] == 2 * sizMarker.iXRsiz[0] &&
       
   483                          sizMarker.iXRsiz[2] == 2 * sizMarker.iXRsiz[0] )
       
   484                         {
       
   485                         if ( sizMarker.iXRsiz[1] == 2 * sizMarker.iXRsiz[0] &&
       
   486                              sizMarker.iXRsiz[2] == 2 * sizMarker.iXRsiz[0] )
       
   487                             {
       
   488                             if( compIndex == 1 || compIndex == 2 )
       
   489                                 {
       
   490                                 blockStepSize.iX = KWaveletBlockSize >> 1;
       
   491                                 blockStepSize.iY = KWaveletBlockSize >> 1;
       
   492                                 compXCoord >>= 1;
       
   493                                 compYCoord >>= 1;
       
   494                                 }
       
   495                             }
       
   496                         else
       
   497                             {
       
   498                             if( compIndex == 1 || compIndex == 2 )
       
   499                                 {
       
   500                                 blockStepSize.iX = KWaveletBlockSize >> 1;
       
   501                                 compXCoord >>= 1;
       
   502                                 blockStepSize.iY = KWaveletBlockSize;
       
   503                                 }
       
   504                             }
       
   505                         }
       
   506                     }
       
   507 
       
   508                 // Check for component truncation
       
   509                 if ( aImageInfo.ComponentDrop() )
       
   510                     {
       
   511                     if ( aImageWriter.SingleFileOutput() )
       
   512                         {
       
   513                         if ( compIndex == ( aImageInfo.ComponentDrop() - 1 ) )
       
   514                             {
       
   515                             numOfComponents = compIndex;
       
   516                             }
       
   517                         else
       
   518                             {
       
   519                             continue;   //lint !e960    Continue is OK.
       
   520                             }
       
   521                         }
       
   522                     else
       
   523                         {
       
   524                         if ( compIndex != ( aImageInfo.ComponentDrop() - 1 ) )
       
   525                             {
       
   526                             continue;   //lint !e960    Continue is OK.
       
   527                             }
       
   528                         }
       
   529                     }
       
   530 
       
   531                 // Get the resolution level for this component
       
   532                 iWaveletLevels = (TInt16)( componentInfo->Levels() - aImageInfo.LevelDrop() );
       
   533 
       
   534                 TInt32 stepSize = 1;
       
   535                 if ( iWaveletLevels < 0 )
       
   536                     {
       
   537                     TInt32 i;
       
   538 
       
   539                     // Compute the output step size, the stepSize indicates how much more 
       
   540                     // resolution has to be dropped if the image didn't have enough wavelet
       
   541                     // levels to begin with. One indicates no extra resolution drop (write
       
   542                     // each sample) and for each extra drop skip half of the samples, i.e.
       
   543                     // stepSize is 2^extraLevels in case extra drop is needed.
       
   544                     
       
   545                     // Adjust the tile starting points and the stepSize
       
   546                     for ( i = 0; i < (-iWaveletLevels); i++ )
       
   547                         {
       
   548                         // Double the step size for every extra level dropped.
       
   549                         stepSize *= 2;
       
   550                         }
       
   551             
       
   552         
       
   553                     iWaveletLevels = 0;
       
   554                     }
       
   555 
       
   556                 // Get the top subband ( original image )
       
   557                 subband = CONST_CAST( CJ2kSubband*, componentInfo->SubbandAt( (TUint8)iWaveletLevels ) );
       
   558 
       
   559                 if ( subband->SubbandResLevel() != 0 )
       
   560                     {
       
   561                     subband = subband->Parent();
       
   562                     }
       
   563 
       
   564                 subbandSize = subband->SubbandCanvasSize();
       
   565 
       
   566                 // Skip the component when subband's height or width is 0
       
   567                 if ( subbandSize.iWidth == 0 || subbandSize.iHeight == 0 )
       
   568                     {
       
   569                     continue;   //lint !e960    Continue is OK.
       
   570                     }
       
   571 
       
   572                 // Check that the block doesn't exceed the boundary of this component
       
   573                 if( (TInt32)compXCoord+blockStepSize.iX > subbandSize.iWidth )
       
   574                     {
       
   575                     blockXEnd = subbandSize.iWidth;
       
   576                     }
       
   577                 else
       
   578                     {
       
   579                     blockXEnd = compXCoord+blockStepSize.iX;
       
   580                     }
       
   581                 if( (TInt32)compYCoord+blockStepSize.iY > subbandSize.iHeight )
       
   582                     {
       
   583                     blockYEnd = subbandSize.iHeight;
       
   584                     }
       
   585                 else
       
   586                     {
       
   587                     blockYEnd = compYCoord+blockStepSize.iY;
       
   588                     }
       
   589 
       
   590                 // Store the block size on the first component in case the others are sub sampled
       
   591                 if( compIndex == 0 )
       
   592                     {
       
   593                     firstCompSize.iWidth = blockXEnd - blockXCoord;
       
   594                     firstCompSize.iHeight = blockYEnd - blockYCoord;
       
   595                     }
       
   596 
       
   597                 // Store the block size of this component
       
   598                 thisCompSize.iWidth = blockXEnd - compXCoord;
       
   599                 thisCompSize.iHeight = blockYEnd - compYCoord;
       
   600 
       
   601                 // This component could be sampled so that the block doesn't "exist" 
       
   602                 // in this component, if so move to next component
       
   603                 if( thisCompSize.iWidth <= 0 || thisCompSize.iHeight <= 0 )         
       
   604                     {
       
   605                     continue;   //lint !e960    Continue is OK.
       
   606                     }
       
   607 
       
   608                 component = CONST_CAST( CJ2kWriterComponentInfo*, &aImageWriter.WriterComponentAt( compIndex ) );
       
   609                 
       
   610                 // Have to allocate memory for each component in the image writer                
       
   611                 subbandSize.iWidth = subbandSize.iHeight = KMaxBlockSupportSize;
       
   612                 component->AllocDataL( subbandSize );
       
   613 
       
   614                 bitDepth = aImageInfo.DepthOfComponent( compIndex );
       
   615         
       
   616                 // Get the right number of levels and transform type 
       
   617                 // reversible == 1 for 5x3 filter and == 0 for 9x7 filter
       
   618                 iReversible = componentInfo->IsReversible();
       
   619                 iROIShift = componentInfo->RoiShift();
       
   620 
       
   621                 quantStyle = componentInfo->QuantizationStyle();
       
   622                 cblkStyle = componentInfo->CodeBlockStyle();
       
   623 
       
   624                 // The support region is the region needed on current level to 
       
   625                 // compute the samples in current block.
       
   626                 supportRegion.iTl.iX = compXCoord;
       
   627                 supportRegion.iTl.iY = compYCoord;
       
   628                 supportRegion.iBr.iX = blockXEnd;
       
   629                 supportRegion.iBr.iY = blockYEnd;
       
   630 
       
   631                 // For each resolution level in the component
       
   632                 for ( levelIndex = 0; levelIndex <= iWaveletLevels; levelIndex++ )
       
   633                     {
       
   634                     // The support region is the region needed on current level to compute the samples in current block.
       
   635                     supportRegion.iTl.iX = compXCoord;
       
   636                     supportRegion.iTl.iY = compYCoord;
       
   637                     supportRegion.iBr.iX = blockXEnd;
       
   638                     supportRegion.iBr.iY = blockYEnd;
       
   639                     parentSupportRegion = supportRegion;
       
   640                     regionOffset.iX = regionOffset.iY = 0;
       
   641 
       
   642                     // Compute the support region of the parent level of the bands that are to be processed
       
   643                     // The support region is computed depending on the level we process currently.
       
   644                     for( tmpLevelIndex = iWaveletLevels; tmpLevelIndex > levelIndex; tmpLevelIndex-- )
       
   645                         {
       
   646                         // Get the subband on this ( temp )level in order to find out if high-pass first is true or not
       
   647                         subband = CONST_CAST( CJ2kSubband*, componentInfo->SubbandAt( (TUint8)( tmpLevelIndex ) ) );
       
   648 
       
   649                         // Level zero has the same support as level 1, so don't update the support for level zero.
       
   650                         if( tmpLevelIndex != 1 )
       
   651                             {
       
   652                             // Compute the new crop coordinates for the subbands on this level
       
   653                             if( iReversible )
       
   654                                 {
       
   655                                 // Support region for low-pass bands for 5x3 filter
       
   656 
       
   657                                 // If this band is computed high-pass first, then one extra low-pass coefficient is needed from left.
       
   658                                 // This is due to the fact that for Output[2n+1], we need five samples H[n-1], L[n], H[n], L[n+1] and H[n+1], but when high-pass 
       
   659                                 // is computed first, we actually need samples H[n-1], L[n-1], H[n], L[n] and H[n+1], where L are the low-pass filtered samples
       
   660                                 // and H are the high-pass filtered samples.
       
   661                                 if( subband->Parent()->HighPassFirst().iX )
       
   662                                     {
       
   663                                     parentSupportRegion.iTl.iX = ( ( ( parentSupportRegion.iTl.iX >> 1 ) - 1 ) > 0 ) ?  //lint !e702    The shifted values cannot be negative here
       
   664                                                                  ( ( parentSupportRegion.iTl.iX >> 1 ) - 1 ) : 0; //lint !e702    The shifted values cannot be negative here
       
   665                                     }
       
   666                                 else
       
   667                                     {
       
   668                                     parentSupportRegion.iTl.iX = parentSupportRegion.iTl.iX >> 1; //lint !e702    The shifted values cannot be negative here
       
   669                                     }
       
   670                                 // If this band is computed high-pass first, then one extra low-pass coefficient is needed from above.
       
   671                                 if( subband->Parent()->HighPassFirst().iY )
       
   672                                     {
       
   673                                     parentSupportRegion.iTl.iY = ( ( ( parentSupportRegion.iTl.iY >> 1 ) - 1 )>0 ) ?  //lint !e702    The shifted values cannot be negative here
       
   674                                                                  ( ( parentSupportRegion.iTl.iY >> 1 ) - 1 ) : 0; //lint !e702    The shifted values cannot be negative here
       
   675                                     }
       
   676                                 else
       
   677                                     {
       
   678                                     parentSupportRegion.iTl.iY = parentSupportRegion.iTl.iY >> 1; //lint !e702    The shifted values cannot be negative here
       
   679                                     }
       
   680 
       
   681                                 parentSupportRegion.iBr.iX = ( ( parentSupportRegion.iBr.iX ) >> 1 ) + 1; //lint !e702    The shifted values cannot be negative here
       
   682                                 parentSupportRegion.iBr.iY = ( ( parentSupportRegion.iBr.iY ) >> 1 ) + 1; //lint !e702    The shifted values cannot be negative here
       
   683                                 }
       
   684                             else
       
   685                                 {
       
   686                                 // Support region for low-pass bands for 9x7 filter
       
   687                                 // If this band is computed high-pass first, then one extra low-pass coefficient is needed ( from left ).
       
   688                                 if( subband->Parent()->HighPassFirst().iX )
       
   689                                     {
       
   690                                     parentSupportRegion.iTl.iX = ( ( parentSupportRegion.iTl.iX >> 1 )-2 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
       
   691                                                                  ( parentSupportRegion.iTl.iX >> 1 )-2 : 0; //lint !e702    the shifted values cannot be negative here
       
   692                                     }
       
   693                                 else
       
   694                                     {
       
   695                                     parentSupportRegion.iTl.iX = ( ( ( parentSupportRegion.iTl.iX >> 1 ) - 1 ) > 0 ) ? //lint !e702    The shifted values cannot be negative here
       
   696                                                                  ( ( parentSupportRegion.iTl.iX >> 1 ) - 1 ) : 0; //lint !e702    the shifted values cannot be negative here
       
   697                                     }
       
   698                                 if( subband->Parent()->HighPassFirst().iY )
       
   699                                     {
       
   700                                     parentSupportRegion.iTl.iY = ( ( ( parentSupportRegion.iTl.iY >> 1 ) - 2 ) > 0 ) ? //lint !e702    The shifted values cannot be negative here
       
   701                                                                  ( ( parentSupportRegion.iTl.iY >> 1 ) - 2 ) : 0; //lint !e702    the shifted values cannot be negative here
       
   702                                     }
       
   703                                 else
       
   704                                     {
       
   705                                     parentSupportRegion.iTl.iY = ( ( ( parentSupportRegion.iTl.iY >> 1 ) - 1 ) > 0 ) ? //lint !e702    The shifted values cannot be negative here
       
   706                                                                  ( ( parentSupportRegion.iTl.iY >> 1 ) - 1 ) : 0; //lint !e702    the shifted values cannot be negative here
       
   707                                     }
       
   708 
       
   709                                 parentSupportRegion.iBr.iX = ( ( parentSupportRegion.iBr.iX ) >> 1 ) + 2; //lint !e702    the shifted values cannot be negative here
       
   710                                 parentSupportRegion.iBr.iY = ( ( parentSupportRegion.iBr.iY ) >> 1 ) + 2; //lint !e702    the shifted values cannot be negative here
       
   711                                 }
       
   712                             }
       
   713                         }
       
   714 
       
   715 
       
   716                     subband = CONST_CAST( CJ2kSubband*, componentInfo->SubbandAt( levelIndex ) );
       
   717 
       
   718                     // For each subband in the resolution level
       
   719                     do    
       
   720                         {
       
   721                         bandIndex = ( quantStyle == 1 ) ? (TUint16)0 : subband->SubbandTreeIndex();
       
   722 
       
   723                         // Get the right magnitude_bits for this band
       
   724                         iMagnitudeBitsHere = componentInfo->MagnitudeBits( bandIndex );
       
   725 
       
   726                         // If iWaveletLevels == 0, do not update the supportRegion, since there is no wavelet decomposition ( zero levels )
       
   727                         if( iWaveletLevels != 0 )
       
   728                             {
       
   729                             // Now compute the support region for this band depending on whether it is LL, LH, HL or HH
       
   730                             // Use the support region of the parent for computation.
       
   731                             //
       
   732                             if( iReversible )
       
   733                                 {
       
   734                                 if( ( subband->SubbandType() ) == 0 || ( subband->SubbandType() ) == 2 )
       
   735                                     {
       
   736                                     if( subband->Parent()->HighPassFirst().iX )
       
   737                                         {
       
   738                                         supportRegion.iTl.iX = ( ( parentSupportRegion.iTl.iX >> 1 )-1 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
       
   739                                                                ( parentSupportRegion.iTl.iX >> 1 )-1 : 0; //lint !e702    the shifted values cannot be negative here
       
   740                                         }
       
   741                                     else
       
   742                                         {
       
   743                                         supportRegion.iTl.iX = parentSupportRegion.iTl.iX >> 1;     //lint !e702    the shifted value cannot be negative here
       
   744                                         }
       
   745                                     }
       
   746                                 else
       
   747                                     {
       
   748                                     supportRegion.iTl.iX = ( ( parentSupportRegion.iTl.iX >> 1 )-1 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
       
   749                                                            ( parentSupportRegion.iTl.iX >> 1 )-1 : 0; //lint !e702    the shifted values cannot be negative here
       
   750                                     }
       
   751 
       
   752 
       
   753                                 if( ( subband->SubbandType() ) == 0 || ( subband->SubbandType() ) == 1 )
       
   754                                     {
       
   755                                     if( subband->Parent()->HighPassFirst().iY )
       
   756                                         {
       
   757                                         supportRegion.iTl.iY = ( ( parentSupportRegion.iTl.iY >> 1 )-1 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
       
   758                                                                ( parentSupportRegion.iTl.iY >> 1 )-1 : 0; //lint !e702    the shifted values cannot be negative here
       
   759                                         }
       
   760                                     else
       
   761                                         {
       
   762                                         supportRegion.iTl.iY = parentSupportRegion.iTl.iY >>1;      //lint !e702    the shifted value cannot be negative here
       
   763                                         }
       
   764                                     }
       
   765                                 else
       
   766                                     {
       
   767                                     supportRegion.iTl.iY = ( ( parentSupportRegion.iTl.iY >> 1 )-1 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
       
   768                                                            ( parentSupportRegion.iTl.iY >> 1 )-1 : 0; //lint !e702    the shifted values cannot be negative here
       
   769                                     }
       
   770 
       
   771                                 // Compute the offset for this level
       
   772                                 regionOffset.iX = parentSupportRegion.iTl.iX - 2*supportRegion.iTl.iX;
       
   773                                 regionOffset.iY = parentSupportRegion.iTl.iY - 2*supportRegion.iTl.iY;
       
   774 
       
   775                                 // Support region's bottom right corner for each band is ( supportParent.iBr>>1 )+1
       
   776                                 supportRegion.iBr.iX = ( ( parentSupportRegion.iBr.iX ) >> 1 ) + 1; //lint !e702    the shifted value cannot be negative here
       
   777                                 supportRegion.iBr.iY = ( ( parentSupportRegion.iBr.iY ) >> 1 ) + 1; //lint !e702    the shifted value cannot be negative here
       
   778                                 }
       
   779                             else        // irreversible ( 9x7 ) filter 
       
   780                                 {
       
   781                                 // For low-pass filtering, the offset for the output is 1
       
   782                                 if( ( subband->SubbandType() ) == 0 || ( subband->SubbandType() ) == 2 )
       
   783                                     {
       
   784                                     if( subband->Parent()->HighPassFirst().iX )
       
   785                                         {
       
   786                                         supportRegion.iTl.iX = ( ( parentSupportRegion.iTl.iX >> 1 )-2 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
       
   787                                                                ( parentSupportRegion.iTl.iX >> 1 )-2 : 0; //lint !e702    the shifted values cannot be negative here
       
   788                                         }
       
   789                                     else
       
   790                                         {
       
   791                                         supportRegion.iTl.iX = ( ( parentSupportRegion.iTl.iX >> 1 )-1 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
       
   792                                                                ( parentSupportRegion.iTl.iX >> 1 )-1 : 0; //lint !e702    the shifted values cannot be negative here
       
   793                                         }
       
   794 
       
   795                                     }
       
   796                                 else
       
   797                                     {
       
   798                                     supportRegion.iTl.iX = ( ( parentSupportRegion.iTl.iX >> 1 )-2 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
       
   799                                                            ( parentSupportRegion.iTl.iX >> 1 )-2 : 0; //lint !e702    the shifted values cannot be negative here
       
   800                                     }
       
   801 
       
   802                                 if( ( subband->SubbandType() ) == 0 || ( subband->SubbandType() ) == 1 )
       
   803                                     {
       
   804                                     if( subband->Parent()->HighPassFirst().iY )
       
   805                                         {
       
   806                                         supportRegion.iTl.iY = ( ( parentSupportRegion.iTl.iY >> 1 )-2 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
       
   807                                                                ( parentSupportRegion.iTl.iY >> 1 )-2 : 0; //lint !e702    the shifted values cannot be negative here
       
   808                                         }
       
   809                                     else
       
   810                                         {
       
   811                                         supportRegion.iTl.iY = ( ( parentSupportRegion.iTl.iY >> 1 )-1 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
       
   812                                                                ( parentSupportRegion.iTl.iY >> 1 )-1 : 0; //lint !e702    the shifted values cannot be negative here
       
   813                                         }   
       
   814                                     }
       
   815                                 else
       
   816                                     {
       
   817                                     supportRegion.iTl.iY = ( ( parentSupportRegion.iTl.iY >> 1 )-2 > 0 ) ?  //lint !e702    The shifted values cannot be negative here
       
   818                                                            ( parentSupportRegion.iTl.iY >> 1 )-2 : 0; //lint !e702    the shifted values cannot be negative here
       
   819                                     }
       
   820 
       
   821                                 // Compute the offset for this level
       
   822                                 regionOffset.iY = parentSupportRegion.iTl.iY - 2*supportRegion.iTl.iY;
       
   823                                 regionOffset.iX = parentSupportRegion.iTl.iX - 2*supportRegion.iTl.iX;
       
   824 
       
   825                                 // Support region's bottom right corner for each band is ( supportParent.iBr>>1 )+2
       
   826                                 supportRegion.iBr.iX = ( ( parentSupportRegion.iBr.iX ) >> 1 ) + 2; //lint !e702    the shifted value cannot be negative here
       
   827                                 supportRegion.iBr.iY = ( ( parentSupportRegion.iBr.iY ) >> 1 ) + 2; //lint !e702    the shifted value cannot be negative here
       
   828                                 }
       
   829                             }
       
   830 
       
   831                         // Check that the support region doesn't exceed the band boundaries
       
   832                         if( supportRegion.iBr.iX > subband->SubbandCanvasSize().iWidth )
       
   833                             {
       
   834                             supportRegion.iBr.iX = subband->SubbandCanvasSize().iWidth;
       
   835                             }
       
   836                         if( supportRegion.iBr.iY > subband->SubbandCanvasSize().iHeight )
       
   837                             {
       
   838                             supportRegion.iBr.iY = subband->SubbandCanvasSize().iHeight;
       
   839                             }
       
   840 
       
   841                         // Store the low-band's dimensions here to later compute the size of the whole region ( low-band plus high-band ).
       
   842                         if( subband->SubbandType() == 2 )
       
   843                             {
       
   844                             regionSize.iWidth = supportRegion.Width();
       
   845                             }
       
   846                         if( subband->SubbandType() == 1 )
       
   847                             {
       
   848                             regionSize.iHeight = supportRegion.Height();
       
   849                             }
       
   850         
       
   851                         // Compute the Quantization parameters here, so we don't repeat that for every codeblock/precinct
       
   852                         ComputeQuantizationParameters( *componentInfo, bandIndex, subband->SubbandGain(), bitDepth );
       
   853 
       
   854                         // Set the lookup table for entropy decoder
       
   855                         aEntropyDecoder.SetCurrentZCLUT( (TUint8)( subband->SubbandType() ) );
       
   856 
       
   857                         packetList = CONST_CAST( RPointerArray<CJ2kPacket>*, &subband->PacketList() );    //lint !e665 the first parameter cannot be parenthesized here
       
   858                         
       
   859                         // For each packet in the subband
       
   860                         for ( packetIndex = 0; packetIndex < componentInfo->NumOfPackets( levelIndex ); 
       
   861                               ++packetIndex )
       
   862                             {
       
   863                             packet = ( *packetList )[packetIndex];
       
   864 
       
   865                             // For each codeblock in the packet
       
   866                             for ( blockIndex = 0; blockIndex < packet->NumOfBlocks(); ++blockIndex )
       
   867                                 {
       
   868                                 codeblock = CONST_CAST( CJ2kCodeBlock*, &packet->CodeBlockAt( blockIndex ) );
       
   869                                 
       
   870                                 const TRect& cbCanvas = codeblock->CodeBlockCanvas();
       
   871                                 
       
   872                                 TInt32 startRow = cbCanvas.iTl.iY - subband->SubbandCanvas().iTl.iY;
       
   873                                 TInt32 startCol = cbCanvas.iTl.iX - subband->SubbandCanvas().iTl.iX;
       
   874                                 TInt32 cblkHeight = cbCanvas.Height();
       
   875                                 TInt32 cblkWidth = cbCanvas.Width();
       
   876                                 TInt32 startRowCblk = 0;
       
   877                                 TInt32 startColCblk = 0;
       
   878                                 TInt32 startRowImage = 0;
       
   879                                 TInt32 startColImage = 0;
       
   880                                 
       
   881                                 if( startRow >= supportRegion.iBr.iY || startCol >= supportRegion.iBr.iX ||
       
   882                                     ( startRow+cblkHeight ) <= supportRegion.iTl.iY ||
       
   883                                     ( startCol+cblkWidth ) <= supportRegion.iTl.iX )
       
   884                                     { 
       
   885                                     }
       
   886                                 else 
       
   887                                     {
       
   888                                     // Compute the start column from which to copy from ( in the codeblock ) and where to copy to ( in the image block )
       
   889                                     if( startCol <= supportRegion.iTl.iX )
       
   890                                         {
       
   891                                         startColCblk  = supportRegion.iTl.iX - startCol;    // Ignore samples outside supportRegion
       
   892                                         startColImage = 0;              // First block, start from supportRegion's start
       
   893                                         cblkWidth -= startColCblk;      // Ignore samples outside supportRegion
       
   894                                         }
       
   895                                     else
       
   896                                         {
       
   897                                         startColCblk  = 0;                              // First block, start from supportRegion's start
       
   898                                         startColImage = startCol-supportRegion.iTl.iX;  // First block, start from supportRegion's start
       
   899                                         }
       
   900                                     // If the last block extends outside supportRegion, we have to adjust codeblock's width
       
   901                                     if( ( startCol+cbCanvas.Width() ) > supportRegion.iBr.iX )
       
   902                                         {
       
   903                                         cblkWidth -= ( ( startCol+cbCanvas.Width() ) - supportRegion.iBr.iX );  // Ignore samples outside supportRegion
       
   904                                         }
       
   905                                     
       
   906                                     // Compute the start row from which to copy from ( in the codeblock ) and where to copy to ( in the image block )
       
   907                                     if( startRow <= supportRegion.iTl.iY )
       
   908                                         {
       
   909                                         startRowCblk  = supportRegion.iTl.iY - startRow;    // ignore samples outside supportRegion
       
   910                                         startRowImage = 0;                                  // First block, start from supportRegion's start
       
   911                                         cblkHeight -= startRowCblk;                         // Ignore samples outside supportRegion
       
   912                                         }
       
   913                                     else
       
   914                                         {
       
   915                                         startRowCblk  = 0;                              // First block, start from supportRegion's start
       
   916                                         startRowImage = startRow-supportRegion.iTl.iY;  // First block, start from supportRegion's start
       
   917                                         }
       
   918                                     // If the last block extends outside supportRegion, we have to adjust codeblock's height
       
   919                                     if( ( startRow+cbCanvas.Height() ) > supportRegion.iBr.iY )
       
   920                                         {
       
   921                                         cblkHeight -= ( ( startRow+cbCanvas.Height() ) - supportRegion.iBr.iY );    // ignore samples outside supportRegion
       
   922                                         }
       
   923                                                                         
       
   924                                     // There is coded data in the codeblock
       
   925                                     if ( codeblock->DataLength() )
       
   926                                         {                                        
       
   927                                         // Decode the codeblock
       
   928                                         aEntropyDecoder.DecodeCodeblock( *codeblock, cblkStyle, 
       
   929                                                                          (TUint8)( iMagnitudeBitsHere + iROIShift ) );
       
   930                                             
       
   931                                         codeblock->SetCodeBlockDecoded();
       
   932 
       
   933                                         CopyDataToBlock( aEntropyDecoder, component->Data(), *subband, quantStyle, 
       
   934                                                          startRowCblk, startColCblk, startRowImage, 
       
   935                                                          startColImage, cblkHeight, cblkWidth );
       
   936                                         }
       
   937                                     else
       
   938                                         {
       
   939                                         // Empty codeblock, fill the corresponding area with zero, since other wise there might be data left from lower levels.
       
   940                                         FillDataWithZeros( component->Data(), *subband, startRowImage, startColImage, cblkHeight, cblkWidth );
       
   941                                         }
       
   942                                     }
       
   943                                 
       
   944                                 } // end of each codeblock
       
   945                             }  // end of each packet
       
   946 
       
   947                         // Get the sibling subband
       
   948                         subband = subband->NextSubbandRaster();
       
   949 
       
   950                         } while ( subband ); // end of each subband in the resolution level
       
   951 
       
   952                     // Now that we have processed all the blocks on this level, we can perform inverse wavelet transform on this level
       
   953                     // On resolution level zero, we don't have to inverse transform
       
   954                     if( levelIndex != 0 )
       
   955                         {
       
   956                         // The size of the inverse transformed region is the size of the low- ( stored in "regionSize" ) 
       
   957                         // and high-pass ( the supportRegion is always for HH-band, when we reach this point ) parts combined
       
   958                         regionSize = regionSize + supportRegion.Size();
       
   959 
       
   960                         subband = CONST_CAST( CJ2kSubband*, componentInfo->SubbandAt( levelIndex ) );
       
   961                         SingleLevelWaveletInverse( component->Data(), subband, regionOffset, regionSize, levelIndex );
       
   962                         }
       
   963                     }  // end of each resolution level in the component
       
   964 
       
   965                 // Check whether extra downsampling is needed
       
   966                 if( stepSize > 1 )
       
   967                     {
       
   968                     
       
   969                     TInt32 i,j;
       
   970                     TInt32 iStep,jStep;
       
   971                     
       
   972                     // If the stepSize is larger than one it means that we have to downsample
       
   973                     // the output. This is because there were not enough wavelet levels to do
       
   974                     // the resolution dropping for this component.
       
   975                     
       
   976                     // The reason why downsampling is done here and not in the ImageWriter is
       
   977                     // that different components might have different number of wavlet levels
       
   978                     // and thus it is easier to downsample the components here (so that we can 
       
   979                     // just write out the samples normally in ImageWriter.
       
   980                     for( i = 0,iStep = 0; iStep<KMaxBlockSupportSize; i++,iStep += stepSize)
       
   981                         {
       
   982                         for( j = 0,jStep = 0; jStep<KMaxBlockSupportSize; j++,jStep += stepSize)
       
   983                             {
       
   984                             
       
   985                             // Downsample the component so that downsampled image is in the
       
   986                             // upper left-hand corner.
       
   987                             component->Data()[i][j] = component->Data()[iStep][jStep];
       
   988                             }
       
   989                         }
       
   990                     }
       
   991 
       
   992                 if ( numOfComponents >= 3 ) 
       
   993                     {
       
   994                     if ( aTile.ColorTransformation() || 
       
   995                         ( aImageWriter.CSCode() == 18 || aImageWriter.CSCode() == 16 ) )
       
   996                         {
       
   997                         // Wait til we finish decoding all components before writing out the image
       
   998                         if ( compIndex < 2 )
       
   999                             {
       
  1000                             continue;   //lint !e960    Continue is OK.
       
  1001                             }
       
  1002                         }
       
  1003                     else if ( aImageWriter.CSCode() == 0 )
       
  1004                         {
       
  1005                         // This case is also valid when no CSCode is defined, e.g. no file format is present
       
  1006                         if( numOfComponents <= 3 )
       
  1007                             {
       
  1008                             if ( compIndex < 2 )
       
  1009                                 {
       
  1010                                 continue;   //lint !e960    Continue is OK.
       
  1011                                 }
       
  1012                             }
       
  1013                         else
       
  1014                             {
       
  1015                             // Proceed to outputBlockL
       
  1016                             }
       
  1017                         }
       
  1018                     }   //lint !e961    no else is needed here at the end of if...else if
       
  1019 
       
  1020                 aImageWriter.OutputBlockL( aTile, compIndex, blockXCoord, blockYCoord, firstCompSize, thisCompSize );
       
  1021                 }   // end of each component in the tile
       
  1022             }   // end of loop on the 256x256 blocks
       
  1023         }
       
  1024     }
       
  1025 
       
  1026 // -----------------------------------------------------------------------------
       
  1027 // CJ2kSynthesis::OneDimReversibleFilter
       
  1028 // Perform one dimensional synthesis using reversible 5/3 filter
       
  1029 // (other items were commented in a header).
       
  1030 // -----------------------------------------------------------------------------
       
  1031 //
       
  1032 void CJ2kSynthesis::OneDimReversibleFilter( TInt32 aStartPos, TInt32 aEndPos )
       
  1033     {
       
  1034     if ( ( aEndPos - aStartPos ) == 1 )
       
  1035         {
       
  1036         if ( aStartPos )
       
  1037             {
       
  1038             iOutputBuffer[aStartPos] = iInputBuffer[aStartPos] / 2;
       
  1039             }
       
  1040         else
       
  1041             {
       
  1042             iOutputBuffer[aStartPos] = iInputBuffer[aStartPos];
       
  1043             }
       
  1044         }
       
  1045     else
       
  1046         {
       
  1047         aEndPos++;
       
  1048         TInt32 idx = 0;
       
  1049         for ( idx = 0; idx < aEndPos; idx += 2 )
       
  1050             {
       
  1051             iOutputBuffer[idx] = iInputBuffer[idx] - 
       
  1052                                  ( ( iInputBuffer[idx - 1] + iInputBuffer[idx + 1] + 2 ) >> 2 );    //lint !e704 shifting is OK.
       
  1053             }
       
  1054 
       
  1055         for ( idx = 1; idx < aEndPos; idx += 2 )
       
  1056             {
       
  1057             iOutputBuffer[idx] = iInputBuffer[idx] + 
       
  1058                                  ( ( iOutputBuffer[idx - 1] + iOutputBuffer[idx + 1] ) >> 1 );      //lint !e704 shifting is OK.
       
  1059             }
       
  1060         }
       
  1061     }
       
  1062 
       
  1063 // -----------------------------------------------------------------------------
       
  1064 // CJ2kSynthesis::PerformExtension
       
  1065 // Performs one dimensional symmetric extension of the line of pixels from
       
  1066 // the 2 extensions of the line.
       
  1067 // (other items were commented in a header).
       
  1068 // -----------------------------------------------------------------------------
       
  1069 //
       
  1070 void CJ2kSynthesis::PerformExtension( TInt32 aStartPos, TInt32 aEndPos )
       
  1071     {
       
  1072     TInt32* high = iInputBuffer + aEndPos - 1;
       
  1073     TInt32 dir = 1;
       
  1074     TInt32 posLeft  = aStartPos;
       
  1075     TInt32 posRight = aEndPos - 1;
       
  1076   
       
  1077     for ( TInt32 idx = 1; idx <= KFilterExtension; ++idx )
       
  1078         {
       
  1079         posLeft += dir;
       
  1080         posRight -= dir;
       
  1081         iInputBuffer[aStartPos - idx] = iInputBuffer[posLeft];
       
  1082         high[idx] = iInputBuffer[posRight];
       
  1083 
       
  1084         if ( posLeft == ( aEndPos - 1 ) )
       
  1085             {
       
  1086             dir = -1;
       
  1087             }
       
  1088         if ( dir == -1 )
       
  1089             {
       
  1090             if ( posLeft == aStartPos )
       
  1091                 {
       
  1092                 dir = 1;
       
  1093                 }
       
  1094             }
       
  1095         }
       
  1096     }
       
  1097 
       
  1098 // -----------------------------------------------------------------------------
       
  1099 // CJ2kSynthesis::OneDimIrrevFilter
       
  1100 // Perform one dimensional synthesis using irreversible 9/7 filter
       
  1101 // (other items were commented in a header).
       
  1102 // -----------------------------------------------------------------------------
       
  1103 //
       
  1104 void CJ2kSynthesis::OneDimIrrevFilter( TInt32 aStartPos, 
       
  1105                                        TInt32 aEndPos,
       
  1106                                        TUint8 aLevel,
       
  1107                                        TUint8 aVertical )
       
  1108     {
       
  1109     if ( ( aEndPos - aStartPos ) == 1 )
       
  1110         {
       
  1111         if ( aStartPos )
       
  1112             {
       
  1113             iOutputBuffer[aStartPos] = iInputBuffer[aStartPos] / 2;
       
  1114             }
       
  1115         else
       
  1116             {
       
  1117             iOutputBuffer[aStartPos] = iInputBuffer[aStartPos];
       
  1118             }
       
  1119         }
       
  1120     else
       
  1121         {
       
  1122         // First the low-pass parts
       
  1123         TInt32 idx = aStartPos + ( aStartPos % 2 );
       
  1124         for ( ; idx < aEndPos; idx += 2 )
       
  1125             {
       
  1126             iOutputBuffer[idx] = iTapsLow[0] * iInputBuffer[idx] + 
       
  1127                                  iTapsLow[2] * ( iInputBuffer[idx - 2] + iInputBuffer[idx + 2] );
       
  1128             }
       
  1129 
       
  1130         idx = aStartPos + ( ( aStartPos + 1 ) % 2 );
       
  1131         for ( ; idx < aEndPos; idx += 2 )
       
  1132             {
       
  1133             iOutputBuffer[idx] = iTapsLow[1] * ( iInputBuffer[idx - 1] + iInputBuffer[idx + 1] ) +
       
  1134                                  iTapsLow[3] * ( iInputBuffer[idx - 3] + iInputBuffer[idx + 3] );
       
  1135             }
       
  1136     
       
  1137         // Then the high-pass parts 
       
  1138         idx = aStartPos + ( ( aStartPos + 1 ) % 2 );
       
  1139         for ( ; idx < aEndPos; idx += 2 )
       
  1140             {
       
  1141             iOutputBuffer[idx] += iTapsHigh[0] * iInputBuffer[idx] +
       
  1142                                   iTapsHigh[2] * ( iInputBuffer[idx - 2] + iInputBuffer[idx + 2] ) +
       
  1143                                   iTapsHigh[4] * ( iInputBuffer[idx - 4] + iInputBuffer[idx + 4] );
       
  1144             }
       
  1145 
       
  1146         idx = aStartPos + ( aStartPos % 2 );
       
  1147         for ( ; idx < aEndPos; idx += 2 )
       
  1148             {
       
  1149             iOutputBuffer[idx] += iTapsHigh[1] * ( iInputBuffer[idx - 1] + iInputBuffer[idx + 1] ) +
       
  1150                                   iTapsHigh[3] * ( iInputBuffer[idx - 3] + iInputBuffer[idx + 3] ); 
       
  1151             }
       
  1152 
       
  1153         TInt32 offset = 0;
       
  1154         TInt32 downshift = 0;
       
  1155 
       
  1156         // Finally downshift all the samples
       
  1157         if ( !aVertical || ( aLevel != 0 ) )
       
  1158             {
       
  1159             downshift = KFilterShift;
       
  1160             }
       
  1161         else
       
  1162             {
       
  1163             downshift = KFilterShift + KWaveletShift;
       
  1164             }
       
  1165 
       
  1166         offset = ( (TUint32)( 1 << downshift ) >> 1 );
       
  1167         idx = aStartPos;
       
  1168 
       
  1169         for ( ; idx < aEndPos; idx++ )
       
  1170             {
       
  1171             iOutputBuffer[idx] = ( iOutputBuffer[idx] + offset ) >> downshift;    //lint !e704 shifting is OK.
       
  1172             }
       
  1173         }
       
  1174     }
       
  1175 
       
  1176 // -----------------------------------------------------------------------------
       
  1177 // CJ2kSynthesis::OneDimFiltering
       
  1178 // Perform one dimensional filtering
       
  1179 // (other items were commented in a header).
       
  1180 // -----------------------------------------------------------------------------
       
  1181 //
       
  1182 void CJ2kSynthesis::OneDimFiltering( TInt32 aStartPos, 
       
  1183                                      TInt32 aEndPos,
       
  1184                                      TUint8 aLevel,
       
  1185                                      TUint8 aVertical )
       
  1186     {
       
  1187     // Extend the signals ( at the start and end )
       
  1188     PerformExtension( aStartPos, aEndPos );
       
  1189 
       
  1190     if ( iReversible )
       
  1191         {
       
  1192         OneDimReversibleFilter( aStartPos, aEndPos );
       
  1193         }
       
  1194     else
       
  1195         {
       
  1196         OneDimIrrevFilter( aStartPos, aEndPos, aLevel, aVertical );
       
  1197         }
       
  1198     }
       
  1199 
       
  1200 // -----------------------------------------------------------------------------
       
  1201 // CJ2kSynthesis::HorizontalFilter
       
  1202 // Perform one dimensional horizontal filtering
       
  1203 // (other items were commented in a header).
       
  1204 // -----------------------------------------------------------------------------
       
  1205 //
       
  1206 void CJ2kSynthesis::HorizontalFilter( TPrecInt** aImage, 
       
  1207                                       TInt32 aRow,
       
  1208                                       TUint32 aXtcSiz, 
       
  1209                                       CJ2kSubband* aSubband )
       
  1210     {
       
  1211     TInt32 endPos = 0;
       
  1212     TInt32 startPos = aSubband->HighPassFirst().iX;
       
  1213   
       
  1214     TInt32* rowImage = (TInt32*)aImage[aRow];
       
  1215     TInt32* rowImageHigh = rowImage + aSubband->ChildAt( CJ2kSubband::EBandLL )->SubbandCanvasSize().iWidth; 
       
  1216     TInt32* iterator = iInputBuffer;
       
  1217 
       
  1218     // Low-pass is first
       
  1219     if ( !startPos )  
       
  1220         {
       
  1221         for ( endPos = aXtcSiz >> 1; endPos > 0; endPos-- )
       
  1222             {
       
  1223             *iterator++ = *rowImage++;
       
  1224             *iterator++ = *rowImageHigh++;
       
  1225             }
       
  1226         if ( aXtcSiz % 2 )  // One extra sample for low-pass
       
  1227             {
       
  1228             *iterator = *rowImage;
       
  1229             }
       
  1230         }
       
  1231     else  // High-pass is first
       
  1232         {
       
  1233         iterator++;
       
  1234         for ( endPos = aXtcSiz >> 1; endPos > 0; endPos-- )
       
  1235             {
       
  1236             *iterator++ = *rowImageHigh++;
       
  1237             *iterator++ = *rowImage++;
       
  1238             }
       
  1239         if ( aXtcSiz % 2 )  // One extra sample for high-pass
       
  1240             {
       
  1241             *iterator = *rowImageHigh;
       
  1242             }
       
  1243         }
       
  1244   
       
  1245     endPos = aXtcSiz + startPos; 
       
  1246 
       
  1247     OneDimFiltering( startPos, endPos, aSubband->SubbandLevel(), 0 ); 
       
  1248     Mem::Copy( aImage[aRow], iOutputBuffer + startPos, aXtcSiz * sizeof( TPrecInt ) );
       
  1249     }
       
  1250 
       
  1251 // -----------------------------------------------------------------------------
       
  1252 // CJ2kSynthesis::VerticalFilter
       
  1253 // Perform one dimensional vertical filtering
       
  1254 // (other items were commented in a header).
       
  1255 // -----------------------------------------------------------------------------
       
  1256 //
       
  1257 void CJ2kSynthesis::VerticalFilter( TPrecInt **aImage, 
       
  1258                                     TInt32 aColumn,
       
  1259                                     TUint32 aYtcSiz, 
       
  1260                                     CJ2kSubband *aSubband )
       
  1261     {
       
  1262     TInt32 startPos = aSubband->HighPassFirst().iY;
       
  1263     TInt32 highStart = aSubband->ChildAt( CJ2kSubband::EBandLL )->SubbandCanvasSize().iHeight;
       
  1264     TInt32 highStop = aSubband->SubbandCanvasSize().iHeight;
       
  1265     TInt32 *iterator = iInputBuffer;
       
  1266  
       
  1267     TInt32 lowIndex = 0;
       
  1268     TInt32 highIndex = highStart;
       
  1269     if ( !startPos )
       
  1270         {
       
  1271         for ( ; highIndex < highStop; lowIndex++, highIndex++ )
       
  1272             {
       
  1273             *iterator++ = aImage[lowIndex][aColumn];
       
  1274             *iterator++ = aImage[highIndex][aColumn];
       
  1275             }
       
  1276         if ( aYtcSiz % 2 )
       
  1277             {
       
  1278             *iterator = aImage[lowIndex][aColumn];
       
  1279             }
       
  1280         }
       
  1281     else 
       
  1282         {
       
  1283         iterator++;
       
  1284         for ( ; lowIndex < highStart; highIndex++, lowIndex++ )
       
  1285             {
       
  1286             *iterator++ = aImage[highIndex][aColumn];
       
  1287             *iterator++ = aImage[lowIndex][aColumn];
       
  1288             }
       
  1289         if ( aYtcSiz % 2 )
       
  1290             {
       
  1291             *iterator = aImage[highIndex][aColumn];
       
  1292             }
       
  1293         }
       
  1294 
       
  1295     OneDimFiltering( startPos, startPos + aYtcSiz, aSubband->SubbandLevel(), 1 );  
       
  1296     iOutputBuffer += ( startPos + aYtcSiz - 1 );
       
  1297 
       
  1298     for ( lowIndex = aYtcSiz - 1; lowIndex >= 0; lowIndex-- )
       
  1299         {
       
  1300         aImage[lowIndex][aColumn] = *iOutputBuffer--;
       
  1301         }
       
  1302     iOutputBuffer += ( 1 - startPos );
       
  1303     }
       
  1304 
       
  1305 // -----------------------------------------------------------------------------
       
  1306 // CJ2kSynthesis::TwoDimFiltering
       
  1307 // Perform two dimensional inverse wavelet transformation
       
  1308 // (other items were commented in a header).
       
  1309 // -----------------------------------------------------------------------------
       
  1310 //
       
  1311 void CJ2kSynthesis::TwoDimFiltering( TPrecInt **aImage, 
       
  1312                                      TInt32 aXtcSiz, 
       
  1313                                      TInt32 aYtcSiz, 
       
  1314                                      CJ2kSubband *aSubband )
       
  1315     {
       
  1316     TInt32 index = 0;
       
  1317 
       
  1318     for ( index = aYtcSiz - 1; index >= 0; index-- )
       
  1319         {
       
  1320         HorizontalFilter( aImage, index, aXtcSiz, aSubband );
       
  1321         }
       
  1322 
       
  1323     for ( index = aXtcSiz - 1; index >= 0; index-- )
       
  1324         {
       
  1325         VerticalFilter( aImage, index, aYtcSiz, aSubband );
       
  1326         }
       
  1327     }
       
  1328 
       
  1329 // -----------------------------------------------------------------------------
       
  1330 // CJ2kSynthesis::FullWaveletInverse
       
  1331 // Perform a full inverse wavelet transformation
       
  1332 // (other items were commented in a header).
       
  1333 // -----------------------------------------------------------------------------
       
  1334 //
       
  1335 void CJ2kSynthesis::FullWaveletInverse( TPrecInt **aImage, CJ2kSubband *aSubband )
       
  1336     {
       
  1337     TSize  canvas( 0, 0 );
       
  1338     TUint8 reduceLevels = 0;
       
  1339     
       
  1340     // If truncating resolution levels, we have to compute the reduced levels,
       
  1341     // so that the final WAVELET_SHIFT in case of 9x7 filter is performed.
       
  1342     if ( aSubband->SubbandLevel() > iWaveletLevels )
       
  1343         {
       
  1344         reduceLevels = (TUint8)( aSubband->SubbandLevel() - iWaveletLevels );
       
  1345         }
       
  1346 
       
  1347     for ( TUint8 levelIndex = (TUint8)iWaveletLevels; levelIndex > 0; levelIndex-- )
       
  1348         {
       
  1349         // The next lines assume that subband points to the LL-band and
       
  1350         // it is then moved to point to the parent i.e. to the last 
       
  1351         // _decomposition level_ of the wavelet transform.
       
  1352         aSubband = aSubband->Parent();
       
  1353 
       
  1354         // Adjust the level in case of resolution truncation
       
  1355         aSubband->SetSubbandLevel( (TUint8)( aSubband->SubbandLevel() - reduceLevels ) );
       
  1356 
       
  1357         canvas = aSubband->SubbandCanvasSize();
       
  1358         if ( canvas.iWidth > 0 && canvas.iHeight > 0 )
       
  1359             {
       
  1360             TwoDimFiltering( aImage, canvas.iWidth, canvas.iHeight, aSubband );
       
  1361             }
       
  1362         }
       
  1363     }
       
  1364 
       
  1365 // -----------------------------------------------------------------------------
       
  1366 // CJ2kSynthesis::ComputeQuantizationParameters
       
  1367 // Compute the quantization parameters for a particular subband in the component
       
  1368 // (other items were commented in a header).
       
  1369 // -----------------------------------------------------------------------------
       
  1370 //
       
  1371 void CJ2kSynthesis::ComputeQuantizationParameters( const CJ2kComponentInfo& aComponentInfo,
       
  1372                                                    TInt16 aBandIndex,
       
  1373                                                    TUint8 aBandGain,
       
  1374                                                    TUint8 aBitDepth )
       
  1375     {
       
  1376     if ( iROIShift != 0 )  
       
  1377         {
       
  1378         // ROI shifting is used
       
  1379         if ( aComponentInfo.QuantizationStyle() == 0 )
       
  1380             {
       
  1381             // Compute the shift for the codeblock's data, which is
       
  1382             // IMPLEMENTATION PRECISION -1( for sign ) - subband's range -
       
  1383             // the guard bits. 
       
  1384             iDataShift = ( KImplementationPrecision - 1 ) - iMagnitudeBitsHere;
       
  1385             }
       
  1386         else  // Irreversible case
       
  1387             {  
       
  1388             // Because we have integer arithmetic only, we subtract WAVELET_SHIFT from the shift.
       
  1389             // This is to compensate for the fractional bits of the inverse quantized wavelet
       
  1390             // coefficients.
       
  1391             iDataShift = ( KImplementationPrecision - 1 ) - iMagnitudeBitsHere - KWaveletShift;
       
  1392 
       
  1393             // The quantization step is computed from the equation
       
  1394             // step = ( 2^( Range-Exponent ) )*( 1+( Mantissa/( 2^11 ) ) ), where Range is the dynamic 
       
  1395             // range of this subband ( = bitdepth + gain ). ( see Annex E of the standard for more
       
  1396             // information ).
       
  1397             //
       
  1398             // The "iStepExponent" is the shift needed to remove "iStepValue"'s fractional
       
  1399             // bits. The "iStepValue" is the shifted quantization step. Shifting back
       
  1400             // is done right after computing the quantized coefficient.
       
  1401             iStepExponent = aBitDepth + aBandGain - aComponentInfo.Exponent( aBandIndex ) - KStepBits;
       
  1402             iStepValue = aComponentInfo.Mantissa( aBandIndex ) + ( 1 << KStepBits );
       
  1403             }
       
  1404 
       
  1405         // Compute the shift for the data inside the ROI
       
  1406         iROIDataShift = iDataShift - iROIShift;      
       
  1407         }
       
  1408     else  
       
  1409         {
       
  1410         // ROI is not present
       
  1411         if ( aComponentInfo.QuantizationStyle() == 0 )
       
  1412             {
       
  1413             // Compute the shift for the codeblock's data, which is
       
  1414             // IMPLEMENTATION PRECISION-1( for sign ) - subband's range -
       
  1415             // the guard bits. 
       
  1416             iDataShift = ( KImplementationPrecision - 1 ) - iMagnitudeBitsHere;
       
  1417             // Shift all the samples in the codeblock
       
  1418             }
       
  1419         else  // Irreversible case 
       
  1420             {
       
  1421             // Because we have integer arithmetic only, we subtract WAVELET_SHIFT from the shift.
       
  1422             // This is to compensate for the fractional bits of the inverse quantized wavelet
       
  1423             // coefficients.
       
  1424             iDataShift = ( KImplementationPrecision - 1 ) - iMagnitudeBitsHere - KWaveletShift;
       
  1425 
       
  1426             // To prevent overflows we check if the "shift" is at least 12. The minimum downshift of 12 is 
       
  1427             // derived from the computation of "value*iStepValue", where "value" is downshifted previously by "shift"
       
  1428             // and "iStepValue" is at maximum 12 bits ( since iStepValue = mantissa + 1<<KStepBits, where mantissa is
       
  1429             // a 11-bit value and KStepBits is 11 ).
       
  1430             //
       
  1431             TInt32 iExtraBits = 0;
       
  1432             // If the implementation precision is 16 then we don't have to check if the shift is at least 12.
       
  1433             // This is because we use 32 bits for the computation and thus have at least 16 zero most significant 
       
  1434             // bits at the "value".
       
  1435 
       
  1436             
       
  1437             if ( iDataShift < 12 )    // Test to prevent overflows 
       
  1438                 {
       
  1439                 iExtraBits = 12 - iDataShift;
       
  1440                 iDataShift += iExtraBits;
       
  1441                 }
       
  1442 
       
  1443             // The quantization step is computed from the equation
       
  1444             // step = ( 2^( Range-Exponent ) )*( 1+( Mantissa/( 2^11 ) ) ), where Range is the dynamic 
       
  1445             // range of this subband ( = bitdepth + gain ). ( see Annex E of the standard for more
       
  1446             // information ).
       
  1447             //
       
  1448             // The "iStepExponent" is the shift needed to remove "iStepValue"'s fractional
       
  1449             // bits. The "iStepValue" is the shifted quantization step. Shifting back
       
  1450             // is done right after computing the quantized coefficient.
       
  1451             //
       
  1452             iStepExponent = aBitDepth + aBandGain - aComponentInfo.Exponent( aBandIndex ) - KStepBits;
       
  1453 
       
  1454             // Test to prevent overflows
       
  1455             iStepExponent += iExtraBits;
       
  1456       
       
  1457             iStepValue = aComponentInfo.Mantissa( aBandIndex ) + ( 1 << KStepBits );
       
  1458             }
       
  1459         }
       
  1460     }
       
  1461 
       
  1462 // -----------------------------------------------------------------------------
       
  1463 // CJ2kSynthesis::CopyDataToImage
       
  1464 // Apply inverse quantization and ROI shifting on the decoded
       
  1465 // codeblock and copy to the image writer
       
  1466 // (other items were commented in a header).
       
  1467 // -----------------------------------------------------------------------------
       
  1468 //
       
  1469 void CJ2kSynthesis::CopyDataToImage( CJ2kEntropyDecoder& aEntropyDecoder, TPrecInt** aImageBlock, 
       
  1470                                      CJ2kSubband& aSubband, CJ2kCodeBlock& aCodeblock,
       
  1471                                      TUint8 aQuantizationStyle )
       
  1472     {
       
  1473     TPrecInt* buffer = 0;    // To buffer one row of the aImageBlock
       
  1474     TPrecInt* imageRow = 0;  // One row of the image
       
  1475     TPrecInt valueInt = 0;
       
  1476     TInt32 value = 0;
       
  1477     TInt32 j = 0;
       
  1478 
       
  1479     const TRect& cbCanvas = aCodeblock.CodeBlockCanvas();
       
  1480 
       
  1481     TInt32 startRow = cbCanvas.iTl.iY - aSubband.SubbandCanvas().iTl.iY + aSubband.SubbandOrigin().iY;
       
  1482     TInt32 startCol = cbCanvas.iTl.iX - aSubband.SubbandCanvas().iTl.iX + aSubband.SubbandOrigin().iX;
       
  1483     TInt32 endRow = startRow + cbCanvas.Height() - 1;
       
  1484     TInt32 endCol = startCol + cbCanvas.Width();
       
  1485 
       
  1486     TInt32 cols = endCol - startCol - 1;
       
  1487 
       
  1488     if ( iROIShift )  // ROI shifting is used
       
  1489         {
       
  1490         // Compute mask to determine which samples are in ROI
       
  1491         // for mask ROI coefficients
       
  1492         TInt32 mask = ( ( 1 << iMagnitudeBitsHere ) - 1 ) << ( ( KImplementationPrecision - 1 ) - iMagnitudeBitsHere );
       
  1493         TInt32 mask2 = ( ~mask ) & KMaximumPrecisionInteger;
       
  1494         TInt32 mask3 = ( ( 1 << iROIShift ) - 1 ) << ( ( KImplementationPrecision - 1 ) - iROIShift );
       
  1495         TInt32 maskShift = ( ~mask3 ) & KMaximumPrecisionInteger;
       
  1496 
       
  1497         if ( !aQuantizationStyle )
       
  1498             {
       
  1499             // Shift all the samples in the codeblock
       
  1500             TInt32 roiDataShift = ( iROIDataShift < 0 ) ? -iROIDataShift : iROIDataShift;
       
  1501             
       
  1502             for ( ; endRow >= startRow; endRow-- )
       
  1503                 {
       
  1504                 buffer = aEntropyDecoder.iData[endRow - startRow] + cols;
       
  1505                 for ( j = endCol - 1; j >= startCol; j-- )
       
  1506                     {
       
  1507                     value = ( *buffer-- );
       
  1508                     if ( !( value & mask ) ) // Background
       
  1509                         {
       
  1510                         // iROIDataShift can never be negative here!
       
  1511                         if ( iROIDataShift < 0 )
       
  1512                             {
       
  1513                             aImageBlock[endRow][j] = ( value < 0 ) ? -( ( value & KMaximumPrecisionInteger ) << roiDataShift ) 
       
  1514                                                                     : ( value  << roiDataShift );               //lint !e704 value is positive here
       
  1515                             }
       
  1516                         else
       
  1517                             {
       
  1518                             aImageBlock[endRow][j] = ( value < 0 ) ? -( ( value & maskShift ) >> roiDataShift )  //lint !e704 value&maskShift is positive, so no risk of right shifting negative values
       
  1519                                                                     : ( ( value & maskShift ) >> roiDataShift );  //lint !e704 value&maskShift is positive
       
  1520                             }
       
  1521                         }
       
  1522                     else  // ROI
       
  1523                         {
       
  1524                         if ( value & mask2 ) 
       
  1525                             {
       
  1526                             // Decoded more than magbits bit-planes, set
       
  1527                             // quantization mid-interval approx. bit just after
       
  1528                             // the magbits.
       
  1529                             value &= ( ~mask2 );
       
  1530                             }
       
  1531 
       
  1532                         aImageBlock[endRow][j] = ( value < 0 ) ? -( ( value & KMaximumPrecisionInteger ) >> iDataShift )
       
  1533                                                                 : ( value >> iDataShift );                      //lint !e704 value is positive here
       
  1534                         }
       
  1535                     }
       
  1536                 }
       
  1537             }
       
  1538         else  // Irreversible case
       
  1539             {
       
  1540             // Shift all the samples in the codeblock
       
  1541             TInt32 stepExponent = ( iStepExponent < 0 ) ? -iStepExponent : iStepExponent;
       
  1542 
       
  1543             // Divide into two cases depending on the sign of the iStepExponent to speed up coding
       
  1544             if ( iStepExponent < 0 )
       
  1545                 {
       
  1546                 for ( ; endRow >= startRow; endRow-- )
       
  1547                     {
       
  1548                     buffer = aEntropyDecoder.iData[endRow - startRow] + cols;
       
  1549                     for ( j = endCol - 1; j >= startCol; j-- )
       
  1550                         {
       
  1551                         value = ( *buffer-- );
       
  1552 
       
  1553                         // Divide into two cases depending on whether value is negative
       
  1554                         if ( value < 0 )
       
  1555                             {
       
  1556                             if ( !( value & mask ) ) // Background
       
  1557                                 {
       
  1558                                 value = ( ( value & maskShift ) >> iROIDataShift );     //lint !e704 value&maskShift is positive
       
  1559                                 valueInt = -( ( value * iStepValue ) >> stepExponent );  //lint !e704 ( value*iStepValue )&KMaximumPrecisionInteger is positive
       
  1560                                 }
       
  1561                             else  // ROI
       
  1562                                 {
       
  1563                                 if ( value & mask2 ) 
       
  1564                                     {
       
  1565                                     // Decoded more than magbits bit-planes, set
       
  1566                                     // quantization mid-interval approx. bit just after
       
  1567                                     // the magbits.
       
  1568                                     value = ( value & ( ~mask2 ) ) | ( 1 << ( KImplementationPrecision - 2 - iMagnitudeBitsHere ) );
       
  1569                                     }
       
  1570 
       
  1571                                 value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
       
  1572                                 valueInt = -( ( value * iStepValue ) >> stepExponent );  //lint !e704 ( value*iStepValue )&KMaximumPrecisionInteger is positive
       
  1573                                 }
       
  1574                             }
       
  1575                         else    // Value is non-negative
       
  1576                             {
       
  1577                             if ( !( value & mask ) ) // background
       
  1578                                 {
       
  1579                                 value = ( ( value & maskShift ) >> iROIDataShift );     //lint !e704 value&maskShift is positive
       
  1580                                 valueInt = ( ( value * iStepValue ) >> stepExponent );  //lint !e704 value*iStepValue is positive
       
  1581                                 }
       
  1582                             else  // ROI
       
  1583                                 {
       
  1584                                 if ( value & mask2 ) 
       
  1585                                     {
       
  1586                                     // Decoded more than magbits bit-planes, set
       
  1587                                     // quantization mid-interval approx. bit just after
       
  1588                                     // the magbits.
       
  1589                                     value = ( value & ( ~mask2 ) ) | ( 1 << ( KImplementationPrecision - 2 - iMagnitudeBitsHere ) );
       
  1590                                     }
       
  1591 
       
  1592                                 value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
       
  1593                                 valueInt = ( ( value * iStepValue ) >> stepExponent );  //lint !e704 value*iStepValue is positive
       
  1594                                 }
       
  1595                             }
       
  1596 
       
  1597                         aImageBlock[endRow][j] = valueInt;       
       
  1598                         }
       
  1599                     }
       
  1600                 }
       
  1601             else    // iStepExponent is non-negative
       
  1602                 {
       
  1603                 for ( ; endRow >= startRow; endRow-- )
       
  1604                     {
       
  1605                     buffer = aEntropyDecoder.iData[endRow - startRow] + cols;
       
  1606                     for ( j = endCol - 1; j >= startCol; j-- )
       
  1607                         {
       
  1608                         value = ( *buffer-- );
       
  1609 
       
  1610                         // Divide into two cases depending on whether value is negative
       
  1611                         if ( value < 0 )
       
  1612                             {
       
  1613 
       
  1614                             // Change value to be positive
       
  1615                             value = -value;
       
  1616 
       
  1617                             if ( !( value & mask ) ) // Background
       
  1618                                 {
       
  1619                                 value = ( ( value & maskShift ) >> iROIDataShift );   //lint !e704 value&maskShift is positive
       
  1620                                 valueInt = ( ( value * iStepValue ) << stepExponent );
       
  1621                                 }
       
  1622                             else  // ROI
       
  1623                                 {
       
  1624                                 if ( value & mask2 ) 
       
  1625                                     {
       
  1626                                     // Decoded more than magbits bit-planes, set
       
  1627                                     // quantization mid-interval approx. bit just after
       
  1628                                     // the magbits.
       
  1629                                     value = ( value & ( ~mask2 ) ) | ( 1 << ( KImplementationPrecision - 2 - iMagnitudeBitsHere ) );
       
  1630                                     }
       
  1631 
       
  1632                                 value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
       
  1633                                 valueInt = ( ( value * iStepValue ) << stepExponent );
       
  1634                                 }
       
  1635 
       
  1636                             // Change the sign back to negative
       
  1637                             aImageBlock[endRow][j] = -valueInt;
       
  1638                             }
       
  1639                         else    // Value is non-negative
       
  1640                             {
       
  1641                             if ( !( value & mask ) ) // Background
       
  1642                                 {
       
  1643                                 value = ( ( value & maskShift ) >> iROIDataShift );   //lint !e704 value&maskShift is positive
       
  1644                                 valueInt = ( ( value * iStepValue ) << stepExponent );
       
  1645                                 }
       
  1646                             else  // ROI
       
  1647                                 {
       
  1648                                 if ( value & mask2 ) 
       
  1649                                     {
       
  1650                                     // Decoded more than magbits bit-planes, set
       
  1651                                     // quantization mid-interval approx. bit just after
       
  1652                                     // the magbits.
       
  1653                                     value = ( value & ( ~mask2 ) ) | ( 1 << ( KImplementationPrecision - 2 - iMagnitudeBitsHere ) );
       
  1654                                     }
       
  1655 
       
  1656                                 value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
       
  1657                                 valueInt = ( ( value * iStepValue ) << stepExponent );
       
  1658                                 }
       
  1659                             aImageBlock[endRow][j] = valueInt;
       
  1660                             }
       
  1661                         }
       
  1662                     }
       
  1663                 }
       
  1664             }
       
  1665         }
       
  1666     else  // ROI is not present
       
  1667         {
       
  1668         if ( !aQuantizationStyle )
       
  1669             {
       
  1670             // Shift all the samples in the codeblock
       
  1671             TInt32 i = endRow - startRow;
       
  1672             for ( ; endRow >= startRow; endRow--, i-- )
       
  1673                 {
       
  1674                 imageRow = aImageBlock[endRow] + endCol - 1;
       
  1675                 buffer = aEntropyDecoder.iData[i] + cols;
       
  1676                 for ( j = endCol - 1; j >= startCol; j-- )
       
  1677                     {
       
  1678                     value = *buffer--;
       
  1679                     if ( value < 0 )
       
  1680                         {
       
  1681                         *imageRow-- = -( ( value & KMaximumPrecisionInteger ) >> iDataShift );
       
  1682                         }
       
  1683                     else
       
  1684                         {
       
  1685                         *imageRow-- = value >> iDataShift;            //lint !e704 value is positive here
       
  1686                         }
       
  1687                     }
       
  1688                 }
       
  1689             }
       
  1690         else  // Irreversible case 
       
  1691             {
       
  1692             // Shift all the samples in the codeblock 
       
  1693             TInt32 stepExponent = ( iStepExponent < 0 ) ? -iStepExponent : iStepExponent;
       
  1694             
       
  1695             // Divide into two cases depending on the sign of the iStepExponent to speed up coding
       
  1696             if ( iStepExponent < 0 )
       
  1697                 {
       
  1698                 for ( ; endRow >= startRow; endRow-- )
       
  1699                     {
       
  1700                     buffer = aEntropyDecoder.iData[endRow - startRow] + cols;
       
  1701                     for ( j = endCol - 1;  j >= startCol; j-- )
       
  1702                         {
       
  1703                         value = ( *buffer-- );
       
  1704 
       
  1705                         if ( value < 0 )   // Negative value
       
  1706                             {
       
  1707                             value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
       
  1708                             aImageBlock[endRow][j] = (TPrecInt)( -( ( value * iStepValue ) >> stepExponent ) );  //lint !e704 value*iStepValue is positive
       
  1709                             }
       
  1710                         else
       
  1711                             {
       
  1712                             value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
       
  1713                             aImageBlock[endRow][j] = (TPrecInt)( ( value * iStepValue ) >> stepExponent );     //lint !e704 value*iStepValue is positive
       
  1714                             }
       
  1715                         }
       
  1716                     }
       
  1717                 }
       
  1718             else    // iStepExponent is non-negative
       
  1719                 {
       
  1720                 for ( ; endRow >= startRow; endRow-- )
       
  1721                     {
       
  1722                     buffer = aEntropyDecoder.iData[endRow - startRow] + cols;
       
  1723                     for ( j = endCol - 1;  j >= startCol; j-- )
       
  1724                         {
       
  1725                         value = ( *buffer-- );
       
  1726 
       
  1727                         if ( value < 0 )   // Negative value
       
  1728                             {
       
  1729                             value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
       
  1730                             aImageBlock[endRow][j] = (TPrecInt)( -( ( value * iStepValue ) << stepExponent ) );
       
  1731                             }
       
  1732                         else
       
  1733                             {
       
  1734                             value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
       
  1735                             aImageBlock[endRow][j] = (TPrecInt)( ( value * iStepValue ) << stepExponent );
       
  1736                             }
       
  1737                         }
       
  1738                     }
       
  1739                 }
       
  1740             }
       
  1741         }
       
  1742   
       
  1743     // If number of levels is zero then we have to do the 
       
  1744     // inverse wavelet shifting here.
       
  1745     //
       
  1746     if ( iWaveletLevels == 0 )
       
  1747         {
       
  1748         endRow = startRow + cbCanvas.Height();
       
  1749         endCol = startCol + cbCanvas.Width();
       
  1750 
       
  1751         if ( aQuantizationStyle )
       
  1752             {
       
  1753             for ( TInt32 i = endRow - 1; i >= startRow; i-- )
       
  1754                 {
       
  1755                 for ( j = endCol - 1; j >= startCol; j-- )
       
  1756                     {
       
  1757                     aImageBlock[i][j] >>= KWaveletShift; //lint !e704 shifting is OK.
       
  1758                     }
       
  1759                 }
       
  1760             }
       
  1761         }
       
  1762     }
       
  1763 
       
  1764 // -----------------------------------------------------------------------------
       
  1765 // CJ2kSynthesis::AllocBufferL
       
  1766 // Allocate internal buffer based on the requested size
       
  1767 // (other items were commented in a header).
       
  1768 // -----------------------------------------------------------------------------
       
  1769 //
       
  1770 void CJ2kSynthesis::AllocBufferL( TInt32 aSize )
       
  1771     {
       
  1772     // Allocate memory for the input and output buffers
       
  1773     TInt32 totalSize = aSize * sizeof( TInt32 );
       
  1774 
       
  1775     if ( iIOBufferSize )
       
  1776         {
       
  1777         // Resize only when the request buffer is larger than current buffer
       
  1778         if ( iIOBufferSize < totalSize )
       
  1779             {
       
  1780             iInputBuffer -= ( KFilterExtension + 1 );
       
  1781             TInt32* tmpBuffer = STATIC_CAST( TInt32*, User::ReAlloc( iInputBuffer, totalSize ) );
       
  1782             if ( !tmpBuffer )
       
  1783                 {
       
  1784                 iInputBuffer += ( KFilterExtension + 1 );
       
  1785                 User::Leave( KErrNoMemory );
       
  1786                 }
       
  1787             iInputBuffer = tmpBuffer;
       
  1788             iInputBuffer += ( KFilterExtension + 1 );
       
  1789 
       
  1790             iOutputBuffer -= ( KFilterExtension + 1 );
       
  1791             tmpBuffer = STATIC_CAST( TInt32*, User::ReAlloc( iOutputBuffer, totalSize ) );
       
  1792             if ( !tmpBuffer )
       
  1793                 {
       
  1794                 iOutputBuffer += ( KFilterExtension + 1 );
       
  1795                 User::Leave( KErrNoMemory );
       
  1796                 }
       
  1797             iOutputBuffer = tmpBuffer;
       
  1798             iOutputBuffer += ( KFilterExtension + 1 );
       
  1799 
       
  1800             iIOBufferSize = totalSize;
       
  1801             }
       
  1802         }
       
  1803     else
       
  1804         {
       
  1805         // First time buffer allocation
       
  1806         iInputBuffer = STATIC_CAST( TInt32*, User::Alloc( totalSize ) );
       
  1807         if ( !iInputBuffer )
       
  1808             {
       
  1809             User::Leave( KErrNoMemory );
       
  1810             }
       
  1811         iInputBuffer += ( KFilterExtension + 1 );
       
  1812         iOutputBuffer = STATIC_CAST( TInt32*, User::Alloc( totalSize ) );
       
  1813         if ( !iOutputBuffer )
       
  1814             {
       
  1815             User::Leave( KErrNoMemory );
       
  1816             }
       
  1817         iOutputBuffer += ( KFilterExtension + 1 );
       
  1818         iIOBufferSize = totalSize;
       
  1819         }
       
  1820     }
       
  1821 
       
  1822 // -----------------------------------------------------------------------------
       
  1823 // CJ2kSynthesis::HorizontalBlockFilter
       
  1824 // Perform one dimensional horizontal filtering ( block-based ).
       
  1825 // (other items were commented in a header).
       
  1826 // -----------------------------------------------------------------------------
       
  1827 //
       
  1828 void CJ2kSynthesis::HorizontalBlockFilter( TPrecInt** aImage, TInt32 aRow,
       
  1829                                            TUint32 aXtcSiz, CJ2kSubband* aSubband,
       
  1830                                            TInt32 aXOffset, TUint8 aCurrentLevel )
       
  1831     {
       
  1832     TInt32 endPos = 0;
       
  1833     TInt32 startPos = aSubband->HighPassFirst().iX;
       
  1834   
       
  1835     TInt32* rowImage = (TInt32*)aImage[aRow];
       
  1836     TInt32* rowImageHigh = rowImage + KWaveletBlockMidPoint; 
       
  1837     TInt32* iterator = iInputBuffer;
       
  1838 
       
  1839     // Insert one extra ( dummy, i.e. zero-valued ) low-pass sample.
       
  1840     // This sample is not actually needed in computations, but now we can use the same 
       
  1841     // functions for filtering for block-based and normal wavelet.
       
  1842     if( !startPos && ( aXOffset > 0 ) )      
       
  1843         {
       
  1844 
       
  1845         // The need for one extra sample derives from the fact that the support region
       
  1846         // for the high-pass is extends one sample further than the low-pass region.
       
  1847         *iterator++ = 0;
       
  1848         *iterator++ = *rowImageHigh++;
       
  1849 
       
  1850         // Increment aXtcSiz by one to account for the dummy sample
       
  1851         aXtcSiz++;
       
  1852         }
       
  1853 
       
  1854     if ( !startPos )  // Low-pass first
       
  1855         {
       
  1856         for ( endPos = aXtcSiz >> 1; endPos > 0; endPos-- )
       
  1857             {
       
  1858             *iterator++ = *rowImage++;
       
  1859             *iterator++ = *rowImageHigh++;
       
  1860             }
       
  1861         if ( aXtcSiz % 2 )  // One extra sample for low-pass
       
  1862             {
       
  1863             *iterator = *rowImage;
       
  1864             }
       
  1865         }
       
  1866     else  // High-pass first
       
  1867         {
       
  1868         iterator++;
       
  1869         for ( endPos = aXtcSiz >> 1; endPos > 0; endPos-- )
       
  1870             {
       
  1871             *iterator++ = *rowImageHigh++;
       
  1872             *iterator++ = *rowImage++;
       
  1873             }
       
  1874         if ( aXtcSiz % 2 )  // One extra sample for high-pass
       
  1875             {
       
  1876             *iterator = *rowImageHigh;
       
  1877             }
       
  1878         }
       
  1879   
       
  1880     endPos = aXtcSiz + startPos; 
       
  1881 
       
  1882     OneDimFiltering( startPos, endPos, (TUint8)( iWaveletLevels - aCurrentLevel ), 0 ); 
       
  1883 
       
  1884     // Copy row back to image, take care of offset
       
  1885     Mem::Copy( aImage[aRow], iOutputBuffer + startPos + ( aXOffset ), ( aXtcSiz - ( aXOffset ) ) * sizeof( TPrecInt ) );
       
  1886     }
       
  1887 
       
  1888 // -----------------------------------------------------------------------------
       
  1889 // CJ2kSynthesis::VerticalBlockFilter
       
  1890 // Perform one dimensional vertical filtering ( block-based )
       
  1891 // (other items were commented in a header).
       
  1892 // -----------------------------------------------------------------------------
       
  1893 //
       
  1894 void CJ2kSynthesis::VerticalBlockFilter( TPrecInt** aImage, TInt32 aColumn, TUint32 aYtcSiz, 
       
  1895                                          CJ2kSubband* aSubband, TInt32 aYOffset,
       
  1896                                          TUint8 aCurrentLevel )
       
  1897     {
       
  1898     TInt32 startPos = aSubband->HighPassFirst().iY;
       
  1899     TInt32 highStart = KWaveletBlockMidPoint;
       
  1900     TInt32* iterator = iInputBuffer;
       
  1901  
       
  1902     TInt32 lowIndex = 0;
       
  1903     TInt32 highIndex = highStart;
       
  1904 
       
  1905     // Insert one extra ( dummy, i.e. zero-valued ) low-pass sample.
       
  1906     if( !startPos && ( aYOffset > 0 ) )      
       
  1907         {
       
  1908         *iterator++ = 0;
       
  1909         *iterator++ = aImage[highIndex++][aColumn];
       
  1910 
       
  1911         // Increment aYtcSiz by one to account for the dummy sample
       
  1912         aYtcSiz++;
       
  1913         }
       
  1914 
       
  1915     TInt32 highStop = KWaveletBlockMidPoint + ( aYtcSiz >> 1 );
       
  1916     TInt32 lowStop = aYtcSiz >> 1;
       
  1917 
       
  1918     if ( !startPos )
       
  1919         {
       
  1920         for ( ; highIndex < highStop; lowIndex++, highIndex++ )
       
  1921             {
       
  1922             *iterator++ = aImage[lowIndex][aColumn];
       
  1923             *iterator++ = aImage[highIndex][aColumn];
       
  1924             }
       
  1925         if ( aYtcSiz % 2 )
       
  1926             {
       
  1927             *iterator = aImage[lowIndex][aColumn];
       
  1928             }
       
  1929         }
       
  1930     else 
       
  1931         {
       
  1932         iterator++;
       
  1933         for ( ; lowIndex < lowStop; highIndex++, lowIndex++ )
       
  1934             {
       
  1935             *iterator++ = aImage[highIndex][aColumn];
       
  1936             *iterator++ = aImage[lowIndex][aColumn];
       
  1937             }
       
  1938         if ( aYtcSiz % 2 )
       
  1939             {
       
  1940             *iterator = aImage[highIndex][aColumn];
       
  1941             }
       
  1942         }
       
  1943 
       
  1944     OneDimFiltering( startPos, startPos + aYtcSiz, (TUint8)( iWaveletLevels - aCurrentLevel ), 1 );  
       
  1945     iOutputBuffer += ( startPos + aYtcSiz - 1 );
       
  1946 
       
  1947     // Copy column back to image, take care of offset
       
  1948     for ( lowIndex = ( aYtcSiz - 1 - aYOffset ); lowIndex >= 0; lowIndex-- )
       
  1949         {
       
  1950         aImage[lowIndex][aColumn] = *iOutputBuffer--;
       
  1951         }
       
  1952     iOutputBuffer += ( 1 - startPos - aYOffset );
       
  1953     }
       
  1954 
       
  1955 // -----------------------------------------------------------------------------
       
  1956 // CJ2kSynthesis::TwoDimBlockFiltering
       
  1957 // Perform two dimensional inverse wavelet transformation ( block-based )
       
  1958 // (other items were commented in a header).
       
  1959 // -----------------------------------------------------------------------------
       
  1960 //
       
  1961 void CJ2kSynthesis::TwoDimBlockFiltering( TPrecInt** aImage, TSize aRegion, CJ2kSubband* aSubband,
       
  1962                                          TPoint aOffset, TUint8 aCurrentLevel )
       
  1963     {
       
  1964     TInt32 index = 0;
       
  1965     TUint32 xtcSiz = aRegion.iWidth;
       
  1966     TUint32 ytcSiz = aRegion.iHeight;
       
  1967 
       
  1968     // For block filtering we have the data in two blocks ( column-wise ), 
       
  1969     // from 0 to ( ytcsiz+1 )>>1 ( +1 to take care of odd number of samples ) 
       
  1970     // and from KWaveletBlockMidPoint to KWaveletBlockMidPoint+( ( ytcsiz+1 )>>1 ).
       
  1971     index = KWaveletBlockMidPoint + ( ( ytcSiz+1 ) >> 1 ) - 1;
       
  1972 
       
  1973     // First apply horizontal filter to the ( vertically ) high-pass samples
       
  1974     for ( ; index >= KWaveletBlockMidPoint; index-- )
       
  1975         {
       
  1976         HorizontalBlockFilter( aImage, index, xtcSiz, aSubband, aOffset.iX, aCurrentLevel );
       
  1977         }
       
  1978 
       
  1979     // Then apply horizontal filter to the ( vertically ) low-pass samples
       
  1980     index = ( ( ytcSiz+1 ) >> 1 ) - 1;
       
  1981     for ( ; index >= 0; index-- )
       
  1982         {
       
  1983        HorizontalBlockFilter( aImage, index, xtcSiz, aSubband, aOffset.iX, aCurrentLevel );
       
  1984         }
       
  1985 
       
  1986     // Because of the horizontal filtering, the data is now in one block row-wise, thus
       
  1987     // two loops are not needed for vertical fitering.
       
  1988     index = xtcSiz-1-( (TUint32)( aOffset.iX ) >> 1 );
       
  1989     for ( ; index >= 0; index-- )
       
  1990         {
       
  1991         VerticalBlockFilter( aImage, index, ytcSiz, aSubband, aOffset.iY, aCurrentLevel );
       
  1992         }
       
  1993     }
       
  1994 
       
  1995 // -----------------------------------------------------------------------------
       
  1996 // CJ2kSynthesis::SingleLevelWaveletInverse
       
  1997 // Perform a full inverse wavelet transformation ( block-based )
       
  1998 // (other items were commented in a header).
       
  1999 // -----------------------------------------------------------------------------
       
  2000 //
       
  2001 void CJ2kSynthesis::SingleLevelWaveletInverse( TPrecInt **aImage, CJ2kSubband *aSubband, 
       
  2002                                                TPoint aOffset, TSize aRegion, TUint8 aCurrentLevel )
       
  2003     {
       
  2004     if ( aRegion.iWidth > 0 && aRegion.iHeight > 0 )
       
  2005         {
       
  2006         aSubband = aSubband->Parent();
       
  2007         TwoDimBlockFiltering( aImage, aRegion, aSubband, aOffset, aCurrentLevel );
       
  2008         }
       
  2009     }
       
  2010 
       
  2011 // -----------------------------------------------------------------------------
       
  2012 // CJ2kSynthesis::CopyDataToBlock
       
  2013 // Apply inverse quantization and ROI shifting on the decoded
       
  2014 // codeblock and copy to the image writer ( block-based ).
       
  2015 // (other items were commented in a header).
       
  2016 // -----------------------------------------------------------------------------
       
  2017 //
       
  2018 void CJ2kSynthesis::CopyDataToBlock( CJ2kEntropyDecoder& aEntropyDecoder, TPrecInt** aImageBlock, 
       
  2019                                      CJ2kSubband& aSubband, TUint8 aQuantizationStyle,
       
  2020                                      TInt32 aStartRowCblk, TInt32 aStartColCblk,
       
  2021                                      TInt32 aStartRowImage, TInt32 aStartColImage,
       
  2022                                      TInt32 aCblkHeight, TInt32 aCblkWidth )
       
  2023     {
       
  2024     TPrecInt* buffer = 0;    // To buffer one row of the image_block
       
  2025     TPrecInt* imageRow = 0;  // One row of the image
       
  2026     TPrecInt valueInt = 0;
       
  2027     TInt32 value = 0;
       
  2028     TInt32 j = 0;
       
  2029 
       
  2030     TInt32 startRowImageBlock = aStartRowImage; // Start row's index in the image to copy to 
       
  2031     TInt32 startColImageBlock = aStartColImage; // Start column's index in the image to copy to 
       
  2032 
       
  2033     TUint8 aBandIndex = (TUint8)( aSubband.SubbandType() );
       
  2034 
       
  2035     // Adjust the place where to copy the data according to the subband type 
       
  2036     // ( i.e. whether we have LL, HL, LH or HH band ).
       
  2037     if( aBandIndex == 1 )
       
  2038         {
       
  2039         startColImageBlock += KWaveletBlockMidPoint;
       
  2040         }
       
  2041     else if( aBandIndex == 2 )
       
  2042         {
       
  2043         startRowImageBlock += KWaveletBlockMidPoint;
       
  2044         }
       
  2045     else if( aBandIndex == 3 )
       
  2046         {
       
  2047         startRowImageBlock += KWaveletBlockMidPoint;
       
  2048         startColImageBlock += KWaveletBlockMidPoint;
       
  2049         }
       
  2050 
       
  2051     // Compute the end of the copy region
       
  2052     TInt32 endRowImageBlock = startRowImageBlock + aCblkHeight - 1; //lint !e961    no else is needed here at the end of if...else if
       
  2053     TInt32 endColImageBlock = startColImageBlock + aCblkWidth;
       
  2054 
       
  2055     // Index of the row to copy from in the codeblock
       
  2056     TInt32 codeblockRow = aStartRowCblk + aCblkHeight-1;
       
  2057 
       
  2058     // Index of the row to copy from in the codeblock
       
  2059     TInt32 codeblockColumn = aStartColCblk + aCblkWidth-1;
       
  2060 
       
  2061     if ( iROIShift )  // ROI shifting is used
       
  2062         {
       
  2063         // Compute mask to determine which samples are in ROI
       
  2064         // for mask ROI coefficients
       
  2065         TInt32 mask = ( ( 1 << iMagnitudeBitsHere ) - 1 ) << ( ( KImplementationPrecision - 1 ) - iMagnitudeBitsHere );
       
  2066         TInt32 mask2 = ( ~mask ) & KMaximumPrecisionInteger;
       
  2067         TInt32 mask3 = ( ( 1 << iROIShift ) - 1 ) << ( ( KImplementationPrecision - 1 ) - iROIShift );
       
  2068         TInt32 maskShift = ( ~mask3 ) & KMaximumPrecisionInteger;
       
  2069 
       
  2070         if ( !aQuantizationStyle )
       
  2071             {
       
  2072             // Shift all the samples in the codeblock
       
  2073             TInt32 roiDataShift = ( iROIDataShift < 0 ) ? -iROIDataShift : iROIDataShift;
       
  2074             
       
  2075             for ( ; endRowImageBlock >= startRowImageBlock; endRowImageBlock--,codeblockRow-- )
       
  2076                 {
       
  2077                 buffer = aEntropyDecoder.iData[codeblockRow] + codeblockColumn;
       
  2078                 for ( j = endColImageBlock-1; j >= startColImageBlock; j-- )
       
  2079                     {
       
  2080                     value = ( *buffer-- );
       
  2081                     if ( !( value & mask ) ) // Background
       
  2082                         {
       
  2083                         if ( iROIDataShift < 0 )
       
  2084                             {
       
  2085                             aImageBlock[endRowImageBlock][j] = ( value < 0 ) ? -( ( value & KMaximumPrecisionInteger ) << roiDataShift ) 
       
  2086                                                              : ( value  << roiDataShift );
       
  2087                             }
       
  2088                         else
       
  2089                             {
       
  2090                             aImageBlock[endRowImageBlock][j] = ( value < 0 ) ? -( ( value & maskShift ) >> roiDataShift )     //lint !e704 value&maskShift is positive, so no risk of right shifting negative values 
       
  2091                                                              : ( ( value & maskShift ) >> roiDataShift );              //lint !e704 value&maskShift is positive, so no risk of right shifting negative values
       
  2092                             }
       
  2093                         }
       
  2094                     else  // ROI
       
  2095                         {
       
  2096                         if ( value & mask2 ) 
       
  2097                             {
       
  2098                             // Decoded more than magbits bit-planes, set
       
  2099                             // quantization mid-interval approx. bit just after
       
  2100                             // the magbits.
       
  2101                             value &= ( ~mask2 );
       
  2102                             }
       
  2103                         aImageBlock[endRowImageBlock][j] = ( value < 0 ) ? -( ( value & KMaximumPrecisionInteger ) >> iDataShift )
       
  2104                                                          : ( value >> iDataShift );              //lint !e704 value is positive here
       
  2105                         }
       
  2106                     }
       
  2107                 }
       
  2108             }
       
  2109         else  // Irreversible case
       
  2110             {
       
  2111             // Shift all the samples in the codeblock
       
  2112             TInt32 stepExponent = ( iStepExponent < 0 ) ? -iStepExponent : iStepExponent;
       
  2113 
       
  2114             // Divide into two cases depending on the sign of the iStepExponent to speed up coding
       
  2115             if ( iStepExponent < 0 )
       
  2116                 {
       
  2117                 for ( ; endRowImageBlock >= startRowImageBlock; endRowImageBlock--, codeblockRow-- )
       
  2118                     {
       
  2119                     buffer = aEntropyDecoder.iData[codeblockRow] + codeblockColumn;
       
  2120                     for ( j = endColImageBlock-1; j >= startColImageBlock; j-- )
       
  2121                         {
       
  2122                         value = ( *buffer-- );
       
  2123 
       
  2124                         // Divide into two cases depending on whether value is negative
       
  2125                         if ( value < 0 )
       
  2126                             {
       
  2127                             if ( !( value & mask ) ) // Background
       
  2128                                 {
       
  2129                                 value = ( ( value & maskShift ) >> iROIDataShift );         //lint !e704 value&maskShift is positive, so no risk of right shifting negative values
       
  2130                                 valueInt = -( ( value * iStepValue ) >> stepExponent );     //lint !e704 value*iStepValue is positive
       
  2131                                 }
       
  2132                             else  // ROI
       
  2133                                 {
       
  2134                                 if ( value & mask2 ) 
       
  2135                                     {
       
  2136                                     // Decoded more than magbits bit-planes, set
       
  2137                                     // quantization mid-interval approx. bit just after
       
  2138                                     // the magbits.
       
  2139                                     value = ( value & ( ~mask2 ) ) | ( 1 << ( KImplementationPrecision - 2 - iMagnitudeBitsHere ) );
       
  2140                                     }
       
  2141 
       
  2142                                 value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
       
  2143                                 valueInt = -( ( value * iStepValue ) >> stepExponent );      //lint !e704 value*iStepValue is positive
       
  2144                                 }
       
  2145                             }
       
  2146                         else    // Value is non-negative
       
  2147                             {
       
  2148                             if ( !( value & mask ) ) // Background
       
  2149                                 {
       
  2150                                 value = ( ( value & maskShift ) >> iROIDataShift );         //lint !e704 value&maskShift is positive, so no risk of right shifting negative values
       
  2151                                 valueInt = ( ( value * iStepValue ) >> stepExponent );      //lint !e704 value*iStepValue is positive
       
  2152                                 }
       
  2153                             else  // ROI
       
  2154                                 {
       
  2155                                 if ( value & mask2 ) 
       
  2156                                     {
       
  2157                                     // Decoded more than magbits bit-planes, set
       
  2158                                     // quantization mid-interval approx. bit just after
       
  2159                                     // the magbits.
       
  2160                                     value = ( value & ( ~mask2 ) ) | ( 1 << ( KImplementationPrecision - 2 - iMagnitudeBitsHere ) );
       
  2161                                     }
       
  2162 
       
  2163                                 value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
       
  2164                                 valueInt = ( ( value * iStepValue ) >> stepExponent );      //lint !e704 value*iStepValue is positive
       
  2165                                 }
       
  2166                             }
       
  2167 
       
  2168                         aImageBlock[endRowImageBlock][j] = valueInt;
       
  2169                         }
       
  2170                     }
       
  2171                 }
       
  2172             else    // iStepExponent is non-negative
       
  2173                 {
       
  2174                 for ( ; endRowImageBlock >= startRowImageBlock; endRowImageBlock--,codeblockRow-- )
       
  2175                     {
       
  2176                     buffer = aEntropyDecoder.iData[codeblockRow] + codeblockColumn;
       
  2177                     for ( j = endColImageBlock-1; j >= startColImageBlock; j-- )
       
  2178                         {
       
  2179                         value = ( *buffer-- );
       
  2180                         if ( !( value & mask ) ) // Background
       
  2181                             {
       
  2182                             if ( value < 0 )   // Get the sign
       
  2183                                 {
       
  2184                                 value = -( ( value & maskShift ) >> iROIDataShift );          //lint !e704 value&maskShift is positive, so no risk of right shifting negative values
       
  2185                                 }
       
  2186                             else
       
  2187                                 {
       
  2188                                 value = ( ( value & maskShift ) >> iROIDataShift );           //lint !e704 value&maskShift is positive, so no risk of right shifting negative values
       
  2189                                 }
       
  2190                             
       
  2191                             valueInt = ( ( value * iStepValue ) << stepExponent );
       
  2192                             }
       
  2193                         else  // ROI
       
  2194                             {
       
  2195                             if ( value & mask2 ) 
       
  2196                                 {
       
  2197                                 // Decoded more than magbits bit-planes, set
       
  2198                                 // quantization mid-interval approx. bit just after
       
  2199                                 // the magbits.
       
  2200                                 value = ( value & ( ~mask2 ) ) | ( 1 << ( KImplementationPrecision - 2 - iMagnitudeBitsHere ) );
       
  2201                                 }
       
  2202                             if ( value < 0 )
       
  2203                                 {
       
  2204                                 value = -( ( value & KMaximumPrecisionInteger ) >> iDataShift );
       
  2205                                 }
       
  2206                             else
       
  2207                                 {
       
  2208                                 value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
       
  2209                                 }
       
  2210                             
       
  2211                             valueInt = ( ( value * iStepValue ) << stepExponent );
       
  2212                             }
       
  2213                         aImageBlock[endRowImageBlock][j] = valueInt;
       
  2214                         }
       
  2215                     }
       
  2216                 }
       
  2217             }
       
  2218         }
       
  2219     else  // ROI is not present
       
  2220         {
       
  2221         if ( !aQuantizationStyle )
       
  2222             {
       
  2223             // Shift all the samples in the codeblock
       
  2224             TInt32 i = codeblockRow;
       
  2225             for ( ; endRowImageBlock >= startRowImageBlock; endRowImageBlock--, i-- )
       
  2226                 {
       
  2227                 imageRow = aImageBlock[endRowImageBlock] + endColImageBlock - 1;
       
  2228                 buffer = aEntropyDecoder.iData[i] + codeblockColumn;
       
  2229 
       
  2230                 for ( j = endColImageBlock-1; j >= startColImageBlock; j-- )
       
  2231                     {
       
  2232                     value = *buffer--;
       
  2233                     if ( value < 0 )
       
  2234                         {
       
  2235                         *imageRow-- = -( ( value & KMaximumPrecisionInteger ) >> iDataShift );
       
  2236                         }
       
  2237                     else
       
  2238                         {
       
  2239                         *imageRow-- = value >> iDataShift;          //lint !e704 value is positive here
       
  2240                         }
       
  2241                     }
       
  2242                 }
       
  2243             }
       
  2244         else  // Irreversible case 
       
  2245             {
       
  2246             // Shift all the samples in the codeblock 
       
  2247             TInt32 stepExponent = ( iStepExponent < 0 ) ? -iStepExponent : iStepExponent;
       
  2248             
       
  2249             // Divide into two cases depending on the sign of the iStepExponent to speed up coding
       
  2250             if ( iStepExponent < 0 )
       
  2251                 {
       
  2252                 for ( ; endRowImageBlock >= startRowImageBlock; endRowImageBlock--,codeblockRow-- )
       
  2253                     {
       
  2254                     buffer = aEntropyDecoder.iData[codeblockRow] + codeblockColumn;
       
  2255                     for ( j = endColImageBlock-1;  j >= startColImageBlock; j-- )
       
  2256                         {
       
  2257                         value = ( *buffer-- );
       
  2258 
       
  2259                         if ( value < 0 )   // Negative value
       
  2260                             {
       
  2261                             value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
       
  2262                             aImageBlock[endRowImageBlock][j] = (TPrecInt)( -( ( value * iStepValue ) >> stepExponent ) ); //lint !e704 value*iStepValue is positive
       
  2263                             }
       
  2264                         else
       
  2265                             {
       
  2266                             value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
       
  2267                             aImageBlock[endRowImageBlock][j] = (TPrecInt)( ( value * iStepValue ) >> stepExponent );    //lint !e704 value*iStepValue is positive
       
  2268                             }
       
  2269                         }
       
  2270                     }
       
  2271                 }
       
  2272             else    // iStepExponent is non-negative
       
  2273                 {
       
  2274                 for ( ; endRowImageBlock >= startRowImageBlock; endRowImageBlock--,codeblockRow-- )
       
  2275                     {
       
  2276                     buffer = aEntropyDecoder.iData[codeblockRow] + codeblockColumn;
       
  2277                     for ( j = endColImageBlock-1;  j >= startColImageBlock; j-- )
       
  2278                         {
       
  2279                         value = ( *buffer-- );
       
  2280 
       
  2281                         if ( value < 0 )   // Negative value
       
  2282                             {
       
  2283                             value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
       
  2284                             aImageBlock[endRowImageBlock][j] = (TPrecInt)( -( ( value * iStepValue ) << stepExponent ) );
       
  2285                             }
       
  2286                         else
       
  2287                             {
       
  2288                             value = ( ( value & KMaximumPrecisionInteger ) >> iDataShift );
       
  2289                             aImageBlock[endRowImageBlock][j] = (TPrecInt)( ( value * iStepValue ) << stepExponent );
       
  2290                             }
       
  2291                         }
       
  2292                     }
       
  2293                 }
       
  2294             }
       
  2295         }
       
  2296   
       
  2297     // If number of levels is zero then we have to do the 
       
  2298     // inverse wavelet shifting here.
       
  2299     //
       
  2300     if ( iWaveletLevels == 0 )
       
  2301         {
       
  2302         endRowImageBlock = startRowImageBlock + aCblkHeight;
       
  2303         endColImageBlock = startColImageBlock + aCblkWidth;
       
  2304 
       
  2305         if ( aQuantizationStyle )
       
  2306             {
       
  2307             for ( TInt32 i = endRowImageBlock - 1; i >= startRowImageBlock; i-- )
       
  2308                 {
       
  2309                 for ( j = endColImageBlock - 1; j >= startColImageBlock; j-- )
       
  2310                     {
       
  2311                     aImageBlock[i][j] >>= KWaveletShift; //lint !e704 shifting is OK.
       
  2312                     }
       
  2313                 }
       
  2314             }
       
  2315         }
       
  2316     }
       
  2317 
       
  2318 // -----------------------------------------------------------------------------
       
  2319 // CJ2kSynthesis::FillDataWithZeros
       
  2320 // Fill a block in image writer with zeros ( corresponding to an empty block )
       
  2321 // (other items were commented in a header).
       
  2322 // -----------------------------------------------------------------------------
       
  2323 //
       
  2324 void CJ2kSynthesis::FillDataWithZeros( TPrecInt** aImageBlock, CJ2kSubband& aSubband, 
       
  2325                                        TInt32 aStartRowImage, TInt32 aStartColImage,
       
  2326                                        TInt32 aCblkHeight, TInt32 aCblkWidth )
       
  2327     {
       
  2328     TPrecInt* imageRow = 0; // One row of the image
       
  2329     TInt32 j = 0;
       
  2330 
       
  2331     TInt32 startRowImageBlock = aStartRowImage; // Start row's index in the image to copy to 
       
  2332     TInt32 startColImageBlock = aStartColImage; // Start column's index in the image to copy to 
       
  2333 
       
  2334     TUint8 aBandIndex = (TUint8)( aSubband.SubbandType() );
       
  2335 
       
  2336     // Adjust the place where to copy the data according to the subband type 
       
  2337     // ( i.e. whether we have LL, HL, LH or HH band ).
       
  2338     if( aBandIndex == 1 )
       
  2339         {
       
  2340         startColImageBlock += KWaveletBlockMidPoint;
       
  2341         }
       
  2342     else if( aBandIndex == 2 )
       
  2343         {
       
  2344         startRowImageBlock += KWaveletBlockMidPoint;
       
  2345         }
       
  2346     else if( aBandIndex == 3 )
       
  2347         {
       
  2348         startRowImageBlock += KWaveletBlockMidPoint;
       
  2349         startColImageBlock += KWaveletBlockMidPoint;
       
  2350         }
       
  2351 
       
  2352     // Compute the end of the copy region
       
  2353     TInt32 endRowImageBlock = startRowImageBlock + aCblkHeight - 1; //lint !e961    no else is needed here at the end of if...else if
       
  2354     TInt32 endColImageBlock = startColImageBlock + aCblkWidth;
       
  2355 
       
  2356     // Shift all the samples in the codeblock
       
  2357     for ( ; endRowImageBlock >= startRowImageBlock; endRowImageBlock-- )
       
  2358         {
       
  2359         imageRow = aImageBlock[endRowImageBlock] + endColImageBlock - 1;
       
  2360         for ( j = endColImageBlock-1; j >= startColImageBlock; j-- )
       
  2361             {
       
  2362              *imageRow-- = 0;
       
  2363             }
       
  2364         }
       
  2365     }
       
  2366