imagingmodules/jp2kcodec/Src/JP2KImageWriter.cpp
changeset 0 469c91dae73b
child 4 3993b8f65362
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:  CJ2kImageWriter class used to perform inverse transformation and
       
    15 *                writing decoded image data to bitmap.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 // INCLUDE FILES
       
    21 #include <e32math.h>
       
    22 #include <fbs.h>
       
    23 #include "JP2KImageUtils.h"
       
    24 #include "JP2KFormat.h"
       
    25 #include "JP2KTileInfo.h"
       
    26 #include "JP2KImageInfo.h"
       
    27 #include "JP2KSubband.h"
       
    28 #include "JP2KComponentInfo.h"
       
    29 #include "JP2KImageWriter.h"
       
    30 
       
    31 // EXTERNAL DATA STRUCTURES
       
    32 
       
    33 // EXTERNAL FUNCTION PROTOTYPES  
       
    34 
       
    35 // CONSTANTS
       
    36 
       
    37 // MACROS
       
    38 #define INT2BYTE( n ) ( ( n ) < 0 ? (TUint8)0 : ( ( n ) > 255 ? (TUint8)255 : (TUint8)( n ) ) )
       
    39 #define CLIPINT( n,bitdepth ) ( ( n >= ( 1 << bitdepth ) ) ? ( ( 1<<bitdepth ) - 1 ) : ( n < 0 ) ? 0 : n )
       
    40 #define CLIP2BITDEPTH( n, maxValue ) ( ( n > maxValue ) ? ( maxValue ) : ( n < 0 ) ? 0 : n )
       
    41 #define CLIP2RANGE( n, minValue, maxValue ) ( ( n > maxValue ) ? ( maxValue ) : ( n < minValue ) ? minValue : n )
       
    42 
       
    43 // LOCAL CONSTANTS AND MACROS
       
    44 
       
    45 // MODULE DATA STRUCTURES
       
    46 
       
    47 // LOCAL FUNCTION PROTOTYPES
       
    48 
       
    49 // FORWARD DECLARATIONS
       
    50 
       
    51 // LOCAL CONSTANTS AND MACROS
       
    52 
       
    53 
       
    54 
       
    55 // ============================ MEMBER FUNCTIONS ===============================
       
    56 
       
    57 // Destructor
       
    58 CJ2kWriterComponentInfo::~CJ2kWriterComponentInfo()
       
    59     {
       
    60     iTileStartList.Close();
       
    61     FreeData();
       
    62     }
       
    63 
       
    64 // -----------------------------------------------------------------------------
       
    65 // CJ2kWriterComponentInfo::AllocDataL
       
    66 // Allocate 2-D data array with a size
       
    67 // (other items were commented in a header).
       
    68 // -----------------------------------------------------------------------------
       
    69 //
       
    70 void CJ2kWriterComponentInfo::AllocDataL( const TSize& aSize )
       
    71     {
       
    72     FreeData();
       
    73     iData = TJ2kUtils::Alloc2DArrayL( aSize.iHeight, aSize.iWidth );
       
    74     }
       
    75 
       
    76 // -----------------------------------------------------------------------------
       
    77 // CJ2kWriterComponentInfo::FreeData
       
    78 // Free the 2-D data array
       
    79 // (other items were commented in a header).
       
    80 // -----------------------------------------------------------------------------
       
    81 //
       
    82 void CJ2kWriterComponentInfo::FreeData()
       
    83     {
       
    84     if ( iData )
       
    85         {
       
    86         TJ2kUtils::Free2DArray( iData );
       
    87         iData = 0;
       
    88         }
       
    89     }
       
    90 
       
    91 // -----------------------------------------------------------------------------
       
    92 // CJ2kWriterComponentInfo::Data
       
    93 // Get the 2-D data array
       
    94 // (other items were commented in a header).
       
    95 // -----------------------------------------------------------------------------
       
    96 //
       
    97 TPrecInt** CJ2kWriterComponentInfo::Data()
       
    98     {
       
    99     return iData;
       
   100     }
       
   101 
       
   102 // -----------------------------------------------------------------------------
       
   103 // CJ2kWriterComponentInfo::TileStartAt
       
   104 // Get the starting point of a tile
       
   105 // (other items were commented in a header).
       
   106 // -----------------------------------------------------------------------------
       
   107 //
       
   108 TPoint& CJ2kWriterComponentInfo::TileStartAt( TUint16 aTileIndex )
       
   109     {
       
   110     return iTileStartList[aTileIndex];
       
   111     }
       
   112 
       
   113 // -----------------------------------------------------------------------------
       
   114 // CJ2kWriterComponentInfo::UpdateNextTileStartAt
       
   115 // Update the starting point of next tile
       
   116 // (other items were commented in a header).
       
   117 // -----------------------------------------------------------------------------
       
   118 //
       
   119 void CJ2kWriterComponentInfo::UpdateNextTileStartAt( TUint16 aTileIndex, 
       
   120                                                      const TSize& aSize,
       
   121                                                      CJ2kImageInfo& aImageInfo )
       
   122     {
       
   123     TUint16 numOfHorizTiles = aImageInfo.NumOfHorizTiles();
       
   124     TUint16 numOfVertTiles  = aImageInfo.NumOfVertTiles();
       
   125 
       
   126     // Calculate the p and q of a tile
       
   127     TDiv tDiv = TJ2kUtils::Div( aTileIndex, numOfHorizTiles );
       
   128     if ( tDiv.rem != ( numOfHorizTiles - 1 ) )
       
   129         {
       
   130         iTileStartList[aTileIndex + 1].iX = iTileStartList[aTileIndex].iX + aSize.iWidth;
       
   131         }
       
   132 
       
   133     if ( tDiv.quot != ( numOfVertTiles - 1 ) )
       
   134         {
       
   135         iTileStartList[aTileIndex + numOfHorizTiles].iY = iTileStartList[aTileIndex].iY + aSize.iHeight;
       
   136         }
       
   137     }
       
   138 
       
   139 
       
   140 // ============================ MEMBER FUNCTIONS ===============================
       
   141 
       
   142 // -----------------------------------------------------------------------------
       
   143 // CJ2kImageWriter::NewL
       
   144 // Two-phased constructor.
       
   145 // -----------------------------------------------------------------------------
       
   146 //
       
   147 CJ2kImageWriter* CJ2kImageWriter::NewL( CImageProcessor* aImageProcessor,
       
   148                                         CJ2kImageInfo& aImageInfo,
       
   149                                         TJ2kInfo& aJ2kInfo )
       
   150     {
       
   151     CJ2kImageWriter *self = new ( ELeave ) CJ2kImageWriter( aImageProcessor, aImageInfo, aJ2kInfo );
       
   152 
       
   153     CleanupStack::PushL( self );
       
   154     self->ConstructL();
       
   155     CleanupStack::Pop();
       
   156     
       
   157     return self;
       
   158     }
       
   159 
       
   160 // Destructor
       
   161 CJ2kImageWriter::~CJ2kImageWriter()
       
   162     {
       
   163     iComponents.ResetAndDestroy();
       
   164     
       
   165     delete iLinearsRGBLut;
       
   166     iLinearsRGBLut = 0;
       
   167 
       
   168     User::Free( iGrayTRCLut );
       
   169     User::Free( iRedTRCLut );
       
   170     User::Free( iGreenTRCLut );
       
   171     User::Free( iBlueTRCLut ); 
       
   172     User::Free( iMonoPixelBlock );
       
   173     User::Free( iColorPixelBlock );
       
   174     }
       
   175 
       
   176 // -----------------------------------------------------------------------------
       
   177 // CJ2kImageWriter::WriterComponentAt
       
   178 // Get the component of the image writer
       
   179 // (other items were commented in a header).
       
   180 // -----------------------------------------------------------------------------
       
   181 //
       
   182 const CJ2kWriterComponentInfo& CJ2kImageWriter::WriterComponentAt( TUint16 aIndex ) const
       
   183     {
       
   184     return *iComponents[aIndex];
       
   185     }
       
   186 
       
   187 // -----------------------------------------------------------------------------
       
   188 // CJ2kImageWriter::OutputImageL
       
   189 // Output the image related to the component of the tile
       
   190 // (other items were commented in a header).
       
   191 // -----------------------------------------------------------------------------
       
   192 //
       
   193 void CJ2kImageWriter::OutputImageL( CJ2kTileInfo& aTile, TUint16 aComponentIndex )
       
   194     {
       
   195     TUint8  bitdepth = 0;
       
   196     TUint16 c = 0;
       
   197     CJ2kComponentInfo& componentInfo = CONST_CAST( CJ2kComponentInfo&, aTile.ComponentAt( aComponentIndex ) );
       
   198 
       
   199     TInt16 reducedLevels = (TInt16)( componentInfo.Levels() - iImageInfo.LevelDrop() );
       
   200     if ( reducedLevels < 0 )
       
   201         {
       
   202         reducedLevels = 0;
       
   203         }
       
   204 
       
   205     CJ2kSubband* subband = CONST_CAST( CJ2kSubband*, componentInfo.SubbandAt( (TUint8)reducedLevels ) );
       
   206 
       
   207     if ( subband->SubbandResLevel() != 0 )
       
   208         {
       
   209         subband = subband->Parent();
       
   210         }
       
   211 
       
   212     TSize subbandSize = subband->SubbandCanvasSize();
       
   213   
       
   214     // Note that in case of component truncation color transform is not performed
       
   215     if ( iImageInfo.ComponentDrop() )
       
   216         {
       
   217         iNumComponents = 1;    
       
   218         }
       
   219     else  // Only perform color transform if we don't drop components
       
   220         {
       
   221         // Perform the color transfrom
       
   222         if ( aComponentIndex == 2 && aTile.ColorTransformation() )
       
   223             {
       
   224             // Perform the inverse color transform
       
   225             if ( aTile.ComponentAt( 0 ).IsReversible() )  // If RCT is used
       
   226                 {
       
   227                 PerformInverseRCT( subbandSize );
       
   228                 }
       
   229             else
       
   230                 {
       
   231                 PerformInverseICT( subbandSize );
       
   232                 }
       
   233             }
       
   234         }
       
   235 
       
   236     // Check if palettes are used. If so, get the number of output channels 
       
   237     if ( iJ2kInfo.iCMPList.Count() )
       
   238         {
       
   239         TUint16 numCSComp = iImageInfo.NumOfComponents();
       
   240 
       
   241         // Allocate more memory for data if needed
       
   242         if ( iNumComponents > numCSComp )
       
   243             {
       
   244             for ( c = numCSComp; c < iNumComponents; c++ )
       
   245                 {
       
   246                 // Allocate memory for component data
       
   247                 iComponents[c]->AllocDataL( subbandSize );
       
   248                 }
       
   249             }
       
   250         // Check if we have all the necessary channels for component mapping
       
   251         if ( aComponentIndex == ( numCSComp - 1 ) )
       
   252             {
       
   253             MapComponentsL( numCSComp, reducedLevels, subbandSize, aTile );
       
   254             }
       
   255         }
       
   256 
       
   257     // We start the output of files:
       
   258     if ( iSingleFileOutput )
       
   259         {
       
   260         if ( iNumComponents == 3 ) // 3 comp to combine
       
   261             {
       
   262             // Compute the subbandSize from the first component since others might be downsampled.
       
   263             TInt16 tempNumLevels = (TUint16)( aTile.ComponentAt( 0 ).Levels() - iImageInfo.LevelDrop() );
       
   264 
       
   265             if ( tempNumLevels < 0 )
       
   266                 {
       
   267                 tempNumLevels = 0;
       
   268                 }
       
   269 
       
   270             CJ2kSubband* tempSubband = CONST_CAST( CJ2kSubband*, aTile.ComponentAt( 0 ).SubbandAt( (TUint8)tempNumLevels ) );
       
   271     
       
   272             if ( tempSubband->SubbandResLevel() != 0 )
       
   273                 {
       
   274                 tempSubband = tempSubband->Parent();
       
   275                 }
       
   276 
       
   277             subbandSize = tempSubband->SubbandCanvasSize();
       
   278 
       
   279             if( !iColorPixelBlock )
       
   280                 {
       
   281                 // Allocate memory for block of color pixels
       
   282                 iColorPixelBlock = STATIC_CAST( TRgb*, User::AllocL( 2 * KPixelsBlock * sizeof( TRgb ) ) );
       
   283                 }
       
   284 
       
   285             CombineOutputFile( aTile, subbandSize );
       
   286             for ( c = 0; c < iNumComponents; c++ )
       
   287                 {
       
   288                 iComponents[c]->FreeData();
       
   289                 }
       
   290             }
       
   291         else // 1 comp to output
       
   292             {
       
   293             if ( iImageInfo.ComponentDrop() )
       
   294                 {
       
   295                 c = ( TUint16 )( iImageInfo.ComponentDrop() - 1 );
       
   296                 }
       
   297             else
       
   298                 {
       
   299                 c = aComponentIndex;
       
   300                 }
       
   301 
       
   302             bitdepth = iImageInfo.DepthOfComponent( c );
       
   303 
       
   304             if( !iMonoPixelBlock )
       
   305                 {
       
   306                 // Allocate memory for block of grayscale pixels
       
   307                 iMonoPixelBlock = STATIC_CAST( TUint32*, User::AllocL( KPixelsBlock * sizeof( TUint32 ) ) );
       
   308                 }
       
   309 
       
   310             // Output a single component
       
   311             WriteOutputFile( aTile, c, subbandSize, bitdepth );
       
   312             iComponents[c]->FreeData();
       
   313             }
       
   314         }
       
   315     else
       
   316         {
       
   317         // Write out three independent output files
       
   318         if( !iMonoPixelBlock )
       
   319             {
       
   320             // Allocate memory for block of grayscale pixels
       
   321             iMonoPixelBlock = STATIC_CAST( TUint32*, User::AllocL( KPixelsBlock * sizeof( TUint32 ) ) );
       
   322             }
       
   323 
       
   324         if ( aComponentIndex == 2 && aTile.ColorTransformation() )
       
   325             {
       
   326             for ( c = 0; c < 3; c++ )
       
   327                 {
       
   328                 bitdepth = iImageInfo.DepthOfComponent( c );
       
   329 
       
   330                 // Output single files 
       
   331                 WriteOutputFile( aTile, c, subbandSize, bitdepth );
       
   332                 iComponents[c]->FreeData();
       
   333                 }
       
   334             }
       
   335         else if ( iJ2kInfo.iCMPList.Count() )
       
   336             {
       
   337             for ( c = 0; c < iNumComponents; c++ ) 
       
   338                 {
       
   339                 // Bitdepth is the lowest seven bits plus one for palettes
       
   340                 bitdepth = ( TUint8 )( ( iJ2kInfo.iPalette.iBList[0] & 0x7f )+1 );
       
   341 
       
   342                 // Output single files 
       
   343                 WriteOutputFile( aTile, c, subbandSize, bitdepth );
       
   344                 iComponents[c]->FreeData();
       
   345                 }
       
   346             }
       
   347         else
       
   348             {
       
   349             bitdepth = iImageInfo.DepthOfComponent( aComponentIndex );
       
   350 
       
   351             // Output only the first component to screen
       
   352             if( aComponentIndex == 0 )
       
   353                 {
       
   354                 WriteOutputFile( aTile, aComponentIndex, subbandSize, bitdepth );
       
   355                 }
       
   356             iComponents[aComponentIndex]->FreeData();
       
   357             }
       
   358         }
       
   359     }
       
   360 
       
   361 // -----------------------------------------------------------------------------
       
   362 // CJ2kImageWriter::OutputImageL
       
   363 // Output the image related to the component of the tile
       
   364 // (other items were commented in a header).
       
   365 // -----------------------------------------------------------------------------
       
   366 //
       
   367 void CJ2kImageWriter::OutputImageL( CJ2kTileInfo& aTile, TUint16 aComponentIndex,
       
   368                                     const TSize& aSize )
       
   369     {
       
   370     TUint8  bitdepth = 0;
       
   371     TUint16 c = 0;
       
   372     CJ2kComponentInfo& componentInfo = CONST_CAST( CJ2kComponentInfo&, aTile.ComponentAt( aComponentIndex ) );
       
   373 
       
   374     TInt16 reducedLevels = (TInt16)( componentInfo.Levels() - iImageInfo.LevelDrop() );
       
   375     if ( reducedLevels < 0 )
       
   376         {
       
   377         reducedLevels = 0;
       
   378         }
       
   379 
       
   380     CJ2kSubband* subband = CONST_CAST( CJ2kSubband*, componentInfo.SubbandAt( (TUint8)reducedLevels ) );
       
   381     if ( subband->SubbandResLevel() != 0 )
       
   382         {
       
   383         subband = subband->Parent();
       
   384         }
       
   385 
       
   386     TSize subbandSize = aSize;
       
   387   
       
   388     // Note that in case of component truncation color transform is not performed
       
   389     if ( iImageInfo.ComponentDrop() )
       
   390         {
       
   391         iNumComponents = 1;    
       
   392         }
       
   393     else  // Only perform color transform if we don't drop components
       
   394         {
       
   395         // Perform the color transfrom
       
   396         if ( aComponentIndex == 2 && aTile.ColorTransformation() )
       
   397             {
       
   398             // Perform the inverse color transform
       
   399             if ( aTile.ComponentAt( 0 ).IsReversible() )  // If RCT is used
       
   400                 {
       
   401                 PerformInverseRCT( subbandSize );
       
   402                 }
       
   403             else
       
   404                 {
       
   405                 PerformInverseICT( subbandSize );
       
   406                 }
       
   407             }
       
   408         }
       
   409 
       
   410     // Check if palettes are used. If so, get the number of output channels 
       
   411     if ( iJ2kInfo.iCMPList.Count() )
       
   412         {
       
   413         TUint16 numCSComp = iImageInfo.NumOfComponents();
       
   414 
       
   415         // Allocate more memory for data if needed
       
   416         if ( iNumComponents > numCSComp )
       
   417             {
       
   418             for ( c = numCSComp; c < iNumComponents; c++ )
       
   419                 {
       
   420                 // Allocate memory for component data
       
   421                 iComponents[c]->AllocDataL( subbandSize );
       
   422                 }
       
   423             }
       
   424         // Check if we have all the necessary channels for component mapping
       
   425         if ( aComponentIndex == ( numCSComp - 1 ) )
       
   426             {
       
   427             MapComponentsL( numCSComp, reducedLevels, subbandSize, aTile );
       
   428             }
       
   429         }
       
   430 
       
   431     // We start the output of files:
       
   432     if ( iSingleFileOutput )
       
   433         {
       
   434         if ( iNumComponents == 3 ) // 3 comp to combine
       
   435             {
       
   436             if( !iColorPixelBlock )
       
   437                 {
       
   438                 // Allocate memory for block of color pixels
       
   439                 iColorPixelBlock = STATIC_CAST( TRgb*, User::AllocL( 2 * KPixelsBlock * sizeof( TRgb ) ) );
       
   440                 }
       
   441 
       
   442             CombineOutputFile( aTile, subbandSize );
       
   443             for ( c = 0; c < iNumComponents; c++ )
       
   444                 {
       
   445                 iComponents[c]->FreeData();
       
   446                 }
       
   447             }
       
   448         else // 1 comp to output
       
   449             {
       
   450             if ( iImageInfo.ComponentDrop() )
       
   451                 {
       
   452                 c = (TUint16)( iImageInfo.ComponentDrop() - 1 );
       
   453                 }
       
   454             else
       
   455                 {
       
   456                 c = aComponentIndex;
       
   457                 }
       
   458 
       
   459             bitdepth = iImageInfo.DepthOfComponent( c );
       
   460 
       
   461             if( !iMonoPixelBlock )
       
   462                 {
       
   463                 // Allocate memory for block of grayscale pixels
       
   464                 iMonoPixelBlock = STATIC_CAST( TUint32*, User::AllocL( KPixelsBlock * sizeof( TUint32 ) ) );
       
   465                 }
       
   466 
       
   467             // Output a single component
       
   468             WriteOutputFile( aTile, c, subbandSize, bitdepth );
       
   469             iComponents[c]->FreeData();
       
   470             }
       
   471         }
       
   472     else
       
   473         {
       
   474         // Write out three independent output files
       
   475         if( !iMonoPixelBlock )
       
   476             {
       
   477             // Allocate memory for block of grayscale pixels
       
   478             iMonoPixelBlock = STATIC_CAST( TUint32*, User::AllocL( KPixelsBlock * sizeof( TUint32 ) ) );
       
   479             }
       
   480 
       
   481         if ( aComponentIndex == 2 && aTile.ColorTransformation() )
       
   482             {
       
   483             for ( c = 0; c < 3; c++ )
       
   484                 {
       
   485                 bitdepth = iImageInfo.DepthOfComponent( c );
       
   486 
       
   487                 // Output single files 
       
   488                 WriteOutputFile( aTile, c, subbandSize, bitdepth );
       
   489                 iComponents[c]->FreeData();
       
   490                 }
       
   491             }
       
   492         else if ( iJ2kInfo.iCMPList.Count() )
       
   493             {
       
   494             for ( c = 0; c < iNumComponents; c++ ) 
       
   495                 {
       
   496                 // Bitdepth is the lowest seven bits plus one for palettes
       
   497                 bitdepth = (TUint8)( ( iJ2kInfo.iPalette.iBList[0] & 0x7f )+1 );
       
   498 
       
   499                 // Output single files 
       
   500                 WriteOutputFile( aTile, c, subbandSize, bitdepth );
       
   501                 iComponents[c]->FreeData();
       
   502                 }
       
   503             }
       
   504         else
       
   505             {
       
   506             bitdepth = iImageInfo.DepthOfComponent( aComponentIndex );
       
   507 
       
   508             // Output only the first component to screen
       
   509             if( aComponentIndex == 0 )
       
   510                 {
       
   511                 WriteOutputFile( aTile, aComponentIndex, subbandSize, bitdepth );
       
   512                 }
       
   513 
       
   514             iComponents[aComponentIndex]->FreeData();
       
   515             }
       
   516         }
       
   517     }
       
   518 
       
   519 // -----------------------------------------------------------------------------
       
   520 // CJ2kImageWriter::OutputBlockL
       
   521 // Output the image related to the component of the tile
       
   522 // (other items were commented in a header).
       
   523 // -----------------------------------------------------------------------------
       
   524 //
       
   525 void CJ2kImageWriter::OutputBlockL( CJ2kTileInfo& aTile, TUint16 aComponentIndex, 
       
   526                                     TInt32 aBlockXCoord, TInt32 aBlockYCoord, 
       
   527                                     TSize aFirstCompSize, TSize aThisCompSize )
       
   528     {
       
   529     TUint32 tileIndex = 0;
       
   530     CJ2kWriterComponentInfo* currentComponent = iComponents[aComponentIndex];
       
   531     TPoint tmpTileStart( 0, 0 );
       
   532     TPoint tmpTileStart1( 0, 0 );
       
   533     TPoint tmpTileStart2( 0, 0 );
       
   534 
       
   535     CJ2kComponentInfo& componentInfo = CONST_CAST( CJ2kComponentInfo&, aTile.ComponentAt( aComponentIndex ) );
       
   536     TSize outputSize( 0, 0 );
       
   537 
       
   538     tileIndex = aTile.SotMarker().iIsot;
       
   539 
       
   540     // Update the subband size ( which will be used to compute output size )
       
   541     TInt16 reducedLevels = (TInt16)( componentInfo.Levels() - iImageInfo.LevelDrop() );
       
   542     if ( reducedLevels < 0 )
       
   543         {
       
   544 
       
   545         TInt32 i;
       
   546         TInt32 stepSize = 1;
       
   547 
       
   548         // Compute the output step size, the stepSize indicates how much more 
       
   549         // resolution has to be dropped if the image didn't have enough wavelet
       
   550         // levels to begin with. One indicates no extra resolution drop (write
       
   551         // each sample) and for each extra drop skip half of the samples, i.e.
       
   552         // stepSize is 2^extraLevels in case extra drop is needed.
       
   553 
       
   554         // Compute the stepSize
       
   555         for ( i = 0; i < (-reducedLevels); i++ )
       
   556             {
       
   557             // Double the step size for every extra level dropped.
       
   558             stepSize *= 2;
       
   559             }
       
   560         
       
   561         // Adjust the block coordinates, so that next block is drawn to the right coordinates
       
   562         aBlockXCoord /= stepSize;
       
   563         aBlockYCoord /= stepSize;
       
   564         
       
   565         reducedLevels = 0;
       
   566         }
       
   567 
       
   568     CJ2kSubband* subband = CONST_CAST( CJ2kSubband*, componentInfo.SubbandAt( (TUint8)reducedLevels ) );
       
   569     if ( subband->SubbandResLevel() != 0 )
       
   570         {
       
   571         subband = subband->Parent();
       
   572         }
       
   573 
       
   574     // If we are going to combine the output into a single file we must use the first components size and 
       
   575     // tile-start values ( other components might be sub sampled ).
       
   576     if( iSingleFileOutput && iNumComponents == 3 )
       
   577         {
       
   578         // Update the tileStartCoordinates
       
   579         tmpTileStart = iComponents[0]->TileStartAt( aTile.SotMarker().iIsot );
       
   580         iComponents[0]->iTileStartList[tileIndex].iX += aBlockXCoord;
       
   581         iComponents[0]->iTileStartList[tileIndex].iY += aBlockYCoord;
       
   582 
       
   583         // Also store and update the tileStartCoordinates of the other two components, as they may be output to file
       
   584         tmpTileStart1 = iComponents[1]->TileStartAt( aTile.SotMarker().iIsot );
       
   585         iComponents[1]->iTileStartList[tileIndex].iX += aBlockXCoord;
       
   586         iComponents[1]->iTileStartList[tileIndex].iY += aBlockYCoord;
       
   587         tmpTileStart2 = iComponents[2]->TileStartAt( aTile.SotMarker().iIsot );
       
   588         iComponents[2]->iTileStartList[tileIndex].iX += aBlockXCoord;
       
   589         iComponents[2]->iTileStartList[tileIndex].iY += aBlockYCoord;
       
   590 
       
   591         outputSize = aFirstCompSize;
       
   592         }
       
   593     else
       
   594         {
       
   595         // Update the tileStartCoordinates
       
   596         tmpTileStart = currentComponent->TileStartAt( aTile.SotMarker().iIsot );
       
   597         currentComponent->iTileStartList[tileIndex].iX += aBlockXCoord;
       
   598         currentComponent->iTileStartList[tileIndex].iY += aBlockYCoord;
       
   599 
       
   600         outputSize = aThisCompSize;
       
   601         }
       
   602 
       
   603     // Call OutputImageL with the changed parameters
       
   604     OutputImageL( aTile, aComponentIndex, outputSize );
       
   605 
       
   606     // Restore the original values
       
   607     if( iSingleFileOutput && iNumComponents == 3 )
       
   608         {
       
   609         iComponents[0]->iTileStartList[tileIndex] = tmpTileStart;
       
   610         iComponents[1]->iTileStartList[tileIndex] = tmpTileStart1;
       
   611         iComponents[2]->iTileStartList[tileIndex] = tmpTileStart2;
       
   612         }
       
   613     else
       
   614         {
       
   615         currentComponent->iTileStartList[tileIndex] = tmpTileStart;
       
   616         }
       
   617     }
       
   618 
       
   619 // -----------------------------------------------------------------------------
       
   620 // CJ2kImageWriter::SetNewImageProcessor
       
   621 // Set the image processor of the image write
       
   622 // (other items were commented in a header).
       
   623 // -----------------------------------------------------------------------------
       
   624 //
       
   625 void CJ2kImageWriter::SetNewImageProcessor( CImageProcessor* aImageProcessor )
       
   626     {
       
   627     iImageProcessor = aImageProcessor;
       
   628     }
       
   629 
       
   630 // -----------------------------------------------------------------------------
       
   631 // CJ2kImageWriter::SingleFileOutput
       
   632 // Get the single output file
       
   633 // (other items were commented in a header).
       
   634 // -----------------------------------------------------------------------------
       
   635 //
       
   636 TUint8 CJ2kImageWriter::SingleFileOutput() const
       
   637     {
       
   638     return iSingleFileOutput;
       
   639     }
       
   640 
       
   641 // -----------------------------------------------------------------------------
       
   642 // CJ2kImageWriter::CSCode
       
   643 // Get the EnumCS
       
   644 // (other items were commented in a header).
       
   645 // -----------------------------------------------------------------------------
       
   646 //
       
   647 TUint8 CJ2kImageWriter::CSCode() const
       
   648     {
       
   649     return (TUint8)iJ2kInfo.iEnumCS;
       
   650     }
       
   651 
       
   652 // -----------------------------------------------------------------------------
       
   653 // CJ2kImageWriter::CJ2kImageWriter
       
   654 // C++ default constructor can NOT contain any code, that
       
   655 // might leave.
       
   656 // -----------------------------------------------------------------------------
       
   657 //
       
   658 CJ2kImageWriter::CJ2kImageWriter( CImageProcessor* aImageProcessor,
       
   659                                   CJ2kImageInfo&   aImageInfo,
       
   660                                   TJ2kInfo&        aJ2kInfo ) : 
       
   661     iImageProcessor( aImageProcessor ), 
       
   662     iImageInfo( aImageInfo ), 
       
   663     iJ2kInfo( aJ2kInfo )
       
   664     {
       
   665     }
       
   666 
       
   667 // -----------------------------------------------------------------------------
       
   668 // CJ2kImageWriter::ConstructL
       
   669 // Symbian 2nd phase constructor can leave.
       
   670 // -----------------------------------------------------------------------------
       
   671 //
       
   672 void CJ2kImageWriter::ConstructL()
       
   673     {
       
   674     TInt32 i = 0;
       
   675 
       
   676     TSizMarker& sizMarker = CONST_CAST( TSizMarker&, iImageInfo.SizMarker() );
       
   677 
       
   678     iNumComponents = iImageInfo.NumOfComponents();
       
   679 
       
   680     if ( iJ2kInfo.iCMPList.Count() )
       
   681         {
       
   682         iNumComponents = (TUint16)( iJ2kInfo.iCMPList.Count() );
       
   683 
       
   684         if(iNumComponents < iImageInfo.NumOfComponents())
       
   685             {
       
   686             // Every component in the codestream must have a mapping defined
       
   687             User::Leave( KErrCorrupt );
       
   688             }
       
   689         }
       
   690 
       
   691     for ( i = 0; i < iNumComponents; i++ )
       
   692         {
       
   693         CJ2kWriterComponentInfo *info = new ( ELeave ) CJ2kWriterComponentInfo;
       
   694         CleanupStack::PushL( info );
       
   695         User::LeaveIfError( iComponents.Append( info ) );
       
   696         CleanupStack::Pop(1);
       
   697         }
       
   698 
       
   699     if ( iNumComponents == 3 )
       
   700         {
       
   701         iSingleFileOutput = 1;
       
   702         if ( sizMarker.iXRsiz[1] == 2 * sizMarker.iXRsiz[0] &&
       
   703             sizMarker.iXRsiz[2] == 2 * sizMarker.iXRsiz[0] )
       
   704             {
       
   705             if ( sizMarker.iYRsiz[1] == 2 * sizMarker.iYRsiz[0] &&
       
   706                 sizMarker.iYRsiz[2] == 2 * sizMarker.iYRsiz[0] )
       
   707                 {
       
   708                 iFileType = KYUV420;
       
   709                 }
       
   710             else
       
   711                 {
       
   712                 iFileType = KYUV422;
       
   713                 }
       
   714             }
       
   715         }
       
   716     else if ( iNumComponents == 1 )
       
   717         {
       
   718         iFileType = KRGB;
       
   719         }
       
   720   
       
   721     if ( iImageInfo.ComponentDrop() )   //lint !e961    no else is needed here at the end of if...else if
       
   722         {
       
   723         iFileType = KRGB;
       
   724         }
       
   725   
       
   726     if ( iJ2kInfo.iICCProfile )
       
   727         {
       
   728         iICCProfile = ETrue;
       
   729         InitializeICCProfileL();
       
   730         }
       
   731 
       
   732     // Initialize the output parameters
       
   733     if ( iImageInfo.Crop() )
       
   734         {
       
   735         // Currently do nothing.
       
   736         }
       
   737     else
       
   738         {
       
   739         InitializeOutputParametersL();
       
   740         }
       
   741     }
       
   742 
       
   743 // -----------------------------------------------------------------------------
       
   744 // CJ2kImageWriter::PerformInverseRCT
       
   745 // Perform the inverse reversible color transformation
       
   746 // (other items were commented in a header).
       
   747 // -----------------------------------------------------------------------------
       
   748 //
       
   749 void CJ2kImageWriter::PerformInverseRCT( const TSize& aSize )
       
   750     {
       
   751     TInt32     col = 0;
       
   752     TPrecInt   red = 0;
       
   753     TPrecInt   green = 0;
       
   754     TPrecInt   blue = 0;
       
   755     TPrecInt** block1 = iComponents[0]->iData;
       
   756     TPrecInt** block2 = iComponents[1]->iData;
       
   757     TPrecInt** block3 = iComponents[2]->iData;
       
   758 
       
   759     for ( TInt32 row = 0; row < aSize.iHeight; row++ )
       
   760         {
       
   761         for ( col = 0; col < aSize.iWidth; col++ )
       
   762             {
       
   763             red   = block1[row][col];
       
   764             green = block2[row][col];
       
   765             blue  = block3[row][col];
       
   766 
       
   767             block2[row][col] = red - ( ( blue + green ) >> 2 ); //lint !e704 shifting is OK.
       
   768             block1[row][col] = blue + block2[row][col];
       
   769             block3[row][col] = green + block2[row][col];
       
   770             }
       
   771         }
       
   772     }
       
   773 
       
   774 // -----------------------------------------------------------------------------
       
   775 // CJ2kImageWriter::PerformInverseICT
       
   776 // Perform the inverse irreversible color transformation
       
   777 // (other items were commented in a header).
       
   778 // -----------------------------------------------------------------------------
       
   779 //
       
   780 void CJ2kImageWriter::PerformInverseICT( const TSize& aSize )
       
   781     {
       
   782     TInt32     col = 0;
       
   783     TPrecInt   red = 0;
       
   784     TPrecInt   green = 0;
       
   785     TPrecInt   blue = 0;
       
   786     TPrecInt** block1 = iComponents[0]->iData;
       
   787     TPrecInt** block2 = iComponents[1]->iData;
       
   788     TPrecInt** block3 = iComponents[2]->iData;
       
   789 
       
   790     for ( TInt32 row = 0; row < aSize.iHeight; row++ )
       
   791         {
       
   792         for ( col = 0; col < aSize.iWidth; col++ )
       
   793             {
       
   794             red   = block1[row][col];
       
   795             green = block2[row][col];
       
   796             blue  = block3[row][col];
       
   797             InverseICTTransform( red, green, blue, block1[row][col], block2[row][col], block3[row][col] );            
       
   798             }
       
   799         }
       
   800     }
       
   801 
       
   802 // -----------------------------------------------------------------------------
       
   803 // CJ2kImageWriter::InverseICTTransform
       
   804 // Inverse irreversible color transformation
       
   805 // (other items were commented in a header).
       
   806 // -----------------------------------------------------------------------------
       
   807 //
       
   808 void CJ2kImageWriter::InverseICTTransform( TPrecInt aY, TPrecInt aU, TPrecInt aV,
       
   809                                            TPrecInt& aR, TPrecInt& aG, TPrecInt& aB )
       
   810     {
       
   811     aR = ( TPrecInt )( ( ( ( aY << KFractionBits ) + 
       
   812                      ( KIctCoefficient11 * aV ) ) + KOffset ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   813     aG = ( TPrecInt )( ( ( ( aY << KFractionBits ) + 
       
   814                      ( KIctCoefficient21 * aU ) + ( KIctCoefficient22 * aV ) ) + KOffset ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   815     aB = ( TPrecInt )( ( ( ( aY << KFractionBits ) + 
       
   816                      ( KIctCoefficient31 * aU ) ) + KOffset ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   817     }
       
   818 
       
   819 // -----------------------------------------------------------------------------
       
   820 // CJ2kImageWriter::InverseICTTransform
       
   821 // Inverse irreversible color transformation.
       
   822 // Performs fast transform and outputs even and odd samples at the same time
       
   823 // (other items were commented in a header).
       
   824 // -----------------------------------------------------------------------------
       
   825 //
       
   826 void CJ2kImageWriter::InverseICTTransform( TPrecInt aY1, TPrecInt aY2, TPrecInt aU, TPrecInt aV,
       
   827                                            TPrecInt& aR1, TPrecInt& aG1, TPrecInt& aB1,
       
   828                                            TPrecInt& aR2, TPrecInt& aG2, TPrecInt& aB2)
       
   829     {
       
   830     TInt32 y1Shifted;
       
   831     TInt32 y2Shifted;
       
   832     TInt32 rTempValue;
       
   833     TInt32 gTempValue;
       
   834     TInt32 bTempValue;
       
   835 
       
   836     y1Shifted = ( aY1 << KFractionBits );
       
   837     y2Shifted = ( aY2 << KFractionBits );
       
   838     rTempValue = ( KIctCoefficient11 * aV ) + KOffset;
       
   839     gTempValue = ( KIctCoefficient21 * aU ) + ( KIctCoefficient22 * aV ) + KOffset;
       
   840     bTempValue = ( KIctCoefficient31 * aU ) + KOffset;
       
   841 
       
   842     aR1 = ( TPrecInt )( ( y1Shifted + rTempValue ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   843     aG1 = ( TPrecInt )( ( y1Shifted + gTempValue ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   844     aB1 = ( TPrecInt )( ( y1Shifted + bTempValue ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   845     aR2 = ( TPrecInt )( ( y2Shifted + rTempValue ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   846     aG2 = ( TPrecInt )( ( y2Shifted + gTempValue ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   847     aB2 = ( TPrecInt )( ( y2Shifted + bTempValue ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   848     }
       
   849 
       
   850 // -----------------------------------------------------------------------------
       
   851 // CJ2kImageWriter::InverseICTFastYUV420Transform
       
   852 // Inverse irreversible color transformation
       
   853 // Performs fast transform and outputs even and odd samples on even and odd
       
   854 // rows (four samples) at the same time.
       
   855 // (other items were commented in a header).
       
   856 // -----------------------------------------------------------------------------
       
   857 //
       
   858 void CJ2kImageWriter::InverseICTTransform( TPrecInt aY1, TPrecInt aY2, TPrecInt aY3, TPrecInt aY4, 
       
   859                                            TPrecInt aU, TPrecInt aV,
       
   860                                            TPrecInt& aR1, TPrecInt& aG1, TPrecInt& aB1,
       
   861                                            TPrecInt& aR2, TPrecInt& aG2, TPrecInt& aB2,
       
   862                                            TPrecInt& aR3, TPrecInt& aG3, TPrecInt& aB3,
       
   863                                            TPrecInt& aR4, TPrecInt& aG4, TPrecInt& aB4)
       
   864     {
       
   865     TInt32 y1Shifted;
       
   866     TInt32 y2Shifted;
       
   867     TInt32 y3Shifted;
       
   868     TInt32 y4Shifted;
       
   869     TInt32 rTempValue;
       
   870     TInt32 gTempValue;
       
   871     TInt32 bTempValue;
       
   872 
       
   873     y1Shifted = ( aY1 << KFractionBits );
       
   874     y2Shifted = ( aY2 << KFractionBits );
       
   875     y3Shifted = ( aY3 << KFractionBits );
       
   876     y4Shifted = ( aY4 << KFractionBits );
       
   877     rTempValue = ( KIctCoefficient11 * aV ) + KOffset;
       
   878     gTempValue = ( KIctCoefficient21 * aU ) + ( KIctCoefficient22 * aV ) + KOffset;
       
   879     bTempValue = ( KIctCoefficient31 * aU ) + KOffset;
       
   880 
       
   881     aR1 = ( TPrecInt )( ( y1Shifted + rTempValue ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   882     aG1 = ( TPrecInt )( ( y1Shifted + gTempValue ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   883     aB1 = ( TPrecInt )( ( y1Shifted + bTempValue ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   884     aR2 = ( TPrecInt )( ( y2Shifted + rTempValue ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   885     aG2 = ( TPrecInt )( ( y2Shifted + gTempValue ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   886     aB2 = ( TPrecInt )( ( y2Shifted + bTempValue ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   887     aR3 = ( TPrecInt )( ( y3Shifted + rTempValue ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   888     aG3 = ( TPrecInt )( ( y3Shifted + gTempValue ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   889     aB3 = ( TPrecInt )( ( y3Shifted + bTempValue ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   890     aR4 = ( TPrecInt )( ( y4Shifted + rTempValue ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   891     aG4 = ( TPrecInt )( ( y4Shifted + gTempValue ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   892     aB4 = ( TPrecInt )( ( y4Shifted + bTempValue ) >> KFractionBits ); //lint !e704 shifting is OK.
       
   893     }
       
   894 
       
   895 // -----------------------------------------------------------------------------
       
   896 // CJ2kImageWriter::InitializeICCProfileL
       
   897 // Initialize the ICC profile from JP2 file format ( iJ2kInfo )
       
   898 // (other items were commented in a header).
       
   899 // -----------------------------------------------------------------------------
       
   900 //
       
   901 void CJ2kImageWriter::InitializeICCProfileL()
       
   902     {   
       
   903     const TUint8* iterator = iJ2kInfo.iICCProfile->Ptr();
       
   904     TUint8* origin = CONST_CAST( TUint8*, iJ2kInfo.iICCProfile->Ptr() );
       
   905 
       
   906     // Skip the first 128 bytes
       
   907     iterator += KICCSkipBytes;
       
   908 
       
   909     // Get the tag count
       
   910     TUint32 tagCount = PtrReadUtil::ReadBigEndianUint32Inc( iterator );
       
   911 
       
   912     TUint32 tagSignature = 0;
       
   913     TUint32 tagSize = 0;
       
   914     TUint32 redXYZOffset = 0;
       
   915     TUint32 greenXYZOffset = 0;
       
   916     TUint32 blueXYZOffset = 0;
       
   917     TUint32 trcOffset = 0;
       
   918     TUint32 index = 0;
       
   919     TInt32 i = 0;
       
   920     TInt entries = 0;
       
   921     HBufC16* redTRC = 0;
       
   922     HBufC16* greenTRC = 0;
       
   923     HBufC16* blueTRC = 0;
       
   924     HBufC16* grayTRC = 0;
       
   925     TUint8 isColor = EFalse;
       
   926     TReal value = 0.0;
       
   927 
       
   928     for ( index = 0; index < tagCount; ++index )
       
   929         {
       
   930         tagSignature = PtrReadUtil::ReadBigEndianUint32Inc( iterator );
       
   931         switch ( tagSignature )
       
   932             {
       
   933             case KRedMatrixTag:
       
   934                 {
       
   935                 redXYZOffset = PtrReadUtil::ReadBigEndianUint32Inc( iterator ) + 8;
       
   936                 iterator += 4;
       
   937                 break;
       
   938                 }
       
   939             case KGreenMatrixTag:
       
   940                 {
       
   941                 greenXYZOffset = PtrReadUtil::ReadBigEndianUint32Inc( iterator ) + 8;
       
   942                 iterator += 4;
       
   943                 break;
       
   944                 }
       
   945             case KBlueMatrixTag:
       
   946                 {
       
   947                 blueXYZOffset = PtrReadUtil::ReadBigEndianUint32Inc( iterator ) + 8;
       
   948                 iterator += 4;
       
   949                 break;
       
   950                 }
       
   951             case KRedTrcTag:
       
   952                 {
       
   953                 isColor = ETrue;
       
   954                 trcOffset = PtrReadUtil::ReadBigEndianUint32Inc( iterator ) + 12;
       
   955                 tagSize = PtrReadUtil::ReadBigEndianUint32Inc( iterator ) - 12;
       
   956                 entries = tagSize >> 1;
       
   957                 redTRC = HBufC16::NewLC( entries );
       
   958                 TPtr16 tmpPtr = ( redTRC->Des() );
       
   959                 
       
   960                 // Read bytes into the TRC values array
       
   961                 for( i = 0; i < entries; i++ )
       
   962                     {
       
   963                     tmpPtr.Append( (TUint16)( ( origin[trcOffset + 2 * i]  << 8 ) | 
       
   964                                                 origin[trcOffset + 2 * i + 1] ) );
       
   965                     }
       
   966                 
       
   967                 break;
       
   968                 }
       
   969             case KGreenTrcTag:
       
   970                 {
       
   971                 isColor = ETrue;
       
   972                 trcOffset = PtrReadUtil::ReadBigEndianUint32Inc( iterator ) + 12;
       
   973                 tagSize = PtrReadUtil::ReadBigEndianUint32Inc( iterator ) - 12;
       
   974                 entries = tagSize >> 1;
       
   975                 greenTRC = HBufC16::NewLC( entries );
       
   976                 TPtr16 tmpPtr = ( greenTRC->Des() );
       
   977 
       
   978                 // Read bytes into the TRC values array
       
   979                 for( i = 0; i < entries; i++ )
       
   980                     {
       
   981                     tmpPtr.Append( (TUint16)( ( origin[trcOffset + 2 * i]  << 8 ) |
       
   982                                                 origin[trcOffset + 2 * i + 1] ) );
       
   983                     }
       
   984                 
       
   985                 break;
       
   986                 }
       
   987             case KBlueTrcTag:
       
   988                 {
       
   989                 isColor = ETrue;
       
   990                 trcOffset = PtrReadUtil::ReadBigEndianUint32Inc( iterator ) + 12;
       
   991                 tagSize = PtrReadUtil::ReadBigEndianUint32Inc( iterator ) - 12;
       
   992                 entries = tagSize >> 1;
       
   993                 blueTRC = HBufC16::NewLC( entries );
       
   994                 TPtr16 tmpPtr = ( blueTRC->Des() );
       
   995 
       
   996                 // Read bytes into the TRC values array
       
   997                 for( i = 0; i < entries; i++ )
       
   998                     {
       
   999                     tmpPtr.Append( (TUint16)( ( origin[trcOffset+2*i]  << 8 ) | 
       
  1000                                                 origin[trcOffset+2*i+1] ) );
       
  1001                     }
       
  1002                 
       
  1003                 break;
       
  1004                 }
       
  1005             case KGrayTrcTag:
       
  1006                 {
       
  1007                 trcOffset = PtrReadUtil::ReadBigEndianUint32Inc( iterator ) + 12;
       
  1008                 tagSize = PtrReadUtil::ReadBigEndianUint32Inc( iterator ) - 12;
       
  1009                 entries = tagSize >> 1;
       
  1010                 grayTRC = HBufC16::NewLC( entries );
       
  1011                 TPtr16 tmpPtr = ( grayTRC->Des() );
       
  1012 
       
  1013                 // Read bytes into the TRC values array
       
  1014                 for( i = 0; i < entries; i++ )
       
  1015                     {
       
  1016                     tmpPtr.Append( (TUint16)( ( origin[trcOffset + 2 * i]  << 8 ) | 
       
  1017                                                 origin[trcOffset + 2 * i + 1] ) );
       
  1018                     }
       
  1019                 
       
  1020                 break;
       
  1021                 }
       
  1022             default:
       
  1023                 {
       
  1024                 iterator += 8;
       
  1025                 break;
       
  1026                 }
       
  1027             }
       
  1028         }
       
  1029 
       
  1030     TReal gamma = 0.0;
       
  1031     TReal maxInput = 0.0;
       
  1032     TReal src = 0.0;
       
  1033     TUint32 numPerSample = 0;
       
  1034     TUint32 lutSize = 0;
       
  1035     if ( iJ2kInfo.iBPCList.Count() )
       
  1036         {
       
  1037         lutSize = 1 << ( iJ2kInfo.iBPCList[0] & 0x7f + 1 );
       
  1038         }
       
  1039     else
       
  1040         {
       
  1041         lutSize = 1 << iImageInfo.DepthOfComponent( 0 );
       
  1042         }
       
  1043 
       
  1044     if ( isColor )
       
  1045         {
       
  1046         // Read the RGB( lin. ) -> XYZ conversion matrix coefficients
       
  1047         // The matrix is the following:
       
  1048         //  _                 _
       
  1049         // | redX greenX blueX |
       
  1050         // | redY greenY blueY |
       
  1051         // | redZ greenZ blueZ |
       
  1052         // |_                 _|
       
  1053         //
       
  1054         TReal redX = ( TReal )PtrReadUtil::ReadBigEndianUint32( origin + redXYZOffset ) / KDivisor;
       
  1055         TReal redY = ( TReal )PtrReadUtil::ReadBigEndianUint32( origin + redXYZOffset + 4 ) / KDivisor;
       
  1056         TReal redZ = ( TReal )PtrReadUtil::ReadBigEndianUint32( origin + redXYZOffset + 8 ) / KDivisor;
       
  1057 
       
  1058         TReal greenX = ( TReal )PtrReadUtil::ReadBigEndianUint32( origin + greenXYZOffset ) / KDivisor;
       
  1059         TReal greenY = ( TReal )PtrReadUtil::ReadBigEndianUint32( origin + greenXYZOffset + 4 ) / KDivisor;
       
  1060         TReal greenZ = ( TReal )PtrReadUtil::ReadBigEndianUint32( origin + greenXYZOffset + 8 ) / KDivisor;
       
  1061 
       
  1062         TReal blueX = ( TReal )PtrReadUtil::ReadBigEndianUint32( origin + blueXYZOffset ) / KDivisor;
       
  1063         TReal blueY = ( TReal )PtrReadUtil::ReadBigEndianUint32( origin + blueXYZOffset + 4 ) / KDivisor;
       
  1064         TReal blueZ = ( TReal )PtrReadUtil::ReadBigEndianUint32( origin + blueXYZOffset + 8 ) / KDivisor;
       
  1065 
       
  1066         // Combine the RGB( lin. ) -> XYZ and the XYZ -> sRGB( lin. ) conversions, i.e. 
       
  1067         // perform the matrix multiplication. Store the result in "iMatrix".
       
  1068         iMatrix[0] = ( TInt32 )( KSRGBMaxIntShifted * ( KSRGB00 * redX   + KSRGB01 * redY   + KSRGB02 * redZ ) );
       
  1069         iMatrix[1] = ( TInt32 )( KSRGBMaxIntShifted * ( KSRGB00 * greenX + KSRGB01 * greenY + KSRGB02 * greenZ ) );
       
  1070         iMatrix[2] = ( TInt32 )( KSRGBMaxIntShifted * ( KSRGB00 * blueX  + KSRGB01 * blueY  + KSRGB02 * blueZ ) );
       
  1071 
       
  1072         iMatrix[3] = ( TInt32 )( KSRGBMaxIntShifted * ( KSRGB10 * redX   + KSRGB11 * redY   + KSRGB12 * redZ ) );
       
  1073         iMatrix[4] = ( TInt32 )( KSRGBMaxIntShifted * ( KSRGB10 * greenX + KSRGB11 * greenY + KSRGB12 * greenZ ) );
       
  1074         iMatrix[5] = ( TInt32 )( KSRGBMaxIntShifted * ( KSRGB10 * blueX  + KSRGB11 * blueY  + KSRGB12 * blueZ ) );
       
  1075 
       
  1076         iMatrix[6] = ( TInt32 )( KSRGBMaxIntShifted * ( KSRGB20 * redX   + KSRGB21 * redY   + KSRGB22 * redZ ) );
       
  1077         iMatrix[7] = ( TInt32 )( KSRGBMaxIntShifted * ( KSRGB20 * greenX + KSRGB21 * greenY + KSRGB22 * greenZ ) );
       
  1078         iMatrix[8] = ( TInt32 )( KSRGBMaxIntShifted * ( KSRGB20 * blueX  + KSRGB21 * blueY  + KSRGB22 * blueZ ) );
       
  1079         
       
  1080         iRedTRCLut = STATIC_CAST( TInt32*, User::AllocL( lutSize * sizeof( TInt32 ) ) );
       
  1081         if ( redTRC->Length() == 1 )
       
  1082             {
       
  1083             gamma = (TReal)( *redTRC )[0] / KGamma;
       
  1084             maxInput = (TReal)( lutSize - 1 );
       
  1085             for ( index = 0; index < lutSize; ++index )
       
  1086                 {
       
  1087                 src = index / maxInput;
       
  1088                 Math::Pow( value, src, gamma );
       
  1089                 iRedTRCLut[index] = (TInt32)( value * KTRCShiftMultiplier + 0.5 );
       
  1090                 }
       
  1091             }
       
  1092         else
       
  1093             {
       
  1094             numPerSample = lutSize / (TUint32)( redTRC->Length() );
       
  1095             if ( numPerSample )
       
  1096                 {
       
  1097                 for ( index = 0; index < lutSize; ++index )
       
  1098                     {
       
  1099                     value = ( *redTRC )[index / numPerSample] / KDivisor;
       
  1100                     iRedTRCLut[index] = (TInt32)( value * KTRCShiftMultiplier + 0.5 );
       
  1101                     }
       
  1102                 }
       
  1103             }
       
  1104 
       
  1105         if ( iJ2kInfo.iBPCList.Count() )
       
  1106             {
       
  1107             lutSize = 1 << ( iJ2kInfo.iBPCList[1] & 0x7f + 1 );
       
  1108             }
       
  1109         else
       
  1110             {
       
  1111             lutSize = 1 << iImageInfo.DepthOfComponent( 1 );
       
  1112             }
       
  1113 
       
  1114         iGreenTRCLut = STATIC_CAST( TInt32*, User::AllocL( lutSize * sizeof( TInt32 ) ) );
       
  1115         if ( greenTRC->Length() == 1 )
       
  1116             {
       
  1117             gamma = (TReal)( *greenTRC )[0] / KGamma;
       
  1118             maxInput = (TReal)( lutSize - 1 );
       
  1119             for ( index = 0; index < lutSize; ++index )
       
  1120                 {
       
  1121                 src = index / maxInput;
       
  1122                 Math::Pow( value, src, gamma );
       
  1123                 iGreenTRCLut[index] = (TInt32)( value * KTRCShiftMultiplier + 0.5 );
       
  1124                 }
       
  1125             }
       
  1126         else
       
  1127             {
       
  1128             numPerSample = lutSize / (TUint32)( greenTRC->Length() );
       
  1129             if ( numPerSample )
       
  1130                 {
       
  1131                 for ( index = 0; index < lutSize; ++index )
       
  1132                     {
       
  1133                     value = ( *greenTRC )[index / numPerSample] / KDivisor;
       
  1134                     iGreenTRCLut[index] = (TInt32)( value * KTRCShiftMultiplier + 0.5 );
       
  1135                     }
       
  1136                 }
       
  1137             }
       
  1138 
       
  1139         if ( iJ2kInfo.iBPCList.Count() )
       
  1140             {
       
  1141             lutSize = 1 << ( iJ2kInfo.iBPCList[2] & 0x7f + 1 );
       
  1142             }
       
  1143         else
       
  1144             {
       
  1145             lutSize = 1 << iImageInfo.DepthOfComponent( 2 );
       
  1146             }
       
  1147 
       
  1148         iBlueTRCLut = STATIC_CAST( TInt32*, User::AllocL( lutSize * sizeof( TInt32 ) ) );
       
  1149         if ( blueTRC->Length() == 1 )
       
  1150             {
       
  1151             gamma = (TReal)( *blueTRC )[0] / KGamma;
       
  1152             maxInput = (TReal)( lutSize - 1 );
       
  1153             for ( index = 0; index < lutSize; ++index )
       
  1154                 {
       
  1155                 src = index / maxInput;
       
  1156                 Math::Pow( value, src, gamma );
       
  1157                 iBlueTRCLut[index] = (TInt32)( value * KTRCShiftMultiplier + 0.5 );
       
  1158                 }
       
  1159             }
       
  1160         else
       
  1161             {
       
  1162             numPerSample = lutSize / (TUint32)( blueTRC->Length() );
       
  1163             if ( numPerSample )
       
  1164                 {
       
  1165                 for ( index = 0; index < lutSize; ++index )
       
  1166                     {
       
  1167                     value = ( *blueTRC )[index / numPerSample] / KDivisor;
       
  1168                     iBlueTRCLut[index] = (TInt32)( value * KTRCShiftMultiplier + 0.5 );
       
  1169                     }
       
  1170                 }
       
  1171             }
       
  1172         }
       
  1173     else
       
  1174         {
       
  1175 
       
  1176         iGrayTRCLut = STATIC_CAST( TInt32*, User::AllocL( lutSize * sizeof( TInt32 ) ) );
       
  1177         if ( grayTRC->Length() == 1 )
       
  1178             {
       
  1179 
       
  1180             gamma = (TReal)( *grayTRC )[0] / KGamma;
       
  1181             maxInput = (TReal)( lutSize - 1 );
       
  1182             for ( index = 0; index < lutSize; ++index )
       
  1183                 {
       
  1184                 src = index / maxInput;
       
  1185                 Math::Pow( value, src, gamma );
       
  1186                 iGrayTRCLut[index] = (TInt32)( value*KSRGBMax+0.5 );
       
  1187                 }
       
  1188             }
       
  1189         else
       
  1190             {
       
  1191             numPerSample = lutSize / (TUint32)( grayTRC->Length() );
       
  1192             if ( numPerSample )
       
  1193                 {
       
  1194                 for ( index = 0; index < lutSize; ++index )
       
  1195                     {
       
  1196                     value = ( *grayTRC )[index / numPerSample] / KDivisor;
       
  1197                     iGrayTRCLut[index] = (TInt32)( value*KSRGBMax + 0.5 );
       
  1198                     }
       
  1199                 }
       
  1200             }
       
  1201         }
       
  1202 
       
  1203     TUint16 cutoffIdx = 0;           // Cutoff index for linear portion of output LUT 
       
  1204     TReal linearSlope = 0.0;         // Slope of output LUT in the linear region 
       
  1205     TReal normalisation = 0.0;       // Scale factor to normalize sRGB linear value to [0,1]
       
  1206 
       
  1207     // Generate the final output LUT for converting linear sRGB to non-linear sRGB.
       
  1208     // Input values are in the range [0,KSRGBMax] and output will be 8-bit [0,255].
       
  1209     // Conversation values can be obtained in e.g. "JPEG2000 - Image compression
       
  1210     // fundamentals, standards and practice" book by Taubman and Marcellin.
       
  1211     cutoffIdx = (TUint16)( KSRGB_CUTOFF * KSRGBMax );
       
  1212     linearSlope = 255.0 * KSRGB_SLOPE / KSRGBMax;
       
  1213     normalisation = 1.0 / KSRGBMax;
       
  1214     
       
  1215     iLinearsRGBLut = HBufC8::NewL( KSRGBMaxInt + 1 );
       
  1216 
       
  1217     // Generate the output lin.sRGB -> non-lin.sRGB LUT
       
  1218     // Linear part
       
  1219     for ( index = 0; index <= cutoffIdx; ++index )
       
  1220         {
       
  1221         iLinearsRGBLut->Des().Append( (TUint8)( linearSlope * index ) );
       
  1222         }
       
  1223 
       
  1224     // Non-linear part
       
  1225     for ( ; index <= (TUint32)KSRGBMaxInt; ++index )
       
  1226         {
       
  1227         gamma = index * normalisation;
       
  1228         Math::Pow( src, gamma , KSRGB_EXPONENT );
       
  1229         iLinearsRGBLut->Des().Append( (TUint8)( 255 * ( KSRGB_MULTIPLIER * src - KSRGB_SUBTRACT ) ) );
       
  1230         }
       
  1231 
       
  1232     // We do not need iJ2kInfo.iICCProfile data anymore
       
  1233     delete iJ2kInfo.iICCProfile;
       
  1234     iJ2kInfo.iICCProfile = 0;
       
  1235     
       
  1236     if ( isColor )
       
  1237         {
       
  1238         CleanupStack::PopAndDestroy( 3 );
       
  1239         }
       
  1240     else
       
  1241         {
       
  1242         CleanupStack::PopAndDestroy( 1 );
       
  1243         }
       
  1244     }
       
  1245 
       
  1246 // -----------------------------------------------------------------------------
       
  1247 // CJ2kImageWriter::InitializeOutputParametersL
       
  1248 // Initialize the output parameters
       
  1249 // (other items were commented in a header).
       
  1250 // -----------------------------------------------------------------------------
       
  1251 //
       
  1252 void CJ2kImageWriter::InitializeOutputParametersL()
       
  1253     {
       
  1254     CJ2kWriterComponentInfo* component = 0;
       
  1255     TUint16 l = 0;
       
  1256     TUint16 m = 0;                 
       
  1257     TUint16 tileIndex = 0;            
       
  1258     TUint16 tileYIndex = 0;
       
  1259     TPoint tileStart( 0, 0 );
       
  1260     TUint16 numOfHorizTiles = iImageInfo.NumOfHorizTiles();
       
  1261     TUint16 numOfVertTiles  = iImageInfo.NumOfVertTiles();
       
  1262     TRect tileCanvas( 0, 0, 0, 0 );
       
  1263     TRect componentCanvas( 0, 0, 0, 0 );
       
  1264     const TSizMarker &sizMarker = iImageInfo.SizMarker();
       
  1265     TInt  useHeight = 0;
       
  1266     TInt  useWidth = 0;
       
  1267 
       
  1268     // Prepare the tile coordinates for output image 
       
  1269     for ( TUint16 compIndex = 0; compIndex < iNumComponents; compIndex++ )
       
  1270         {    
       
  1271         component = iComponents[compIndex];
       
  1272       
       
  1273         for ( l = 0; l < numOfVertTiles; l++ )
       
  1274             {
       
  1275             tileYIndex = (TUint16)( l * numOfHorizTiles );
       
  1276 
       
  1277             for ( m = 0; m < numOfHorizTiles; m++ )
       
  1278                 {
       
  1279                 // Tile index
       
  1280                 tileIndex = (TUint16)( tileYIndex + m );
       
  1281 
       
  1282                 // Tile canvas
       
  1283                 tileCanvas.iTl = TPoint( Max( sizMarker.iXTOsiz + m * sizMarker.iXTsiz, sizMarker.iXOsiz ),
       
  1284                                          Max( sizMarker.iYTOsiz + l * sizMarker.iYTsiz, sizMarker.iYOsiz ) );
       
  1285 
       
  1286                 tileCanvas.iBr = TPoint( Min( sizMarker.iXTOsiz + ( m + 1 ) * sizMarker.iXTsiz, sizMarker.iXsiz ),
       
  1287                                          Min( sizMarker.iYTOsiz + ( l + 1 ) * sizMarker.iYTsiz, sizMarker.iYsiz ) );
       
  1288                 // Component canvas
       
  1289                 componentCanvas.iTl = TPoint( TJ2kUtils::Ceil( tileCanvas.iTl.iX, sizMarker.iXRsiz[compIndex] ),
       
  1290                                               TJ2kUtils::Ceil( tileCanvas.iTl.iY, sizMarker.iYRsiz[compIndex] ) );
       
  1291 
       
  1292                 componentCanvas.iBr = TPoint( TJ2kUtils::Ceil( tileCanvas.iBr.iX, sizMarker.iXRsiz[compIndex] ),
       
  1293                                               TJ2kUtils::Ceil( tileCanvas.iBr.iY, sizMarker.iYRsiz[compIndex] ) );
       
  1294 
       
  1295                 if ( m )
       
  1296                     {
       
  1297                     tileStart.iX = component->iTileStartList[tileIndex - 1].iX + useWidth;
       
  1298                     }
       
  1299                 else
       
  1300                     {
       
  1301                     tileStart.iX = 0;
       
  1302                     }
       
  1303 
       
  1304                 // Width to be used on the next horizontal tile
       
  1305                 useWidth = componentCanvas.Width();
       
  1306 
       
  1307                 if ( l )          
       
  1308                     {
       
  1309                     tileStart.iY = component->iTileStartList[tileIndex - 1].iY + useHeight;
       
  1310                     useHeight = 0;
       
  1311                     }
       
  1312                 else
       
  1313                     {
       
  1314                     tileStart.iY = 0;
       
  1315                     }
       
  1316 
       
  1317                 User::LeaveIfError( component->iTileStartList.Append( tileStart ) );
       
  1318                 }
       
  1319             // Height to be used on the next vertical tile
       
  1320             useHeight = componentCanvas.Height();
       
  1321             }
       
  1322         }        
       
  1323     }
       
  1324 
       
  1325 // -----------------------------------------------------------------------------
       
  1326 // CJ2kImageWriter::DoICCConversion
       
  1327 // Perform XYZ to sRGB conversion with the ICC profile.
       
  1328 // (other items were commented in a header).
       
  1329 // -----------------------------------------------------------------------------
       
  1330 //
       
  1331 void CJ2kImageWriter::DoICCConversion( TInt32 aX,
       
  1332                                       TInt32 aY,
       
  1333                                       TInt32 aZ,
       
  1334                                       TPrecInt& aR,
       
  1335                                       TPrecInt& aG,
       
  1336                                       TPrecInt& aB )
       
  1337     {
       
  1338     TInt32 tmpX = 0;
       
  1339     TInt32 tmpY = 0;
       
  1340     TInt32 tmpZ = 0;
       
  1341     TInt32 tmpR = 0;
       
  1342     TInt32 tmpG = 0;
       
  1343     TInt32 tmpB = 0;
       
  1344 
       
  1345     // First perform the input linearization 
       
  1346     tmpX = iRedTRCLut[aX];
       
  1347     tmpY = iGreenTRCLut[aY];
       
  1348     tmpZ = iBlueTRCLut[aZ];
       
  1349 
       
  1350     // Then perform the matrix multiplication to obtain the nonlinear RGB 
       
  1351     tmpR = ( iMatrix[0] * tmpX + iMatrix[1] * tmpY + iMatrix[2] * tmpZ ) >> KICCDownshift; //lint !e704 shifting is OK.
       
  1352     tmpG = ( iMatrix[3] * tmpX + iMatrix[4] * tmpY + iMatrix[5] * tmpZ ) >> KICCDownshift; //lint !e704 shifting is OK.
       
  1353     tmpB = ( iMatrix[6] * tmpX + iMatrix[7] * tmpY + iMatrix[8] * tmpZ ) >> KICCDownshift; //lint !e704 shifting is OK.
       
  1354 
       
  1355     // Get rid of values outside the range of legal values 
       
  1356     tmpR = CLIP2RANGE( tmpR, 0, KSRGBMaxInt );
       
  1357     tmpG = CLIP2RANGE( tmpG, 0, KSRGBMaxInt );
       
  1358     tmpB = CLIP2RANGE( tmpB, 0, KSRGBMaxInt );
       
  1359 
       
  1360     // De-linearize the output RGB values 
       
  1361     aR = ( *iLinearsRGBLut )[tmpR];
       
  1362     aG = ( *iLinearsRGBLut )[tmpG];
       
  1363     aB = ( *iLinearsRGBLut )[tmpB];
       
  1364     }
       
  1365 
       
  1366 // -----------------------------------------------------------------------------
       
  1367 // CJ2kImageWriter::MapToEightBits
       
  1368 // Map data less than 8 bits to 8 bits data
       
  1369 // (other items were commented in a header).
       
  1370 // -----------------------------------------------------------------------------
       
  1371 //
       
  1372 void CJ2kImageWriter::MapToEightBits( CJ2kWriterComponentInfo& aComponent,
       
  1373                                       const TSize& aSize,
       
  1374                                       TUint16 aBitDepth )
       
  1375     {
       
  1376     TPrecInt* imageRow;
       
  1377     TInt32 i = 0;
       
  1378     TInt32 j = 0;
       
  1379 
       
  1380     // DC-shift is always non zero, since we map signed data to unsigned 
       
  1381     if ( aBitDepth < 8 )
       
  1382         {
       
  1383         TPrecInt upshift = KByteBits - aBitDepth;
       
  1384         TPrecInt dcShiftUp = 1 << ( KByteBits - 1 );
       
  1385 
       
  1386         for ( i = aSize.iHeight - 1; i >= 0; i-- )
       
  1387             {
       
  1388             imageRow = aComponent.Data()[i];
       
  1389             for ( j = aSize.iWidth - 1; j >= 0; j-- )
       
  1390                 {
       
  1391                 imageRow[j] = ( imageRow[j] * ( 1 << upshift ) ) + dcShiftUp;
       
  1392                 }
       
  1393             }
       
  1394         }
       
  1395     else  // The original bitdepth is more than eight
       
  1396         {
       
  1397         TPrecInt dcShift = 1 << ( aBitDepth - 1 );
       
  1398         TPrecInt downshift = aBitDepth - KByteBits;
       
  1399         for ( i = aSize.iHeight - 1; i >= 0; --i )
       
  1400             {
       
  1401             imageRow = aComponent.Data()[i];
       
  1402             for ( j = aSize.iWidth - 1; j >= 0; j-- )
       
  1403                 {
       
  1404                 imageRow[j] = ( imageRow[j] + dcShift ) >> downshift; //lint !e704 shifting is OK.
       
  1405                 }
       
  1406             }
       
  1407         }
       
  1408     }
       
  1409 
       
  1410 // -----------------------------------------------------------------------------
       
  1411 // CJ2kImageWriter::MapComponentsL
       
  1412 // Map data using the component mapping box from JP2 file format
       
  1413 // (other items were commented in a header).
       
  1414 // -----------------------------------------------------------------------------
       
  1415 //
       
  1416 void CJ2kImageWriter::MapComponentsL( TUint16 aNumCSComp,
       
  1417                                       TUint16  aReducedLevels,
       
  1418                                       const TSize& aSize,
       
  1419                                       CJ2kTileInfo& aTile )
       
  1420     {
       
  1421     TInt32 i = 0;
       
  1422     TInt32 j = 0;
       
  1423     TInt32 k = 0;              // Indices
       
  1424     TInt32 compIndex = 0;      // Index of the component in the codestream 
       
  1425     TInt32 paletteIndex = 0;   // Index of the component in the palette
       
  1426     TInt32 value = 0;
       
  1427     TInt32 dcShift = 0;
       
  1428     TPrecInt*** tempData = 0;  // temporary storage for codestream data
       
  1429     TUint8 bitdepth = 0;
       
  1430 
       
  1431     CJ2kWriterComponentInfo* componentFrom = 0;
       
  1432     CJ2kWriterComponentInfo* componentTo = 0;
       
  1433     CJ2kSubband* subband = 0;
       
  1434 
       
  1435     TSize subbandSize( 0, 0 );
       
  1436 
       
  1437     // First allocate the temporary storage
       
  1438     tempData = STATIC_CAST( TPrecInt***, User::Alloc( aNumCSComp * sizeof( TPrecInt** ) ) );  
       
  1439     if ( !tempData )
       
  1440         {
       
  1441         User::Leave( KErrNoMemory );
       
  1442         }
       
  1443     CleanupStack::PushL( tempData );
       
  1444     for ( i = 0; i < aNumCSComp; i++ )
       
  1445         {
       
  1446         subband = CONST_CAST( CJ2kSubband*, aTile.ComponentAt( (TUint16)i ).SubbandAt( (TUint8)aReducedLevels ) );
       
  1447 
       
  1448         if( subband->SubbandResLevel() != 0 )
       
  1449             {
       
  1450             subband = subband->Parent();
       
  1451             }
       
  1452         subbandSize = subband->SubbandCanvasSize();
       
  1453 
       
  1454         // Check that this component's size doesn't exceed the output size
       
  1455         if( subbandSize.iWidth > aSize.iWidth )
       
  1456             {
       
  1457             subbandSize.iWidth = aSize.iWidth;
       
  1458             }
       
  1459         if( subbandSize.iHeight > aSize.iHeight )
       
  1460             {
       
  1461             subbandSize.iHeight = aSize.iHeight;
       
  1462             }
       
  1463     
       
  1464         // Allocate the temporary storage
       
  1465         tempData[i] = TJ2kUtils::Alloc2DArrayL( subbandSize.iHeight, subbandSize.iWidth );
       
  1466         CleanupStack::PushL( TCleanupItem( ( TCleanupOperation )&( TJ2kUtils::Free2DArray ),  ( TAny* )tempData[i] ) );
       
  1467         componentFrom = iComponents[i];
       
  1468 
       
  1469         for ( j = subbandSize.iHeight - 1; j >= 0; j-- )
       
  1470             {
       
  1471             Mem::Copy( tempData[i][j], componentFrom->Data()[j], subbandSize.iWidth * sizeof( TPrecInt ) );
       
  1472             }
       
  1473         }
       
  1474 
       
  1475     for ( k = 0; k < iNumComponents; k++ )
       
  1476         {
       
  1477         // Get the channel in the codestream from which to map
       
  1478         compIndex = iJ2kInfo.iCMPList[k].iCmp;
       
  1479         componentFrom = iComponents[compIndex];
       
  1480     
       
  1481         subband = CONST_CAST( CJ2kSubband*, aTile.ComponentAt( (TUint16)compIndex ).SubbandAt( (TUint8)aReducedLevels ) );
       
  1482 
       
  1483         if( subband->SubbandResLevel() != 0 )
       
  1484             {
       
  1485             subband = subband->Parent();
       
  1486             }
       
  1487 
       
  1488         subbandSize = subband->SubbandCanvasSize();
       
  1489     
       
  1490         // Check that this component's size doesn't exceed the output size
       
  1491         if( subbandSize.iWidth > aSize.iWidth )
       
  1492             {
       
  1493             subbandSize.iWidth = aSize.iWidth;
       
  1494             }
       
  1495         if( subbandSize.iHeight > aSize.iHeight )
       
  1496             {
       
  1497             subbandSize.iHeight = aSize.iHeight;
       
  1498             }
       
  1499     
       
  1500         // Get the output channel
       
  1501         componentTo = iComponents[k];
       
  1502     
       
  1503         // Check if palette is used for mapping
       
  1504         if ( iJ2kInfo.iCMPList[k].iMtyp == 1 )
       
  1505             {
       
  1506             // Get the right palette channel for mapping
       
  1507             paletteIndex = iJ2kInfo.iCMPList[k].iPcol;
       
  1508 
       
  1509             // Bitdepth is the lowest seven bits plus one for palettes
       
  1510             bitdepth = (TUint8)( ( iJ2kInfo.iPalette.iBList[paletteIndex] & 0x7f ) + 1 );
       
  1511             dcShift = 1 << ( bitdepth - 1 );
       
  1512 
       
  1513             for ( i = 0; i < subbandSize.iHeight; i++ )
       
  1514                 {
       
  1515                 for ( j = 0; j < subbandSize.iWidth; j++ )
       
  1516                     {
       
  1517                     // Map the input codestream channel into the output component
       
  1518                     // using the palette value.
       
  1519                     value = tempData[compIndex][i][j] + dcShift;
       
  1520                     if ( value < 0 ) 
       
  1521                         {
       
  1522                         value = 0;
       
  1523                         }
       
  1524                     if ( value >= iJ2kInfo.iPalette.iC2DArray.Count() )
       
  1525                         {
       
  1526                         value = iJ2kInfo.iPalette.iC2DArray.Count() - 1;
       
  1527                         }
       
  1528 
       
  1529                     componentTo->iData[i][j] = ( *iJ2kInfo.iPalette.iC2DArray[value] )[paletteIndex] - dcShift;
       
  1530                     }
       
  1531                 }
       
  1532             }
       
  1533         else  // Direct mapping 
       
  1534             {
       
  1535             for ( i = subbandSize.iHeight - 1; i >= 0; --i )
       
  1536                 {
       
  1537                 for ( j = subbandSize.iWidth - 1; j >= 0; --j )
       
  1538                     {
       
  1539                     // Map the input codestream channel into the output component directly.
       
  1540                     componentTo->iData[i][j] = componentFrom->iData[i][j];
       
  1541                     }
       
  1542                 }
       
  1543             }
       
  1544         }
       
  1545 
       
  1546     CleanupStack::PopAndDestroy( aNumCSComp + 1 );
       
  1547     }
       
  1548 
       
  1549 // -----------------------------------------------------------------------------
       
  1550 // CJ2kImageWriter::WriteOutputFile
       
  1551 // Write the component to the single output file
       
  1552 // (other items were commented in a header).
       
  1553 // -----------------------------------------------------------------------------
       
  1554 //
       
  1555 void CJ2kImageWriter::WriteOutputFile( CJ2kTileInfo& aTile,
       
  1556                                        TUint16 aCompIndex,
       
  1557                                        const TSize& aSize,
       
  1558                                        TUint16 aBitDepth )
       
  1559     {
       
  1560     TPrecInt* imageRow = 0;
       
  1561     CJ2kWriterComponentInfo* currentComponent = iComponents[aCompIndex];
       
  1562     TSize outputSize = aSize;
       
  1563 
       
  1564     TUint16 numLevels = aTile.ComponentAt( aCompIndex ).Levels();
       
  1565     TInt16 tempNumLevels = (TUint16)( numLevels - iImageInfo.LevelDrop() );
       
  1566    
       
  1567     TPoint tileStartCoord = currentComponent->TileStartAt( aTile.SotMarker().iIsot );
       
  1568     currentComponent->UpdateNextTileStartAt( aTile.SotMarker().iIsot, aSize, iImageInfo );
       
  1569 
       
  1570     if ( tempNumLevels < 0 )
       
  1571         {
       
  1572    
       
  1573         TInt32 i;
       
  1574         TInt32 stepSize = 1;
       
  1575 
       
  1576         // Compute the output step size, the stepSize indicates how much more 
       
  1577         // resolution has to be dropped if the image didn't have enough wavelet
       
  1578         // levels to begin with. One indicates no extra resolution drop (write
       
  1579         // each sample) and for each extra drop skip half of the samples, i.e.
       
  1580         // stepSize is 2^extraLevels in case extra drop is needed.
       
  1581 
       
  1582         // Adjust the tile starting points and the stepSize
       
  1583         for ( i = 0; i < (-tempNumLevels); i++ )
       
  1584             {
       
  1585             // Double the step size for every extra level dropped.
       
  1586             stepSize *= 2;
       
  1587             }
       
  1588         
       
  1589         // Also take care of next tile's starting position
       
  1590         outputSize.iHeight /= stepSize;
       
  1591         outputSize.iWidth /= stepSize;
       
  1592         iComponents[0]->UpdateNextTileStartAt( aTile.SotMarker().iIsot, outputSize, iImageInfo );
       
  1593         }
       
  1594 
       
  1595     TInt32 dcShift = 0;
       
  1596     TInt32 j = 0;
       
  1597     if ( aBitDepth == 8 )
       
  1598         {
       
  1599         if ( !( iImageInfo.SignOfComponent( aCompIndex ) ) )
       
  1600             {
       
  1601             dcShift = 1 << ( aBitDepth - 1 );
       
  1602             }
       
  1603         }
       
  1604     
       
  1605     // Convert with an ICC profile if necessary
       
  1606     if( iICCProfile )
       
  1607         {
       
  1608         TInt32 value = 0;
       
  1609         TInt32 outputValue = 0;
       
  1610         
       
  1611         // Compute the dcShift again, we must have dcShift != 0 for other than 8-bit input.
       
  1612         dcShift = 1 << ( iImageInfo.DepthOfComponent( 0 )-1 );
       
  1613         
       
  1614         for ( TInt32 i = 0; i < outputSize.iHeight; i++ )
       
  1615             {
       
  1616             imageRow = currentComponent->Data()[i];
       
  1617             
       
  1618             SetPixelPos( tileStartCoord.iX, tileStartCoord.iY +  i );
       
  1619             for ( j = 0; j < outputSize.iWidth; j++ )
       
  1620                 {
       
  1621                 // Use a clipped value of input sample for an index to the grayscale TRC LUT.
       
  1622                 value = iGrayTRCLut[CLIPINT( ( imageRow[j]+dcShift ), aBitDepth )];
       
  1623                 
       
  1624                 // Get rid of values outside the range of legal values.
       
  1625                 value = CLIP2RANGE( value, 0, KSRGBMaxInt );
       
  1626                 
       
  1627                 // De-linearize the output values.
       
  1628                 outputValue = ( *iLinearsRGBLut )[value];
       
  1629                 
       
  1630                 iMonoPixelBlock[j] = (TUint32)( INT2BYTE( outputValue ) );
       
  1631                 }
       
  1632 
       
  1633             // Flush the row of grayscale pixels to image processor
       
  1634             iImageProcessor->SetMonoPixels( iMonoPixelBlock, outputSize.iWidth );
       
  1635             }
       
  1636 
       
  1637         SetPixelPos( tileStartCoord );
       
  1638         }
       
  1639     else    // No ICC profile was used.
       
  1640         {
       
  1641         
       
  1642         // Take care of bitdepths != 8
       
  1643         if ( aBitDepth != 8  )
       
  1644             {
       
  1645             MapToEightBits( *currentComponent, outputSize, aBitDepth );
       
  1646             }
       
  1647         
       
  1648         SetPixelPos( tileStartCoord );
       
  1649         
       
  1650         for ( TInt32 i = 0; i < outputSize.iHeight; i++ )
       
  1651             {
       
  1652             imageRow = currentComponent->Data()[i];
       
  1653             
       
  1654 
       
  1655             SetPixelPos( tileStartCoord.iX, tileStartCoord.iY +  i );
       
  1656 
       
  1657             for ( j = 0; j < outputSize.iWidth; j++ )
       
  1658                 {
       
  1659                 // Store the value in the RGB "block"
       
  1660                 iMonoPixelBlock[j] = (TUint32)( INT2BYTE( ( imageRow[j] + dcShift ) ) );
       
  1661                 }
       
  1662 
       
  1663             // Flush the row of grayscale pixels to image processor
       
  1664             iImageProcessor->SetMonoPixels( iMonoPixelBlock, outputSize.iWidth );
       
  1665             }
       
  1666 
       
  1667         SetPixelPos( tileStartCoord );
       
  1668         }
       
  1669     }
       
  1670 
       
  1671 // -----------------------------------------------------------------------------
       
  1672 // CJ2kImageWriter::CombineOutputFile
       
  1673 // Write all components of the tile to the single output file
       
  1674 // (other items were commented in a header).
       
  1675 // -----------------------------------------------------------------------------
       
  1676 //
       
  1677 void CJ2kImageWriter::CombineOutputFile( CJ2kTileInfo& aTile, const TSize& aSize )
       
  1678     {
       
  1679     TInt32 i = 0;
       
  1680     TInt32 j = 0;
       
  1681     TUint16 numLevels = aTile.ComponentAt( 0 ).Levels();
       
  1682     TInt16 tempNumLevels = (TUint16)( numLevels - iImageInfo.LevelDrop() );
       
  1683 
       
  1684     TSize outputSize = aSize;
       
  1685     TPoint& tileStartCoord = iComponents[0]->TileStartAt( aTile.SotMarker().iIsot );
       
  1686     iComponents[0]->UpdateNextTileStartAt( aTile.SotMarker().iIsot, outputSize, iImageInfo );
       
  1687 
       
  1688     if ( tempNumLevels < 0 )
       
  1689         {
       
  1690         TInt32 stepSize = 1;
       
  1691     
       
  1692         // Compute the output step size, the stepSize indicates how much more 
       
  1693         // resolution has to be dropped if the image didn't have enough wavelet
       
  1694         // levels to begin with. One indicates no extra resolution drop (write
       
  1695         // each sample) and for each extra drop skip half of the samples, i.e.
       
  1696         // stepSize is 2^extraLevels in case extra drop is needed.
       
  1697         
       
  1698         // Adjust the tile starting points and the stepSize
       
  1699         for ( i = 0; i < (-tempNumLevels); i++ )
       
  1700             {
       
  1701             // Double the step size for every extra level dropped.
       
  1702             stepSize *= 2;
       
  1703             }
       
  1704         
       
  1705         // Also take care of next tile's starting position
       
  1706         outputSize.iHeight /= stepSize;
       
  1707         outputSize.iWidth /= stepSize;
       
  1708         iComponents[0]->UpdateNextTileStartAt( aTile.SotMarker().iIsot, outputSize, iImageInfo );
       
  1709         
       
  1710         tempNumLevels = 0;
       
  1711         }
       
  1712 
       
  1713     TInt32 dcShift = 0;
       
  1714     if ( iImageInfo.DepthOfComponent( 0 ) == 8 )
       
  1715         {
       
  1716         if ( !( iImageInfo.SignOfComponent( 0 ) ) )
       
  1717             {
       
  1718             dcShift = 1 << ( iImageInfo.DepthOfComponent( 0 ) - 1 );
       
  1719             }
       
  1720         }
       
  1721 
       
  1722     TSize subSamplingSize( 0, 0 );
       
  1723 
       
  1724     // Due to subsampling we might have one more sample than the result of
       
  1725     // height/2 or width/2 will give thus we have to check whether we an
       
  1726     // extra row/column .
       
  1727     //
       
  1728     if ( iImageInfo.NumOfComponents() == 3 && iJ2kInfo.iEnumCS == 18 ) 
       
  1729         {
       
  1730         CJ2kSubband* subband = CONST_CAST( CJ2kSubband*, aTile.ComponentAt( 1 ).SubbandAt( (TUint8)tempNumLevels ) );
       
  1731 
       
  1732         if ( subband->SubbandResLevel() != 0 )
       
  1733             {
       
  1734             subband = subband->Parent();
       
  1735             }
       
  1736 
       
  1737         subSamplingSize = subband->SubbandCanvasSize();
       
  1738 
       
  1739         if ( subSamplingSize.iWidth )
       
  1740             {
       
  1741             --subSamplingSize.iWidth;
       
  1742             }
       
  1743 
       
  1744         if ( subSamplingSize.iHeight )
       
  1745             {
       
  1746             --subSamplingSize.iHeight;
       
  1747             }
       
  1748         }
       
  1749 
       
  1750     TPrecInt** c1 = iComponents[0]->Data();
       
  1751     TPrecInt** c2 = iComponents[1]->Data();
       
  1752     TPrecInt** c3 = iComponents[2]->Data();
       
  1753 
       
  1754     TPrecInt* c1Row = c1[0];
       
  1755     TPrecInt* c2Row = c2[0];
       
  1756     TPrecInt* c3Row = c3[0];
       
  1757 
       
  1758     // For taking care of channel definition box order
       
  1759     if ( iJ2kInfo.iCNList.Count() > 0 )
       
  1760         {
       
  1761         for ( i = 0; i < 3; i++ )
       
  1762             {
       
  1763             if ( iJ2kInfo.iCNList[i].iAsoc == 1 )
       
  1764                 {
       
  1765                 c1 = iComponents[i]->Data();
       
  1766                 }
       
  1767             else if ( iJ2kInfo.iCNList[i].iAsoc == 2 )
       
  1768                 {
       
  1769                 c2 = iComponents[i]->Data();
       
  1770                 }
       
  1771             else if( iJ2kInfo.iCNList[i].iAsoc == 3 )
       
  1772                 {
       
  1773                 c3 = iComponents[i]->Data();
       
  1774                 }
       
  1775             }   //lint !e961    no else is needed here at the end of if...else if
       
  1776         }
       
  1777 
       
  1778     // If dithering is needed the following lines should be used:
       
  1779     //    TInt32 A = KDitherCoeffcient11 + dcShift; 
       
  1780     //    TInt32 B = KDitherCoeffcient12 + dcShift;  
       
  1781     //    TInt32 C = KDitherCoeffcient21 + dcShift; 
       
  1782     //    TInt32 D = KDitherCoeffcient22 + dcShift;
       
  1783     // Without dithering, use dcShift only.
       
  1784     //
       
  1785     TInt32 ditherA = dcShift; 
       
  1786     TInt32 ditherB = dcShift;  
       
  1787     TInt32 ditherC = dcShift; 
       
  1788     TInt32 ditherD = dcShift;
       
  1789 
       
  1790     TUint8 values[6];
       
  1791 
       
  1792     // Convert with the ICC profile values if necessary.
       
  1793     if( iICCProfile )
       
  1794         {
       
  1795         TInt32 x = 0;
       
  1796         TInt32 y = 0;
       
  1797         TInt32 z = 0;
       
  1798         TPrecInt sR = 0;
       
  1799         TPrecInt sG = 0;
       
  1800         TPrecInt sB = 0;
       
  1801         TInt32 maxValue = 0;
       
  1802         
       
  1803         // Compute the dcShift again, we must have dcShift != 0 for other than 8-bit input.
       
  1804         dcShift = 1 << ( iImageInfo.DepthOfComponent( 0 ) - 1 );
       
  1805         maxValue = ( 1 << iImageInfo.DepthOfComponent( 0 ) ) - 1;   // Maximum value for this bitdepth
       
  1806 
       
  1807         for( i = 0; i < outputSize.iHeight; i++ )
       
  1808             {
       
  1809             
       
  1810             // Set the current coordinate in the output image
       
  1811             SetPixelPos( tileStartCoord.iX, tileStartCoord.iY +  i );
       
  1812             
       
  1813             for( j = 0; j < outputSize.iWidth; j++ )
       
  1814                 {
       
  1815                 x = CLIP2BITDEPTH( ( c1[i][j] + dcShift ),maxValue );
       
  1816                 y = CLIP2BITDEPTH( ( c2[i][j] + dcShift ),maxValue ); 
       
  1817                 z = CLIP2BITDEPTH( ( c3[i][j] + dcShift ),maxValue );
       
  1818                 
       
  1819                 DoICCConversion( x,y,z,sR,sG,sB );
       
  1820                 
       
  1821                 values[0] = INT2BYTE( sB );          
       
  1822                 values[1] = INT2BYTE( sG );
       
  1823                 values[2]= INT2BYTE( sR );
       
  1824                 
       
  1825                 WritePixel( values[2], values[1], values[0] );
       
  1826                 }
       
  1827             }
       
  1828 
       
  1829         // Set the current coordinate in the output image
       
  1830         SetPixelPos( tileStartCoord );
       
  1831         }
       
  1832     else
       
  1833         {
       
  1834 
       
  1835         // To speed up output writing (for subsampled samples), compute the number of half the samples
       
  1836         TInt32 halfOfWidth = outputSize.iWidth / 2;
       
  1837 
       
  1838         // If the bitdepth is not eight, shift values so that output is unsigned eight bit
       
  1839         for ( i = 0; i < iImageInfo.NumOfComponents(); i++ )
       
  1840             {
       
  1841             if ( iImageInfo.DepthOfComponent( ( TUint16 )i ) != 8 )
       
  1842                 {
       
  1843                 MapToEightBits( *iComponents[i], outputSize, iImageInfo.DepthOfComponent( (TUint16)i ) );
       
  1844                 }
       
  1845             }
       
  1846         
       
  1847         // Do the YUV to RGB conversion if needed
       
  1848         if ( iJ2kInfo.iEnumCS == 18 )
       
  1849             {
       
  1850             TPrecInt y1 = 0;
       
  1851             TPrecInt y2 = 0;
       
  1852             TPrecInt u = 0;
       
  1853             TPrecInt v = 0;
       
  1854             TPrecInt r = 0;
       
  1855             TPrecInt g = 0;
       
  1856             TPrecInt b = 0;
       
  1857             TPrecInt r1 = 0;
       
  1858             TPrecInt g1 = 0;
       
  1859             TPrecInt b1 = 0;
       
  1860             TPrecInt r2 = 0;
       
  1861             TPrecInt g2 = 0;
       
  1862             TPrecInt b2 = 0;
       
  1863             
       
  1864             if ( iFileType == KYUV420 ) // YUV 4:2:0
       
  1865                 {
       
  1866 
       
  1867                 TPrecInt* c1EvenRow = c1[0];
       
  1868                 TPrecInt* c1OddRow = c1[0];
       
  1869                 TPrecInt y3 = 0;
       
  1870                 TPrecInt y4 = 0;
       
  1871                 TPrecInt r3 = 0;
       
  1872                 TPrecInt g3 = 0;
       
  1873                 TPrecInt b3 = 0;
       
  1874                 TPrecInt r4 = 0;
       
  1875                 TPrecInt g4 = 0;
       
  1876                 TPrecInt b4 = 0;
       
  1877 
       
  1878                 for ( i = 0; i < outputSize.iHeight / 2; i++ )
       
  1879                     { 
       
  1880                     SetPixelPos( tileStartCoord.iX, ( tileStartCoord.iY + 2 * i ) );
       
  1881                     
       
  1882                     c1EvenRow = c1[2 * i];
       
  1883                     c1OddRow = c1[2 * i + 1];
       
  1884                     c2Row = c2[i];
       
  1885                     c3Row = c3[i];
       
  1886 
       
  1887                     for ( j = 0; j < halfOfWidth; j++ )
       
  1888                         {
       
  1889                         y1 = *c1EvenRow++;
       
  1890                         y2 = *c1EvenRow++;
       
  1891                         y3 = *c1OddRow++;
       
  1892                         y4 = *c1OddRow++;
       
  1893                         u = *c2Row++; 
       
  1894                         v = *c3Row++;        
       
  1895                         
       
  1896                         InverseICTTransform(y1,y2,y3,y4,u,v,r1,g1,b1,r2,g2,b2,r3,g3,b3,r4,g4,b4);
       
  1897 
       
  1898                         // Even rows, even columns
       
  1899                         values[0] = INT2BYTE( ( r1 + ditherA ) );          
       
  1900                         values[1] = INT2BYTE( ( g1 + ditherA ) );
       
  1901                         values[2] = INT2BYTE( ( b1 + ditherA ) );
       
  1902                         
       
  1903                         // Even rows, odd columns:
       
  1904                         values[3] = INT2BYTE( ( r2 + ditherB ) );          
       
  1905                         values[4] = INT2BYTE( ( g2 + ditherB ) );
       
  1906                         values[5] = INT2BYTE( ( b2 + ditherB ) );  
       
  1907                         
       
  1908                         // Store the values in the RGB "block"
       
  1909                         iColorPixelBlock[2 * j] = TRgb( values[0], values[1], values[2] );
       
  1910                         iColorPixelBlock[2 * j + 1] = TRgb( values[3], values[4], values[5] );
       
  1911 
       
  1912                         // Now the odd row:
       
  1913                         // Odd rows, even column
       
  1914                         values[0] = INT2BYTE( ( r3 + ditherC ) );          
       
  1915                         values[1] = INT2BYTE( ( g3 + ditherC ) );
       
  1916                         values[2] = INT2BYTE( ( b3 + ditherC ) );
       
  1917                         
       
  1918                         // Odd rows, odd columns:
       
  1919                         values[3] = INT2BYTE( ( r4 + ditherD ) );          
       
  1920                         values[4] = INT2BYTE( ( g4 + ditherD ) );
       
  1921                         values[5] = INT2BYTE( ( b4 + ditherD ) );  
       
  1922                     
       
  1923                         // Store the values in the RGB "block"
       
  1924                         iColorPixelBlock[KPixelsBlock + 2 * j] = TRgb( values[0], values[1], values[2] );
       
  1925                         iColorPixelBlock[KPixelsBlock + 2 * j + 1] = TRgb( values[3], values[4], values[5] );
       
  1926                         }
       
  1927                     
       
  1928                     if ( outputSize.iWidth & 1 ) // If the width is odd:
       
  1929                         {
       
  1930                         // The even row:
       
  1931                         y1 = c1[2 * i][outputSize.iWidth - 1];
       
  1932                         // And the odd row:
       
  1933                         y2 = c1[2 * i + 1][outputSize.iWidth - 1];
       
  1934                         u  = c2[i][subSamplingSize.iWidth];
       
  1935                         v  = c3[i][subSamplingSize.iWidth];
       
  1936                         
       
  1937                         InverseICTTransform(y1,y2,u,v,r1,g1,b1,r2,g2,b2); 
       
  1938 
       
  1939                         values[0] = INT2BYTE( ( r1 + ditherA ) );          
       
  1940                         values[1] = INT2BYTE( ( g1 + ditherA ) );
       
  1941                         values[2] = INT2BYTE( ( b1 + ditherA ) );
       
  1942                         
       
  1943                         // Store the value in the RGB "block"
       
  1944                         iColorPixelBlock[outputSize.iWidth - 1] = TRgb( values[0], values[1], values[2] );
       
  1945 
       
  1946                         values[0] = INT2BYTE( ( r2 + ditherC ) );
       
  1947                         values[1] = INT2BYTE( ( g2 + ditherC ) );
       
  1948                         values[2] = INT2BYTE( ( b2 + ditherC ) );
       
  1949                         
       
  1950                         // Store the value in the RGB "block"
       
  1951                         iColorPixelBlock[KPixelsBlock + outputSize.iWidth - 1] = TRgb( values[0], values[1], values[2] );
       
  1952                         }
       
  1953                     
       
  1954                     // Flush the row of color pixels to image processor
       
  1955                     iImageProcessor->SetPixels( iColorPixelBlock, outputSize.iWidth );
       
  1956 
       
  1957                     // Duplicated processing for the odd rows
       
  1958                     SetPixelPos( tileStartCoord.iX, ( tileStartCoord.iY + 2 * i + 1 ) );
       
  1959 
       
  1960                     // Flush the row of color pixels to image processor
       
  1961                     iImageProcessor->SetPixels( (iColorPixelBlock + KPixelsBlock), outputSize.iWidth );
       
  1962 
       
  1963                     } // End of loop on rows
       
  1964                 
       
  1965                 if ( outputSize.iHeight & 1 )  // If the height is odd:
       
  1966                     { 
       
  1967                     SetPixelPos( tileStartCoord.iX, ( tileStartCoord.iY + outputSize.iHeight - 1 ) );
       
  1968                     
       
  1969                     c1Row = c1[outputSize.iHeight - 1];
       
  1970                     c2Row = c2[subSamplingSize.iHeight];
       
  1971                     c3Row = c3[subSamplingSize.iHeight];
       
  1972 
       
  1973                     for ( i = 0; i < halfOfWidth; i++ ) 
       
  1974                         {
       
  1975                         y1 = *c1Row++;  
       
  1976                         y2 = *c1Row++; 
       
  1977                         u = *c2Row++;
       
  1978                         v = *c3Row++;
       
  1979                         
       
  1980                         InverseICTTransform(y1,y2,u,v,r1,g1,b1,r2,g2,b2); 
       
  1981 
       
  1982                         values[0] = INT2BYTE( ( r1 + ditherA ) );          
       
  1983                         values[1] = INT2BYTE( ( g1 + ditherA ) );
       
  1984                         values[2] = INT2BYTE( ( b1 + ditherA ) );
       
  1985                         
       
  1986                         values[3] = INT2BYTE( ( r2 + ditherB ) );          
       
  1987                         values[4] = INT2BYTE( ( g2 + ditherB ) );
       
  1988                         values[5] = INT2BYTE( ( b2 + ditherB ) );  
       
  1989                         
       
  1990                         // Store the value in the RGB "block"
       
  1991                         iColorPixelBlock[2 * i] = TRgb( values[0], values[1], values[2] );
       
  1992                         iColorPixelBlock[2 * i + 1] = TRgb( values[3], values[4], values[5] );
       
  1993                         }
       
  1994                     
       
  1995                     if ( outputSize.iWidth & 1 ) // if the width is odd:
       
  1996                         {
       
  1997                         y1 = c1[outputSize.iHeight - 1][outputSize.iWidth - 1];
       
  1998                         u = c2[subSamplingSize.iHeight][subSamplingSize.iWidth];
       
  1999                         v = c3[subSamplingSize.iHeight][subSamplingSize.iWidth];
       
  2000                         
       
  2001                         InverseICTTransform( y1, u, v, r, g, b );
       
  2002                         values[0] = INT2BYTE( ( r + ditherA ) );          
       
  2003                         values[1] = INT2BYTE( ( g + ditherA ) );
       
  2004                         values[2] = INT2BYTE( ( b + ditherA ) );
       
  2005                         
       
  2006                         // Store the value in the RGB "block"
       
  2007                         iColorPixelBlock[outputSize.iWidth - 1] = TRgb( values[0], values[1], values[2] );
       
  2008                         }
       
  2009 
       
  2010                     // Flush the row of color pixels to image processor
       
  2011                     iImageProcessor->SetPixels( iColorPixelBlock, outputSize.iWidth );
       
  2012 
       
  2013                     }
       
  2014 
       
  2015                 SetPixelPos( tileStartCoord );
       
  2016                 } 
       
  2017             else if ( iFileType == KYUV422 )
       
  2018                 {
       
  2019 
       
  2020                 for ( i = 0; i < outputSize.iHeight; i++ )
       
  2021                     {
       
  2022                     SetPixelPos( tileStartCoord.iX, ( tileStartCoord.iY + 2 * i ) );
       
  2023 
       
  2024                     c1Row = c1[i];
       
  2025                     c2Row = c2[i];
       
  2026                     c3Row = c3[i];
       
  2027 
       
  2028                     for ( j = 0; j < halfOfWidth; j++ )
       
  2029                         {
       
  2030                         y1 = *c1Row++;
       
  2031                         y2 = *c1Row++;
       
  2032                         u = c2Row[j]; 
       
  2033                         v = c3Row[j];      
       
  2034 
       
  2035                         InverseICTTransform(y1,y2,u,v,r1,g1,b1,r2,g2,b2); 
       
  2036 
       
  2037                         values[0] = INT2BYTE( ( r1 + dcShift ) );          
       
  2038                         values[1] = INT2BYTE( ( g1 + dcShift ) );
       
  2039                         values[2] = INT2BYTE( ( b1 + dcShift ) );
       
  2040                         
       
  2041                         values[3] = INT2BYTE( ( r2 + dcShift ) );          
       
  2042                         values[4] = INT2BYTE( ( g2 + dcShift ) );
       
  2043                         values[5] = INT2BYTE( ( b2 + dcShift ) );  
       
  2044                         
       
  2045                         // Store the value in the RGB "block"
       
  2046                         iColorPixelBlock[j] = TRgb( values[0], values[1], values[2] );
       
  2047                         iColorPixelBlock[j+1] = TRgb( values[3], values[4], values[5] );
       
  2048                         }
       
  2049                     
       
  2050                     if ( outputSize.iWidth & 1 ) // if the width is odd:
       
  2051                         {
       
  2052                         y1 = c1Row[outputSize.iWidth - 1];
       
  2053                         u  = c2Row[subSamplingSize.iWidth];
       
  2054                         v  = c3Row[subSamplingSize.iWidth];
       
  2055                         
       
  2056                         InverseICTTransform( y1, u, v, r, g, b );
       
  2057                         
       
  2058                         values[0] = INT2BYTE( ( r + dcShift ) );          
       
  2059                         values[1] = INT2BYTE( ( g + dcShift ) );
       
  2060                         values[2] = INT2BYTE( ( b + dcShift ) );
       
  2061                         
       
  2062                         // Store the value in the RGB "block"
       
  2063                         iColorPixelBlock[outputSize.iWidth-1] = TRgb( values[0], values[1], values[2] );
       
  2064                         }
       
  2065                     
       
  2066                     // Flush the row of color pixels to image processor
       
  2067                     iImageProcessor->SetPixels( iColorPixelBlock, outputSize.iWidth );
       
  2068                     }
       
  2069 
       
  2070                 SetPixelPos( tileStartCoord );
       
  2071                 }
       
  2072             else // To take care of YUV 4:4:4
       
  2073                 {
       
  2074 
       
  2075                 for ( i = 0; i < outputSize.iHeight; i++ )
       
  2076                     {
       
  2077                     SetPixelPos( tileStartCoord.iX, ( tileStartCoord.iY + i ) );
       
  2078 
       
  2079                     c1Row = c1[i];
       
  2080                     c2Row = c2[i];
       
  2081                     c3Row = c3[i];
       
  2082 
       
  2083                     for ( j = 0; j < outputSize.iWidth; j++ )
       
  2084                         {       
       
  2085                         y1 = *c1Row++;
       
  2086                         u = *c2Row++; 
       
  2087                         v = *c3Row++;
       
  2088                         
       
  2089                         InverseICTTransform( y1, u, v, r, g, b );
       
  2090                         
       
  2091                         values[0] = INT2BYTE( ( r + dcShift ) );          
       
  2092                         values[1] = INT2BYTE( ( g + dcShift ) );
       
  2093                         values[2] = INT2BYTE( ( b + dcShift ) );
       
  2094                         
       
  2095                         // Store the value in the RGB "block"
       
  2096                         iColorPixelBlock[j] = TRgb( values[0], values[1], values[2] );
       
  2097                         }
       
  2098 
       
  2099                     // Flush the row of color pixels to image processor
       
  2100                     iImageProcessor->SetPixels( iColorPixelBlock, outputSize.iWidth );
       
  2101                     }
       
  2102 
       
  2103                 SetPixelPos( tileStartCoord );
       
  2104                 }
       
  2105             }
       
  2106         else // RGB 
       
  2107             {
       
  2108             TInt32 r = 0;
       
  2109             TInt32 g = 0;
       
  2110             TInt32 b = 0;
       
  2111 
       
  2112             for ( i = 0; i < outputSize.iHeight; i++ )
       
  2113                 {
       
  2114 
       
  2115                 SetPixelPos( tileStartCoord.iX, tileStartCoord.iY +  i );
       
  2116 
       
  2117                 c1Row = c1[i];
       
  2118                 c2Row = c2[i];
       
  2119                 c3Row = c3[i];
       
  2120 
       
  2121                 for ( j = 0; j < outputSize.iWidth; j++ )
       
  2122                     {
       
  2123                     r = *c1Row++; 
       
  2124                     g = *c2Row++; 
       
  2125                     b = *c3Row++; 
       
  2126                     
       
  2127                     values[0] = INT2BYTE( r + dcShift );
       
  2128                     values[1] = INT2BYTE( g + dcShift );
       
  2129                     values[2] = INT2BYTE( b + dcShift );
       
  2130                     
       
  2131                     // Store the value in the RGB "block"
       
  2132                     iColorPixelBlock[j] = TRgb( values[0], values[1], values[2] );
       
  2133                     }
       
  2134 
       
  2135                 // Flush the row of color pixels to image processor
       
  2136                 iImageProcessor->SetPixels( iColorPixelBlock, outputSize.iWidth );
       
  2137                 }
       
  2138 
       
  2139             SetPixelPos( tileStartCoord );
       
  2140             }
       
  2141         }
       
  2142     }
       
  2143 
       
  2144 // -----------------------------------------------------------------------------
       
  2145 // CJ2kImageWriter::WritePixel
       
  2146 // Write out a color pixel
       
  2147 // (other items were commented in a header).
       
  2148 // -----------------------------------------------------------------------------
       
  2149 //
       
  2150 void CJ2kImageWriter::WritePixel( TUint8 aR, TUint8 aG, TUint8 aB )
       
  2151     {
       
  2152     iImageProcessor->SetPixel( TRgb( aR, aG, aB ) );
       
  2153     }
       
  2154 
       
  2155 // -----------------------------------------------------------------------------
       
  2156 // CJ2kImageWriter::WritePixel
       
  2157 // Write out a grayscale pixel
       
  2158 // (other items were commented in a header).
       
  2159 // -----------------------------------------------------------------------------
       
  2160 //
       
  2161 void CJ2kImageWriter::WritePixel( TUint8 aGray256 )
       
  2162     {
       
  2163     iImageProcessor->SetMonoPixel( aGray256 );
       
  2164     }
       
  2165 
       
  2166 // -----------------------------------------------------------------------------
       
  2167 // CJ2kImageWriter::SetPixelPos
       
  2168 // Set the position of the pixel
       
  2169 // (other items were commented in a header).
       
  2170 // -----------------------------------------------------------------------------
       
  2171 //
       
  2172 void CJ2kImageWriter::SetPixelPos( const TPoint& aPosition )
       
  2173     {
       
  2174     iImageProcessor->SetPos( aPosition );
       
  2175     }
       
  2176 
       
  2177 // -----------------------------------------------------------------------------
       
  2178 // CJ2kImageWriter::SetPixelPos
       
  2179 // Set the position of the pixel
       
  2180 // (other items were commented in a header).
       
  2181 // -----------------------------------------------------------------------------
       
  2182 //
       
  2183 void CJ2kImageWriter::SetPixelPos( const TInt aX, const TInt aY )
       
  2184     {
       
  2185     iImageProcessor->SetPos( TPoint( aX, aY ) );
       
  2186     }
       
  2187