LCOV - code coverage report
Current view: directory - gcore - gdaljp2box.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 141 114 80.9 %
Date: 2010-01-09 Functions: 18 17 94.4 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdaljp2box.cpp 17636 2009-09-12 23:19:18Z warmerdam $
       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 17636 2009-09-12 23:19:18Z warmerdam $");
      34                 : 
      35                 : /************************************************************************/
      36                 : /*                             GDALJP2Box()                             */
      37                 : /************************************************************************/
      38                 : 
      39             225 : GDALJP2Box::GDALJP2Box( FILE *fpIn )
      40                 : 
      41                 : {
      42             225 :     fpVSIL = fpIn;
      43             225 :     szBoxType[0] = '\0';
      44             225 :     nBoxOffset = -1;
      45             225 :     nDataOffset = -1;
      46             225 :     nBoxLength = 0;
      47                 :     
      48             225 :     pabyData = NULL;
      49             225 : }
      50                 : 
      51                 : /************************************************************************/
      52                 : /*                            ~GDALJP2Box()                             */
      53                 : /************************************************************************/
      54                 : 
      55             225 : GDALJP2Box::~GDALJP2Box()
      56                 : 
      57                 : {
      58             225 :     CPLFree( pabyData );
      59             225 : }
      60                 : 
      61                 : /************************************************************************/
      62                 : /*                             SetOffset()                              */
      63                 : /************************************************************************/
      64                 : 
      65             456 : int  GDALJP2Box::SetOffset( GIntBig nNewOffset )
      66                 : 
      67                 : {
      68             456 :     szBoxType[0] = '\0';
      69             456 :     return VSIFSeekL( fpVSIL, nNewOffset, SEEK_SET ) == 0;
      70                 : }
      71                 : 
      72                 : /************************************************************************/
      73                 : /*                             ReadFirst()                              */
      74                 : /************************************************************************/
      75                 : 
      76              82 : int GDALJP2Box::ReadFirst()
      77                 : 
      78                 : {
      79              82 :     return SetOffset(0) && ReadBox();
      80                 : }
      81                 : 
      82                 : /************************************************************************/
      83                 : /*                              ReadNext()                              */
      84                 : /************************************************************************/
      85                 : 
      86             323 : int GDALJP2Box::ReadNext()
      87                 : 
      88                 : {
      89             323 :     return SetOffset( nBoxOffset + nBoxLength ) && ReadBox();
      90                 : }
      91                 : 
      92                 : /************************************************************************/
      93                 : /*                           ReadFirstChild()                           */
      94                 : /************************************************************************/
      95                 : 
      96              51 : int GDALJP2Box::ReadFirstChild( GDALJP2Box *poSuperBox )
      97                 : 
      98                 : {
      99              51 :     if( !poSuperBox->IsSuperBox() )
     100               0 :         return FALSE;
     101                 : 
     102              51 :     return SetOffset( poSuperBox->nDataOffset ) && ReadBox();
     103                 : }
     104                 : 
     105                 : /************************************************************************/
     106                 : /*                           ReadNextChild()                            */
     107                 : /************************************************************************/
     108                 : 
     109              68 : int GDALJP2Box::ReadNextChild( GDALJP2Box *poSuperBox )
     110                 : 
     111                 : {
     112              68 :     if( !ReadNext() )
     113               0 :         return FALSE;
     114                 : 
     115              68 :     if( nBoxOffset >= poSuperBox->nBoxOffset + poSuperBox->nBoxLength )
     116                 :     {
     117              34 :         szBoxType[0] = '\0';
     118              34 :         return FALSE;
     119                 :     }
     120                 : 
     121              34 :     return TRUE;
     122                 : }
     123                 : 
     124                 : /************************************************************************/
     125                 : /*                              ReadBox()                               */
     126                 : /************************************************************************/
     127                 : 
     128             456 : int GDALJP2Box::ReadBox()
     129                 : 
     130                 : {
     131                 :     GUInt32   nLBox;
     132                 :     GUInt32   nTBox;
     133                 : 
     134             456 :     nBoxOffset = VSIFTellL( fpVSIL );
     135                 : 
     136             456 :     if( VSIFReadL( &nLBox, 4, 1, fpVSIL ) != 1
     137                 :         || VSIFReadL( &nTBox, 4, 1, fpVSIL ) != 1 )
     138                 :     {
     139              54 :         return FALSE;
     140                 :     }
     141                 : 
     142             402 :     memcpy( szBoxType, &nTBox, 4 );
     143             402 :     szBoxType[4] = '\0';
     144                 : 
     145             402 :     nLBox = CPL_MSBWORD32( nLBox );
     146                 : 
     147             402 :     if( nLBox != 1 )
     148                 :     {
     149             402 :         nBoxLength = nLBox;
     150             402 :         nDataOffset = nBoxOffset + 8;
     151                 :     }
     152                 :     else
     153                 :     {
     154                 :         GByte abyXLBox[8];
     155               0 :         if( VSIFReadL( abyXLBox, 8, 1, fpVSIL ) != 1 )
     156               0 :             return FALSE;
     157                 : 
     158                 :         
     159                 :         if( sizeof(nBoxLength) == 8 )
     160                 :         {
     161               0 :             CPL_MSBPTR64( abyXLBox );
     162               0 :             memcpy( &nBoxLength, abyXLBox, 8 );
     163                 :         }
     164                 :         else
     165                 :         {
     166                 :             CPL_MSBPTR32( abyXLBox+4 );
     167                 :             memcpy( &nBoxLength, abyXLBox+4, 4 );
     168                 :         }
     169                 : 
     170               0 :         nDataOffset = nBoxOffset + 16;
     171                 :     }
     172                 : 
     173             402 :     if( nBoxLength == 0 )
     174                 :     {
     175              50 :         VSIFSeekL( fpVSIL, 0, SEEK_END );
     176              50 :         nBoxLength = VSIFTellL( fpVSIL ) - nBoxOffset;
     177                 :     }
     178                 : 
     179             402 :     if( EQUAL(szBoxType,"uuid") )
     180                 :     {
     181              61 :         VSIFReadL( abyUUID, 16, 1, fpVSIL );
     182              61 :         nDataOffset += 16;
     183                 :     }
     184                 : 
     185             402 :     return TRUE;
     186                 : }
     187                 : 
     188                 : /************************************************************************/
     189                 : /*                             IsSuperBox()                             */
     190                 : /************************************************************************/
     191                 : 
     192              51 : int GDALJP2Box::IsSuperBox()
     193                 : 
     194                 : {
     195              51 :     if( EQUAL(GetType(),"asoc") || EQUAL(GetType(),"jp2h") )
     196              51 :         return TRUE;
     197                 :     else
     198               0 :         return FALSE;
     199                 : }
     200                 : 
     201                 : /************************************************************************/
     202                 : /*                            ReadBoxData()                             */
     203                 : /************************************************************************/
     204                 : 
     205              85 : GByte *GDALJP2Box::ReadBoxData()
     206                 : 
     207                 : {
     208              85 :     char *pszData = (char *) CPLMalloc((int)GetDataLength() + 1);
     209                 : 
     210              85 :     if( (GIntBig) VSIFReadL( pszData, 1, (int)GetDataLength(), fpVSIL ) 
     211                 :         != GetDataLength() )
     212                 :     {
     213               0 :         CPLFree( pszData );
     214               0 :         return NULL;
     215                 :     }
     216                 : 
     217              85 :     pszData[GetDataLength()] = '\0';
     218                 : 
     219              85 :     return (GByte *) pszData;
     220                 : }
     221                 : 
     222                 : /************************************************************************/
     223                 : /*                           GetDataLength()                            */
     224                 : /************************************************************************/
     225                 : 
     226             583 : GIntBig GDALJP2Box::GetDataLength()
     227                 : {
     228             583 :     return nBoxLength - (nDataOffset - nBoxOffset);
     229                 : }
     230                 : 
     231                 : /************************************************************************/
     232                 : /*                            DumpReadable()                            */
     233                 : /************************************************************************/
     234                 : 
     235               0 : int GDALJP2Box::DumpReadable( FILE *fpOut )
     236                 : 
     237                 : {
     238               0 :     if( fpOut == NULL )
     239               0 :         fpOut = stdout;
     240                 : 
     241                 :     fprintf( fpOut, "  Type=%s, Offset=%d/%d, Data Size=%d",
     242                 :              szBoxType, (int) nBoxOffset, (int) nDataOffset, 
     243               0 :              (int)(nBoxLength - (nDataOffset - nBoxOffset)) );
     244                 : 
     245               0 :     if( IsSuperBox() )
     246               0 :         fprintf( fpOut, " (super)" );
     247                 : 
     248               0 :     fprintf( fpOut, "\n" );
     249               0 :     if( EQUAL(GetType(),"uuid") )
     250                 :     {
     251               0 :         char *pszHex = CPLBinaryToHex( 16, GetUUID() );
     252               0 :         fprintf( fpOut, "    UUID=%s", pszHex );
     253                 : 
     254               0 :         if( EQUAL(pszHex,"B14BF8BD083D4B43A5AE8CD7D5A6CE03") )
     255               0 :             fprintf( fpOut, " (GeoTIFF)" );
     256               0 :         if( EQUAL(pszHex,"96A9F1F1DC98402DA7AED68E34451809") )
     257               0 :             fprintf( fpOut, " (MSI Worldfile)" );
     258               0 :         CPLFree( pszHex );
     259                 : 
     260               0 :         fprintf( fpOut, "\n" );
     261                 :     }
     262               0 :     return 0;
     263                 : }
     264                 : 
     265                 : /************************************************************************/
     266                 : /*                              SetType()                               */
     267                 : /************************************************************************/
     268                 : 
     269              92 : void GDALJP2Box::SetType( const char *pszType )
     270                 : 
     271                 : {
     272                 :     CPLAssert( strlen(pszType) == 4 );
     273                 : 
     274              92 :     szBoxType[0] = pszType[3];
     275              92 :     szBoxType[1] = pszType[2];
     276              92 :     szBoxType[2] = pszType[1];
     277              92 :     szBoxType[3] = pszType[0];
     278              92 :     szBoxType[4] = '\0';
     279              92 : }
     280                 : 
     281                 : /************************************************************************/
     282                 : /*                          SetWritableData()                           */
     283                 : /************************************************************************/
     284                 : 
     285              92 : void GDALJP2Box::SetWritableData( int nLength, const GByte *pabyDataIn )
     286                 : 
     287                 : {
     288              92 :     CPLFree( pabyData );
     289                 :     
     290              92 :     pabyData = (GByte *) CPLMalloc(nLength);
     291              92 :     memcpy( pabyData, pabyDataIn, nLength );
     292                 : 
     293              92 :     nBoxOffset = -9; // virtual offsets for data length computation.
     294              92 :     nDataOffset = -1;
     295                 :     
     296              92 :     nBoxLength = 8 + nLength;
     297              92 : }
     298                 : 
     299                 : /************************************************************************/
     300                 : /*                           CreateUUIDBox()                            */
     301                 : /************************************************************************/
     302                 : 
     303              17 : GDALJP2Box *GDALJP2Box::CreateUUIDBox( 
     304                 :     const GByte *pabyUUID, int nDataSize, GByte *pabyData )
     305                 : 
     306                 : {
     307                 :     GDALJP2Box *poBox;
     308                 : 
     309              17 :     poBox = new GDALJP2Box();
     310              17 :     poBox->SetType( "uuid" );
     311              17 :     memcpy( poBox->abyUUID, pabyUUID, 16 );
     312                 : 
     313              17 :     GByte *pabyMergedData = (GByte *) CPLMalloc(16+nDataSize);
     314              17 :     memcpy( pabyMergedData, pabyUUID, 16 );
     315              17 :     memcpy( pabyMergedData+16, pabyData, nDataSize );
     316                 :     
     317              17 :     poBox->SetWritableData( 16 + nDataSize, pabyMergedData );
     318                 :     
     319              17 :     CPLFree( pabyMergedData );
     320                 : 
     321              17 :     return poBox;
     322                 : }
     323                 : 
     324                 : /************************************************************************/
     325                 : /*                           CreateAsocBox()                            */
     326                 : /************************************************************************/
     327                 : 
     328              30 : GDALJP2Box *GDALJP2Box::CreateAsocBox( int nCount, GDALJP2Box **papoBoxes )
     329                 : 
     330                 : 
     331                 : {
     332              30 :     int nDataSize=0, iBox;
     333                 :     GByte *pabyCompositeData, *pabyNext;
     334                 : 
     335                 : /* -------------------------------------------------------------------- */
     336                 : /*      Compute size of data area of asoc box.                          */
     337                 : /* -------------------------------------------------------------------- */
     338              90 :     for( iBox = 0; iBox < nCount; iBox++ )
     339              60 :         nDataSize += 8 + (int) papoBoxes[iBox]->GetDataLength();
     340                 : 
     341              30 :     pabyNext = pabyCompositeData = (GByte *) CPLMalloc(nDataSize);
     342                 : 
     343                 : /* -------------------------------------------------------------------- */
     344                 : /*      Copy subboxes headers and data into buffer.                     */
     345                 : /* -------------------------------------------------------------------- */
     346              90 :     for( iBox = 0; iBox < nCount; iBox++ )
     347                 :     {
     348                 :         GUInt32   nLBox, nTBox;
     349                 : 
     350              60 :         nLBox = CPL_MSBWORD32(papoBoxes[iBox]->nBoxLength);
     351              60 :         memcpy( pabyNext, &nLBox, 4 );
     352              60 :         pabyNext += 4;
     353                 : 
     354              60 :         memcpy( &nTBox, papoBoxes[iBox]->szBoxType, 4 );
     355              60 :         nTBox = CPL_MSBWORD32( nTBox );
     356              60 :         memcpy( pabyNext, &nTBox, 4 );
     357              60 :         pabyNext += 4;
     358                 : 
     359              60 :         memcpy( pabyNext, papoBoxes[iBox]->pabyData, 
     360             120 :                 (int) papoBoxes[iBox]->GetDataLength() );
     361              60 :         pabyNext += papoBoxes[iBox]->GetDataLength();
     362                 :     }
     363                 :     
     364                 : /* -------------------------------------------------------------------- */
     365                 : /*      Create asoc box.                                                */
     366                 : /* -------------------------------------------------------------------- */
     367              30 :     GDALJP2Box *poAsoc = new GDALJP2Box();
     368                 : 
     369              30 :     poAsoc->SetType( "asoc" );
     370              30 :     poAsoc->SetWritableData( nDataSize, pabyCompositeData );
     371                 :     
     372              30 :     CPLFree( pabyCompositeData );
     373                 : 
     374              30 :     return poAsoc;
     375                 : }
     376                 : 
     377                 : /************************************************************************/
     378                 : /*                            CreateLblBox()                            */
     379                 : /************************************************************************/
     380                 : 
     381              15 : GDALJP2Box *GDALJP2Box::CreateLblBox( const char *pszLabel )
     382                 : 
     383                 : {
     384                 :     GDALJP2Box *poBox;
     385                 : 
     386              15 :     poBox = new GDALJP2Box();
     387              15 :     poBox->SetType( "lbl " );
     388              15 :     poBox->SetWritableData( strlen(pszLabel)+1, (const GByte *) pszLabel );
     389                 : 
     390              15 :     return poBox;
     391                 : }
     392                 : 
     393                 : /************************************************************************/
     394                 : /*                       CreateLabelledXMLAssoc()                       */
     395                 : /************************************************************************/
     396                 : 
     397              15 : GDALJP2Box *GDALJP2Box::CreateLabelledXMLAssoc( const char *pszLabel,
     398                 :                                                 const char *pszXML )
     399                 : 
     400                 : {
     401              15 :     GDALJP2Box oLabel, oXML;
     402                 :     GDALJP2Box *aoList[2];
     403                 : 
     404              15 :     oLabel.SetType( "lbl " );
     405              15 :     oLabel.SetWritableData( strlen(pszLabel)+1, (const GByte *) pszLabel );
     406                 : 
     407              15 :     oXML.SetType( "xml " );
     408              15 :     oXML.SetWritableData( strlen(pszXML)+1, (const GByte *) pszXML );
     409                 : 
     410              15 :     aoList[0] = &oLabel;
     411              15 :     aoList[1] = &oXML;
     412                 :     
     413              15 :     return CreateAsocBox( 2, aoList );
     414                 : }
     415                 : 

Generated by: LCOV version 1.7