LCOV - code coverage report
Current view: top level - frmts/ceos - ceosopen.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 90 125 72.0 %
Date: 2017-12-17 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  * $Id$
       3             :  *
       4             :  * Project:  CEOS Translator
       5             :  * Purpose:  Implementation of non-GDAL dependent CEOS support.
       6             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 1999, Frank Warmerdam
      10             :  * Copyright (c) 2007-2012, Even Rouault <even dot rouault at mines-paris dot org>
      11             :  *
      12             :  * Permission is hereby granted, free of charge, to any person obtaining a
      13             :  * copy of this software and associated documentation files (the "Software"),
      14             :  * to deal in the Software without restriction, including without limitation
      15             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16             :  * and/or sell copies of the Software, and to permit persons to whom the
      17             :  * Software is furnished to do so, subject to the following conditions:
      18             :  *
      19             :  * The above copyright notice and this permission notice shall be included
      20             :  * in all copies or substantial portions of the Software.
      21             :  *
      22             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28             :  * DEALINGS IN THE SOFTWARE.
      29             :  ****************************************************************************/
      30             : 
      31             : #include "ceosopen.h"
      32             : 
      33             : CPL_CVSID("$Id$")
      34             : 
      35           2 : CPL_INLINE static void CPL_IGNORE_RET_VAL_INT(CPL_UNUSED int unused) {}
      36             : 
      37             : /************************************************************************/
      38             : /*                            CEOSScanInt()                             */
      39             : /*                                                                      */
      40             : /*      Read up to nMaxChars from the passed string, and interpret      */
      41             : /*      as an integer.                                                  */
      42             : /************************************************************************/
      43             : 
      44          18 : static int CEOSScanInt( const char * pszString, int nMaxChars )
      45             : 
      46             : {
      47          18 :     char  szWorking[33] = { 0 };
      48             :     int   i;
      49             : 
      50          18 :     if( nMaxChars > 32 || nMaxChars == 0 )
      51           0 :         nMaxChars = 32;
      52             : 
      53         114 :     for( i = 0; i < nMaxChars && pszString[i] != '\0'; i++ )
      54          96 :         szWorking[i] = pszString[i];
      55             : 
      56          18 :     szWorking[i] = '\0';
      57             : 
      58          18 :     return( atoi(szWorking) );
      59             : }
      60             : 
      61             : /************************************************************************/
      62             : /*                           CEOSReadRecord()                           */
      63             : /*                                                                      */
      64             : /*      Read a single CEOS record at the current point in the file.     */
      65             : /*      Return NULL after reporting an error if it fails, otherwise     */
      66             : /*      return the record.                                              */
      67             : /************************************************************************/
      68             : 
      69           2 : CEOSRecord * CEOSReadRecord( CEOSImage *psImage )
      70             : 
      71             : {
      72             :     GByte abyHeader[12];
      73             :     CEOSRecord  *psRecord;
      74             :     GUInt32 nRecordNumUInt32, nLengthUInt32;
      75             : 
      76             : /* -------------------------------------------------------------------- */
      77             : /*      Read the standard CEOS header.                                  */
      78             : /* -------------------------------------------------------------------- */
      79           2 :     if( VSIFEofL( psImage->fpImage ) )
      80           0 :         return NULL;
      81             : 
      82           2 :     if( VSIFReadL( abyHeader, 1, 12, psImage->fpImage ) != 12 )
      83             :     {
      84           0 :         CPLError( CE_Failure, CPLE_FileIO,
      85             :                   "Ran out of data reading CEOS record." );
      86           0 :         return NULL;
      87             :     }
      88             : 
      89             : /* -------------------------------------------------------------------- */
      90             : /*      Extract this information.                                       */
      91             : /* -------------------------------------------------------------------- */
      92           2 :     psRecord = (CEOSRecord *) CPLMalloc(sizeof(CEOSRecord));
      93           2 :     if( psImage->bLittleEndian )
      94             :     {
      95           2 :         CPL_SWAP32PTR( abyHeader + 0 );
      96           2 :         CPL_SWAP32PTR( abyHeader + 8 );
      97             :     }
      98             : 
      99           4 :     nRecordNumUInt32 = ((unsigned)abyHeader[0] << 24)
     100           2 :                          + (abyHeader[1] << 16)
     101           2 :                          + (abyHeader[2] << 8)
     102           2 :                          + abyHeader[3];
     103             : 
     104           4 :     psRecord->nRecordType = ((unsigned)abyHeader[4] << 24)
     105           2 :                          + (abyHeader[5] << 16)
     106           2 :                          + (abyHeader[6] << 8)
     107           2 :                          + abyHeader[7];
     108             : 
     109           4 :     nLengthUInt32 = ((unsigned)abyHeader[8] << 24)
     110           2 :                          + (abyHeader[9] << 16)
     111           2 :                          + (abyHeader[10] << 8)
     112           2 :                          + abyHeader[11];
     113             : 
     114             : /* -------------------------------------------------------------------- */
     115             : /*      Does it look reasonable?  We assume there can't be too many     */
     116             : /*      records and that the length must be between 12 and 200000.      */
     117             : /* -------------------------------------------------------------------- */
     118           2 :     if( nRecordNumUInt32 > 200000
     119           2 :         || nLengthUInt32 < 12 || nLengthUInt32 > 200000 )
     120             :     {
     121           0 :         CPLError( CE_Failure, CPLE_AppDefined,
     122             :                   "CEOS record leader appears to be corrupt.\n"
     123             :                   "Record Number = %u, Record Length = %u\n",
     124             :                   nRecordNumUInt32, nLengthUInt32 );
     125           0 :         CPLFree( psRecord );
     126           0 :         return NULL;
     127             :     }
     128             : 
     129           2 :     psRecord->nRecordNum = (int)nRecordNumUInt32;
     130           2 :     psRecord->nLength = (int)nLengthUInt32;
     131             : 
     132             : /* -------------------------------------------------------------------- */
     133             : /*      Read the remainder of the record into a buffer.  Ensure that    */
     134             : /*      the first 12 bytes gets moved into this buffer as well.         */
     135             : /* -------------------------------------------------------------------- */
     136           2 :     psRecord->pachData = (char *) VSI_MALLOC_VERBOSE(psRecord->nLength );
     137           2 :     if( psRecord->pachData == NULL )
     138             :     {
     139           0 :         CPLFree( psRecord );
     140           0 :         return NULL;
     141             :     }
     142             : 
     143           2 :     memcpy( psRecord->pachData, abyHeader, 12 );
     144             : 
     145           4 :     if( (int)VSIFReadL( psRecord->pachData + 12, 1, psRecord->nLength-12,
     146             :                        psImage->fpImage )
     147           2 :         != psRecord->nLength - 12 )
     148             :     {
     149           0 :         CPLError( CE_Failure, CPLE_FileIO,
     150             :                   "Short read on CEOS record data.\n" );
     151           0 :         CPLFree( psRecord->pachData );
     152           0 :         CPLFree( psRecord );
     153           0 :         return NULL;
     154             :     }
     155             : 
     156           2 :     return psRecord;
     157             : }
     158             : 
     159             : /************************************************************************/
     160             : /*                         CEOSDestroyRecord()                          */
     161             : /*                                                                      */
     162             : /*      Free a record.                                                  */
     163             : /************************************************************************/
     164             : 
     165           2 : void CEOSDestroyRecord( CEOSRecord * psRecord )
     166             : 
     167             : {
     168           2 :     if( psRecord )
     169             :     {
     170           2 :         CPLFree( psRecord->pachData );
     171           2 :         CPLFree( psRecord );
     172             :     }
     173           2 : }
     174             : 
     175             : /************************************************************************/
     176             : /*                              CEOSOpen()                              */
     177             : /************************************************************************/
     178             : 
     179             : /**
     180             :  * Open a CEOS transfer.
     181             :  *
     182             :  * @param pszFilename The name of the CEOS imagery file (i.e. imag_01.dat).
     183             :  * @param pszAccess An fopen() style access string.  Should be either "rb" for
     184             :  * read-only access, or "r+b" for read, and update access.
     185             :  *
     186             :  * @return A CEOSImage pointer as a handle to the image.  The CEOSImage also
     187             :  * has various information about the image available.  A NULL is returned
     188             :  * if an error occurs.
     189             :  */
     190             : 
     191           2 : CEOSImage * CEOSOpen( const char * pszFilename, const char * pszAccess )
     192             : 
     193             : {
     194             :     VSILFILE  *fp;
     195             :     CEOSRecord  *psRecord;
     196             :     CEOSImage   *psImage;
     197             :     int   nSeqNum, i;
     198             :     GByte       abyHeader[16];
     199             : 
     200             : /* -------------------------------------------------------------------- */
     201             : /*      Try to open the imagery file.                                   */
     202             : /* -------------------------------------------------------------------- */
     203           2 :     fp = VSIFOpenL( pszFilename, pszAccess );
     204             : 
     205           2 :     if( fp == NULL )
     206             :     {
     207           0 :         CPLError( CE_Failure, CPLE_OpenFailed,
     208             :                   "Failed to open CEOS file `%s' with access `%s'.\n",
     209             :                   pszFilename, pszAccess );
     210           0 :         return NULL;
     211             :     }
     212             : 
     213             : /* -------------------------------------------------------------------- */
     214             : /*      Create a CEOSImage structure, and initialize it.                */
     215             : /* -------------------------------------------------------------------- */
     216           2 :     psImage = (CEOSImage *) CPLCalloc(1,sizeof(CEOSImage));
     217           2 :     psImage->fpImage = fp;
     218             : 
     219           2 :     psImage->nPixels = psImage->nLines = psImage->nBands = 0;
     220             : 
     221             : /* -------------------------------------------------------------------- */
     222             : /*      Preread info on the first record, to establish if it is         */
     223             : /*      little endian.                                                  */
     224             : /* -------------------------------------------------------------------- */
     225           4 :     if( VSIFReadL( abyHeader, 16, 1, fp ) != 1 ||
     226           2 :         VSIFSeekL( fp, 0, SEEK_SET ) < 0 )
     227             :     {
     228           0 :         CEOSClose( psImage );
     229           0 :         return NULL;
     230             :     }
     231             : 
     232           2 :     if( abyHeader[0] != 0 || abyHeader[1] != 0 )
     233           2 :         psImage->bLittleEndian = TRUE;
     234             : 
     235             : /* -------------------------------------------------------------------- */
     236             : /*      Try to read the header record.                                  */
     237             : /* -------------------------------------------------------------------- */
     238           2 :     psRecord = CEOSReadRecord( psImage );
     239           2 :     if( psRecord == NULL || psRecord->nLength < 288 + 4 )
     240             :     {
     241           0 :         CEOSDestroyRecord( psRecord );
     242           0 :         CEOSClose( psImage );
     243           0 :         return NULL;
     244             :     }
     245             : 
     246           2 :     if( psRecord->nRecordType != CRT_IMAGE_FDR )
     247             :     {
     248           0 :         CPLError( CE_Failure, CPLE_AppDefined,
     249             :                   "Got a %X type record, instead of the expected\n"
     250             :                   "file descriptor record on file %s.\n",
     251             :                   psRecord->nRecordType, pszFilename );
     252             : 
     253           0 :         CEOSDestroyRecord( psRecord );
     254           0 :         CEOSClose( psImage );
     255           0 :         return NULL;
     256             :     }
     257             : 
     258             : /* -------------------------------------------------------------------- */
     259             : /*      The sequence number should be 2 indicating this is the          */
     260             : /*      imagery file.                                                   */
     261             : /* -------------------------------------------------------------------- */
     262           2 :     nSeqNum = CEOSScanInt( psRecord->pachData + 44, 4 );
     263           2 :     if( nSeqNum != 2 )
     264             :     {
     265           0 :         CPLError( CE_Warning, CPLE_AppDefined,
     266             :                   "Got a %d file sequence number, instead of the expected\n"
     267             :                   "2 indicating imagery on file %s.\n"
     268             :                   "Continuing to access anyways.\n",
     269             :                   nSeqNum, pszFilename );
     270             :     }
     271             : 
     272             : /* -------------------------------------------------------------------- */
     273             : /*      Extract various information.                                    */
     274             : /* -------------------------------------------------------------------- */
     275           2 :     psImage->nImageRecCount = CEOSScanInt( psRecord->pachData+180, 6 );
     276           2 :     psImage->nImageRecLength = CEOSScanInt( psRecord->pachData+186, 6 );
     277           2 :     psImage->nBitsPerPixel = CEOSScanInt( psRecord->pachData+216, 4 );
     278           2 :     psImage->nBands = CEOSScanInt( psRecord->pachData+232, 4 );
     279           2 :     psImage->nLines = CEOSScanInt( psRecord->pachData+236, 8 );
     280           2 :     psImage->nPixels = CEOSScanInt( psRecord->pachData+248, 8 );
     281             : 
     282           2 :     psImage->nPrefixBytes = CEOSScanInt( psRecord->pachData+276, 4 );
     283           2 :     psImage->nSuffixBytes = CEOSScanInt( psRecord->pachData+288, 4 );
     284             : 
     285             : 
     286           4 :     if( psImage->nImageRecLength <= 0 ||
     287           4 :         psImage->nPrefixBytes < 0 ||
     288           4 :         psImage->nBands > INT_MAX / psImage->nImageRecLength ||
     289           2 :         (size_t)psImage->nBands > INT_MAX / sizeof(int))
     290             :     {
     291           0 :         CEOSDestroyRecord( psRecord );
     292           0 :         CEOSClose( psImage );
     293           0 :         return NULL;
     294             :     }
     295             : 
     296             : /* -------------------------------------------------------------------- */
     297             : /*      Try to establish the layout of the imagery data.                */
     298             : /* -------------------------------------------------------------------- */
     299           2 :     psImage->nLineOffset = psImage->nBands * psImage->nImageRecLength;
     300             : 
     301           2 :     psImage->panDataStart = (int *) VSIMalloc(sizeof(int) * psImage->nBands);
     302           2 :     if( psImage->panDataStart == NULL )
     303             :     {
     304           0 :         CEOSDestroyRecord( psRecord );
     305           0 :         CEOSClose( psImage );
     306           0 :         return NULL;
     307             :     }
     308             : 
     309          10 :     for( i = 0; i < psImage->nBands; i++ )
     310             :     {
     311          16 :         psImage->panDataStart[i] =
     312           8 :             psRecord->nLength + i * psImage->nImageRecLength
     313           8 :               + 12 + psImage->nPrefixBytes;
     314             :     }
     315             : 
     316           2 :     CEOSDestroyRecord( psRecord );
     317             : 
     318           2 :     return psImage;
     319             : }
     320             : 
     321             : /************************************************************************/
     322             : /*                          CEOSReadScanline()                          */
     323             : /************************************************************************/
     324             : 
     325             : /**
     326             :  * Read a scanline of image.
     327             :  *
     328             :  * @param psCEOS The CEOS dataset handle returned by CEOSOpen().
     329             :  * @param nBand The band number (i.e. 1, 2, 3).
     330             :  * @param nScanline The scanline requested, one based.
     331             :  * @param pData The data buffer to read into.  Must be at least nPixels *
     332             :  * nBitesPerPixel bits long.
     333             :  *
     334             :  * @return CPLErr Returns error indicator or CE_None if the read succeeds.
     335             :  */
     336             : 
     337           3 : CPLErr CEOSReadScanline( CEOSImage * psCEOS, int nBand, int nScanline,
     338             :                          void * pData )
     339             : 
     340             : {
     341             :     int   nOffset, nBytes;
     342             : 
     343             :     /*
     344             :      * As a short cut, I currently just seek to the data, and read it
     345             :      * raw, rather than trying to read ceos records properly.
     346             :      */
     347             : 
     348           6 :     nOffset = psCEOS->panDataStart[nBand-1]
     349           3 :           + (nScanline-1) * psCEOS->nLineOffset;
     350             : 
     351           3 :     if( VSIFSeekL( psCEOS->fpImage, nOffset, SEEK_SET ) != 0 )
     352             :     {
     353           0 :         CPLError( CE_Failure, CPLE_FileIO,
     354             :                   "Seek to %d for scanline %d failed.\n",
     355             :                   nOffset, nScanline );
     356           0 :         return CE_Failure;
     357             :     }
     358             : 
     359             : /* -------------------------------------------------------------------- */
     360             : /*      Read the data.                                                  */
     361             : /* -------------------------------------------------------------------- */
     362           3 :     nBytes = psCEOS->nPixels * psCEOS->nBitsPerPixel / 8;
     363           3 :     if( (int) VSIFReadL( pData, 1, nBytes, psCEOS->fpImage ) != nBytes )
     364             :     {
     365           0 :         CPLError( CE_Failure, CPLE_FileIO,
     366             :                   "Read of %d bytes for scanline %d failed.\n",
     367             :                   nBytes, nScanline );
     368           0 :         return CE_Failure;
     369             :     }
     370             : 
     371           3 :     return CE_None;
     372             : }
     373             : 
     374             : /************************************************************************/
     375             : /*                             CEOSClose()                              */
     376             : /************************************************************************/
     377             : 
     378             : /**
     379             :  * Close a CEOS transfer.  Any open files are closed, and memory deallocated.
     380             :  *
     381             :  * @param psCEOS The CEOSImage handle from CEOSOpen to be closed.
     382             :  */
     383             : 
     384           2 : void CEOSClose( CEOSImage * psCEOS )
     385             : 
     386             : {
     387           2 :     CPLFree( psCEOS->panDataStart );
     388           2 :     CPL_IGNORE_RET_VAL_INT(VSIFCloseL( psCEOS->fpImage ));
     389           2 :     CPLFree( psCEOS );
     390           2 : }

Generated by: LCOV version 1.10