LCOV - code coverage report
Current view: directory - gcore - gdaljp2box.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 150 112 74.7 %
Date: 2012-12-26 Functions: 20 17 85.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdaljp2box.cpp 24227 2012-04-13 20:55:20Z rouault $
       3                 :  *
       4                 :  * Project:  GDAL 
       5                 :  * Purpose:  GDALJP2Box Implementation - Low level JP2 box reader.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "gdaljp2metadata.h"
      31                 : #include "cpl_string.h"
      32                 : 
      33                 : CPL_CVSID("$Id: gdaljp2box.cpp 24227 2012-04-13 20:55:20Z rouault $");
      34                 : 
      35                 : /************************************************************************/
      36                 : /*                             GDALJP2Box()                             */
      37                 : /************************************************************************/
      38                 : 
      39             475 : GDALJP2Box::GDALJP2Box( VSILFILE *fpIn )
      40                 : 
      41                 : {
      42             475 :     fpVSIL = fpIn;
      43             475 :     szBoxType[0] = '\0';
      44             475 :     nBoxOffset = -1;
      45             475 :     nDataOffset = -1;
      46             475 :     nBoxLength = 0;
      47                 :     
      48             475 :     pabyData = NULL;
      49             475 : }
      50                 : 
      51                 : /************************************************************************/
      52                 : /*                            ~GDALJP2Box()                             */
      53                 : /************************************************************************/
      54                 : 
      55             475 : GDALJP2Box::~GDALJP2Box()
      56                 : 
      57                 : {
      58             475 :     CPLFree( pabyData );
      59             475 : }
      60                 : 
      61                 : /************************************************************************/
      62                 : /*                             SetOffset()                              */
      63                 : /************************************************************************/
      64                 : 
      65            1150 : int  GDALJP2Box::SetOffset( GIntBig nNewOffset )
      66                 : 
      67                 : {
      68            1150 :     szBoxType[0] = '\0';
      69            1150 :     return VSIFSeekL( fpVSIL, nNewOffset, SEEK_SET ) == 0;
      70                 : }
      71                 : 
      72                 : /************************************************************************/
      73                 : /*                             ReadFirst()                              */
      74                 : /************************************************************************/
      75                 : 
      76             143 : int GDALJP2Box::ReadFirst()
      77                 : 
      78                 : {
      79             143 :     return SetOffset(0) && ReadBox();
      80                 : }
      81                 : 
      82                 : /************************************************************************/
      83                 : /*                              ReadNext()                              */
      84                 : /************************************************************************/
      85                 : 
      86             828 : int GDALJP2Box::ReadNext()
      87                 : 
      88                 : {
      89             828 :     return SetOffset( nBoxOffset + nBoxLength ) && ReadBox();
      90                 : }
      91                 : 
      92                 : /************************************************************************/
      93                 : /*                           ReadFirstChild()                           */
      94                 : /************************************************************************/
      95                 : 
      96             179 : int GDALJP2Box::ReadFirstChild( GDALJP2Box *poSuperBox )
      97                 : 
      98                 : {
      99             179 :     szBoxType[0] = '\0';
     100             179 :     if( !poSuperBox->IsSuperBox() )
     101               0 :         return FALSE;
     102                 : 
     103             179 :     return SetOffset( poSuperBox->nDataOffset ) && ReadBox();
     104                 : }
     105                 : 
     106                 : /************************************************************************/
     107                 : /*                           ReadNextChild()                            */
     108                 : /************************************************************************/
     109                 : 
     110             341 : int GDALJP2Box::ReadNextChild( GDALJP2Box *poSuperBox )
     111                 : 
     112                 : {
     113             341 :     if( !ReadNext() )
     114               0 :         return FALSE;
     115                 : 
     116             341 :     if( nBoxOffset >= poSuperBox->nBoxOffset + poSuperBox->nBoxLength )
     117                 :     {
     118             148 :         szBoxType[0] = '\0';
     119             148 :         return FALSE;
     120                 :     }
     121                 : 
     122             193 :     return TRUE;
     123                 : }
     124                 : 
     125                 : /************************************************************************/
     126                 : /*                              ReadBox()                               */
     127                 : /************************************************************************/
     128                 : 
     129            1150 : int GDALJP2Box::ReadBox()
     130                 : 
     131                 : {
     132                 :     GUInt32   nLBox;
     133                 :     GUInt32   nTBox;
     134                 : 
     135            1150 :     nBoxOffset = VSIFTellL( fpVSIL );
     136                 : 
     137            1150 :     if( VSIFReadL( &nLBox, 4, 1, fpVSIL ) != 1
     138                 :         || VSIFReadL( &nTBox, 4, 1, fpVSIL ) != 1 )
     139                 :     {
     140              94 :         return FALSE;
     141                 :     }
     142                 : 
     143            1056 :     memcpy( szBoxType, &nTBox, 4 );
     144            1056 :     szBoxType[4] = '\0';
     145                 : 
     146            1056 :     nLBox = CPL_MSBWORD32( nLBox );
     147                 : 
     148            1056 :     if( nLBox != 1 )
     149                 :     {
     150            1056 :         nBoxLength = nLBox;
     151            1056 :         nDataOffset = nBoxOffset + 8;
     152                 :     }
     153                 :     else
     154                 :     {
     155                 :         GByte abyXLBox[8];
     156               0 :         if( VSIFReadL( abyXLBox, 8, 1, fpVSIL ) != 1 )
     157               0 :             return FALSE;
     158                 : 
     159                 :         
     160                 :         if( sizeof(nBoxLength) == 8 )
     161                 :         {
     162               0 :             CPL_MSBPTR64( abyXLBox );
     163               0 :             memcpy( &nBoxLength, abyXLBox, 8 );
     164                 :         }
     165                 :         else
     166                 :         {
     167                 :             CPL_MSBPTR32( abyXLBox+4 );
     168                 :             memcpy( &nBoxLength, abyXLBox+4, 4 );
     169                 :         }
     170                 : 
     171               0 :         nDataOffset = nBoxOffset + 16;
     172                 :     }
     173                 : 
     174            1056 :     if( nBoxLength == 0 )
     175                 :     {
     176              92 :         VSIFSeekL( fpVSIL, 0, SEEK_END );
     177              92 :         nBoxLength = VSIFTellL( fpVSIL ) - nBoxOffset;
     178                 :     }
     179                 : 
     180            1056 :     if( EQUAL(szBoxType,"uuid") )
     181                 :     {
     182             169 :         VSIFReadL( abyUUID, 16, 1, fpVSIL );
     183             169 :         nDataOffset += 16;
     184                 :     }
     185                 : 
     186            1056 :     if( GetDataLength() < 0 )
     187                 :     {
     188               0 :         CPLDebug("GDALJP2", "Invalid length for box %s", szBoxType);
     189               0 :         return FALSE;
     190                 :     }
     191                 : 
     192            1056 :     return TRUE;
     193                 : }
     194                 : 
     195                 : /************************************************************************/
     196                 : /*                             IsSuperBox()                             */
     197                 : /************************************************************************/
     198                 : 
     199             179 : int GDALJP2Box::IsSuperBox()
     200                 : 
     201                 : {
     202             179 :     if( EQUAL(GetType(),"asoc") || EQUAL(GetType(),"jp2h")
     203                 :         || EQUAL(GetType(),"res ") )
     204             179 :         return TRUE;
     205                 :     else
     206               0 :         return FALSE;
     207                 : }
     208                 : 
     209                 : /************************************************************************/
     210                 : /*                            ReadBoxData()                             */
     211                 : /************************************************************************/
     212                 : 
     213             169 : GByte *GDALJP2Box::ReadBoxData()
     214                 : 
     215                 : {
     216             169 :     char *pszData = (char *) CPLMalloc((int)GetDataLength() + 1);
     217                 : 
     218             169 :     if( (GIntBig) VSIFReadL( pszData, 1, (int)GetDataLength(), fpVSIL ) 
     219                 :         != GetDataLength() )
     220                 :     {
     221               0 :         CPLFree( pszData );
     222               0 :         return NULL;
     223                 :     }
     224                 : 
     225             169 :     pszData[GetDataLength()] = '\0';
     226                 : 
     227             169 :     return (GByte *) pszData;
     228                 : }
     229                 : 
     230                 : /************************************************************************/
     231                 : /*                           GetDataLength()                            */
     232                 : /************************************************************************/
     233                 : 
     234            2185 : GIntBig GDALJP2Box::GetDataLength()
     235                 : {
     236            2185 :     return nBoxLength - (nDataOffset - nBoxOffset);
     237                 : }
     238                 : 
     239                 : /************************************************************************/
     240                 : /*                            DumpReadable()                            */
     241                 : /************************************************************************/
     242                 : 
     243               0 : int GDALJP2Box::DumpReadable( FILE *fpOut, int nIndentLevel )
     244                 : 
     245                 : {
     246               0 :     if( fpOut == NULL )
     247               0 :         fpOut = stdout;
     248                 : 
     249                 :     int i;
     250               0 :     for(i=0;i<nIndentLevel;i++)
     251               0 :         fprintf( fpOut, "  " );
     252                 : 
     253                 :     fprintf( fpOut, "  Type=%s, Offset=%d/%d, Data Size=%d",
     254                 :              szBoxType, (int) nBoxOffset, (int) nDataOffset, 
     255               0 :              (int)(nBoxLength - (nDataOffset - nBoxOffset)) );
     256                 : 
     257               0 :     if( IsSuperBox() )
     258                 :     {
     259               0 :         fprintf( fpOut, " (super)" );
     260                 :     }
     261                 : 
     262               0 :     fprintf( fpOut, "\n" );
     263                 :     
     264               0 :     if( IsSuperBox() ) 
     265                 :     {
     266               0 :         GDALJP2Box oSubBox( GetFILE() );
     267                 : 
     268               0 :         for( oSubBox.ReadFirstChild( this );
     269                 :              strlen(oSubBox.GetType()) > 0;
     270                 :              oSubBox.ReadNextChild( this ) )
     271                 :         {
     272               0 :             oSubBox.DumpReadable( fpOut, nIndentLevel + 1 );
     273               0 :         }
     274                 :     }
     275                 : 
     276               0 :     if( EQUAL(GetType(),"uuid") )
     277                 :     {
     278               0 :         char *pszHex = CPLBinaryToHex( 16, GetUUID() );
     279               0 :         for(i=0;i<nIndentLevel;i++)
     280               0 :             fprintf( fpOut, "  " );
     281                 : 
     282               0 :         fprintf( fpOut, "    UUID=%s", pszHex );
     283                 : 
     284               0 :         if( EQUAL(pszHex,"B14BF8BD083D4B43A5AE8CD7D5A6CE03") )
     285               0 :             fprintf( fpOut, " (GeoTIFF)" );
     286               0 :         if( EQUAL(pszHex,"96A9F1F1DC98402DA7AED68E34451809") )
     287               0 :             fprintf( fpOut, " (MSI Worldfile)" );
     288               0 :         CPLFree( pszHex );
     289                 : 
     290               0 :         fprintf( fpOut, "\n" );
     291                 :     }
     292                 : 
     293               0 :     return 0;
     294                 : }
     295                 : 
     296                 : /************************************************************************/
     297                 : /*                              SetType()                               */
     298                 : /************************************************************************/
     299                 : 
     300             155 : void GDALJP2Box::SetType( const char *pszType )
     301                 : 
     302                 : {
     303             155 :     CPLAssert( strlen(pszType) == 4 );
     304                 : 
     305             155 :     memcpy(szBoxType, pszType, 4);
     306             155 :     szBoxType[4] = '\0';
     307             155 : }
     308                 : 
     309                 : /************************************************************************/
     310                 : /*                          SetWritableData()                           */
     311                 : /************************************************************************/
     312                 : 
     313             153 : void GDALJP2Box::SetWritableData( int nLength, const GByte *pabyDataIn )
     314                 : 
     315                 : {
     316             153 :     CPLFree( pabyData );
     317                 :     
     318             153 :     pabyData = (GByte *) CPLMalloc(nLength);
     319             153 :     memcpy( pabyData, pabyDataIn, nLength );
     320                 : 
     321             153 :     nBoxOffset = -9; // virtual offsets for data length computation.
     322             153 :     nDataOffset = -1;
     323                 :     
     324             153 :     nBoxLength = 8 + nLength;
     325             153 : }
     326                 : 
     327                 : /************************************************************************/
     328                 : /*                           CreateUUIDBox()                            */
     329                 : /************************************************************************/
     330                 : 
     331              32 : GDALJP2Box *GDALJP2Box::CreateUUIDBox( 
     332                 :     const GByte *pabyUUID, int nDataSize, GByte *pabyData )
     333                 : 
     334                 : {
     335                 :     GDALJP2Box *poBox;
     336                 : 
     337              32 :     poBox = new GDALJP2Box();
     338              32 :     poBox->SetType( "uuid" );
     339              32 :     memcpy( poBox->abyUUID, pabyUUID, 16 );
     340                 : 
     341              32 :     GByte *pabyMergedData = (GByte *) CPLMalloc(16+nDataSize);
     342              32 :     memcpy( pabyMergedData, pabyUUID, 16 );
     343              32 :     memcpy( pabyMergedData+16, pabyData, nDataSize );
     344                 :     
     345              32 :     poBox->SetWritableData( 16 + nDataSize, pabyMergedData );
     346                 :     
     347              32 :     CPLFree( pabyMergedData );
     348                 : 
     349              32 :     return poBox;
     350                 : }
     351                 : 
     352                 : /************************************************************************/
     353                 : /*                           CreateAsocBox()                            */
     354                 : /************************************************************************/
     355                 : 
     356              48 : GDALJP2Box *GDALJP2Box::CreateAsocBox( int nCount, GDALJP2Box **papoBoxes )
     357                 : 
     358                 : 
     359                 : {
     360              48 :     int nDataSize=0, iBox;
     361                 :     GByte *pabyCompositeData, *pabyNext;
     362                 : 
     363                 : /* -------------------------------------------------------------------- */
     364                 : /*      Compute size of data area of asoc box.                          */
     365                 : /* -------------------------------------------------------------------- */
     366             146 :     for( iBox = 0; iBox < nCount; iBox++ )
     367              98 :         nDataSize += 8 + (int) papoBoxes[iBox]->GetDataLength();
     368                 : 
     369              48 :     pabyNext = pabyCompositeData = (GByte *) CPLMalloc(nDataSize);
     370                 : 
     371                 : /* -------------------------------------------------------------------- */
     372                 : /*      Copy subboxes headers and data into buffer.                     */
     373                 : /* -------------------------------------------------------------------- */
     374             146 :     for( iBox = 0; iBox < nCount; iBox++ )
     375                 :     {
     376                 :         GUInt32   nLBox;
     377                 : 
     378              98 :         nLBox = CPL_MSBWORD32(papoBoxes[iBox]->nBoxLength);
     379              98 :         memcpy( pabyNext, &nLBox, 4 );
     380              98 :         pabyNext += 4;
     381                 : 
     382              98 :         memcpy( pabyNext, papoBoxes[iBox]->szBoxType, 4 );
     383              98 :         pabyNext += 4;
     384                 : 
     385              98 :         memcpy( pabyNext, papoBoxes[iBox]->pabyData, 
     386             196 :                 (int) papoBoxes[iBox]->GetDataLength() );
     387              98 :         pabyNext += papoBoxes[iBox]->GetDataLength();
     388                 :     }
     389                 :     
     390                 : /* -------------------------------------------------------------------- */
     391                 : /*      Create asoc box.                                                */
     392                 : /* -------------------------------------------------------------------- */
     393              48 :     GDALJP2Box *poAsoc = new GDALJP2Box();
     394                 : 
     395              48 :     poAsoc->SetType( "asoc" );
     396              48 :     poAsoc->SetWritableData( nDataSize, pabyCompositeData );
     397                 :     
     398              48 :     CPLFree( pabyCompositeData );
     399                 : 
     400              48 :     return poAsoc;
     401                 : }
     402                 : 
     403                 : /************************************************************************/
     404                 : /*                            CreateLblBox()                            */
     405                 : /************************************************************************/
     406                 : 
     407              21 : GDALJP2Box *GDALJP2Box::CreateLblBox( const char *pszLabel )
     408                 : 
     409                 : {
     410                 :     GDALJP2Box *poBox;
     411                 : 
     412              21 :     poBox = new GDALJP2Box();
     413              21 :     poBox->SetType( "lbl " );
     414              21 :     poBox->SetWritableData( strlen(pszLabel)+1, (const GByte *) pszLabel );
     415                 : 
     416              21 :     return poBox;
     417                 : }
     418                 : 
     419                 : /************************************************************************/
     420                 : /*                       CreateLabelledXMLAssoc()                       */
     421                 : /************************************************************************/
     422                 : 
     423              25 : GDALJP2Box *GDALJP2Box::CreateLabelledXMLAssoc( const char *pszLabel,
     424                 :                                                 const char *pszXML )
     425                 : 
     426                 : {
     427              25 :     GDALJP2Box oLabel, oXML;
     428                 :     GDALJP2Box *aoList[2];
     429                 : 
     430              25 :     oLabel.SetType( "lbl " );
     431              25 :     oLabel.SetWritableData( strlen(pszLabel)+1, (const GByte *) pszLabel );
     432                 : 
     433              25 :     oXML.SetType( "xml " );
     434              25 :     oXML.SetWritableData( strlen(pszXML)+1, (const GByte *) pszXML );
     435                 : 
     436              25 :     aoList[0] = &oLabel;
     437              25 :     aoList[1] = &oXML;
     438                 :     
     439              25 :     return CreateAsocBox( 2, aoList );
     440                 : }
     441                 : 

Generated by: LCOV version 1.7